@fbsm/saga-core 0.1.0-beta.4 → 0.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -121,13 +121,13 @@ interface RunnerOptions {
121
121
 
122
122
  **Handler execution flow**:
123
123
 
124
- 1. Parse inbound message via `SagaParser`
125
- 2. Look up handler in route map
126
- 3. Wrap emit with `final` hint (if `{ final: true }`)
127
- 4. Wrap emit with fork logic (if `{ fork: true }`) — creates sub-saga per emit
128
- 5. Set `SagaContext` via `AsyncLocalStorage`
129
- 6. Execute handler with retry on `SagaRetryableError`
130
- 7. On retry exhaustion, call `participant.onRetryExhausted()` if defined
124
+ 1. Parse inbound message via `SagaParser` — if parsed (saga metadata found), route to saga handler; if null (no metadata), route to plain handler
125
+ 2. Look up handler in route map (`RouteEntry` supports both `sagaHandler` and `plainHandler` per topic)
126
+ 3. **Saga path**: Wrap emit with `final` hint (if `{ final: true }`), fork logic (if `{ fork: true }`), set `SagaContext` via `AsyncLocalStorage`
127
+ 4. Execute handler with retry on `SagaRetryableError`
128
+ 5. On non-retryable error: call `participant.onFail()` if defined (with independent retry)
129
+ 6. On retry exhaustion (from handle or onFail): call `participant.onRetryExhausted()` if defined
130
+ 7. **Plain path**: Parse payload, call `plainHandler(PlainMessage)` no context, no emit, no retry
131
131
 
132
132
  ## SagaParser
133
133
 
@@ -173,7 +173,21 @@ When using the header-based format (default with `@fbsm/saga-transport-kafka`):
173
173
  | `SagaNoParentError` | `emitToParent()` called in a saga without `parentSagaId` |
174
174
  | `SagaInvalidHandlerConfigError` | Handler has conflicting options (e.g., both `final` and `fork`) |
175
175
 
176
- **Retry behavior**: `SagaRetryableError` triggers exponential backoff: `initialDelayMs * 2^attempt`. After `maxRetries` attempts, `onRetryExhausted()` is called if defined. Non-retryable errors are logged and skipped.
176
+ **Retry behavior**: `SagaRetryableError` triggers exponential backoff: `initialDelayMs * 2^attempt`. After `maxRetries` attempts, `onRetryExhausted()` is called if defined. Non-retryable errors are routed to `onFail()` if defined; otherwise logged and skipped.
177
+
178
+ **Error flow**:
179
+
180
+ ```
181
+ handle(event, emit)
182
+ ├── SUCCESS → done
183
+ ├── throws SagaRetryableError → retry → exhausted → onRetryExhausted?
184
+ └── throws non-retryable Error
185
+ ├── onFail defined → call onFail (retries independently)
186
+ │ ├── onFail succeeds → done
187
+ │ ├── onFail retries exhausted → onRetryExhausted?
188
+ │ └── onFail throws non-retryable → log → done
189
+ └── onFail not defined → log → done
190
+ ```
177
191
 
178
192
  ## OTel Integration
179
193
 
package/dist/index.cjs CHANGED
@@ -162,11 +162,22 @@ var SagaRunner = class {
162
162
  };
163
163
  }
