@fbsm/saga-core 0.3.0-beta.0 → 0.3.1-beta.0
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 +34 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.js +34 -11
- 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
|
@@ -190,20 +190,38 @@ var SagaRunner = class {
|
|
|
190
190
|
rootSagaId: event.rootSagaId,
|
|
191
191
|
ancestorChain: event.ancestorChain,
|
|
192
192
|
payload: event.payload,
|
|
193
|
+
hint: event.hint,
|
|
193
194
|
key: event.key,
|
|
194
195
|
sagaName: event.sagaName,
|
|
195
196
|
sagaDescription: event.sagaDescription
|
|
196
197
|
};
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
198
|
+
const isChildFinalized = event.hint === "final" && event.parentSagaId;
|
|
199
|
+
let emit;
|
|
200
|
+
if (isChildFinalized) {
|
|
201
|
+
const parentAncestorChain = (event.ancestorChain ?? []).slice(1);
|
|
202
|
+
const grandparent = parentAncestorChain[0];
|
|
203
|
+
emit = this.publisher.forSaga(
|
|
204
|
+
event.parentSagaId,
|
|
205
|
+
{
|
|
206
|
+
parentSagaId: grandparent,
|
|
207
|
+
rootSagaId: event.rootSagaId,
|
|
208
|
+
ancestorChain: parentAncestorChain
|
|
209
|
+
},
|
|
210
|
+
event.eventId,
|
|
211
|
+
event.key
|
|
212
|
+
);
|
|
213
|
+
} else {
|
|
214
|
+
emit = this.publisher.forSaga(
|
|
215
|
+
event.sagaId,
|
|
216
|
+
{
|
|
217
|
+
parentSagaId: event.parentSagaId,
|
|
218
|
+
rootSagaId: event.rootSagaId,
|
|
219
|
+
ancestorChain: event.ancestorChain
|
|
220
|
+
},
|
|
221
|
+
event.eventId,
|
|
222
|
+
event.key
|
|
223
|
+
);
|
|
224
|
+
}
|
|
207
225
|
const wrappedEmit = async (params) => {
|
|
208
226
|
const finalParams = isFinalHandler ? { ...params, hint: "final" } : params;
|
|
209
227
|
return emit(finalParams);
|
|
@@ -426,6 +444,10 @@ var SagaPublisher = class {
|
|
|
426
444
|
this.topicPrefix = topicPrefix;
|
|
427
445
|
}
|
|
428
446
|
async start(fn, opts) {
|
|
447
|
+
const existingContext = SagaContext.current();
|
|
448
|
+
if (existingContext && !opts?.independent) {
|
|
449
|
+
return this.startChild(fn, opts);
|
|
450
|
+
}
|
|
429
451
|
const sagaId = (0, import_uuid2.v7)();
|
|
430
452
|
const ctxData = {
|
|
431
453
|
sagaId,
|
|
@@ -620,7 +642,8 @@ var SagaParser = class {
|
|
|
620
642
|
sagaName: headers["saga-name"] || void 0,
|
|
621
643
|
sagaDescription: headers["saga-description"] || void 0,
|
|
622
644
|
stepDescription: headers["saga-step-description"] || void 0,
|
|
623
|
-
key: headers["saga-key"] || void 0
|
|
645
|
+
key: headers["saga-key"] || void 0,
|
|
646
|
+
hint: headers["saga-event-hint"] || void 0
|
|
624
647
|
};
|
|
625
648
|
}
|
|
626
649
|
parseFromBaggage(message) {
|
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 hint: event.hint,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n // When the inbound event is a finalized child saga, promote emit\n // to the parent context so the handler's output continues the parent flow.\n const isChildFinalized = event.hint === \"final\" && event.parentSagaId;\n\n let emit: Emit;\n if (isChildFinalized) {\n const parentAncestorChain = (event.ancestorChain ?? []).slice(1);\n const grandparent = parentAncestorChain[0];\n emit = this.publisher.forSaga(\n event.parentSagaId!,\n {\n parentSagaId: grandparent,\n rootSagaId: event.rootSagaId,\n ancestorChain: parentAncestorChain,\n },\n event.eventId,\n event.key,\n );\n } else {\n 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\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 { EventHint } from \"../interfaces/emit.type\";\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 hint: (headers[\"saga-event-hint\"] as EventHint) || 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
|
@@ -42,6 +42,17 @@ interface RunnerOptions {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
type EventHint = "compensation" | "final" | "fork";
|
|
46
|
+
interface EmitParams<T extends object = Record<string, unknown>> {
|
|
47
|
+
topic: string;
|
|
48
|
+
stepName: string;
|
|
49
|
+
stepDescription?: string;
|
|
50
|
+
payload: T;
|
|
51
|
+
hint?: EventHint;
|
|
52
|
+
key?: string;
|
|
53
|
+
}
|
|
54
|
+
type Emit = <T extends object>(params: EmitParams<T>) => Promise<void>;
|
|
55
|
+
|
|
45
56
|
interface IncomingEvent<T = Record<string, unknown>> {
|
|
46
57
|
eventId: string;
|
|
47
58
|
sagaId: string;
|
|
@@ -56,19 +67,9 @@ interface IncomingEvent<T = Record<string, unknown>> {
|
|
|
56
67
|
stepDescription?: string;
|
|
57
68
|
occurredAt: string;
|
|
58
69
|
payload: T;
|
|
59
|
-
key?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
type EventHint = "compensation" | "final" | "fork";
|
|
63
|
-
interface EmitParams<T extends object = Record<string, unknown>> {
|
|
64
|
-
topic: string;
|
|
65
|
-
stepName: string;
|
|
66
|
-
stepDescription?: string;
|
|
67
|
-
payload: T;
|
|
68
70
|
hint?: EventHint;
|
|
69
71
|
key?: string;
|
|
70
72
|
}
|
|
71
|
-
type Emit = <T extends object>(params: EmitParams<T>) => Promise<void>;
|
|
72
73
|
|
|
73
74
|
type EventHandler<T = Record<string, unknown>> = (event: IncomingEvent<T>, emit: Emit) => Promise<void>;
|
|
74
75
|
|
|
@@ -193,6 +194,7 @@ interface SagaStartOptions {
|
|
|
193
194
|
sagaName?: string;
|
|
194
195
|
sagaDescription?: string;
|
|
195
196
|
key?: string;
|
|
197
|
+
independent?: boolean;
|
|
196
198
|
}
|
|
197
199
|
declare class SagaPublisher {
|
|
198
200
|
private transport;
|
package/dist/index.d.ts
CHANGED
|
@@ -42,6 +42,17 @@ interface RunnerOptions {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
type EventHint = "compensation" | "final" | "fork";
|
|
46
|
+
interface EmitParams<T extends object = Record<string, unknown>> {
|
|
47
|
+
topic: string;
|
|
48
|
+
stepName: string;
|
|
49
|
+
stepDescription?: string;
|
|
50
|
+
payload: T;
|
|
51
|
+
hint?: EventHint;
|
|
52
|
+
key?: string;
|
|
53
|
+
}
|
|
54
|
+
type Emit = <T extends object>(params: EmitParams<T>) => Promise<void>;
|
|
55
|
+
|
|
45
56
|
interface IncomingEvent<T = Record<string, unknown>> {
|
|
46
57
|
eventId: string;
|
|
47
58
|
sagaId: string;
|
|
@@ -56,19 +67,9 @@ interface IncomingEvent<T = Record<string, unknown>> {
|
|
|
56
67
|
stepDescription?: string;
|
|
57
68
|
occurredAt: string;
|
|
58
69
|
payload: T;
|
|
59
|
-
key?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
type EventHint = "compensation" | "final" | "fork";
|
|
63
|
-
interface EmitParams<T extends object = Record<string, unknown>> {
|
|
64
|
-
topic: string;
|
|
65
|
-
stepName: string;
|
|
66
|
-
stepDescription?: string;
|
|
67
|
-
payload: T;
|
|
68
70
|
hint?: EventHint;
|
|
69
71
|
key?: string;
|
|
70
72
|
}
|
|
71
|
-
type Emit = <T extends object>(params: EmitParams<T>) => Promise<void>;
|
|
72
73
|
|
|
73
74
|
type EventHandler<T = Record<string, unknown>> = (event: IncomingEvent<T>, emit: Emit) => Promise<void>;
|
|
74
75
|
|
|
@@ -193,6 +194,7 @@ interface SagaStartOptions {
|
|
|
193
194
|
sagaName?: string;
|
|
194
195
|
sagaDescription?: string;
|
|
195
196
|
key?: string;
|
|
197
|
+
independent?: boolean;
|
|
196
198
|
}
|
|
197
199
|
declare class SagaPublisher {
|
|
198
200
|
private transport;
|
package/dist/index.js
CHANGED
|
@@ -154,20 +154,38 @@ var SagaRunner = class {
|
|
|
154
154
|
rootSagaId: event.rootSagaId,
|
|
155
155
|
ancestorChain: event.ancestorChain,
|
|
156
156
|
payload: event.payload,
|
|
157
|
+
hint: event.hint,
|
|
157
158
|
key: event.key,
|
|
158
159
|
sagaName: event.sagaName,
|
|
159
160
|
sagaDescription: event.sagaDescription
|
|
160
161
|
};
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
162
|
+
const isChildFinalized = event.hint === "final" && event.parentSagaId;
|
|
163
|
+
let emit;
|
|
164
|
+
if (isChildFinalized) {
|
|
165
|
+
const parentAncestorChain = (event.ancestorChain ?? []).slice(1);
|
|
166
|
+
const grandparent = parentAncestorChain[0];
|
|
167
|
+
emit = this.publisher.forSaga(
|
|
168
|
+
event.parentSagaId,
|
|
169
|
+
{
|
|
170
|
+
parentSagaId: grandparent,
|
|
171
|
+
rootSagaId: event.rootSagaId,
|
|
172
|
+
ancestorChain: parentAncestorChain
|
|
173
|
+
},
|
|
174
|
+
event.eventId,
|
|
175
|
+
event.key
|
|
176
|
+
);
|
|
177
|
+
} else {
|
|
178
|
+
emit = this.publisher.forSaga(
|
|
179
|
+
event.sagaId,
|
|
180
|
+
{
|
|
181
|
+
parentSagaId: event.parentSagaId,
|
|
182
|
+
rootSagaId: event.rootSagaId,
|
|
183
|
+
ancestorChain: event.ancestorChain
|
|
184
|
+
},
|
|
185
|
+
event.eventId,
|
|
186
|
+
event.key
|
|
187
|
+
);
|
|
188
|
+
}
|
|
171
189
|
const wrappedEmit = async (params) => {
|
|
172
190
|
const finalParams = isFinalHandler ? { ...params, hint: "final" } : params;
|
|
173
191
|
return emit(finalParams);
|
|
@@ -390,6 +408,10 @@ var SagaPublisher = class {
|
|
|
390
408
|
this.topicPrefix = topicPrefix;
|
|
391
409
|
}
|
|
392
410
|
async start(fn, opts) {
|
|
411
|
+
const existingContext = SagaContext.current();
|
|
412
|
+
if (existingContext && !opts?.independent) {
|
|
413
|
+
return this.startChild(fn, opts);
|
|
414
|
+
}
|
|
393
415
|
const sagaId = uuidv72();
|
|
394
416
|
const ctxData = {
|
|
395
417
|
sagaId,
|
|
@@ -584,7 +606,8 @@ var SagaParser = class {
|
|
|
584
606
|
sagaName: headers["saga-name"] || void 0,
|
|
585
607
|
sagaDescription: headers["saga-description"] || void 0,
|
|
586
608
|
stepDescription: headers["saga-step-description"] || void 0,
|
|
587
|
-
key: headers["saga-key"] || void 0
|
|
609
|
+
key: headers["saga-key"] || void 0,
|
|
610
|
+
hint: headers["saga-event-hint"] || void 0
|
|
588
611
|
};
|
|
589
612
|
}
|
|
590
613
|
parseFromBaggage(message) {
|
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 hint: event.hint,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n // When the inbound event is a finalized child saga, promote emit\n // to the parent context so the handler's output continues the parent flow.\n const isChildFinalized = event.hint === \"final\" && event.parentSagaId;\n\n let emit: Emit;\n if (isChildFinalized) {\n const parentAncestorChain = (event.ancestorChain ?? []).slice(1);\n const grandparent = parentAncestorChain[0];\n emit = this.publisher.forSaga(\n event.parentSagaId!,\n {\n parentSagaId: grandparent,\n rootSagaId: event.rootSagaId,\n ancestorChain: parentAncestorChain,\n },\n event.eventId,\n event.key,\n );\n } else {\n 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\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 { EventHint } from \"../interfaces/emit.type\";\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 hint: (headers[\"saga-event-hint\"] as EventHint) || 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":";;;;;;;;AAuCO,SAAS,kBACd,WAC8C;AAC9C,SAAO,OAAQ,UAAkB,gBAAgB;AACnD;;;AC3CO,IAAM,YAAN,cAAwB,MAAM;AAAA,EAC5B,cAAc;AAAA,EAErB,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACLO,IAAM,qBAAN,cAAiC,UAAU;AAAA,EAChD,YACE,SACS,aAAa,GACtB;AACA,UAAM,OAAO;AAFJ;AAGT,SAAK,OAAO;AAAA,EACd;AACF;;;ACJO,IAAM,oBAAN,MAA8C;AAAA,EACnD,KAAK,YAAoB,MAAuB;AAC9C,YAAQ,IAAI,SAAS,GAAG,IAAI;AAAA,EAC9B;AAAA,EAEA,KAAK,YAAoB,MAAuB;AAC9C,YAAQ,KAAK,SAAS,GAAG,IAAI;AAAA,EAC/B;AAAA,EAEA,MAAM,YAAoB,MAAuB;AAC/C,YAAQ,MAAM,SAAS,GAAG,IAAI;AAAA,EAChC;AACF;;;AClBA,SAAS,yBAAyB;;;ACE3B,IAAM,2BAAN,cAAuC,UAAU;AAAA,EACtD,cAAc;AACZ;AAAA,MACE;AAAA,IACF;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ADKO,IAAM,cAAN,MAAM,aAAY;AAAA,EACvB,OAAe,UAAU,IAAI,kBAAmC;AAAA,EAEhE,OAAO,IAAO,MAAuB,IAAgB;AACnD,WAAO,aAAY,QAAQ,IAAI,MAAM,EAAE;AAAA,EACzC;AAAA,EAEA,OAAO,UAAuC;AAC5C,WAAO,aAAY,QAAQ,SAAS;AAAA,EACtC;AAAA,EAEA,OAAO,UAA2B;AAChC,UAAM,MAAM,aAAY,QAAQ;AAChC,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,yBAAyB;AAAA,IACrC;AACA,WAAO;AAAA,EACT;AACF;;;AEXA,SAAS,MAAM,cAAc;AAEtB,IAAM,aAAN,MAAiB;AAAA,EAGtB,YACU,UACA,WACA,WACA,QACA,SACA,SACA,SAAqB,IAAI,kBAAkB,GACnD;AAPQ;AACA;AACA;AACA;AACA;AACA;AACA;AAAA,EACP;AAAA,EAVK;AAAA,EAYR,MAAM,QAAuB;AAC3B,UAAM,eAAe,KAAK,SAAS,cAAc;AACjD,UAAM,SAAS,KAAK,QAAQ,eAAe;AAE3C,SAAK,WAAW,oBAAI,IAAI;AACxB,eAAW,CAAC,OAAO,KAAK,KAAK,cAAc;AACzC,WAAK,SAAS,IAAI,GAAG,MAAM,GAAG,KAAK,IAAI,KAAK;AAAA,IAC9C;AAEA,UAAM,SAAS,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAE9C,UAAM,KAAK,UAAU,QAAQ;AAE7B,QAAI,OAAO,SAAS,GAAG;AACrB,WAAK,OAAO;AAAA,QACV,+BAA+B,OAAO,MAAM,eAAe,OAAO,KAAK,IAAI,CAAC;AAAA,MAC9E;AACA,YAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA,CAAC,YAAY,KAAK,cAAc,OAAO;AAAA,QACvC;AAAA,UACE,eAAe,KAAK,QAAQ;AAAA,UAC5B,SAAS,KAAK,QAAQ;AAAA,QACxB;AAAA,MACF;AACA,WAAK,OAAO,KAAK,+BAA+B;AAAA,IAClD,OAAO;AACL,WAAK,OAAO;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OAAsB;AAC1B,UAAM,KAAK,UAAU,WAAW;AAAA,EAClC;AAAA,EAEA,MAAM,cAA8C;AAClD,QAAI,kBAAkB,KAAK,SAAS,GAAG;AACrC,aAAO,KAAK,UAAU,YAAY;AAAA,IACpC;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,EAAE,QAAQ,2CAA2C;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,SAAwC;AAClE,UAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK;AAC7C,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAGA,UAAM,QAAQ,KAAK,OAAO,MAA+B,OAAO;AAEhE,QAAI,SAAS,MAAM,aAAa;AAC9B,YAAM,KAAK,kBAAkB,SAAS,OAAO,KAAK;AAClD;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,MAAM,cAAc;AAChC,YAAM,KAAK,mBAAmB,SAAS,KAAK;AAC5C;AAAA,IACF;AAAA,EAGF;AAAA,EAEA,MAAc,kBACZ,SACA,OACA,OACe;AACf,UAAM,iBAAiB,MAAM,aAAa,UAAU;AAEpD,UAAM,WAA0B;AAAA,MAC9B,QAAQ,MAAM;AAAA,MACd,SAAS,MAAM;AAAA,MACf,aAAa,MAAM;AAAA,MACnB,OAAO,MAAM;AAAA,MACb,UAAU,MAAM;AAAA,MAChB,iBAAiB,MAAM;AAAA,MACvB,YAAY,MAAM;AAAA,MAClB,cAAc,MAAM;AAAA,MACpB,YAAY,MAAM;AAAA,MAClB,eAAe,MAAM;AAAA,MACrB,SAAS,MAAM;AAAA,MACf,MAAM,MAAM;AAAA,MACZ,KAAK,MAAM;AAAA,MACX,UAAU,MAAM;AAAA,MAChB,iBAAiB,MAAM;AAAA,IACzB;AAIA,UAAM,mBAAmB,MAAM,SAAS,WAAW,MAAM;AAEzD,QAAI;AACJ,QAAI,kBAAkB;AACpB,YAAM,uBAAuB,MAAM,iBAAiB,CAAC,GAAG,MAAM,CAAC;AAC/D,YAAM,cAAc,oBAAoB,CAAC;AACzC,aAAO,KAAK,UAAU;AAAA,QACpB,MAAM;AAAA,QACN;AAAA,UACE,cAAc;AAAA,UACd,YAAY,MAAM;AAAA,UAClB,eAAe;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF,OAAO;AACL,aAAO,KAAK,UAAU;AAAA,QACpB,MAAM;AAAA,QACN;AAAA,UACE,cAAc,MAAM;AAAA,UACpB,YAAY,MAAM;AAAA,UAClB,eAAe,MAAM;AAAA,QACvB;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAGA,UAAM,cAAoB,OAAO,WAAW;AAC1C,YAAM,cAAc,iBAChB,EAAE,GAAG,QAAQ,MAAM,QAAiB,IACpC;AACJ,aAAO,KAAK,WAAW;AAAA,IACzB;AAGA,UAAM,aAAa,MAAM,aAAa;AACtC,UAAM,YAAkB,aACpB,OAAO,WAAW;AAChB,YAAM,YAAY,OAAO;AAEzB,YAAM,mBAAmB;AAAA,QACvB,MAAM;AAAA,QACN,GAAI,MAAM,iBAAiB,CAAC;AAAA,MAC9B;AAEA,YAAM,UAAU,KAAK,UAAU;AAAA,QAC7B;AAAA,QACA;AAAA,UACE,cAAc,MAAM;AAAA,UACpB,YAAY,MAAM;AAAA,UAClB,eAAe;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAEA,YAAM,WAAW,OAAO,eAAe,WAAW,aAAa,CAAC;AAChE,YAAM,UAAU;AAAA,QACd,QAAQ;AAAA,QACR,YAAY,MAAM;AAAA,QAClB,cAAc,MAAM;AAAA,QACpB,eAAe;AAAA,QACf,aAAa,MAAM;AAAA,QACnB,KAAK,MAAM;AAAA,QACX,UAAU,SAAS;AAAA,QACnB,iBAAiB,SAAS;AAAA,MAC5B;AACA,YAAM,YAAY;AAAA,QAAI;AAAA,QAAS,MAC7B,QAAQ,EAAE,GAAG,QAAQ,MAAM,OAAO,CAAC;AAAA,MACrC;AAAA,IACF,IACA;AAEJ,UAAM,YAAoC;AAAA,MACxC,WAAW,MAAM;AAAA,MACjB,cAAc,MAAM;AAAA,MACpB,kBAAkB,MAAM;AAAA,MACxB,iBAAiB,MAAM;AAAA,MACvB,gBAAgB,MAAM;AAAA,MACtB,wBAAwB,MAAM,gBAAiB;AAAA,IACjD;AACA,QAAI,MAAM,SAAU,WAAU,WAAW,IAAI,MAAM;AACnD,QAAI,MAAM;AACR,gBAAU,kBAAkB,IAAI,MAAM;AACxC,QAAI,MAAM;AACR,gBAAU,uBAAuB,IAAI,MAAM;AAC7C,QAAI,MAAM,aAAc,WAAU,gBAAgB,IAAI,MAAM;AAE5D,UAAM,cAAc;AAAA,MAClB,QAAQ,MAAM;AAAA,MACd,YAAY,MAAM;AAAA,MAClB,cAAc,MAAM;AAAA,MACpB,eAAe,MAAM;AAAA,MACrB,aAAa,MAAM;AAAA,MACnB,KAAK,MAAM;AAAA,MACX,UAAU,MAAM;AAAA,MAChB,iBAAiB,MAAM;AAAA,IACzB;AAEA,UAAM,aAAa,MACjB,YAAY;AAAA,MAAI;AAAA,MAAa,MAC3B,KAAK;AAAA,QACH,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEF,QAAI,KAAK,SAAS;AAChB,YAAM,KAAK,QAAQ;AAAA,QACjB,eAAe,MAAM,KAAK;AAAA,QAC1B;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAc,mBACZ,SACA,OACe;AACf,QAAI;AACJ,QAAI;AACF,gBAAU,KAAK,MAAM,QAAQ,KAAK;AAAA,IACpC,QAAQ;AACN,gBAAU,QAAQ;AAAA,IACpB;AAEA,UAAM,eAA6B;AAAA,MACjC,OAAO,QAAQ;AAAA,MACf,KAAK,QAAQ;AAAA,MACb;AAAA,MACA,SAAS,QAAQ;AAAA,IACnB;AAEA,UAAM,MAAM,aAAc,YAAY;AAAA,EACxC;AAAA,EAEA,MAAc,aACZ,SACA,aACA,OACA,MACe;AACf,QAAI;AACF,YAAM,KAAK,iBAAiB,SAAS,OAAO,IAAI;AAAA,IAClD,SAAS,OAAO;AACd,UAAI,iBAAiB,oBAAoB;AAEvC,cAAM,KAAK,qBAAqB,aAAa,OAAO,OAAO,IAAI;AAC/D;AAAA,MACF;AAGA,UAAI,YAAY,QAAQ;AACtB,YAAI;AACF,gBAAM,KAAK;AAAA,YACT,CAAC,IAAI,OAAO,YAAY,OAAQ,IAAI,OAAgB,EAAE;AAAA,YACtD;AAAA,YACA;AAAA,UACF;AAAA,QACF,SAAS,WAAW;AAClB,cAAI,qBAAqB,oBAAoB;AAC3C,kBAAM,KAAK;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF,OAAO;AACL,iBAAK,OAAO;AAAA,cACV,qDAAqD,MAAM,KAAK;AAAA,cAChE;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAEA,WAAK,OAAO;AAAA,QACV,mDAAmD,MAAM,KAAK;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,IACA,OACA,MACe;AACf,UAAM,aAAa,KAAK,QAAQ,aAAa,cAAc;AAC3D,UAAM,iBAAiB,KAAK,QAAQ,aAAa,kBAAkB;AAEnE,aAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,UAAI;AACF,cAAM,GAAG,OAAO,IAAI;AACpB;AAAA,MACF,SAAS,OAAO;AACd,YAAI,iBAAiB,oBAAoB;AACvC,cAAI,UAAU,YAAY;AACxB,kBAAM,QAAQ,iBAAiB,KAAK,IAAI,GAAG,OAAO;AAClD,kBAAM,KAAK,MAAM,KAAK;AACtB;AAAA,UACF;AAEA,gBAAM;AAAA,QACR;AAEA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,qBACZ,aACA,OACA,OACA,MACe;AACf,QAAI,YAAY,kBAAkB;AAChC,YAAM,YAAY,iBAAiB,OAAO,OAAO,IAAI;AAAA,IACvD;AAAA,EACF;AAAA,EAEQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AACF;;;AC/WA,SAAS,MAAMA,eAAc;;;ACEtB,IAAM,oBAAN,cAAgC,UAAU;AAAA,EAC/C,cAAc;AACZ,UAAM,0CAA0C;AAChD,SAAK,OAAO;AAAA,EACd;AACF;;;ACJO,SAAS,qBACd,OACA,cAAc,IACG;AACjB,QAAM,QAAQ,GAAG,WAAW,GAAG,MAAM,KAAK;AAC1C,QAAM,MAAM,MAAM,OAAO,MAAM;AAE/B,QAAM,UAAkC;AAAA,IACtC,WAAW,MAAM;AAAA,IACjB,qBAAqB,MAAM;AAAA,IAC3B,iBAAiB,MAAM;AAAA,IACvB,kBAAkB,MAAM;AAAA,IACxB,qBAAqB,MAAM;AAAA,IAC3B,uBAAuB,OAAO,MAAM,aAAa;AAAA,IACjD,gBAAgB,MAAM;AAAA,EACxB;AAEA,MAAI,MAAM,cAAc;AACtB,YAAQ,gBAAgB,IAAI,MAAM;AAAA,EACpC;AAEA,MAAI,MAAM,MAAM;AACd,YAAQ,iBAAiB,IAAI,MAAM;AAAA,EACrC;AAEA,MAAI,MAAM,UAAU;AAClB,YAAQ,WAAW,IAAI,MAAM;AAAA,EAC/B;AAEA,MAAI,MAAM,iBAAiB;AACzB,YAAQ,kBAAkB,IAAI,MAAM;AAAA,EACtC;AAEA,MAAI,MAAM,iBAAiB;AACzB,YAAQ,uBAAuB,IAAI,MAAM;AAAA,EAC3C;AAEA,MAAI,MAAM,KAAK;AACb,YAAQ,UAAU,IAAI,MAAM;AAAA,EAC9B;AAEA,MAAI,MAAM,iBAAiB,MAAM,cAAc,SAAS,GAAG;AACzD,YAAQ,qBAAqB,IAAI,MAAM,cAAc,KAAK,GAAG;AAAA,EAC/D;AAEA,UAAQ,kBAAkB,IAAI,MAAM;AAEpC,QAAM,QAAQ,KAAK,UAAU,MAAM,OAAO;AAE1C,SAAO,EAAE,OAAO,KAAK,OAAO,QAAQ;AACtC;;;AFpCO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YACU,WACA,SACA,cAAc,IACtB;AAHQ;AACA;AACA;AAAA,EACP;AAAA,EAEH,MAAM,MACJ,IACA,MACiD;AACjD,UAAM,kBAAkB,YAAY,QAAQ;AAC5C,QAAI,mBAAmB,CAAC,MAAM,aAAa;AACzC,aAAO,KAAK,WAAW,IAAI,IAAI;AAAA,IACjC;AAEA,UAAM,SAASC,QAAO;AACtB,UAAM,UAAU;AAAA,MACd;AAAA,MACA,YAAY;AAAA,MACZ,eAAe,CAAC;AAAA,MAChB,aAAa;AAAA,MACb,KAAK,MAAM;AAAA,MACX,UAAU,MAAM;AAAA,MAChB,iBAAiB,MAAM;AAAA,IACzB;AACA,UAAM,SAAS,MAAM,YAAY,IAAI,SAAS,EAAE;AAChD,WAAO,EAAE,QAAQ,OAA6B;AAAA,EAChD;AAAA,EAEA,MAAM,KAAuB,QAAsC;AACjE,UAAM,MAAM,YAAY,QAAQ;AAChC,UAAM,YAAY,KAAK;AAAA,MACrB,IAAI;AAAA,MACJ;AAAA,QACE,cAAc,IAAI;AAAA,QAClB,YAAY,IAAI;AAAA,QAChB,eAAe,IAAI;AAAA,MACrB;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AACA,WAAO,UAAU,MAAM;AAAA,EACzB;AAAA,EAEA,MAAM,WACJ,IACA,MACiD;AACjD,UAAM,MAAM,YAAY,QAAQ;AAChC,UAAM,SAASA,QAAO;AACtB,UAAM,WAAW;AAAA,MACf;AAAA,MACA,YAAY,IAAI;AAAA,MAChB,cAAc,IAAI;AAAA,MAClB,eAAe,CAAC,IAAI,QAAQ,GAAI,IAAI,iBAAiB,CAAC,CAAE;AAAA,MACxD,aAAa,IAAI;AAAA,MACjB,KAAK,MAAM,OAAO,IAAI;AAAA,MACtB,UAAU,MAAM,YAAY,IAAI;AAAA,MAChC,iBAAiB,MAAM,mBAAmB,IAAI;AAAA,IAChD;AACA,UAAM,SAAS,MAAM,YAAY,IAAI,UAAU,EAAE;AACjD,WAAO,EAAE,QAAQ,OAA6B;AAAA,EAChD;AAAA,EAEA,MAAM,aACJ,YACe;AACf,UAAM,MAAM,YAAY,QAAQ;AAChC,QAAI,CAAC,IAAI,cAAc;AACrB,YAAM,IAAI,kBAAkB;AAAA,IAC9B;AAEA,UAAM,uBAAuB,IAAI,iBAAiB,CAAC,GAAG,MAAM,CAAC;AAC7D,UAAM,cAAc,oBAAoB,CAAC;AAEzC,QAAI,OAAO,eAAe,YAAY;AACpC,YAAM,YAAY;AAAA,QAChB,QAAQ,IAAI;AAAA,QACZ,YAAY,IAAI;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,aAAa,IAAI;AAAA,QACjB,KAAK,IAAI;AAAA,MACX;AACA,YAAM,YAAY,IAAI,WAAW,UAAU;AAC3C;AAAA,IACF;AAEA,UAAM,aAAa,KAAK;AAAA,MACtB,IAAI;AAAA,MACJ;AAAA,QACE,cAAc;AAAA,QACd,YAAY,IAAI;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AACA,WAAO,WAAW,UAAU;AAAA,EAC9B;AAAA,EAEA,QACE,QACA,WACA,aACA,SACM;AACN,UAAM,aAAa,WAAW,cAAc;AAC5C,UAAM,eAAe,WAAW;AAChC,UAAM,gBAAgB,WAAW;AACjC,UAAM,kBAAkB,eAAe;AACvC,WAAO,OAAyB;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAAoC;AAClC,YAAM,MAAM,YAAY,QAAQ;AAChC,YAAM,cAAc,OAAO,WAAW,KAAK;AAC3C,YAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,YAAM,QAAsB;AAAA,QAC1B;AAAA,QACA,aAAa;AAAA,QACb,SAASA,QAAO;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,UAAU,KAAK;AAAA,QACf,iBAAiB,KAAK;AAAA,MACxB;AAEA,YAAM,KAAK,QAAQ,KAAK;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAM,QAAW,OAAoC;AACnD,SAAK,QAAQ;AAAA,MACX,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,UAAM,QAAgC;AAAA,MACpC,WAAW,MAAM;AAAA,MACjB,cAAc,MAAM;AAAA,MACpB,kBAAkB,MAAM;AAAA,MACxB,gBAAgB,MAAM;AAAA,IACxB;AACA,QAAI,MAAM,UAAU;AAClB,YAAM,WAAW,IAAI,MAAM;AAAA,IAC7B;AACA,QAAI,MAAM,iBAAiB;AACzB,YAAM,kBAAkB,IAAI,MAAM;AAAA,IACpC;AACA,QAAI,MAAM,iBAAiB;AACzB,YAAM,uBAAuB,IAAI,MAAM;AAAA,IACzC;AACA,QAAI,MAAM,cAAc;AACtB,YAAM,gBAAgB,IAAI,MAAM;AAAA,IAClC;AAEA,SAAK,QAAQ,WAAW,KAAK;AAE7B,UAAM,UAAU,qBAAqB,OAAO,KAAK,WAAW;AAE5D,SAAK,QAAQ,mBAAmB,QAAQ,OAAO;AAE/C,UAAM,KAAK,QAAQ;AAAA,MAAS,gBAAgB,MAAM,KAAK;AAAA,MAAI;AAAA,MAAO,MAChE,KAAK,UAAU,QAAQ,OAAO;AAAA,IAChC;AAAA,EACF;AACF;;;AGxMA,SAAS,MAAMC,eAAc;AAMtB,IAAM,aAAN,MAAiB;AAAA,EACtB,YAAoB,SAAsB;AAAtB;AAAA,EAAuB;AAAA,EAE3C,MAAS,SAA8C;AACrD,QAAI;AACF,UAAI,QAAQ,QAAQ,SAAS,GAAG;AAC9B,eAAO,KAAK,iBAAoB,OAAO;AAAA,MACzC;AAEA,YAAM,gBAAgB,KAAK,iBAAoB,OAAO;AACtD,UAAI,cAAe,QAAO;AAE1B,YAAM,OAAO,KAAK,MAAM,QAAQ,KAAK;AACrC,UAAI,QAAQ,KAAK,QAAQ;AACvB,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,iBAAoB,SAA8C;AACxE,UAAM,UAAU,QAAQ;AACxB,UAAM,UAAU,KAAK,MAAM,QAAQ,KAAK;AAExC,UAAM,SAAS,QAAQ,SAAS;AAChC,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAEA,UAAM,mBAAmB,QAAQ,qBAAqB;AACtD,UAAM,gBAAgB,mBAClB,iBAAiB,MAAM,GAAG,EAAE,OAAO,OAAO,IAC1C;AAEJ,WAAO;AAAA,MACL;AAAA,MACA,aAAa,QAAQ,mBAAmB,KAAK;AAAA,MAC7C,SAAS,QAAQ,eAAe,KAAKA,QAAO;AAAA,MAC5C,OAAO,QAAQ;AAAA,MACf,UAAU,QAAQ,gBAAgB,KAAK;AAAA,MACvC,YAAY,QAAQ,kBAAkB,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClE,aAAa,QAAQ,mBAAmB,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpE,eAAe;AAAA,MACf,YAAY,QAAQ,cAAc,KAAK;AAAA,MACvC,cAAc,QAAQ,gBAAgB,KAAK;AAAA,MAC3C;AAAA,MACA;AAAA,MACA,UAAU,QAAQ,WAAW,KAAK;AAAA,MAClC,iBAAiB,QAAQ,kBAAkB,KAAK;AAAA,MAChD,iBAAiB,QAAQ,uBAAuB,KAAK;AAAA,MACrD,KAAK,QAAQ,UAAU,KAAK;AAAA,MAC5B,MAAO,QAAQ,iBAAiB,KAAmB;AAAA,IACrD;AAAA,EACF;AAAA,EAEQ,iBAAoB,SAA8C;AACxE,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,UAAM,gBAAgB,QAAQ,QAAQ,SAAS;AAC/C,QAAI,eAAe;AACjB,YAAM,UAAU,KAAK,mBAAmB,aAAa;AACrD,eAAS,QAAQ,SAAS;AAC1B,mBAAa,QAAQ,cAAc;AACnC,qBAAe,QAAQ,gBAAgB;AAAA,IACzC;AAGA,QAAI,CAAC,QAAQ;AACX,YAAM,YAAY,KAAK,QAAQ,eAAe;AAC9C,eAAS,UAAU;AACnB,mBAAa,UAAU;AACvB,qBAAe,UAAU;AAAA,IAC3B;AAEA,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,OAAO,KAAK,MAAM,QAAQ,KAAK;AAErC,WAAO;AAAA,MACL;AAAA,MACA,aAAa;AAAA,MACb,SAASA,QAAO;AAAA,MAChB,OAAO,KAAK;AAAA,MACZ,UAAU;AAAA,MACV,YAAY,KAAK,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,MACtD,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,eAAe;AAAA,MACf,YAAY,cAAc;AAAA,MAC1B,cAAc,gBAAgB;AAAA,MAC9B,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,mBAAmB,SAAyC;AAClE,UAAM,SAAiC,CAAC;AACxC,eAAW,SAAS,QAAQ,MAAM,GAAG,GAAG;AACtC,YAAM,CAAC,KAAK,KAAK,IAAI,MAAM,KAAK,EAAE,MAAM,GAAG;AAC3C,UAAI,OAAO,OAAO;AAChB,eAAO,IAAI,KAAK,CAAC,IAAI,mBAAmB,MAAM,KAAK,CAAC;AAAA,MACtD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;AChHO,IAAM,4BAAN,cAAwC,UAAU;AAAA,EACvD,YACE,OACA,mBACA,cACA;AACA;AAAA,MACE,qCAAqC,KAAK,qBACtB,iBAAiB,UAAU,YAAY;AAAA,IAC7D;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ACZO,IAAM,gCAAN,cAA4C,UAAU;AAAA,EAC3D,YAAY,OAAe,WAAmB,QAAgB;AAC5D;AAAA,MACE,+BAA+B,KAAK,SAAS,SAAS,MAAM,MAAM;AAAA,IACpE;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ACSO,IAAM,eAAN,MAAmB;AAAA,EAChB,eAAkC,CAAC;AAAA,EAE3C,SAAS,aAAoC;AAC3C,SAAK,aAAa,KAAK,WAAW;AAAA,EACpC;AAAA,EAEA,SAA4B;AAC1B,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA,EAEA,gBAAyC;AACvC,UAAM,MAAM,oBAAI,IAAwB;AAExC,eAAW,eAAe,KAAK,cAAc;AAE3C,iBAAW,CAAC,OAAO,OAAO,KAAK,OAAO,QAAQ,YAAY,EAAE,GAAG;AAC7D,cAAM,WAAW,IAAI,IAAI,KAAK,KAAK,CAAC;AAEpC,YAAI,SAAS,aAAa;AACxB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,SAAS,gBAAiB;AAAA,YAC1B,YAAY;AAAA,UACd;AAAA,QACF;AAEA,cAAM,UAAU,YAAY,iBAAiB,KAAK;AAClD,YAAI,SAAS,SAAS,SAAS,MAAM;AACnC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAEA,YAAI,IAAI,OAAO;AAAA,UACb,GAAG;AAAA,UACH,iBAAiB;AAAA,UACjB,aAAa;AAAA,UACb,aAAa;AAAA,QACf,CAAC;AAAA,MACH;AAGA,UAAI,YAAY,SAAS;AACvB,mBAAW,CAAC,OAAO,OAAO,KAAK,OAAO,QAAQ,YAAY,OAAO,GAAG;AAClE,gBAAM,WAAW,IAAI,IAAI,KAAK,KAAK,CAAC;AAEpC,cAAI,SAAS,cAAc;AACzB,kBAAM,IAAI;AAAA,cACR;AAAA,cACA,SAAS,iBAAkB;AAAA,cAC3B,YAAY;AAAA,YACd;AAAA,UACF;AAEA,cAAI,IAAI,OAAO;AAAA,YACb,GAAG;AAAA,YACH,kBAAkB;AAAA,YAClB,cAAc;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;ACpFO,IAAM,iBAAN,cAA6B,UAAU;AAAA,EAC5C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACLO,IAAM,iCAAN,cAA6C,UAAU;AAAA,EAC5D,cAAc;AACZ,UAAM,yBAAyB;AAC/B,SAAK,OAAO;AAAA,EACd;AACF;;;ACmBO,IAAM,kBAAN,MAA6C;AAAA,EAClD,gBAAsB;AAAA,EAAC;AAAA,EACvB,iBAIE;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EACA,aAAmB;AAAA,EAAC;AAAA,EACpB,MAAM,SACJ,OACA,QACA,IACY;AACZ,WAAO,GAAG;AAAA,EACZ;AAAA,EACA,qBAA2B;AAAA,EAAC;AAAA,EAC5B,MAAM,kBACJ,OACA,QACA,UACA,IACY;AACZ,WAAO,GAAG;AAAA,EACZ;AACF;AAIO,IAAM,iBAAN,MAA4C;AAAA,EACzC;AAAA,EAER,YAAY,KAAc;AACxB,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,cACE,QACA,YACA,cACM;AACN,UAAM,UAA6C;AAAA,MACjD,WAAW,EAAE,OAAO,OAAO;AAAA,MAC3B,gBAAgB,EAAE,OAAO,WAAW;AAAA,IACtC;AACA,QAAI,cAAc;AAChB,cAAQ,gBAAgB,IAAI,EAAE,OAAO,aAAa;AAAA,IACpD;AAEA,UAAM,UAAU,KAAK,IAAI,YAAY,cAAc,OAAO;AAC1D,UAAM,MAAM,KAAK,IAAI,YAAY;AAAA,MAC/B,KAAK,IAAI,QAAQ,OAAO;AAAA,MACxB;AAAA,IACF;AACA,SAAK,IAAI,QAAQ,KAAK,KAAK,MAAM;AAAA,IAAC,CAAC;AAAA,EACrC;AAAA,EAEA,iBAIE;AACA,UAAM,UAAU,KAAK,IAAI,YAAY,WAAW,KAAK,IAAI,QAAQ,OAAO,CAAC;AACzE,QAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,WAAO;AAAA,MACL,QAAQ,QAAQ,SAAS,SAAS,GAAG;AAAA,MACrC,YAAY,QAAQ,SAAS,cAAc,GAAG;AAAA,MAC9C,cAAc,QAAQ,SAAS,gBAAgB,GAAG;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,WAAW,OAAqC;AAC9C,UAAM,OAAO,KAAK,IAAI,MAAM,cAAc;AAC1C,QAAI,MAAM;AACR,WAAK,cAAc,KAAK;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,MACA,OACA,IACY;AACZ,UAAM,SAAS,KAAK,IAAI,MAAM,UAAU,iBAAiB;AACzD,WAAO,OAAO,gBAAgB,MAAM,OAAO,SAAS;AAClD,WAAK,cAAc,KAAK;AACxB,UAAI;AACF,cAAM,SAAS,MAAM,GAAG;AACxB,aAAK,UAAU,EAAE,MAAM,KAAK,IAAI,eAAe,GAAG,CAAC;AACnD,eAAO;AAAA,MACT,SAAS,OAAO;AACd,aAAK,UAAU;AAAA,UACb,MAAM,KAAK,IAAI,eAAe;AAAA,UAC9B,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAChE,CAAC;AACD,aAAK;AAAA,UACH,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,QAC1D;AACA,cAAM;AAAA,MACR,UAAE;AACA,aAAK,IAAI;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,mBAAmB,SAAuC;AACxD,SAAK,IAAI,YAAY,OAAO,KAAK,IAAI,QAAQ,OAAO,GAAG,OAAO;AAAA,EAChE;AAAA,EAEA,MAAM,kBACJ,MACA,OACA,SACA,IACY;AACZ,UAAM,YAAY,KAAK,IAAI,YAAY;AAAA,MACrC,KAAK,IAAI;AAAA,MACT;AAAA,IACF;AACA,UAAM,SAAS,KAAK,IAAI,MAAM,UAAU,iBAAiB;AAEzD,WAAO,KAAK,IAAI,QAAQ;AAAA,MAAK;AAAA,MAAW,MACtC,OAAO;AAAA,QACL;AAAA,QACA,EAAE,MAAM,KAAK,IAAI,SAAS,SAAS;AAAA,QACnC,OAAO,SAAS;AACd,eAAK,cAAc,KAAK;AACxB,cAAI;AACF,kBAAM,SAAS,MAAM,GAAG;AACxB,iBAAK,UAAU,EAAE,MAAM,KAAK,IAAI,eAAe,GAAG,CAAC;AACnD,mBAAO;AAAA,UACT,SAAS,OAAO;AACd,iBAAK,UAAU;AAAA,cACb,MAAM,KAAK,IAAI,eAAe;AAAA,cAC9B,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAChE,CAAC;AACD,iBAAK;AAAA,cACH,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,YAC1D;AACA,kBAAM;AAAA,UACR,UAAE;AACA,iBAAK,IAAI;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,kBAAkB,SAA+B;AAC/D,MAAI,CAAC,QAAS,QAAO,IAAI,gBAAgB;AAEzC,MAAI;AAEF,UAAM,MAAM,UAAQ,oBAAoB;AACxC,WAAO,IAAI,eAAe,GAAG;AAAA,EAC/B,QAAQ;AACN,WAAO,IAAI,gBAAgB;AAAA,EAC7B;AACF;","names":["uuidv7","uuidv7","uuidv7"]}
|