@fbsm/saga-core 0.3.0-beta.0 → 0.3.0-beta.1
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 +2 -1
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ const publisher = new SagaPublisher(transport, otelContext, topicPrefix);
|
|
|
64
64
|
|
|
65
65
|
| Method | Description |
|
|
66
66
|
| ------------------------------------------------- | ------------------------------------- |
|
|
67
|
-
| `start(fn, opts?)` |
|
|
67
|
+
| `start(fn, opts?)` | Context-aware: creates child if inside existing context, root otherwise |
|
|
68
68
|
| `startChild(fn, opts?)` | Create a child saga linked to current |
|
|
69
69
|
| `emit(params)` | Publish event in current context |
|
|
70
70
|
| `emitToParent(params \| fn)` | Emit to parent saga |
|
|
@@ -77,6 +77,7 @@ interface SagaStartOptions {
|
|
|
77
77
|
sagaName?: string;
|
|
78
78
|
sagaDescription?: string;
|
|
79
79
|
key?: string;
|
|
80
|
+
independent?: boolean; // Force root saga even inside existing context
|
|
80
81
|
}
|
|
81
82
|
```
|
|
82
83
|
|
package/dist/index.cjs
CHANGED
|
@@ -426,6 +426,10 @@ var SagaPublisher = class {
|
|
|
426
426
|
this.topicPrefix = topicPrefix;
|
|
427
427
|
}
|
|
428
428
|
async start(fn, opts) {
|
|
429
|
+
const existingContext = SagaContext.current();
|
|
430
|
+
if (existingContext && !opts?.independent) {
|
|
431
|
+
return this.startChild(fn, opts);
|
|
432
|
+
}
|
|
429
433
|
const sagaId = (0, import_uuid2.v7)();
|
|
430
434
|
const ctxData = {
|
|
431
435
|
sagaId,
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 {\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 ancestorChain?: 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 ancestorChain: event.ancestorChain,\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 ancestorChain: event.ancestorChain,\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 subAncestorChain = [\n event.sagaId,\n ...(event.ancestorChain ?? []),\n ];\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n ancestorChain: subAncestorChain,\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 ancestorChain: subAncestorChain,\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 ancestorChain: event.ancestorChain,\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 ancestorChain: [] as string[],\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 ancestorChain: ctx.ancestorChain,\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 ancestorChain: [ctx.sagaId, ...(ctx.ancestorChain ?? [])],\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 const parentAncestorChain = (ctx.ancestorChain ?? []).slice(1);\n const grandparent = parentAncestorChain[0];\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: grandparent,\n ancestorChain: parentAncestorChain,\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: grandparent,\n rootSagaId: ctx.rootSagaId,\n ancestorChain: parentAncestorChain,\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 ancestorChain = parentCtx?.ancestorChain;\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 ancestorChain,\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 if (event.ancestorChain && event.ancestorChain.length > 0) {\n headers[\"saga-ancestor-chain\"] = event.ancestorChain.join(\",\");\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 const rawAncestorChain = headers[\"saga-ancestor-chain\"];\n const ancestorChain = rawAncestorChain\n ? rawAncestorChain.split(\",\").filter(Boolean)\n : undefined;\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 ancestorChain,\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"]}
|
|
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 ancestorChain?: 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 ancestorChain: event.ancestorChain,\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 ancestorChain: event.ancestorChain,\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 subAncestorChain = [\n event.sagaId,\n ...(event.ancestorChain ?? []),\n ];\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n ancestorChain: subAncestorChain,\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 ancestorChain: subAncestorChain,\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 ancestorChain: event.ancestorChain,\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 independent?: boolean;\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 existingContext = SagaContext.current();\n if (existingContext && !opts?.independent) {\n return this.startChild(fn, opts);\n }\n\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n ancestorChain: [] as string[],\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 ancestorChain: ctx.ancestorChain,\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 ancestorChain: [ctx.sagaId, ...(ctx.ancestorChain ?? [])],\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 const parentAncestorChain = (ctx.ancestorChain ?? []).slice(1);\n const grandparent = parentAncestorChain[0];\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: grandparent,\n ancestorChain: parentAncestorChain,\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: grandparent,\n rootSagaId: ctx.rootSagaId,\n ancestorChain: parentAncestorChain,\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 ancestorChain = parentCtx?.ancestorChain;\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 ancestorChain,\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 if (event.ancestorChain && event.ancestorChain.length > 0) {\n headers[\"saga-ancestor-chain\"] = event.ancestorChain.join(\",\");\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 const rawAncestorChain = headers[\"saga-ancestor-chain\"];\n const ancestorChain = rawAncestorChain\n ? rawAncestorChain.split(\",\").filter(Boolean)\n : undefined;\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 ancestorChain,\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
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -390,6 +390,10 @@ var SagaPublisher = class {
|
|
|
390
390
|
this.topicPrefix = topicPrefix;
|
|
391
391
|
}
|
|
392
392
|
async start(fn, opts) {
|
|
393
|
+
const existingContext = SagaContext.current();
|
|
394
|
+
if (existingContext && !opts?.independent) {
|
|
395
|
+
return this.startChild(fn, opts);
|
|
396
|
+
}
|
|
393
397
|
const sagaId = uuidv72();
|
|
394
398
|
const ctxData = {
|
|
395
399
|
sagaId,
|
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 ancestorChain?: 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 ancestorChain: event.ancestorChain,\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 ancestorChain: event.ancestorChain,\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 subAncestorChain = [\n event.sagaId,\n ...(event.ancestorChain ?? []),\n ];\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n ancestorChain: subAncestorChain,\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 ancestorChain: subAncestorChain,\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 ancestorChain: event.ancestorChain,\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 ancestorChain: [] as string[],\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 ancestorChain: ctx.ancestorChain,\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 ancestorChain: [ctx.sagaId, ...(ctx.ancestorChain ?? [])],\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 const parentAncestorChain = (ctx.ancestorChain ?? []).slice(1);\n const grandparent = parentAncestorChain[0];\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: grandparent,\n ancestorChain: parentAncestorChain,\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: grandparent,\n rootSagaId: ctx.rootSagaId,\n ancestorChain: parentAncestorChain,\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 ancestorChain = parentCtx?.ancestorChain;\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 ancestorChain,\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 if (event.ancestorChain && event.ancestorChain.length > 0) {\n headers[\"saga-ancestor-chain\"] = event.ancestorChain.join(\",\");\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 const rawAncestorChain = headers[\"saga-ancestor-chain\"];\n const ancestorChain = rawAncestorChain\n ? rawAncestorChain.split(\",\").filter(Boolean)\n : undefined;\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 ancestorChain,\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"]}
|
|
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 ancestorChain?: 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 ancestorChain: event.ancestorChain,\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 ancestorChain: event.ancestorChain,\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 subAncestorChain = [\n event.sagaId,\n ...(event.ancestorChain ?? []),\n ];\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n ancestorChain: subAncestorChain,\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 ancestorChain: subAncestorChain,\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 ancestorChain: event.ancestorChain,\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 independent?: boolean;\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 existingContext = SagaContext.current();\n if (existingContext && !opts?.independent) {\n return this.startChild(fn, opts);\n }\n\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n ancestorChain: [] as string[],\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 ancestorChain: ctx.ancestorChain,\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 ancestorChain: [ctx.sagaId, ...(ctx.ancestorChain ?? [])],\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 const parentAncestorChain = (ctx.ancestorChain ?? []).slice(1);\n const grandparent = parentAncestorChain[0];\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: grandparent,\n ancestorChain: parentAncestorChain,\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: grandparent,\n rootSagaId: ctx.rootSagaId,\n ancestorChain: parentAncestorChain,\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 ancestorChain = parentCtx?.ancestorChain;\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 ancestorChain,\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 if (event.ancestorChain && event.ancestorChain.length > 0) {\n headers[\"saga-ancestor-chain\"] = event.ancestorChain.join(\",\");\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 const rawAncestorChain = headers[\"saga-ancestor-chain\"];\n const ancestorChain = rawAncestorChain\n ? rawAncestorChain.split(\",\").filter(Boolean)\n : undefined;\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 ancestorChain,\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"]}
|