164
164
  async handleMessage(message) {
165
+ const route = this.routeMap.get(message.topic);
166
+ if (!route) {
167
+ return;
168
+ }
165
169
  const event = this.parser.parse(message);
166
- if (!event) return;
167
- const route = this.routeMap.get(event.topic);
168
- if (!route) return;
169
- const isFinalHandler = route.options?.final === true;
170
+ if (event && route.sagaHandler) {
171
+ await this.handleSagaMessage(message, event, route);
172
+ return;
173
+ }
174
+ if (!event && route.plainHandler) {
175
+ await this.handlePlainMessage(message, route);
176
+ return;
177
+ }
178
+ }
179
+ async handleSagaMessage(message, event, route) {
180
+ const isFinalHandler = route.sagaOptions?.final === true;
170
181
  const incoming = {
171
182
  sagaId: event.sagaId,
172
183
  eventId: event.eventId,
@@ -195,7 +206,7 @@ var SagaRunner = class {
195
206
  const finalParams = isFinalHandler ? { ...params, hint: "final" } : params;
196
207
  return emit(finalParams);
197
208
  };
198
- const forkConfig = route.options?.fork;
209
+ const forkConfig = route.sagaOptions?.fork;
199
210
  const finalEmit = forkConfig ? async (params) => {
200
211
  const subSagaId = (0, import_uuid.v7)();
201
212
  const subEmit = this.publisher.forSaga(
@@ -228,7 +239,7 @@ var SagaRunner = class {
228
239
  "saga.step.name": event.stepName,
229
240
  "saga.event.id": event.eventId,
230
241
  "saga.root.id": event.rootSagaId,
231
- "saga.handler.service": route.participant.serviceId
242
+ "saga.handler.service": route.sagaParticipant.serviceId
232
243
  };
233
244
  if (event.sagaName) spanAttrs["saga.name"] = event.sagaName;
234
245
  if (event.sagaDescription)
@@ -248,8 +259,8 @@ var SagaRunner = class {
248
259
  const runHandler = () => SagaContext.run(
249
260
  sagaCtxData,
250
261
  () => this.runWithRetry(
251
- route.handler,
252
- route.participant,
262
+ route.sagaHandler,
263
+ route.sagaParticipant,
253
264
  incoming,
254
265
  finalEmit
255
266
  )
@@ -265,12 +276,65 @@ var SagaRunner = class {
265
276
  await runHandler();
266
277
  }
267
278
  }
279
+ async handlePlainMessage(message, route) {
280
+ let payload;
281
+ try {
282
+ payload = JSON.parse(message.value);
283
+ } catch {
284
+ payload = message.value;
285
+ }
286
+ const plainMessage = {
287
+ topic: message.topic,
288
+ key: message.key,
289
+ payload,
290
+ headers: message.headers
291
+ };
292
+ await route.plainHandler(plainMessage);
293
+ }
268
294
  async runWithRetry(handler, participant, event, emit) {
295
+ try {
296
+ await this.executeWithRetry(handler, event, emit);
297
+ } catch (error) {
298
+ if (error instanceof SagaRetryableError) {
299
+ await this.callOnRetryExhausted(participant, event, error, emit);
300
+ return;
301
+ }
302
+ if (participant.onFail) {
303
+ try {
304
+ await this.executeWithRetry(
305
+ (ev, em) => participant.onFail(ev, error, em),
306
+ event,
307
+ emit
308
+ );
309
+ } catch (failError) {
310
+ if (failError instanceof SagaRetryableError) {
311
+ await this.callOnRetryExhausted(
312
+ participant,
313
+ event,
314
+ failError,
315
+ emit
316
+ );
317
+ } else {
318
+ this.logger.error(
319
+ `[SagaRunner] onFail threw non-retryable error for ${event.topic}:`,
320
+ failError
321
+ );
322
+ }
323
+ }
324
+ return;
325
+ }
326
+ this.logger.error(
327
+ `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,
328
+ error
329
+ );
330
+ }
331
+ }
332
+ async executeWithRetry(fn, event, emit) {
269
333
  const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;
270
334
  const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;
271
335
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
272
336
  try {
273
- await handler(event, emit);
337
+ await fn(event, emit);
274
338
  return;
275
339
  } catch (error) {
276
340
  if (error instanceof SagaRetryableError) {
@@ -279,19 +343,17 @@ var SagaRunner = class {
279
343
  await this.sleep(delay);
280
344
  continue;
281
345
  }
282
- if (participant.onRetryExhausted) {
283
- await participant.onRetryExhausted(event, error, emit);
284
- }
285
- return;
346
+ throw error;
286
347
  }
287
- this.logger.error(
288
- `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,
289
- error
290
- );
291
- return;
348
+ throw error;
292
349
  }
293
350
  }
294
351
  }
352
+ async callOnRetryExhausted(participant, event, error, emit) {
353
+ if (participant.onRetryExhausted) {
354
+ await participant.onRetryExhausted(event, error, emit);
355
+ }
356
+ }
295
357
  sleep(ms) {
296
358
  return new Promise((resolve) => setTimeout(resolve, ms));
297
359
  }
@@ -615,11 +677,11 @@ var SagaRegistry = class {
615
677
  const map = /* @__PURE__ */ new Map();
616
678
  for (const participant of this.participants) {
617
679
  for (const [topic, handler] of Object.entries(participant.on)) {
618
- if (map.has(topic)) {
619
- const existing = map.get(topic);
680
+ const existing = map.get(topic) ?? {};
681
+ if (existing.sagaHandler) {
620
682
  throw new SagaDuplicateHandlerError(
621
683
  topic,
622
- existing.participant.serviceId,
684
+ existing.sagaParticipant.serviceId,
623
685
  participant.serviceId
624
686
  );
625
687
  }
@@ -631,7 +693,29 @@ var SagaRegistry = class {
631
693
  "cannot have both final and fork options"
632
694
  );
633
695
  }
634
- map.set(topic, { participant, handler, options });
696
+ map.set(topic, {
697
+ ...existing,
698
+ sagaParticipant: participant,
699
+ sagaHandler: handler,
700
+ sagaOptions: options
701
+ });
702
+ }
703
+ if (participant.onPlain) {
704
+ for (const [topic, handler] of Object.entries(participant.onPlain)) {
705
+ const existing = map.get(topic) ?? {};
706
+ if (existing.plainHandler) {
707
+ throw new SagaDuplicateHandlerError(
708
+ topic,
709
+ existing.plainParticipant.serviceId,
710
+ participant.serviceId
711
+ );
712
+ }
713
+ map.set(topic, {
714
+ ...existing,
715
+ plainParticipant: participant,
716
+ plainHandler: handler
717
+ });
718
+ }
635
719
  }
636
720
  }
637
721
  return map;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/transport/transport.interface.ts","../src/errors/saga.error.ts","../src/errors/saga-retryable.error.ts","../src/logger/saga-logger.ts","../src/context/saga-context.ts","../src/errors/saga-context-not-found.error.ts","../src/runner/saga-runner.ts","../src/publisher/saga-publisher.ts","../src/errors/saga-no-parent.error.ts","../src/publisher/message-builder.ts","../src/parser/saga-parser.ts","../src/errors/saga-duplicate-handler.error.ts","../src/errors/saga-invalid-handler-config.error.ts","../src/registry/saga-registry.ts","../src/errors/saga-parse.error.ts","../src/errors/saga-transport-not-connected.error.ts","../src/otel/otel-context.ts"],"sourcesContent":["// Classes\nexport { SagaRunner } from \"./runner/saga-runner\";\nexport { SagaPublisher } from \"./publisher/saga-publisher\";\nexport type { SagaStartOptions } from \"./publisher/saga-publisher\";\nexport { SagaParser } from \"./parser/saga-parser\";\nexport { SagaRegistry } from \"./registry/saga-registry\";\nexport { SagaContext } from \"./context/saga-context\";\nexport type { SagaContextData } from \"./context/saga-context\";\n\n// Errors\nexport { SagaError } from \"./errors/saga.error\";\nexport { SagaRetryableError } from \"./errors/saga-retryable.error\";\nexport { SagaDuplicateHandlerError } from \"./errors/saga-duplicate-handler.error\";\nexport { SagaParseError } from \"./errors/saga-parse.error\";\nexport { SagaTransportNotConnectedError } from \"./errors/saga-transport-not-connected.error\";\nexport { SagaContextNotFoundError } from \"./errors/saga-context-not-found.error\";\nexport { SagaNoParentError } from \"./errors/saga-no-parent.error\";\nexport { SagaInvalidHandlerConfigError } from \"./errors/saga-invalid-handler-config.error\";\n\n// Logger\nexport type { SagaLogger } from \"./logger/saga-logger\";\nexport { ConsoleSagaLogger } from \"./logger/saga-logger\";\n\n// OTel\nexport type { OtelContext } from \"./otel/otel-context\";\nexport {\n NoopOtelContext,\n W3cOtelContext,\n createOtelContext,\n} from \"./otel/otel-context\";\n\n// Transport interfaces\nexport type {\n SagaTransport,\n OutboundMessage,\n InboundMessage,\n TransportSubscribeOptions,\n TransportHealthResult,\n HealthCheckable,\n} from \"./transport/transport.interface\";\nexport { isHealthCheckable } from \"./transport/transport.interface\";\n\n// Domain interfaces\nexport type { SagaEvent } from \"./interfaces/saga-event.interface\";\nexport type { IncomingEvent } from \"./interfaces/incoming-event.interface\";\nexport type { Emit, EmitParams, EventHint } from \"./interfaces/emit.type\";\nexport type { EventHandler } from \"./interfaces/event-handler.type\";\nexport type {\n SagaParticipant,\n HandlerConfig,\n ForkConfig,\n} from \"./interfaces/saga-participant.interface\";\nexport type { ParentSagaContext } from \"./interfaces/parent-saga-context.interface\";\nexport type { RunnerOptions } from \"./interfaces/runner-options.interface\";\n","export interface SagaTransport {\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n publish(message: OutboundMessage): Promise<void>;\n subscribe(\n topics: string[],\n handler: (message: InboundMessage) => Promise<void>,\n options?: TransportSubscribeOptions,\n ): Promise<void>;\n}\n\nexport interface OutboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface InboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface TransportSubscribeOptions {\n fromBeginning?: boolean;\n groupId?: string;\n}\n\nexport interface TransportHealthResult {\n status: \"up\" | \"down\";\n details?: Record<string, unknown>;\n}\n\nexport interface HealthCheckable {\n healthCheck(): Promise<TransportHealthResult>;\n}\n\nexport function isHealthCheckable(\n transport: SagaTransport,\n): transport is SagaTransport & HealthCheckable {\n return typeof (transport as any).healthCheck === \"function\";\n}\n","export class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n TransportHealthResult,\n} from \"../transport/transport.interface\";\nimport { isHealthCheckable } from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n const baseRouteMap = this.registry.buildRouteMap();\n const prefix = this.options.topicPrefix ?? \"\";\n\n this.routeMap = new Map();\n for (const [topic, entry] of baseRouteMap) {\n this.routeMap.set(`${prefix}${topic}`, entry);\n }\n\n const topics = Array.from(this.routeMap.keys());\n\n await this.transport.connect();\n\n if (topics.length > 0) {\n this.logger.info(\n `[SagaRunner] Subscribing to ${topics.length} topic(s): [${topics.join(\", \")}]`,\n );\n await this.transport.subscribe(\n topics,\n (message) => this.handleMessage(message),\n {\n fromBeginning: this.options.fromBeginning,\n groupId: this.options.groupId,\n },\n );\n this.logger.info(\"[SagaRunner] Consumer running\");\n } else {\n this.logger.warn(\n \"[SagaRunner] No handlers registered — nothing to subscribe\",\n );\n }\n }\n\n async stop(): Promise<void> {\n await this.transport.disconnect();\n }\n\n async healthCheck(): Promise<TransportHealthResult> {\n if (isHealthCheckable(this.transport)) {\n return this.transport.healthCheck();\n }\n return {\n status: \"up\",\n details: { reason: \"Transport does not support health checks\" },\n };\n }\n\n private async handleMessage(message: InboundMessage): Promise<void> {\n const event = this.parser.parse<Record<string, unknown>>(message);\n if (!event) return;\n\n const route = this.routeMap.get(event.topic);\n if (!route) return;\n\n const isFinalHandler = route.options?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n topic: event.topic,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.options?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.participant.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.handler,\n route.participant,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.topic}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await handler(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n return;\n }\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,\n error,\n );\n return;\n }\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n topic,\n stepName,\n stepDescription,\n payload,\n hint,\n key,\n }: EmitParams<T>): Promise<void> => {\n const ctx = SagaContext.current();\n const resolvedKey = key ?? baseKey ?? ctx?.key;\n const now = new Date().toISOString();\n const event: SagaEvent<T> = {\n sagaId,\n causationId: baseCausationId,\n eventId: uuidv7(),\n topic,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.root.id\": event.rootSagaId,\n };\n if (event.sagaName) {\n attrs[\"saga.name\"] = event.sagaName;\n }\n if (event.sagaDescription) {\n attrs[\"saga.description\"] = event.sagaDescription;\n }\n if (event.stepDescription) {\n attrs[\"saga.step.description\"] = event.stepDescription;\n }\n if (event.parentSagaId) {\n attrs[\"saga.parent.id\"] = event.parentSagaId;\n }\n\n this.otelCtx.enrichSpan(attrs);\n\n const message = buildOutboundMessage(event, this.topicPrefix);\n\n this.otelCtx.injectTraceContext(message.headers);\n\n await this.otelCtx.withSpan(`saga.publish ${event.topic}`, attrs, () =>\n this.transport.publish(message),\n );\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaNoParentError extends SagaError {\n constructor() {\n super(\"No parentSagaId in current saga context.\");\n this.name = \"SagaNoParentError\";\n }\n}\n","import type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { OutboundMessage } from \"../transport/transport.interface\";\n\nexport function buildOutboundMessage<T>(\n event: SagaEvent<T>,\n topicPrefix = \"\",\n): OutboundMessage {\n const topic = `${topicPrefix}${event.topic}`;\n const key = event.key ?? event.rootSagaId;\n\n const headers: Record<string, string> = {\n \"saga-id\": event.sagaId,\n \"saga-causation-id\": event.causationId,\n \"saga-event-id\": event.eventId,\n \"saga-step-name\": event.stepName,\n \"saga-published-at\": event.publishedAt,\n \"saga-schema-version\": String(event.schemaVersion),\n \"saga-root-id\": event.rootSagaId,\n };\n\n if (event.parentSagaId) {\n headers[\"saga-parent-id\"] = event.parentSagaId;\n }\n\n if (event.hint) {\n headers[\"saga-event-hint\"] = event.hint;\n }\n\n if (event.sagaName) {\n headers[\"saga-name\"] = event.sagaName;\n }\n\n if (event.sagaDescription) {\n headers[\"saga-description\"] = event.sagaDescription;\n }\n\n if (event.stepDescription) {\n headers[\"saga-step-description\"] = event.stepDescription;\n }\n\n if (event.key) {\n headers[\"saga-key\"] = event.key;\n }\n\n headers[\"saga-occurred-at\"] = event.occurredAt;\n\n const value = JSON.stringify(event.payload);\n\n return { topic, key, value, headers };\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { InboundMessage } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\n\nexport class SagaParser {\n constructor(private otelCtx: OtelContext) {}\n\n parse<T>(message: InboundMessage): SagaEvent<T> | null {\n try {\n if (message.headers[\"saga-id\"]) {\n return this.parseFromHeaders<T>(message);\n }\n\n const baggageResult = this.parseFromBaggage<T>(message);\n if (baggageResult) return baggageResult;\n\n const body = JSON.parse(message.value);\n if (body && body.sagaId) {\n return body as SagaEvent<T>;\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n private parseFromHeaders<T>(message: InboundMessage): SagaEvent<T> | null {\n const headers = message.headers;\n const payload = JSON.parse(message.value) as T;\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n topic: message.topic,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: headers[\"saga-occurred-at\"] ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload,\n sagaName: headers[\"saga-name\"] || undefined,\n sagaDescription: headers[\"saga-description\"] || undefined,\n stepDescription: headers[\"saga-step-description\"] || undefined,\n key: headers[\"saga-key\"] || undefined,\n };\n }\n\n private parseFromBaggage<T>(message: InboundMessage): SagaEvent<T> | null {\n let sagaId: string | undefined;\n let rootSagaId: string | undefined;\n let parentSagaId: string | undefined;\n\n const baggageHeader = message.headers[\"baggage\"];\n if (baggageHeader) {\n const entries = this.parseBaggageHeader(baggageHeader);\n sagaId = entries[\"saga.id\"];\n rootSagaId = entries[\"saga.root.id\"];\n parentSagaId = entries[\"saga.parent.id\"];\n }\n\n // Fallback to OTel context extraction\n if (!sagaId) {\n const extracted = this.otelCtx.extractBaggage();\n sagaId = extracted.sagaId;\n rootSagaId = extracted.rootSagaId;\n parentSagaId = extracted.parentSagaId;\n }\n\n if (!sagaId) return null;\n\n const body = JSON.parse(message.value);\n\n return {\n sagaId,\n causationId: sagaId,\n eventId: uuidv7(),\n topic: body.topic,\n stepName: \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: rootSagaId ?? sagaId,\n parentSagaId: parentSagaId || undefined,\n payload: body.payload as T,\n };\n }\n\n private parseBaggageHeader(baggage: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (const entry of baggage.split(\",\")) {\n const [key, value] = entry.trim().split(\"=\");\n if (key && value) {\n result[key.trim()] = decodeURIComponent(value.trim());\n }\n }\n return result;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaDuplicateHandlerError extends SagaError {\n constructor(\n topic: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${topic}\": ` +\n `registered by \"${existingServiceId}\" and \"${newServiceId}\"`,\n );\n this.name = \"SagaDuplicateHandlerError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaInvalidHandlerConfigError extends SagaError {\n constructor(topic: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${topic}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n participant: SagaParticipant;\n handler: EventHandler;\n options?: HandlerConfig;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n for (const [topic, handler] of Object.entries(participant.on)) {\n if (map.has(topic)) {\n const existing = map.get(topic)!;\n throw new SagaDuplicateHandlerError(\n topic,\n existing.participant.serviceId,\n participant.serviceId,\n );\n }\n const options = participant.handlerOptions?.[topic];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n topic,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n map.set(topic, { participant, handler, options });\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":"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","names":["uuidv7","import_uuid","uuidv7","import_uuid","uuidv7"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/transport/transport.interface.ts","../src/errors/saga.error.ts","../src/errors/saga-retryable.error.ts","../src/logger/saga-logger.ts","../src/context/saga-context.ts","../src/errors/saga-context-not-found.error.ts","../src/runner/saga-runner.ts","../src/publisher/saga-publisher.ts","../src/errors/saga-no-parent.error.ts","../src/publisher/message-builder.ts","../src/parser/saga-parser.ts","../src/errors/saga-duplicate-handler.error.ts","../src/errors/saga-invalid-handler-config.error.ts","../src/registry/saga-registry.ts","../src/errors/saga-parse.error.ts","../src/errors/saga-transport-not-connected.error.ts","../src/otel/otel-context.ts"],"sourcesContent":["// Classes\nexport { SagaRunner } from \"./runner/saga-runner\";\nexport { SagaPublisher } from \"./publisher/saga-publisher\";\nexport type { SagaStartOptions } from \"./publisher/saga-publisher\";\nexport { SagaParser } from \"./parser/saga-parser\";\nexport { SagaRegistry } from \"./registry/saga-registry\";\nexport { SagaContext } from \"./context/saga-context\";\nexport type { SagaContextData } from \"./context/saga-context\";\n\n// Errors\nexport { SagaError } from \"./errors/saga.error\";\nexport { SagaRetryableError } from \"./errors/saga-retryable.error\";\nexport { SagaDuplicateHandlerError } from \"./errors/saga-duplicate-handler.error\";\nexport { SagaParseError } from \"./errors/saga-parse.error\";\nexport { SagaTransportNotConnectedError } from \"./errors/saga-transport-not-connected.error\";\nexport { SagaContextNotFoundError } from \"./errors/saga-context-not-found.error\";\nexport { SagaNoParentError } from \"./errors/saga-no-parent.error\";\nexport { SagaInvalidHandlerConfigError } from \"./errors/saga-invalid-handler-config.error\";\n\n// Logger\nexport type { SagaLogger } from \"./logger/saga-logger\";\nexport { ConsoleSagaLogger } from \"./logger/saga-logger\";\n\n// OTel\nexport type { OtelContext } from \"./otel/otel-context\";\nexport {\n NoopOtelContext,\n W3cOtelContext,\n createOtelContext,\n} from \"./otel/otel-context\";\n\n// Transport interfaces\nexport type {\n SagaTransport,\n OutboundMessage,\n InboundMessage,\n TransportSubscribeOptions,\n TransportHealthResult,\n HealthCheckable,\n} from \"./transport/transport.interface\";\nexport { isHealthCheckable } from \"./transport/transport.interface\";\n\n// Domain interfaces\nexport type { SagaEvent } from \"./interfaces/saga-event.interface\";\nexport type { IncomingEvent } from \"./interfaces/incoming-event.interface\";\nexport type { Emit, EmitParams, EventHint } from \"./interfaces/emit.type\";\nexport type { EventHandler } from \"./interfaces/event-handler.type\";\nexport type {\n SagaParticipant,\n HandlerConfig,\n ForkConfig,\n} from \"./interfaces/saga-participant.interface\";\nexport type {\n PlainMessage,\n PlainHandler,\n} from \"./interfaces/plain-message.interface\";\nexport type { ParentSagaContext } from \"./interfaces/parent-saga-context.interface\";\nexport type { RunnerOptions } from \"./interfaces/runner-options.interface\";\n","export interface SagaTransport {\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n publish(message: OutboundMessage): Promise<void>;\n subscribe(\n topics: string[],\n handler: (message: InboundMessage) => Promise<void>,\n options?: TransportSubscribeOptions,\n ): Promise<void>;\n}\n\nexport interface OutboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface InboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface TransportSubscribeOptions {\n fromBeginning?: boolean;\n groupId?: string;\n}\n\nexport interface TransportHealthResult {\n status: \"up\" | \"down\";\n details?: Record<string, unknown>;\n}\n\nexport interface HealthCheckable {\n healthCheck(): Promise<TransportHealthResult>;\n}\n\nexport function isHealthCheckable(\n transport: SagaTransport,\n): transport is SagaTransport & HealthCheckable {\n return typeof (transport as any).healthCheck === \"function\";\n}\n","export class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n TransportHealthResult,\n} from \"../transport/transport.interface\";\nimport { isHealthCheckable } from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { PlainMessage } from \"../interfaces/plain-message.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n const baseRouteMap = this.registry.buildRouteMap();\n const prefix = this.options.topicPrefix ?? \"\";\n\n this.routeMap = new Map();\n for (const [topic, entry] of baseRouteMap) {\n this.routeMap.set(`${prefix}${topic}`, entry);\n }\n\n const topics = Array.from(this.routeMap.keys());\n\n await this.transport.connect();\n\n if (topics.length > 0) {\n this.logger.info(\n `[SagaRunner] Subscribing to ${topics.length} topic(s): [${topics.join(\", \")}]`,\n );\n await this.transport.subscribe(\n topics,\n (message) => this.handleMessage(message),\n {\n fromBeginning: this.options.fromBeginning,\n groupId: this.options.groupId,\n },\n );\n this.logger.info(\"[SagaRunner] Consumer running\");\n } else {\n this.logger.warn(\n \"[SagaRunner] No handlers registered — nothing to subscribe\",\n );\n }\n }\n\n async stop(): Promise<void> {\n await this.transport.disconnect();\n }\n\n async healthCheck(): Promise<TransportHealthResult> {\n if (isHealthCheckable(this.transport)) {\n return this.transport.healthCheck();\n }\n return {\n status: \"up\",\n details: { reason: \"Transport does not support health checks\" },\n };\n }\n\n private async handleMessage(message: InboundMessage): Promise<void> {\n const route = this.routeMap.get(message.topic);\n if (!route) {\n return;\n }\n\n // Try to parse as saga event\n const event = this.parser.parse<Record<string, unknown>>(message);\n\n if (event && route.sagaHandler) {\n await this.handleSagaMessage(message, event, route);\n return;\n }\n\n if (!event && route.plainHandler) {\n await this.handlePlainMessage(message, route);\n return;\n }\n\n // No matching handler for this message type — skip\n }\n\n private async handleSagaMessage(\n message: InboundMessage,\n event: SagaEvent<Record<string, unknown>>,\n route: RouteEntry,\n ): Promise<void> {\n const isFinalHandler = route.sagaOptions?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n topic: event.topic,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.sagaOptions?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.sagaParticipant!.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.sagaHandler!,\n route.sagaParticipant!,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.topic}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async handlePlainMessage(\n message: InboundMessage,\n route: RouteEntry,\n ): Promise<void> {\n let payload: unknown;\n try {\n payload = JSON.parse(message.value);\n } catch {\n payload = message.value;\n }\n\n const plainMessage: PlainMessage = {\n topic: message.topic,\n key: message.key,\n payload,\n headers: message.headers,\n };\n\n await route.plainHandler!(plainMessage);\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n try {\n await this.executeWithRetry(handler, event, emit);\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n // Retries exhausted\n await this.callOnRetryExhausted(participant, event, error, emit);\n return;\n }\n\n // Non-retryable error — route to onFail if defined\n if (participant.onFail) {\n try {\n await this.executeWithRetry(\n (ev, em) => participant.onFail!(ev, error as Error, em),\n event,\n emit,\n );\n } catch (failError) {\n if (failError instanceof SagaRetryableError) {\n await this.callOnRetryExhausted(\n participant,\n event,\n failError,\n emit,\n );\n } else {\n this.logger.error(\n `[SagaRunner] onFail threw non-retryable error for ${event.topic}:`,\n failError,\n );\n }\n }\n return;\n }\n\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,\n error,\n );\n }\n }\n\n private async executeWithRetry(\n fn: (event: IncomingEvent, emit: Emit) => Promise<void>,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await fn(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n // Exhausted — re-throw so caller can handle\n throw error;\n }\n // Non-retryable — re-throw immediately\n throw error;\n }\n }\n }\n\n private async callOnRetryExhausted(\n participant: SagaParticipant,\n event: IncomingEvent,\n error: SagaRetryableError,\n emit: Emit,\n ): Promise<void> {\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n topic,\n stepName,\n stepDescription,\n payload,\n hint,\n key,\n }: EmitParams<T>): Promise<void> => {\n const ctx = SagaContext.current();\n const resolvedKey = key ?? baseKey ?? ctx?.key;\n const now = new Date().toISOString();\n const event: SagaEvent<T> = {\n sagaId,\n causationId: baseCausationId,\n eventId: uuidv7(),\n topic,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.root.id\": event.rootSagaId,\n };\n if (event.sagaName) {\n attrs[\"saga.name\"] = event.sagaName;\n }\n if (event.sagaDescription) {\n attrs[\"saga.description\"] = event.sagaDescription;\n }\n if (event.stepDescription) {\n attrs[\"saga.step.description\"] = event.stepDescription;\n }\n if (event.parentSagaId) {\n attrs[\"saga.parent.id\"] = event.parentSagaId;\n }\n\n this.otelCtx.enrichSpan(attrs);\n\n const message = buildOutboundMessage(event, this.topicPrefix);\n\n this.otelCtx.injectTraceContext(message.headers);\n\n await this.otelCtx.withSpan(`saga.publish ${event.topic}`, attrs, () =>\n this.transport.publish(message),\n );\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaNoParentError extends SagaError {\n constructor() {\n super(\"No parentSagaId in current saga context.\");\n this.name = \"SagaNoParentError\";\n }\n}\n","import type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { OutboundMessage } from \"../transport/transport.interface\";\n\nexport function buildOutboundMessage<T>(\n event: SagaEvent<T>,\n topicPrefix = \"\",\n): OutboundMessage {\n const topic = `${topicPrefix}${event.topic}`;\n const key = event.key ?? event.rootSagaId;\n\n const headers: Record<string, string> = {\n \"saga-id\": event.sagaId,\n \"saga-causation-id\": event.causationId,\n \"saga-event-id\": event.eventId,\n \"saga-step-name\": event.stepName,\n \"saga-published-at\": event.publishedAt,\n \"saga-schema-version\": String(event.schemaVersion),\n \"saga-root-id\": event.rootSagaId,\n };\n\n if (event.parentSagaId) {\n headers[\"saga-parent-id\"] = event.parentSagaId;\n }\n\n if (event.hint) {\n headers[\"saga-event-hint\"] = event.hint;\n }\n\n if (event.sagaName) {\n headers[\"saga-name\"] = event.sagaName;\n }\n\n if (event.sagaDescription) {\n headers[\"saga-description\"] = event.sagaDescription;\n }\n\n if (event.stepDescription) {\n headers[\"saga-step-description\"] = event.stepDescription;\n }\n\n if (event.key) {\n headers[\"saga-key\"] = event.key;\n }\n\n headers[\"saga-occurred-at\"] = event.occurredAt;\n\n const value = JSON.stringify(event.payload);\n\n return { topic, key, value, headers };\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { InboundMessage } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\n\nexport class SagaParser {\n constructor(private otelCtx: OtelContext) {}\n\n parse<T>(message: InboundMessage): SagaEvent<T> | null {\n try {\n if (message.headers[\"saga-id\"]) {\n return this.parseFromHeaders<T>(message);\n }\n\n const baggageResult = this.parseFromBaggage<T>(message);\n if (baggageResult) return baggageResult;\n\n const body = JSON.parse(message.value);\n if (body && body.sagaId) {\n return body as SagaEvent<T>;\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n private parseFromHeaders<T>(message: InboundMessage): SagaEvent<T> | null {\n const headers = message.headers;\n const payload = JSON.parse(message.value) as T;\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n topic: message.topic,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: headers[\"saga-occurred-at\"] ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload,\n sagaName: headers[\"saga-name\"] || undefined,\n sagaDescription: headers[\"saga-description\"] || undefined,\n stepDescription: headers[\"saga-step-description\"] || undefined,\n key: headers[\"saga-key\"] || undefined,\n };\n }\n\n private parseFromBaggage<T>(message: InboundMessage): SagaEvent<T> | null {\n let sagaId: string | undefined;\n let rootSagaId: string | undefined;\n let parentSagaId: string | undefined;\n\n const baggageHeader = message.headers[\"baggage\"];\n if (baggageHeader) {\n const entries = this.parseBaggageHeader(baggageHeader);\n sagaId = entries[\"saga.id\"];\n rootSagaId = entries[\"saga.root.id\"];\n parentSagaId = entries[\"saga.parent.id\"];\n }\n\n // Fallback to OTel context extraction\n if (!sagaId) {\n const extracted = this.otelCtx.extractBaggage();\n sagaId = extracted.sagaId;\n rootSagaId = extracted.rootSagaId;\n parentSagaId = extracted.parentSagaId;\n }\n\n if (!sagaId) return null;\n\n const body = JSON.parse(message.value);\n\n return {\n sagaId,\n causationId: sagaId,\n eventId: uuidv7(),\n topic: body.topic,\n stepName: \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: rootSagaId ?? sagaId,\n parentSagaId: parentSagaId || undefined,\n payload: body.payload as T,\n };\n }\n\n private parseBaggageHeader(baggage: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (const entry of baggage.split(\",\")) {\n const [key, value] = entry.trim().split(\"=\");\n if (key && value) {\n result[key.trim()] = decodeURIComponent(value.trim());\n }\n }\n return result;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaDuplicateHandlerError extends SagaError {\n constructor(\n topic: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${topic}\": ` +\n `registered by \"${existingServiceId}\" and \"${newServiceId}\"`,\n );\n this.name = \"SagaDuplicateHandlerError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaInvalidHandlerConfigError extends SagaError {\n constructor(topic: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${topic}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { PlainHandler } from \"../interfaces/plain-message.interface\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n sagaParticipant?: SagaParticipant;\n sagaHandler?: EventHandler;\n sagaOptions?: HandlerConfig;\n\n plainParticipant?: SagaParticipant;\n plainHandler?: PlainHandler;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n // Register saga handlers\n for (const [topic, handler] of Object.entries(participant.on)) {\n const existing = map.get(topic) ?? {};\n\n if (existing.sagaHandler) {\n throw new SagaDuplicateHandlerError(\n topic,\n existing.sagaParticipant!.serviceId,\n participant.serviceId,\n );\n }\n\n const options = participant.handlerOptions?.[topic];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n topic,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n\n map.set(topic, {\n ...existing,\n sagaParticipant: participant,\n sagaHandler: handler,\n sagaOptions: options,\n });\n }\n\n // Register plain handlers\n if (participant.onPlain) {\n for (const [topic, handler] of Object.entries(participant.onPlain)) {\n const existing = map.get(topic) ?? {};\n\n if (existing.plainHandler) {\n throw new SagaDuplicateHandlerError(\n topic,\n existing.plainParticipant!.serviceId,\n participant.serviceId,\n );\n }\n\n map.set(topic, {\n ...existing,\n plainParticipant: participant,\n plainHandler: handler,\n });\n }\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":"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","names":["uuidv7","import_uuid","uuidv7","import_uuid","uuidv7"]}
package/dist/index.d.cts CHANGED
@@ -81,6 +81,15 @@ declare class SagaRetryableError extends SagaError {
81
81
  constructor(message: string, maxRetries?: number);
82
82
  }
83
83
 
84
+ interface PlainMessage<T = unknown> {
85
+ topic: string;
86
+ key: string;
87
+ payload: T;
88
+ headers: Record<string, string>;
89
+ timestamp?: string;
90
+ }
91
+ type PlainHandler<T = unknown> = (message: PlainMessage<T>) => Promise<void>;
92
+
84
93
  interface ForkConfig {
85
94
  sagaName?: string;
86
95
  sagaDescription?: string;
@@ -93,13 +102,17 @@ interface SagaParticipant {
93
102
  readonly serviceId: string;
94
103
  readonly on: Record<string, EventHandler<any>>;
95
104
  readonly handlerOptions?: Record<string, HandlerConfig>;
105
+ readonly onPlain?: Record<string, PlainHandler>;
106
+ onFail?(event: IncomingEvent, error: Error, emit: Emit): Promise<void>;
96
107
  onRetryExhausted?(event: IncomingEvent, error: SagaRetryableError, emit: Emit): Promise<void>;
97
108
  }
98
109
 
99
110
  interface RouteEntry {
100
- participant: SagaParticipant;
101
- handler: EventHandler;
102
- options?: HandlerConfig;
111
+ sagaParticipant?: SagaParticipant;
112
+ sagaHandler?: EventHandler;
113
+ sagaOptions?: HandlerConfig;
114
+ plainParticipant?: SagaParticipant;
115
+ plainHandler?: PlainHandler;
103
116
  }
104
117
  declare class SagaRegistry {
105
118
  private participants;
@@ -231,7 +244,11 @@ declare class SagaRunner {
231
244
  stop(): Promise<void>;
232
245
  healthCheck(): Promise<TransportHealthResult>;
233
246
  private handleMessage;
247
+ private handleSagaMessage;
248
+ private handlePlainMessage;
234
249
  private runWithRetry;
250
+ private executeWithRetry;
251
+ private callOnRetryExhausted;
235
252
  private sleep;
236
253
  }
237
254
 
@@ -275,4 +292,4 @@ declare class SagaInvalidHandlerConfigError extends SagaError {
275
292
  constructor(topic: string, serviceId: string, reason: string);
276
293
  }
277
294
 
278
- export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type HealthCheckable, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportHealthResult, type TransportSubscribeOptions, W3cOtelContext, createOtelContext, isHealthCheckable };
295
+ export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type HealthCheckable, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type PlainHandler, type PlainMessage, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportHealthResult, type TransportSubscribeOptions, W3cOtelContext, createOtelContext, isHealthCheckable };
package/dist/index.d.ts CHANGED
@@ -81,6 +81,15 @@ declare class SagaRetryableError extends SagaError {
81
81
  constructor(message: string, maxRetries?: number);
82
82
  }
83
83
 
84
+ interface PlainMessage<T = unknown> {
85
+ topic: string;
86
+ key: string;
87
+ payload: T;
88
+ headers: Record<string, string>;
89
+ timestamp?: string;
90
+ }
91
+ type PlainHandler<T = unknown> = (message: PlainMessage<T>) => Promise<void>;
92
+
84
93
  interface ForkConfig {
85
94
  sagaName?: string;
86
95
  sagaDescription?: string;
@@ -93,13 +102,17 @@ interface SagaParticipant {
93
102
  readonly serviceId: string;
94
103
  readonly on: Record<string, EventHandler<any>>;
95
104
  readonly handlerOptions?: Record<string, HandlerConfig>;
105
+ readonly onPlain?: Record<string, PlainHandler>;
106
+ onFail?(event: IncomingEvent, error: Error, emit: Emit): Promise<void>;
96
107
  onRetryExhausted?(event: IncomingEvent, error: SagaRetryableError, emit: Emit): Promise<void>;
97
108
  }
98
109
 
99
110
  interface RouteEntry {
100
- participant: SagaParticipant;
101
- handler: EventHandler;
102
- options?: HandlerConfig;
111
+ sagaParticipant?: SagaParticipant;
112
+ sagaHandler?: EventHandler;
113
+ sagaOptions?: HandlerConfig;
114
+ plainParticipant?: SagaParticipant;
115
+ plainHandler?: PlainHandler;
103
116
  }
104
117
  declare class SagaRegistry {
105
118
  private participants;
@@ -231,7 +244,11 @@ declare class SagaRunner {
231
244
  stop(): Promise<void>;
232
245
  healthCheck(): Promise<TransportHealthResult>;
233
246
  private handleMessage;
247
+ private handleSagaMessage;
248
+ private handlePlainMessage;
234
249
  private runWithRetry;
250
+ private executeWithRetry;
251
+ private callOnRetryExhausted;
235
252
  private sleep;
236
253
  }
237
254
 
@@ -275,4 +292,4 @@ declare class SagaInvalidHandlerConfigError extends SagaError {
275
292
  constructor(topic: string, serviceId: string, reason: string);
276
293
  }
277
294
 
278
- export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type HealthCheckable, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportHealthResult, type TransportSubscribeOptions, W3cOtelContext, createOtelContext, isHealthCheckable };
295
+ export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type HealthCheckable, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type PlainHandler, type PlainMessage, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportHealthResult, type TransportSubscribeOptions, W3cOtelContext, createOtelContext, isHealthCheckable };
package/dist/index.js CHANGED
@@ -126,11 +126,22 @@ var SagaRunner = class {
126
126
  };
127
127
  }
128
128
  async handleMessage(message) {
129
+ const route = this.routeMap.get(message.topic);
130
+ if (!route) {
131
+ return;
132
+ }
129
133
  const event = this.parser.parse(message);
130
- if (!event) return;
131
- const route = this.routeMap.get(event.topic);
132
- if (!route) return;
133
- const isFinalHandler = route.options?.final === true;
134
+ if (event && route.sagaHandler) {
135
+ await this.handleSagaMessage(message, event, route);
136
+ return;
137
+ }
138
+ if (!event && route.plainHandler) {
139
+ await this.handlePlainMessage(message, route);
140
+ return;
141
+ }
142
+ }
143
+ async handleSagaMessage(message, event, route) {
144
+ const isFinalHandler = route.sagaOptions?.final === true;
134
145
  const incoming = {
135
146
  sagaId: event.sagaId,
136
147
  eventId: event.eventId,
@@ -159,7 +170,7 @@ var SagaRunner = class {
159
170
  const finalParams = isFinalHandler ? { ...params, hint: "final" } : params;
160
171
  return emit(finalParams);
161
172
  };
162
- const forkConfig = route.options?.fork;
173
+ const forkConfig = route.sagaOptions?.fork;
163
174
  const finalEmit = forkConfig ? async (params) => {
164
175
  const subSagaId = uuidv7();
165
176
  const subEmit = this.publisher.forSaga(
@@ -192,7 +203,7 @@ var SagaRunner = class {
192
203
  "saga.step.name": event.stepName,
193
204
  "saga.event.id": event.eventId,
194
205
  "saga.root.id": event.rootSagaId,
195
- "saga.handler.service": route.participant.serviceId
206
+ "saga.handler.service": route.sagaParticipant.serviceId
196
207
  };
197
208
  if (event.sagaName) spanAttrs["saga.name"] = event.sagaName;
198
209
  if (event.sagaDescription)
@@ -212,8 +223,8 @@ var SagaRunner = class {
212
223
  const runHandler = () => SagaContext.run(
213
224
  sagaCtxData,
214
225
  () => this.runWithRetry(
215
- route.handler,
216
- route.participant,
226
+ route.sagaHandler,
227
+ route.sagaParticipant,
217
228
  incoming,
218
229
  finalEmit
219
230
  )
@@ -229,12 +240,65 @@ var SagaRunner = class {
229
240
  await runHandler();
230
241
  }
231
242
  }
243
+ async handlePlainMessage(message, route) {
244
+ let payload;
245
+ try {
246
+ payload = JSON.parse(message.value);
247
+ } catch {
248
+ payload = message.value;
249
+ }
250
+ const plainMessage = {
251
+ topic: message.topic,
252
+ key: message.key,
253
+ payload,
254
+ headers: message.headers
255
+ };
256
+ await route.plainHandler(plainMessage);
257
+ }
232
258
  async runWithRetry(handler, participant, event, emit) {
259
+ try {
260
+ await this.executeWithRetry(handler, event, emit);
261
+ } catch (error) {
262
+ if (error instanceof SagaRetryableError) {
263
+ await this.callOnRetryExhausted(participant, event, error, emit);
264
+ return;
265
+ }
266
+ if (participant.onFail) {
267
+ try {
268
+ await this.executeWithRetry(
269
+ (ev, em) => participant.onFail(ev, error, em),
270
+ event,
271
+ emit
272
+ );
273
+ } catch (failError) {
274
+ if (failError instanceof SagaRetryableError) {
275
+ await this.callOnRetryExhausted(
276
+ participant,
277
+ event,
278
+ failError,
279
+ emit
280
+ );
281
+ } else {
282
+ this.logger.error(
283
+ `[SagaRunner] onFail threw non-retryable error for ${event.topic}:`,
284
+ failError
285
+ );
286
+ }
287
+ }
288
+ return;
289
+ }
290
+ this.logger.error(
291
+ `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,
292
+ error
293
+ );
294
+ }
295
+ }
296
+ async executeWithRetry(fn, event, emit) {
233
297
  const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;
234
298
  const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;
235
299
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
236
300
  try {
237
- await handler(event, emit);
301
+ await fn(event, emit);
238
302
  return;
239
303
  } catch (error) {
240
304
  if (error instanceof SagaRetryableError) {
@@ -243,19 +307,17 @@ var SagaRunner = class {
243
307
  await this.sleep(delay);
244
308
  continue;
245
309
  }
246
- if (participant.onRetryExhausted) {
247
- await participant.onRetryExhausted(event, error, emit);
248
- }
249
- return;
310
+ throw error;
250
311
  }
251
- this.logger.error(
252
- `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,
253
- error
254
- );
255
- return;
312
+ throw error;
256
313
  }
257
314
  }
258
315
  }
316
+ async callOnRetryExhausted(participant, event, error, emit) {
317
+ if (participant.onRetryExhausted) {
318
+ await participant.onRetryExhausted(event, error, emit);
319
+ }
320
+ }
259
321
  sleep(ms) {
260
322
  return new Promise((resolve) => setTimeout(resolve, ms));
261
323
  }
@@ -579,11 +641,11 @@ var SagaRegistry = class {
579
641
  const map = /* @__PURE__ */ new Map();
580
642
  for (const participant of this.participants) {
581
643
  for (const [topic, handler] of Object.entries(participant.on)) {
582
- if (map.has(topic)) {
583
- const existing = map.get(topic);
644
+ const existing = map.get(topic) ?? {};
645
+ if (existing.sagaHandler) {
584
646
  throw new SagaDuplicateHandlerError(
585
647
  topic,
586
- existing.participant.serviceId,
648
+ existing.sagaParticipant.serviceId,
587
649
  participant.serviceId
588
650
  );
589
651
  }
@@ -595,7 +657,29 @@ var SagaRegistry = class {
595
657
  "cannot have both final and fork options"
596
658
  );
597
659
  }
598
- map.set(topic, { participant, handler, options });
660
+ map.set(topic, {
661
+ ...existing,
662
+ sagaParticipant: participant,
663
+ sagaHandler: handler,
664
+ sagaOptions: options
665
+ });
666
+ }
667
+ if (participant.onPlain) {
668
+ for (const [topic, handler] of Object.entries(participant.onPlain)) {
669
+ const existing = map.get(topic) ?? {};
670
+ if (existing.plainHandler) {
671
+ throw new SagaDuplicateHandlerError(
672
+ topic,
673
+ existing.plainParticipant.serviceId,
674
+ participant.serviceId
675
+ );
676
+ }
677
+ map.set(topic, {
678
+ ...existing,
679
+ plainParticipant: participant,
680
+ plainHandler: handler
681
+ });
682
+ }
599
683
  }
600
684
  }
601
685
  return map;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transport/transport.interface.ts","../src/errors/saga.error.ts","../src/errors/saga-retryable.error.ts","../src/logger/saga-logger.ts","../src/context/saga-context.ts","../src/errors/saga-context-not-found.error.ts","../src/runner/saga-runner.ts","../src/publisher/saga-publisher.ts","../src/errors/saga-no-parent.error.ts","../src/publisher/message-builder.ts","../src/parser/saga-parser.ts","../src/errors/saga-duplicate-handler.error.ts","../src/errors/saga-invalid-handler-config.error.ts","../src/registry/saga-registry.ts","../src/errors/saga-parse.error.ts","../src/errors/saga-transport-not-connected.error.ts","../src/otel/otel-context.ts"],"sourcesContent":["export interface SagaTransport {\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n publish(message: OutboundMessage): Promise<void>;\n subscribe(\n topics: string[],\n handler: (message: InboundMessage) => Promise<void>,\n options?: TransportSubscribeOptions,\n ): Promise<void>;\n}\n\nexport interface OutboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface InboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface TransportSubscribeOptions {\n fromBeginning?: boolean;\n groupId?: string;\n}\n\nexport interface TransportHealthResult {\n status: \"up\" | \"down\";\n details?: Record<string, unknown>;\n}\n\nexport interface HealthCheckable {\n healthCheck(): Promise<TransportHealthResult>;\n}\n\nexport function isHealthCheckable(\n transport: SagaTransport,\n): transport is SagaTransport & HealthCheckable {\n return typeof (transport as any).healthCheck === \"function\";\n}\n","export class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n TransportHealthResult,\n} from \"../transport/transport.interface\";\nimport { isHealthCheckable } from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n const baseRouteMap = this.registry.buildRouteMap();\n const prefix = this.options.topicPrefix ?? \"\";\n\n this.routeMap = new Map();\n for (const [topic, entry] of baseRouteMap) {\n this.routeMap.set(`${prefix}${topic}`, entry);\n }\n\n const topics = Array.from(this.routeMap.keys());\n\n await this.transport.connect();\n\n if (topics.length > 0) {\n this.logger.info(\n `[SagaRunner] Subscribing to ${topics.length} topic(s): [${topics.join(\", \")}]`,\n );\n await this.transport.subscribe(\n topics,\n (message) => this.handleMessage(message),\n {\n fromBeginning: this.options.fromBeginning,\n groupId: this.options.groupId,\n },\n );\n this.logger.info(\"[SagaRunner] Consumer running\");\n } else {\n this.logger.warn(\n \"[SagaRunner] No handlers registered — nothing to subscribe\",\n );\n }\n }\n\n async stop(): Promise<void> {\n await this.transport.disconnect();\n }\n\n async healthCheck(): Promise<TransportHealthResult> {\n if (isHealthCheckable(this.transport)) {\n return this.transport.healthCheck();\n }\n return {\n status: \"up\",\n details: { reason: \"Transport does not support health checks\" },\n };\n }\n\n private async handleMessage(message: InboundMessage): Promise<void> {\n const event = this.parser.parse<Record<string, unknown>>(message);\n if (!event) return;\n\n const route = this.routeMap.get(event.topic);\n if (!route) return;\n\n const isFinalHandler = route.options?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n topic: event.topic,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.options?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.participant.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.handler,\n route.participant,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.topic}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await handler(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n return;\n }\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,\n error,\n );\n return;\n }\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n topic,\n stepName,\n stepDescription,\n payload,\n hint,\n key,\n }: EmitParams<T>): Promise<void> => {\n const ctx = SagaContext.current();\n const resolvedKey = key ?? baseKey ?? ctx?.key;\n const now = new Date().toISOString();\n const event: SagaEvent<T> = {\n sagaId,\n causationId: baseCausationId,\n eventId: uuidv7(),\n topic,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.root.id\": event.rootSagaId,\n };\n if (event.sagaName) {\n attrs[\"saga.name\"] = event.sagaName;\n }\n if (event.sagaDescription) {\n attrs[\"saga.description\"] = event.sagaDescription;\n }\n if (event.stepDescription) {\n attrs[\"saga.step.description\"] = event.stepDescription;\n }\n if (event.parentSagaId) {\n attrs[\"saga.parent.id\"] = event.parentSagaId;\n }\n\n this.otelCtx.enrichSpan(attrs);\n\n const message = buildOutboundMessage(event, this.topicPrefix);\n\n this.otelCtx.injectTraceContext(message.headers);\n\n await this.otelCtx.withSpan(`saga.publish ${event.topic}`, attrs, () =>\n this.transport.publish(message),\n );\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaNoParentError extends SagaError {\n constructor() {\n super(\"No parentSagaId in current saga context.\");\n this.name = \"SagaNoParentError\";\n }\n}\n","import type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { OutboundMessage } from \"../transport/transport.interface\";\n\nexport function buildOutboundMessage<T>(\n event: SagaEvent<T>,\n topicPrefix = \"\",\n): OutboundMessage {\n const topic = `${topicPrefix}${event.topic}`;\n const key = event.key ?? event.rootSagaId;\n\n const headers: Record<string, string> = {\n \"saga-id\": event.sagaId,\n \"saga-causation-id\": event.causationId,\n \"saga-event-id\": event.eventId,\n \"saga-step-name\": event.stepName,\n \"saga-published-at\": event.publishedAt,\n \"saga-schema-version\": String(event.schemaVersion),\n \"saga-root-id\": event.rootSagaId,\n };\n\n if (event.parentSagaId) {\n headers[\"saga-parent-id\"] = event.parentSagaId;\n }\n\n if (event.hint) {\n headers[\"saga-event-hint\"] = event.hint;\n }\n\n if (event.sagaName) {\n headers[\"saga-name\"] = event.sagaName;\n }\n\n if (event.sagaDescription) {\n headers[\"saga-description\"] = event.sagaDescription;\n }\n\n if (event.stepDescription) {\n headers[\"saga-step-description\"] = event.stepDescription;\n }\n\n if (event.key) {\n headers[\"saga-key\"] = event.key;\n }\n\n headers[\"saga-occurred-at\"] = event.occurredAt;\n\n const value = JSON.stringify(event.payload);\n\n return { topic, key, value, headers };\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { InboundMessage } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\n\nexport class SagaParser {\n constructor(private otelCtx: OtelContext) {}\n\n parse<T>(message: InboundMessage): SagaEvent<T> | null {\n try {\n if (message.headers[\"saga-id\"]) {\n return this.parseFromHeaders<T>(message);\n }\n\n const baggageResult = this.parseFromBaggage<T>(message);\n if (baggageResult) return baggageResult;\n\n const body = JSON.parse(message.value);\n if (body && body.sagaId) {\n return body as SagaEvent<T>;\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n private parseFromHeaders<T>(message: InboundMessage): SagaEvent<T> | null {\n const headers = message.headers;\n const payload = JSON.parse(message.value) as T;\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n topic: message.topic,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: headers[\"saga-occurred-at\"] ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload,\n sagaName: headers[\"saga-name\"] || undefined,\n sagaDescription: headers[\"saga-description\"] || undefined,\n stepDescription: headers[\"saga-step-description\"] || undefined,\n key: headers[\"saga-key\"] || undefined,\n };\n }\n\n private parseFromBaggage<T>(message: InboundMessage): SagaEvent<T> | null {\n let sagaId: string | undefined;\n let rootSagaId: string | undefined;\n let parentSagaId: string | undefined;\n\n const baggageHeader = message.headers[\"baggage\"];\n if (baggageHeader) {\n const entries = this.parseBaggageHeader(baggageHeader);\n sagaId = entries[\"saga.id\"];\n rootSagaId = entries[\"saga.root.id\"];\n parentSagaId = entries[\"saga.parent.id\"];\n }\n\n // Fallback to OTel context extraction\n if (!sagaId) {\n const extracted = this.otelCtx.extractBaggage();\n sagaId = extracted.sagaId;\n rootSagaId = extracted.rootSagaId;\n parentSagaId = extracted.parentSagaId;\n }\n\n if (!sagaId) return null;\n\n const body = JSON.parse(message.value);\n\n return {\n sagaId,\n causationId: sagaId,\n eventId: uuidv7(),\n topic: body.topic,\n stepName: \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: rootSagaId ?? sagaId,\n parentSagaId: parentSagaId || undefined,\n payload: body.payload as T,\n };\n }\n\n private parseBaggageHeader(baggage: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (const entry of baggage.split(\",\")) {\n const [key, value] = entry.trim().split(\"=\");\n if (key && value) {\n result[key.trim()] = decodeURIComponent(value.trim());\n }\n }\n return result;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaDuplicateHandlerError extends SagaError {\n constructor(\n topic: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${topic}\": ` +\n `registered by \"${existingServiceId}\" and \"${newServiceId}\"`,\n );\n this.name = \"SagaDuplicateHandlerError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaInvalidHandlerConfigError extends SagaError {\n constructor(topic: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${topic}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n participant: SagaParticipant;\n handler: EventHandler;\n options?: HandlerConfig;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n for (const [topic, handler] of Object.entries(participant.on)) {\n if (map.has(topic)) {\n const existing = map.get(topic)!;\n throw new SagaDuplicateHandlerError(\n topic,\n existing.participant.serviceId,\n participant.serviceId,\n );\n }\n const options = participant.handlerOptions?.[topic];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n topic,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n map.set(topic, { participant, handler, options });\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":"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","names":["uuidv7","uuidv7","uuidv7"]}
1
+ {"version":3,"sources":["../src/transport/transport.interface.ts","../src/errors/saga.error.ts","../src/errors/saga-retryable.error.ts","../src/logger/saga-logger.ts","../src/context/saga-context.ts","../src/errors/saga-context-not-found.error.ts","../src/runner/saga-runner.ts","../src/publisher/saga-publisher.ts","../src/errors/saga-no-parent.error.ts","../src/publisher/message-builder.ts","../src/parser/saga-parser.ts","../src/errors/saga-duplicate-handler.error.ts","../src/errors/saga-invalid-handler-config.error.ts","../src/registry/saga-registry.ts","../src/errors/saga-parse.error.ts","../src/errors/saga-transport-not-connected.error.ts","../src/otel/otel-context.ts"],"sourcesContent":["export interface SagaTransport {\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n publish(message: OutboundMessage): Promise<void>;\n subscribe(\n topics: string[],\n handler: (message: InboundMessage) => Promise<void>,\n options?: TransportSubscribeOptions,\n ): Promise<void>;\n}\n\nexport interface OutboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface InboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface TransportSubscribeOptions {\n fromBeginning?: boolean;\n groupId?: string;\n}\n\nexport interface TransportHealthResult {\n status: \"up\" | \"down\";\n details?: Record<string, unknown>;\n}\n\nexport interface HealthCheckable {\n healthCheck(): Promise<TransportHealthResult>;\n}\n\nexport function isHealthCheckable(\n transport: SagaTransport,\n): transport is SagaTransport & HealthCheckable {\n return typeof (transport as any).healthCheck === \"function\";\n}\n","export class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n TransportHealthResult,\n} from \"../transport/transport.interface\";\nimport { isHealthCheckable } from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { PlainMessage } from \"../interfaces/plain-message.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n const baseRouteMap = this.registry.buildRouteMap();\n const prefix = this.options.topicPrefix ?? \"\";\n\n this.routeMap = new Map();\n for (const [topic, entry] of baseRouteMap) {\n this.routeMap.set(`${prefix}${topic}`, entry);\n }\n\n const topics = Array.from(this.routeMap.keys());\n\n await this.transport.connect();\n\n if (topics.length > 0) {\n this.logger.info(\n `[SagaRunner] Subscribing to ${topics.length} topic(s): [${topics.join(\", \")}]`,\n );\n await this.transport.subscribe(\n topics,\n (message) => this.handleMessage(message),\n {\n fromBeginning: this.options.fromBeginning,\n groupId: this.options.groupId,\n },\n );\n this.logger.info(\"[SagaRunner] Consumer running\");\n } else {\n this.logger.warn(\n \"[SagaRunner] No handlers registered — nothing to subscribe\",\n );\n }\n }\n\n async stop(): Promise<void> {\n await this.transport.disconnect();\n }\n\n async healthCheck(): Promise<TransportHealthResult> {\n if (isHealthCheckable(this.transport)) {\n return this.transport.healthCheck();\n }\n return {\n status: \"up\",\n details: { reason: \"Transport does not support health checks\" },\n };\n }\n\n private async handleMessage(message: InboundMessage): Promise<void> {\n const route = this.routeMap.get(message.topic);\n if (!route) {\n return;\n }\n\n // Try to parse as saga event\n const event = this.parser.parse<Record<string, unknown>>(message);\n\n if (event && route.sagaHandler) {\n await this.handleSagaMessage(message, event, route);\n return;\n }\n\n if (!event && route.plainHandler) {\n await this.handlePlainMessage(message, route);\n return;\n }\n\n // No matching handler for this message type — skip\n }\n\n private async handleSagaMessage(\n message: InboundMessage,\n event: SagaEvent<Record<string, unknown>>,\n route: RouteEntry,\n ): Promise<void> {\n const isFinalHandler = route.sagaOptions?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n topic: event.topic,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.sagaOptions?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.sagaParticipant!.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.sagaHandler!,\n route.sagaParticipant!,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.topic}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async handlePlainMessage(\n message: InboundMessage,\n route: RouteEntry,\n ): Promise<void> {\n let payload: unknown;\n try {\n payload = JSON.parse(message.value);\n } catch {\n payload = message.value;\n }\n\n const plainMessage: PlainMessage = {\n topic: message.topic,\n key: message.key,\n payload,\n headers: message.headers,\n };\n\n await route.plainHandler!(plainMessage);\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n try {\n await this.executeWithRetry(handler, event, emit);\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n // Retries exhausted\n await this.callOnRetryExhausted(participant, event, error, emit);\n return;\n }\n\n // Non-retryable error — route to onFail if defined\n if (participant.onFail) {\n try {\n await this.executeWithRetry(\n (ev, em) => participant.onFail!(ev, error as Error, em),\n event,\n emit,\n );\n } catch (failError) {\n if (failError instanceof SagaRetryableError) {\n await this.callOnRetryExhausted(\n participant,\n event,\n failError,\n emit,\n );\n } else {\n this.logger.error(\n `[SagaRunner] onFail threw non-retryable error for ${event.topic}:`,\n failError,\n );\n }\n }\n return;\n }\n\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.topic}:`,\n error,\n );\n }\n }\n\n private async executeWithRetry(\n fn: (event: IncomingEvent, emit: Emit) => Promise<void>,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await fn(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n // Exhausted — re-throw so caller can handle\n throw error;\n }\n // Non-retryable — re-throw immediately\n throw error;\n }\n }\n }\n\n private async callOnRetryExhausted(\n participant: SagaParticipant,\n event: IncomingEvent,\n error: SagaRetryableError,\n emit: Emit,\n ): Promise<void> {\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n topic,\n stepName,\n stepDescription,\n payload,\n hint,\n key,\n }: EmitParams<T>): Promise<void> => {\n const ctx = SagaContext.current();\n const resolvedKey = key ?? baseKey ?? ctx?.key;\n const now = new Date().toISOString();\n const event: SagaEvent<T> = {\n sagaId,\n causationId: baseCausationId,\n eventId: uuidv7(),\n topic,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.topic\": event.topic,\n \"saga.step.name\": event.stepName,\n \"saga.root.id\": event.rootSagaId,\n };\n if (event.sagaName) {\n attrs[\"saga.name\"] = event.sagaName;\n }\n if (event.sagaDescription) {\n attrs[\"saga.description\"] = event.sagaDescription;\n }\n if (event.stepDescription) {\n attrs[\"saga.step.description\"] = event.stepDescription;\n }\n if (event.parentSagaId) {\n attrs[\"saga.parent.id\"] = event.parentSagaId;\n }\n\n this.otelCtx.enrichSpan(attrs);\n\n const message = buildOutboundMessage(event, this.topicPrefix);\n\n this.otelCtx.injectTraceContext(message.headers);\n\n await this.otelCtx.withSpan(`saga.publish ${event.topic}`, attrs, () =>\n this.transport.publish(message),\n );\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaNoParentError extends SagaError {\n constructor() {\n super(\"No parentSagaId in current saga context.\");\n this.name = \"SagaNoParentError\";\n }\n}\n","import type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { OutboundMessage } from \"../transport/transport.interface\";\n\nexport function buildOutboundMessage<T>(\n event: SagaEvent<T>,\n topicPrefix = \"\",\n): OutboundMessage {\n const topic = `${topicPrefix}${event.topic}`;\n const key = event.key ?? event.rootSagaId;\n\n const headers: Record<string, string> = {\n \"saga-id\": event.sagaId,\n \"saga-causation-id\": event.causationId,\n \"saga-event-id\": event.eventId,\n \"saga-step-name\": event.stepName,\n \"saga-published-at\": event.publishedAt,\n \"saga-schema-version\": String(event.schemaVersion),\n \"saga-root-id\": event.rootSagaId,\n };\n\n if (event.parentSagaId) {\n headers[\"saga-parent-id\"] = event.parentSagaId;\n }\n\n if (event.hint) {\n headers[\"saga-event-hint\"] = event.hint;\n }\n\n if (event.sagaName) {\n headers[\"saga-name\"] = event.sagaName;\n }\n\n if (event.sagaDescription) {\n headers[\"saga-description\"] = event.sagaDescription;\n }\n\n if (event.stepDescription) {\n headers[\"saga-step-description\"] = event.stepDescription;\n }\n\n if (event.key) {\n headers[\"saga-key\"] = event.key;\n }\n\n headers[\"saga-occurred-at\"] = event.occurredAt;\n\n const value = JSON.stringify(event.payload);\n\n return { topic, key, value, headers };\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { InboundMessage } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\n\nexport class SagaParser {\n constructor(private otelCtx: OtelContext) {}\n\n parse<T>(message: InboundMessage): SagaEvent<T> | null {\n try {\n if (message.headers[\"saga-id\"]) {\n return this.parseFromHeaders<T>(message);\n }\n\n const baggageResult = this.parseFromBaggage<T>(message);\n if (baggageResult) return baggageResult;\n\n const body = JSON.parse(message.value);\n if (body && body.sagaId) {\n return body as SagaEvent<T>;\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n private parseFromHeaders<T>(message: InboundMessage): SagaEvent<T> | null {\n const headers = message.headers;\n const payload = JSON.parse(message.value) as T;\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n topic: message.topic,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: headers[\"saga-occurred-at\"] ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload,\n sagaName: headers[\"saga-name\"] || undefined,\n sagaDescription: headers[\"saga-description\"] || undefined,\n stepDescription: headers[\"saga-step-description\"] || undefined,\n key: headers[\"saga-key\"] || undefined,\n };\n }\n\n private parseFromBaggage<T>(message: InboundMessage): SagaEvent<T> | null {\n let sagaId: string | undefined;\n let rootSagaId: string | undefined;\n let parentSagaId: string | undefined;\n\n const baggageHeader = message.headers[\"baggage\"];\n if (baggageHeader) {\n const entries = this.parseBaggageHeader(baggageHeader);\n sagaId = entries[\"saga.id\"];\n rootSagaId = entries[\"saga.root.id\"];\n parentSagaId = entries[\"saga.parent.id\"];\n }\n\n // Fallback to OTel context extraction\n if (!sagaId) {\n const extracted = this.otelCtx.extractBaggage();\n sagaId = extracted.sagaId;\n rootSagaId = extracted.rootSagaId;\n parentSagaId = extracted.parentSagaId;\n }\n\n if (!sagaId) return null;\n\n const body = JSON.parse(message.value);\n\n return {\n sagaId,\n causationId: sagaId,\n eventId: uuidv7(),\n topic: body.topic,\n stepName: \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: rootSagaId ?? sagaId,\n parentSagaId: parentSagaId || undefined,\n payload: body.payload as T,\n };\n }\n\n private parseBaggageHeader(baggage: string): Record<string, string> {\n const result: Record<string, string> = {};\n for (const entry of baggage.split(\",\")) {\n const [key, value] = entry.trim().split(\"=\");\n if (key && value) {\n result[key.trim()] = decodeURIComponent(value.trim());\n }\n }\n return result;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaDuplicateHandlerError extends SagaError {\n constructor(\n topic: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${topic}\": ` +\n `registered by \"${existingServiceId}\" and \"${newServiceId}\"`,\n );\n this.name = \"SagaDuplicateHandlerError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaInvalidHandlerConfigError extends SagaError {\n constructor(topic: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${topic}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { PlainHandler } from \"../interfaces/plain-message.interface\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n sagaParticipant?: SagaParticipant;\n sagaHandler?: EventHandler;\n sagaOptions?: HandlerConfig;\n\n plainParticipant?: SagaParticipant;\n plainHandler?: PlainHandler;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n // Register saga handlers\n for (const [topic, handler] of Object.entries(participant.on)) {\n const existing = map.get(topic) ?? {};\n\n if (existing.sagaHandler) {\n throw new SagaDuplicateHandlerError(\n topic,\n existing.sagaParticipant!.serviceId,\n participant.serviceId,\n );\n }\n\n const options = participant.handlerOptions?.[topic];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n topic,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n\n map.set(topic, {\n ...existing,\n sagaParticipant: participant,\n sagaHandler: handler,\n sagaOptions: options,\n });\n }\n\n // Register plain handlers\n if (participant.onPlain) {\n for (const [topic, handler] of Object.entries(participant.onPlain)) {\n const existing = map.get(topic) ?? {};\n\n if (existing.plainHandler) {\n throw new SagaDuplicateHandlerError(\n topic,\n existing.plainParticipant!.serviceId,\n participant.serviceId,\n );\n }\n\n map.set(topic, {\n ...existing,\n plainParticipant: participant,\n plainHandler: handler,\n });\n }\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":"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","names":["uuidv7","uuidv7","uuidv7"]}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@fbsm/saga-core",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.2.0-beta.2",
4
4
  "description": "Framework-agnostic saga choreography core: runner, publisher, parser, context management",
5
5
  "license": "MIT",
6
6
  "author": "fbsm",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/fbsm/saga-library",
9
+ "url": "https://github.com/filipebsmaia/saga-library",
10
10
  "directory": "packages/saga-core"
11
11
  },
12
12
  "keywords": [