@fbsm/saga-core 0.1.0-beta.2 → 0.1.0-beta.3
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 +25 -0
- package/dist/index.cjs +18 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,6 +99,10 @@ const runner = new SagaRunner(
|
|
|
99
99
|
|
|
100
100
|
await runner.start(); // Subscribe and begin consuming
|
|
101
101
|
await runner.stop(); // Disconnect
|
|
102
|
+
|
|
103
|
+
// Health check (delegates to transport if it implements HealthCheckable)
|
|
104
|
+
const health = await runner.healthCheck();
|
|
105
|
+
// { status: 'up' | 'down', details?: { consumerGroupState, groupId, memberCount } }
|
|
102
106
|
```
|
|
103
107
|
|
|
104
108
|
**`RunnerOptions`**:
|
|
@@ -209,6 +213,27 @@ interface SagaTransport {
|
|
|
209
213
|
}
|
|
210
214
|
```
|
|
211
215
|
|
|
216
|
+
## Health Checks
|
|
217
|
+
|
|
218
|
+
Transports can optionally implement the `HealthCheckable` interface to support health checks.
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { isHealthCheckable } from "@fbsm/saga-core";
|
|
222
|
+
import type { HealthCheckable, TransportHealthResult } from "@fbsm/saga-core";
|
|
223
|
+
|
|
224
|
+
// Check if a transport supports health checks
|
|
225
|
+
if (isHealthCheckable(transport)) {
|
|
226
|
+
const result: TransportHealthResult = await transport.healthCheck();
|
|
227
|
+
// result.status: 'up' | 'down'
|
|
228
|
+
// result.details: transport-specific details
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Or use SagaRunner.healthCheck() which delegates automatically
|
|
232
|
+
const health = await runner.healthCheck();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
`KafkaTransport` from `@fbsm/saga-transport-kafka` implements `HealthCheckable` using `consumer.describeGroup()`. Healthy states: `Stable`, `CompletingRebalance`, `PreparingRebalance`.
|
|
236
|
+
|
|
212
237
|
## SagaLogger
|
|
213
238
|
|
|
214
239
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -36,10 +36,16 @@ __export(index_exports, {
|
|
|
36
36
|
SagaRunner: () => SagaRunner,
|
|
37
37
|
SagaTransportNotConnectedError: () => SagaTransportNotConnectedError,
|
|
38
38
|
W3cOtelContext: () => W3cOtelContext,
|
|
39
|
-
createOtelContext: () => createOtelContext
|
|
39
|
+
createOtelContext: () => createOtelContext,
|
|
40
|
+
isHealthCheckable: () => isHealthCheckable
|
|
40
41
|
});
|
|
41
42
|
module.exports = __toCommonJS(index_exports);
|
|
42
43
|
|
|
44
|
+
// src/transport/transport.interface.ts
|
|
45
|
+
function isHealthCheckable(transport) {
|
|
46
|
+
return typeof transport.healthCheck === "function";
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
// src/errors/saga.error.ts
|
|
44
50
|
var SagaError = class extends Error {
|
|
45
51
|
isSagaError = true;
|
|
@@ -144,6 +150,15 @@ var SagaRunner = class {
|
|
|
144
150
|
async stop() {
|
|
145
151
|
await this.transport.disconnect();
|
|
146
152
|
}
|
|
153
|
+
async healthCheck() {
|
|
154
|
+
if (isHealthCheckable(this.transport)) {
|
|
155
|
+
return this.transport.healthCheck();
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
status: "up",
|
|
159
|
+
details: { reason: "Transport does not support health checks" }
|
|
160
|
+
};
|
|
161
|
+
}
|
|
147
162
|
async handleMessage(message) {
|
|
148
163
|
const event = this.parser.parse(message);
|
|
149
164
|
if (!event) return;
|
|
@@ -780,6 +795,7 @@ function createOtelContext(enabled) {
|
|
|
780
795
|
SagaRunner,
|
|
781
796
|
SagaTransportNotConnectedError,
|
|
782
797
|
W3cOtelContext,
|
|
783
|
-
createOtelContext
|
|
798
|
+
createOtelContext,
|
|
799
|
+
isHealthCheckable
|
|
784
800
|
});
|
|
785
801
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.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} from \"./transport/transport.interface\";\n\n// Domain interfaces\nexport type { SagaEvent } from \"./interfaces/saga-event.interface\";\nexport type { IncomingEvent } from \"./interfaces/incoming-event.interface\";\nexport type { Emit, EmitParams, EventHint } from \"./interfaces/emit.type\";\nexport type { EventHandler } from \"./interfaces/event-handler.type\";\nexport type {\n SagaParticipant,\n HandlerConfig,\n ForkConfig,\n} from \"./interfaces/saga-participant.interface\";\nexport type { ParentSagaContext } from \"./interfaces/parent-saga-context.interface\";\nexport type { RunnerOptions } from \"./interfaces/runner-options.interface\";\n","export class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n} from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n this.routeMap = this.registry.buildRouteMap();\n\n const prefix = this.options.topicPrefix ?? \"\";\n const topics = Array.from(this.routeMap.keys()).map(\n (et) => `${prefix}${et}`,\n );\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 private async handleMessage(message: InboundMessage): Promise<void> {\n const event = this.parser.parse<Record<string, unknown>>(message);\n if (!event) return;\n\n const route = this.routeMap.get(event.eventType);\n if (!route) return;\n\n const isFinalHandler = route.options?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n eventType: event.eventType,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.options?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.participant.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.handler,\n route.participant,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.eventType}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await handler(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n return;\n }\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.eventType}:`,\n error,\n );\n return;\n }\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n eventType,\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 eventType,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\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.eventType}`, 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.eventType}`;\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 const value = JSON.stringify({\n eventType: event.eventType,\n occurredAt: event.occurredAt,\n payload: event.payload,\n });\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 body = JSON.parse(message.value);\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n eventType: body.eventType,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload: body.payload as T,\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 eventType: body.eventType,\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 eventType: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${eventType}\": ` +\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(eventType: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${eventType}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n participant: SagaParticipant;\n handler: EventHandler;\n options?: HandlerConfig;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n for (const [eventType, handler] of Object.entries(participant.on)) {\n if (map.has(eventType)) {\n const existing = map.get(eventType)!;\n throw new SagaDuplicateHandlerError(\n eventType,\n existing.participant.serviceId,\n participant.serviceId,\n );\n }\n const options = participant.handlerOptions?.[eventType];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n eventType,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n map.set(eventType, { participant, handler, options });\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":"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","names":["uuidv7","import_uuid","uuidv7","import_uuid","uuidv7"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/transport/transport.interface.ts","../src/errors/saga.error.ts","../src/errors/saga-retryable.error.ts","../src/logger/saga-logger.ts","../src/context/saga-context.ts","../src/errors/saga-context-not-found.error.ts","../src/runner/saga-runner.ts","../src/publisher/saga-publisher.ts","../src/errors/saga-no-parent.error.ts","../src/publisher/message-builder.ts","../src/parser/saga-parser.ts","../src/errors/saga-duplicate-handler.error.ts","../src/errors/saga-invalid-handler-config.error.ts","../src/registry/saga-registry.ts","../src/errors/saga-parse.error.ts","../src/errors/saga-transport-not-connected.error.ts","../src/otel/otel-context.ts"],"sourcesContent":["// Classes\nexport { SagaRunner } from \"./runner/saga-runner\";\nexport { SagaPublisher } from \"./publisher/saga-publisher\";\nexport type { SagaStartOptions } from \"./publisher/saga-publisher\";\nexport { SagaParser } from \"./parser/saga-parser\";\nexport { SagaRegistry } from \"./registry/saga-registry\";\nexport { SagaContext } from \"./context/saga-context\";\nexport type { SagaContextData } from \"./context/saga-context\";\n\n// Errors\nexport { SagaError } from \"./errors/saga.error\";\nexport { SagaRetryableError } from \"./errors/saga-retryable.error\";\nexport { SagaDuplicateHandlerError } from \"./errors/saga-duplicate-handler.error\";\nexport { SagaParseError } from \"./errors/saga-parse.error\";\nexport { SagaTransportNotConnectedError } from \"./errors/saga-transport-not-connected.error\";\nexport { SagaContextNotFoundError } from \"./errors/saga-context-not-found.error\";\nexport { SagaNoParentError } from \"./errors/saga-no-parent.error\";\nexport { SagaInvalidHandlerConfigError } from \"./errors/saga-invalid-handler-config.error\";\n\n// Logger\nexport type { SagaLogger } from \"./logger/saga-logger\";\nexport { ConsoleSagaLogger } from \"./logger/saga-logger\";\n\n// OTel\nexport type { OtelContext } from \"./otel/otel-context\";\nexport {\n NoopOtelContext,\n W3cOtelContext,\n createOtelContext,\n} from \"./otel/otel-context\";\n\n// Transport interfaces\nexport type {\n SagaTransport,\n OutboundMessage,\n InboundMessage,\n TransportSubscribeOptions,\n TransportHealthResult,\n HealthCheckable,\n} from \"./transport/transport.interface\";\nexport { isHealthCheckable } from \"./transport/transport.interface\";\n\n// Domain interfaces\nexport type { SagaEvent } from \"./interfaces/saga-event.interface\";\nexport type { IncomingEvent } from \"./interfaces/incoming-event.interface\";\nexport type { Emit, EmitParams, EventHint } from \"./interfaces/emit.type\";\nexport type { EventHandler } from \"./interfaces/event-handler.type\";\nexport type {\n SagaParticipant,\n HandlerConfig,\n ForkConfig,\n} from \"./interfaces/saga-participant.interface\";\nexport type { ParentSagaContext } from \"./interfaces/parent-saga-context.interface\";\nexport type { RunnerOptions } from \"./interfaces/runner-options.interface\";\n","export interface SagaTransport {\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n publish(message: OutboundMessage): Promise<void>;\n subscribe(\n topics: string[],\n handler: (message: InboundMessage) => Promise<void>,\n options?: TransportSubscribeOptions,\n ): Promise<void>;\n}\n\nexport interface OutboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface InboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface TransportSubscribeOptions {\n fromBeginning?: boolean;\n groupId?: string;\n}\n\nexport interface TransportHealthResult {\n status: \"up\" | \"down\";\n details?: Record<string, unknown>;\n}\n\nexport interface HealthCheckable {\n healthCheck(): Promise<TransportHealthResult>;\n}\n\nexport function isHealthCheckable(\n transport: SagaTransport,\n): transport is SagaTransport & HealthCheckable {\n return typeof (transport as any).healthCheck === \"function\";\n}\n","export class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n TransportHealthResult,\n} from \"../transport/transport.interface\";\nimport { isHealthCheckable } from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n this.routeMap = this.registry.buildRouteMap();\n\n const prefix = this.options.topicPrefix ?? \"\";\n const topics = Array.from(this.routeMap.keys()).map(\n (et) => `${prefix}${et}`,\n );\n\n await this.transport.connect();\n\n if (topics.length > 0) {\n this.logger.info(\n `[SagaRunner] Subscribing to ${topics.length} topic(s): [${topics.join(\", \")}]`,\n );\n await this.transport.subscribe(\n topics,\n (message) => this.handleMessage(message),\n {\n fromBeginning: this.options.fromBeginning,\n groupId: this.options.groupId,\n },\n );\n this.logger.info(\"[SagaRunner] Consumer running\");\n } else {\n this.logger.warn(\n \"[SagaRunner] No handlers registered — nothing to subscribe\",\n );\n }\n }\n\n async stop(): Promise<void> {\n await this.transport.disconnect();\n }\n\n async healthCheck(): Promise<TransportHealthResult> {\n if (isHealthCheckable(this.transport)) {\n return this.transport.healthCheck();\n }\n return {\n status: \"up\",\n details: { reason: \"Transport does not support health checks\" },\n };\n }\n\n private async handleMessage(message: InboundMessage): Promise<void> {\n const event = this.parser.parse<Record<string, unknown>>(message);\n if (!event) return;\n\n const route = this.routeMap.get(event.eventType);\n if (!route) return;\n\n const isFinalHandler = route.options?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n eventType: event.eventType,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.options?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.participant.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.handler,\n route.participant,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.eventType}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await handler(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n return;\n }\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.eventType}:`,\n error,\n );\n return;\n }\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n eventType,\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 eventType,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\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.eventType}`, 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.eventType}`;\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 const value = JSON.stringify({\n eventType: event.eventType,\n occurredAt: event.occurredAt,\n payload: event.payload,\n });\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 body = JSON.parse(message.value);\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n eventType: body.eventType,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload: body.payload as T,\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 eventType: body.eventType,\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 eventType: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${eventType}\": ` +\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(eventType: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${eventType}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n participant: SagaParticipant;\n handler: EventHandler;\n options?: HandlerConfig;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n for (const [eventType, handler] of Object.entries(participant.on)) {\n if (map.has(eventType)) {\n const existing = map.get(eventType)!;\n throw new SagaDuplicateHandlerError(\n eventType,\n existing.participant.serviceId,\n participant.serviceId,\n );\n }\n const options = participant.handlerOptions?.[eventType];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n eventType,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n map.set(eventType, { participant, handler, options });\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":"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","names":["uuidv7","import_uuid","uuidv7","import_uuid","uuidv7"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -22,6 +22,14 @@ interface TransportSubscribeOptions {
|
|
|
22
22
|
fromBeginning?: boolean;
|
|
23
23
|
groupId?: string;
|
|
24
24
|
}
|
|
25
|
+
interface TransportHealthResult {
|
|
26
|
+
status: "up" | "down";
|
|
27
|
+
details?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
interface HealthCheckable {
|
|
30
|
+
healthCheck(): Promise<TransportHealthResult>;
|
|
31
|
+
}
|
|
32
|
+
declare function isHealthCheckable(transport: SagaTransport): transport is SagaTransport & HealthCheckable;
|
|
25
33
|
|
|
26
34
|
interface RunnerOptions {
|
|
27
35
|
groupId: string;
|
|
@@ -221,6 +229,7 @@ declare class SagaRunner {
|
|
|
221
229
|
constructor(registry: SagaRegistry, transport: SagaTransport, publisher: SagaPublisher, parser: SagaParser, options: RunnerOptions, otelCtx?: OtelContext | undefined, logger?: SagaLogger);
|
|
222
230
|
start(): Promise<void>;
|
|
223
231
|
stop(): Promise<void>;
|
|
232
|
+
healthCheck(): Promise<TransportHealthResult>;
|
|
224
233
|
private handleMessage;
|
|
225
234
|
private runWithRetry;
|
|
226
235
|
private sleep;
|
|
@@ -266,4 +275,4 @@ declare class SagaInvalidHandlerConfigError extends SagaError {
|
|
|
266
275
|
constructor(eventType: string, serviceId: string, reason: string);
|
|
267
276
|
}
|
|
268
277
|
|
|
269
|
-
export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportSubscribeOptions, W3cOtelContext, createOtelContext };
|
|
278
|
+
export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type HealthCheckable, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportHealthResult, type TransportSubscribeOptions, W3cOtelContext, createOtelContext, isHealthCheckable };
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,14 @@ interface TransportSubscribeOptions {
|
|
|
22
22
|
fromBeginning?: boolean;
|
|
23
23
|
groupId?: string;
|
|
24
24
|
}
|
|
25
|
+
interface TransportHealthResult {
|
|
26
|
+
status: "up" | "down";
|
|
27
|
+
details?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
interface HealthCheckable {
|
|
30
|
+
healthCheck(): Promise<TransportHealthResult>;
|
|
31
|
+
}
|
|
32
|
+
declare function isHealthCheckable(transport: SagaTransport): transport is SagaTransport & HealthCheckable;
|
|
25
33
|
|
|
26
34
|
interface RunnerOptions {
|
|
27
35
|
groupId: string;
|
|
@@ -221,6 +229,7 @@ declare class SagaRunner {
|
|
|
221
229
|
constructor(registry: SagaRegistry, transport: SagaTransport, publisher: SagaPublisher, parser: SagaParser, options: RunnerOptions, otelCtx?: OtelContext | undefined, logger?: SagaLogger);
|
|
222
230
|
start(): Promise<void>;
|
|
223
231
|
stop(): Promise<void>;
|
|
232
|
+
healthCheck(): Promise<TransportHealthResult>;
|
|
224
233
|
private handleMessage;
|
|
225
234
|
private runWithRetry;
|
|
226
235
|
private sleep;
|
|
@@ -266,4 +275,4 @@ declare class SagaInvalidHandlerConfigError extends SagaError {
|
|
|
266
275
|
constructor(eventType: string, serviceId: string, reason: string);
|
|
267
276
|
}
|
|
268
277
|
|
|
269
|
-
export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportSubscribeOptions, W3cOtelContext, createOtelContext };
|
|
278
|
+
export { ConsoleSagaLogger, type Emit, type EmitParams, type EventHandler, type EventHint, type ForkConfig, type HandlerConfig, type HealthCheckable, type InboundMessage, type IncomingEvent, NoopOtelContext, type OtelContext, type OutboundMessage, type ParentSagaContext, type RunnerOptions, SagaContext, type SagaContextData, SagaContextNotFoundError, SagaDuplicateHandlerError, SagaError, type SagaEvent, SagaInvalidHandlerConfigError, type SagaLogger, SagaNoParentError, SagaParseError, SagaParser, type SagaParticipant, SagaPublisher, SagaRegistry, SagaRetryableError, SagaRunner, type SagaStartOptions, type SagaTransport, SagaTransportNotConnectedError, type TransportHealthResult, type TransportSubscribeOptions, W3cOtelContext, createOtelContext, isHealthCheckable };
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
5
5
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
+
// src/transport/transport.interface.ts
|
|
9
|
+
function isHealthCheckable(transport) {
|
|
10
|
+
return typeof transport.healthCheck === "function";
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
// src/errors/saga.error.ts
|
|
9
14
|
var SagaError = class extends Error {
|
|
10
15
|
isSagaError = true;
|
|
@@ -109,6 +114,15 @@ var SagaRunner = class {
|
|
|
109
114
|
async stop() {
|
|
110
115
|
await this.transport.disconnect();
|
|
111
116
|
}
|
|
117
|
+
async healthCheck() {
|
|
118
|
+
if (isHealthCheckable(this.transport)) {
|
|
119
|
+
return this.transport.healthCheck();
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
status: "up",
|
|
123
|
+
details: { reason: "Transport does not support health checks" }
|
|
124
|
+
};
|
|
125
|
+
}
|
|
112
126
|
async handleMessage(message) {
|
|
113
127
|
const event = this.parser.parse(message);
|
|
114
128
|
if (!event) return;
|
|
@@ -744,6 +758,7 @@ export {
|
|
|
744
758
|
SagaRunner,
|
|
745
759
|
SagaTransportNotConnectedError,
|
|
746
760
|
W3cOtelContext,
|
|
747
|
-
createOtelContext
|
|
761
|
+
createOtelContext,
|
|
762
|
+
isHealthCheckable
|
|
748
763
|
};
|
|
749
764
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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 class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n} from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n this.routeMap = this.registry.buildRouteMap();\n\n const prefix = this.options.topicPrefix ?? \"\";\n const topics = Array.from(this.routeMap.keys()).map(\n (et) => `${prefix}${et}`,\n );\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 private async handleMessage(message: InboundMessage): Promise<void> {\n const event = this.parser.parse<Record<string, unknown>>(message);\n if (!event) return;\n\n const route = this.routeMap.get(event.eventType);\n if (!route) return;\n\n const isFinalHandler = route.options?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n eventType: event.eventType,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.options?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.participant.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.handler,\n route.participant,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.eventType}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await handler(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n return;\n }\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.eventType}:`,\n error,\n );\n return;\n }\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n eventType,\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 eventType,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\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.eventType}`, 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.eventType}`;\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 const value = JSON.stringify({\n eventType: event.eventType,\n occurredAt: event.occurredAt,\n payload: event.payload,\n });\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 body = JSON.parse(message.value);\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n eventType: body.eventType,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload: body.payload as T,\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 eventType: body.eventType,\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 eventType: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${eventType}\": ` +\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(eventType: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${eventType}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n participant: SagaParticipant;\n handler: EventHandler;\n options?: HandlerConfig;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n for (const [eventType, handler] of Object.entries(participant.on)) {\n if (map.has(eventType)) {\n const existing = map.get(eventType)!;\n throw new SagaDuplicateHandlerError(\n eventType,\n existing.participant.serviceId,\n participant.serviceId,\n );\n }\n const options = participant.handlerOptions?.[eventType];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n eventType,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n map.set(eventType, { participant, handler, options });\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":"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","names":["uuidv7","uuidv7","uuidv7"]}
|
|
1
|
+
{"version":3,"sources":["../src/transport/transport.interface.ts","../src/errors/saga.error.ts","../src/errors/saga-retryable.error.ts","../src/logger/saga-logger.ts","../src/context/saga-context.ts","../src/errors/saga-context-not-found.error.ts","../src/runner/saga-runner.ts","../src/publisher/saga-publisher.ts","../src/errors/saga-no-parent.error.ts","../src/publisher/message-builder.ts","../src/parser/saga-parser.ts","../src/errors/saga-duplicate-handler.error.ts","../src/errors/saga-invalid-handler-config.error.ts","../src/registry/saga-registry.ts","../src/errors/saga-parse.error.ts","../src/errors/saga-transport-not-connected.error.ts","../src/otel/otel-context.ts"],"sourcesContent":["export interface SagaTransport {\n connect(): Promise<void>;\n disconnect(): Promise<void>;\n publish(message: OutboundMessage): Promise<void>;\n subscribe(\n topics: string[],\n handler: (message: InboundMessage) => Promise<void>,\n options?: TransportSubscribeOptions,\n ): Promise<void>;\n}\n\nexport interface OutboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface InboundMessage {\n topic: string;\n key: string;\n value: string;\n headers: Record<string, string>;\n}\n\nexport interface TransportSubscribeOptions {\n fromBeginning?: boolean;\n groupId?: string;\n}\n\nexport interface TransportHealthResult {\n status: \"up\" | \"down\";\n details?: Record<string, unknown>;\n}\n\nexport interface HealthCheckable {\n healthCheck(): Promise<TransportHealthResult>;\n}\n\nexport function isHealthCheckable(\n transport: SagaTransport,\n): transport is SagaTransport & HealthCheckable {\n return typeof (transport as any).healthCheck === \"function\";\n}\n","export class SagaError extends Error {\n public isSagaError = true;\n\n constructor(message: string) {\n super(message);\n this.name = \"SagaError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaRetryableError extends SagaError {\n constructor(\n message: string,\n readonly maxRetries = 3,\n ) {\n super(message);\n this.name = \"SagaRetryableError\";\n }\n}\n","export interface SagaLogger {\n info(message: string, ...args: unknown[]): void;\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport class ConsoleSagaLogger implements SagaLogger {\n info(message: string, ...args: unknown[]): void {\n console.log(message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(message, ...args);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { SagaContextNotFoundError } from \"../errors/saga-context-not-found.error\";\n\nexport interface SagaContextData {\n sagaId: string;\n rootSagaId: string;\n parentSagaId?: string;\n causationId: string;\n key?: string;\n sagaName?: string;\n sagaDescription?: string;\n}\n\nexport class SagaContext {\n private static storage = new AsyncLocalStorage<SagaContextData>();\n\n static run<T>(data: SagaContextData, fn: () => T): T {\n return SagaContext.storage.run(data, fn);\n }\n\n static current(): SagaContextData | undefined {\n return SagaContext.storage.getStore();\n }\n\n static require(): SagaContextData {\n const ctx = SagaContext.current();\n if (!ctx) {\n throw new SagaContextNotFoundError();\n }\n return ctx;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaContextNotFoundError extends SagaError {\n constructor() {\n super(\n \"No saga context found. Ensure you are inside a saga handler or after sagaPublisher.start().\",\n );\n this.name = \"SagaContextNotFoundError\";\n }\n}\n","import type {\n SagaTransport,\n InboundMessage,\n TransportHealthResult,\n} from \"../transport/transport.interface\";\nimport { isHealthCheckable } from \"../transport/transport.interface\";\nimport type { IncomingEvent } from \"../interfaces/incoming-event.interface\";\nimport type { Emit } from \"../interfaces/emit.type\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport type { SagaParticipant } from \"../interfaces/saga-participant.interface\";\nimport type { RunnerOptions } from \"../interfaces/runner-options.interface\";\nimport { SagaRetryableError } from \"../errors/saga-retryable.error\";\nimport { SagaRegistry, type RouteEntry } from \"../registry/saga-registry\";\nimport { SagaPublisher } from \"../publisher/saga-publisher\";\nimport { SagaParser } from \"../parser/saga-parser\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport type { SagaLogger } from \"../logger/saga-logger\";\nimport { ConsoleSagaLogger } from \"../logger/saga-logger\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport class SagaRunner {\n private routeMap!: Map<string, RouteEntry>;\n\n constructor(\n private registry: SagaRegistry,\n private transport: SagaTransport,\n private publisher: SagaPublisher,\n private parser: SagaParser,\n private options: RunnerOptions,\n private otelCtx?: OtelContext,\n private logger: SagaLogger = new ConsoleSagaLogger(),\n ) {}\n\n async start(): Promise<void> {\n this.routeMap = this.registry.buildRouteMap();\n\n const prefix = this.options.topicPrefix ?? \"\";\n const topics = Array.from(this.routeMap.keys()).map(\n (et) => `${prefix}${et}`,\n );\n\n await this.transport.connect();\n\n if (topics.length > 0) {\n this.logger.info(\n `[SagaRunner] Subscribing to ${topics.length} topic(s): [${topics.join(\", \")}]`,\n );\n await this.transport.subscribe(\n topics,\n (message) => this.handleMessage(message),\n {\n fromBeginning: this.options.fromBeginning,\n groupId: this.options.groupId,\n },\n );\n this.logger.info(\"[SagaRunner] Consumer running\");\n } else {\n this.logger.warn(\n \"[SagaRunner] No handlers registered — nothing to subscribe\",\n );\n }\n }\n\n async stop(): Promise<void> {\n await this.transport.disconnect();\n }\n\n async healthCheck(): Promise<TransportHealthResult> {\n if (isHealthCheckable(this.transport)) {\n return this.transport.healthCheck();\n }\n return {\n status: \"up\",\n details: { reason: \"Transport does not support health checks\" },\n };\n }\n\n private async handleMessage(message: InboundMessage): Promise<void> {\n const event = this.parser.parse<Record<string, unknown>>(message);\n if (!event) return;\n\n const route = this.routeMap.get(event.eventType);\n if (!route) return;\n\n const isFinalHandler = route.options?.final === true;\n\n const incoming: IncomingEvent = {\n sagaId: event.sagaId,\n eventId: event.eventId,\n causationId: event.causationId,\n eventType: event.eventType,\n stepName: event.stepName,\n stepDescription: event.stepDescription,\n occurredAt: event.occurredAt,\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n payload: event.payload,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const emit = this.publisher.forSaga(\n event.sagaId,\n {\n parentSagaId: event.parentSagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n // Wrap emit: if handler is final, auto-add hint\n const wrappedEmit: Emit = async (params) => {\n const finalParams = isFinalHandler\n ? { ...params, hint: \"final\" as const }\n : params;\n return emit(finalParams);\n };\n\n // Fork layer: if handler has fork config, wrap emit to auto-create sub-sagas\n const forkConfig = route.options?.fork;\n const finalEmit: Emit = forkConfig\n ? async (params) => {\n const subSagaId = uuidv7();\n\n const subEmit = this.publisher.forSaga(\n subSagaId,\n {\n parentSagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n },\n event.eventId,\n event.key,\n );\n\n const forkMeta = typeof forkConfig === \"object\" ? forkConfig : {};\n const forkCtx = {\n sagaId: subSagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.sagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: forkMeta.sagaName,\n sagaDescription: forkMeta.sagaDescription,\n };\n await SagaContext.run(forkCtx, () =>\n subEmit({ ...params, hint: \"fork\" }),\n );\n }\n : wrappedEmit;\n\n const spanAttrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\n \"saga.step.name\": event.stepName,\n \"saga.event.id\": event.eventId,\n \"saga.root.id\": event.rootSagaId,\n \"saga.handler.service\": route.participant.serviceId,\n };\n if (event.sagaName) spanAttrs[\"saga.name\"] = event.sagaName;\n if (event.sagaDescription)\n spanAttrs[\"saga.description\"] = event.sagaDescription;\n if (event.stepDescription)\n spanAttrs[\"saga.step.description\"] = event.stepDescription;\n if (event.parentSagaId) spanAttrs[\"saga.parent.id\"] = event.parentSagaId;\n\n const sagaCtxData = {\n sagaId: event.sagaId,\n rootSagaId: event.rootSagaId,\n parentSagaId: event.parentSagaId,\n causationId: event.eventId,\n key: event.key,\n sagaName: event.sagaName,\n sagaDescription: event.sagaDescription,\n };\n\n const runHandler = () =>\n SagaContext.run(sagaCtxData, () =>\n this.runWithRetry(\n route.handler,\n route.participant,\n incoming,\n finalEmit,\n ),\n );\n\n if (this.otelCtx) {\n await this.otelCtx.withExtractedSpan(\n `saga.handle ${event.eventType}`,\n spanAttrs,\n message.headers,\n runHandler,\n );\n } else {\n await runHandler();\n }\n }\n\n private async runWithRetry(\n handler: EventHandler,\n participant: SagaParticipant,\n event: IncomingEvent,\n emit: Emit,\n ): Promise<void> {\n const maxRetries = this.options.retryPolicy?.maxRetries ?? 3;\n const initialDelayMs = this.options.retryPolicy?.initialDelayMs ?? 200;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n await handler(event, emit);\n return;\n } catch (error) {\n if (error instanceof SagaRetryableError) {\n if (attempt < maxRetries) {\n const delay = initialDelayMs * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n if (participant.onRetryExhausted) {\n await participant.onRetryExhausted(event, error, emit);\n }\n return;\n }\n this.logger.error(\n `[SagaRunner] Non-retryable error in handler for ${event.eventType}:`,\n error,\n );\n return;\n }\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { v7 as uuidv7 } from \"uuid\";\nimport type { SagaEvent } from \"../interfaces/saga-event.interface\";\nimport type { Emit, EmitParams } from \"../interfaces/emit.type\";\nimport type { ParentSagaContext } from \"../interfaces/parent-saga-context.interface\";\nimport type { SagaTransport } from \"../transport/transport.interface\";\nimport type { OtelContext } from \"../otel/otel-context\";\nimport { SagaContext } from \"../context/saga-context\";\nimport { SagaNoParentError } from \"../errors/saga-no-parent.error\";\nimport { buildOutboundMessage } from \"./message-builder\";\n\nexport interface SagaStartOptions {\n sagaName?: string;\n sagaDescription?: string;\n key?: string;\n}\n\nexport class SagaPublisher {\n constructor(\n private transport: SagaTransport,\n private otelCtx: OtelContext,\n private topicPrefix = \"\",\n ) {}\n\n async start<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const sagaId = uuidv7();\n const ctxData = {\n sagaId,\n rootSagaId: sagaId,\n causationId: sagaId,\n key: opts?.key,\n sagaName: opts?.sagaName,\n sagaDescription: opts?.sagaDescription,\n };\n const result = await SagaContext.run(ctxData, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emit<T extends object>(params: EmitParams<T>): Promise<void> {\n const ctx = SagaContext.require();\n const boundEmit = this.forSaga(\n ctx.sagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return boundEmit(params);\n }\n\n async startChild<R>(\n fn: () => R | Promise<R>,\n opts?: SagaStartOptions,\n ): Promise<{ sagaId: string; result: Awaited<R> }> {\n const ctx = SagaContext.require();\n const sagaId = uuidv7();\n const childCtx = {\n sagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.sagaId,\n causationId: ctx.causationId,\n key: opts?.key ?? ctx.key,\n sagaName: opts?.sagaName ?? ctx.sagaName,\n sagaDescription: opts?.sagaDescription ?? ctx.sagaDescription,\n };\n const result = await SagaContext.run(childCtx, fn);\n return { sagaId, result: result as Awaited<R> };\n }\n\n async emitToParent<T extends object>(\n paramsOrFn: EmitParams<T> | (() => void | Promise<void>),\n ): Promise<void> {\n const ctx = SagaContext.require();\n if (!ctx.parentSagaId) {\n throw new SagaNoParentError();\n }\n\n if (typeof paramsOrFn === \"function\") {\n const parentCtx = {\n sagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n parentSagaId: ctx.parentSagaId,\n causationId: ctx.causationId,\n key: ctx.key,\n };\n await SagaContext.run(parentCtx, paramsOrFn);\n return;\n }\n\n const parentEmit = this.forSaga(\n ctx.parentSagaId,\n {\n parentSagaId: ctx.parentSagaId,\n rootSagaId: ctx.rootSagaId,\n },\n ctx.causationId,\n ctx.key,\n );\n return parentEmit(paramsOrFn);\n }\n\n forSaga(\n sagaId: string,\n parentCtx?: ParentSagaContext,\n causationId?: string,\n baseKey?: string,\n ): Emit {\n const rootSagaId = parentCtx?.rootSagaId ?? sagaId;\n const parentSagaId = parentCtx?.parentSagaId;\n const baseCausationId = causationId ?? sagaId;\n return async <T extends object>({\n eventType,\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 eventType,\n stepName,\n stepDescription,\n occurredAt: now,\n publishedAt: now,\n schemaVersion: 1,\n rootSagaId,\n parentSagaId,\n payload,\n hint,\n key: resolvedKey,\n sagaName: ctx?.sagaName,\n sagaDescription: ctx?.sagaDescription,\n };\n\n await this.publish(event);\n };\n }\n\n async publish<T>(event: SagaEvent<T>): Promise<void> {\n this.otelCtx.injectBaggage(\n event.sagaId,\n event.rootSagaId,\n event.parentSagaId,\n );\n\n const attrs: Record<string, string> = {\n \"saga.id\": event.sagaId,\n \"saga.event.type\": event.eventType,\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.eventType}`, 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.eventType}`;\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 const value = JSON.stringify({\n eventType: event.eventType,\n occurredAt: event.occurredAt,\n payload: event.payload,\n });\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 body = JSON.parse(message.value);\n\n const sagaId = headers[\"saga-id\"];\n if (!sagaId) {\n return null;\n }\n\n return {\n sagaId,\n causationId: headers[\"saga-causation-id\"] ?? sagaId,\n eventId: headers[\"saga-event-id\"] ?? uuidv7(),\n eventType: body.eventType,\n stepName: headers[\"saga-step-name\"] ?? \"\",\n occurredAt: body.occurredAt ?? new Date().toISOString(),\n publishedAt: headers[\"saga-published-at\"] ?? new Date().toISOString(),\n schemaVersion: 1,\n rootSagaId: headers[\"saga-root-id\"] ?? sagaId,\n parentSagaId: headers[\"saga-parent-id\"] || undefined,\n payload: body.payload as T,\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 eventType: body.eventType,\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 eventType: string,\n existingServiceId: string,\n newServiceId: string,\n ) {\n super(\n `Duplicate handler for event type \"${eventType}\": ` +\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(eventType: string, serviceId: string, reason: string) {\n super(\n `Invalid handler config for \"${eventType}\" in \"${serviceId}\": ${reason}`,\n );\n this.name = \"SagaInvalidHandlerConfigError\";\n }\n}\n","import type {\n SagaParticipant,\n HandlerConfig,\n} from \"../interfaces/saga-participant.interface\";\nimport type { EventHandler } from \"../interfaces/event-handler.type\";\nimport { SagaDuplicateHandlerError } from \"../errors/saga-duplicate-handler.error\";\nimport { SagaInvalidHandlerConfigError } from \"../errors/saga-invalid-handler-config.error\";\n\nexport interface RouteEntry {\n participant: SagaParticipant;\n handler: EventHandler;\n options?: HandlerConfig;\n}\n\nexport class SagaRegistry {\n private participants: SagaParticipant[] = [];\n\n register(participant: SagaParticipant): void {\n this.participants.push(participant);\n }\n\n getAll(): SagaParticipant[] {\n return [...this.participants];\n }\n\n buildRouteMap(): Map<string, RouteEntry> {\n const map = new Map<string, RouteEntry>();\n\n for (const participant of this.participants) {\n for (const [eventType, handler] of Object.entries(participant.on)) {\n if (map.has(eventType)) {\n const existing = map.get(eventType)!;\n throw new SagaDuplicateHandlerError(\n eventType,\n existing.participant.serviceId,\n participant.serviceId,\n );\n }\n const options = participant.handlerOptions?.[eventType];\n if (options?.final && options?.fork) {\n throw new SagaInvalidHandlerConfigError(\n eventType,\n participant.serviceId,\n \"cannot have both final and fork options\",\n );\n }\n map.set(eventType, { participant, handler, options });\n }\n }\n\n return map;\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaParseError extends SagaError {\n constructor(message: string) {\n super(message);\n this.name = \"SagaParseError\";\n }\n}\n","import { SagaError } from \"./saga.error\";\n\nexport class SagaTransportNotConnectedError extends SagaError {\n constructor() {\n super(\"Transport not connected\");\n this.name = \"SagaTransportNotConnectedError\";\n }\n}\n","export interface OtelContext {\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void;\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n };\n enrichSpan(attrs: Record<string, string>): void;\n withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n injectTraceContext(headers: Record<string, string>): void;\n withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T>;\n}\n\nexport class NoopOtelContext implements OtelContext {\n injectBaggage(): void {}\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n return {};\n }\n enrichSpan(): void {}\n async withSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n injectTraceContext(): void {}\n async withExtractedSpan<T>(\n _name: string,\n _attrs: Record<string, string>,\n _headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n return fn();\n }\n}\n\ntype OtelAPI = typeof import(\"@opentelemetry/api\");\n\nexport class W3cOtelContext implements OtelContext {\n private api: OtelAPI;\n\n constructor(api: OtelAPI) {\n this.api = api;\n }\n\n injectBaggage(\n sagaId: string,\n rootSagaId: string,\n parentSagaId?: string,\n ): void {\n const entries: Record<string, { value: string }> = {\n \"saga.id\": { value: sagaId },\n \"saga.root.id\": { value: rootSagaId },\n };\n if (parentSagaId) {\n entries[\"saga.parent.id\"] = { value: parentSagaId };\n }\n\n const baggage = this.api.propagation.createBaggage(entries);\n const ctx = this.api.propagation.setBaggage(\n this.api.context.active(),\n baggage,\n );\n this.api.context.with(ctx, () => {});\n }\n\n extractBaggage(): {\n sagaId?: string;\n rootSagaId?: string;\n parentSagaId?: string;\n } {\n const baggage = this.api.propagation.getBaggage(this.api.context.active());\n if (!baggage) return {};\n\n return {\n sagaId: baggage.getEntry(\"saga.id\")?.value,\n rootSagaId: baggage.getEntry(\"saga.root.id\")?.value,\n parentSagaId: baggage.getEntry(\"saga.parent.id\")?.value,\n };\n }\n\n enrichSpan(attrs: Record<string, string>): void {\n const span = this.api.trace.getActiveSpan();\n if (span) {\n span.setAttributes(attrs);\n }\n }\n\n async withSpan<T>(\n name: string,\n attrs: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n return tracer.startActiveSpan(name, async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n });\n }\n\n injectTraceContext(headers: Record<string, string>): void {\n this.api.propagation.inject(this.api.context.active(), headers);\n }\n\n async withExtractedSpan<T>(\n name: string,\n attrs: Record<string, string>,\n headers: Record<string, string>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const parentCtx = this.api.propagation.extract(\n this.api.ROOT_CONTEXT,\n headers,\n );\n const tracer = this.api.trace.getTracer(\"@fbsm/saga-core\");\n\n return this.api.context.with(parentCtx, () =>\n tracer.startActiveSpan(\n name,\n { kind: this.api.SpanKind.CONSUMER },\n async (span) => {\n span.setAttributes(attrs);\n try {\n const result = await fn();\n span.setStatus({ code: this.api.SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({\n code: this.api.SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n span.recordException(\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n } finally {\n span.end();\n }\n },\n ),\n );\n }\n}\n\nexport function createOtelContext(enabled: boolean): OtelContext {\n if (!enabled) return new NoopOtelContext();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const api = require(\"@opentelemetry/api\");\n return new W3cOtelContext(api);\n } catch {\n return new NoopOtelContext();\n }\n}\n"],"mappings":";;;;;;;;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;;;ADIO,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;;;AEZA,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,SAAK,WAAW,KAAK,SAAS,cAAc;AAE5C,UAAM,SAAS,KAAK,QAAQ,eAAe;AAC3C,UAAM,SAAS,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC,EAAE;AAAA,MAC9C,CAAC,OAAO,GAAG,MAAM,GAAG,EAAE;AAAA,IACxB;AAEA,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,OAAO,MAA+B,OAAO;AAChE,QAAI,CAAC,MAAO;AAEZ,UAAM,QAAQ,KAAK,SAAS,IAAI,MAAM,SAAS;AAC/C,QAAI,CAAC,MAAO;AAEZ,UAAM,iBAAiB,MAAM,SAAS,UAAU;AAEhD,UAAM,WAA0B;AAAA,MAC9B,QAAQ,MAAM;AAAA,MACd,SAAS,MAAM;AAAA,MACf,aAAa,MAAM;AAAA,MACnB,WAAW,MAAM;AAAA,MACjB,UAAU,MAAM;AAAA,MAChB,iBAAiB,MAAM;AAAA,MACvB,YAAY,MAAM;AAAA,MAClB,cAAc,MAAM;AAAA,MACpB,YAAY,MAAM;AAAA,MAClB,SAAS,MAAM;AAAA,MACf,KAAK,MAAM;AAAA,MACX,UAAU,MAAM;AAAA,MAChB,iBAAiB,MAAM;AAAA,IACzB;AAEA,UAAM,OAAO,KAAK,UAAU;AAAA,MAC1B,MAAM;AAAA,MACN;AAAA,QACE,cAAc,MAAM;AAAA,QACpB,YAAY,MAAM;AAAA,MACpB;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,IACR;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,SAAS;AAClC,UAAM,YAAkB,aACpB,OAAO,WAAW;AAChB,YAAM,YAAY,OAAO;AAEzB,YAAM,UAAU,KAAK,UAAU;AAAA,QAC7B;AAAA,QACA;AAAA,UACE,cAAc,MAAM;AAAA,UACpB,YAAY,MAAM;AAAA,QACpB;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,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,mBAAmB,MAAM;AAAA,MACzB,kBAAkB,MAAM;AAAA,MACxB,iBAAiB,MAAM;AAAA,MACvB,gBAAgB,MAAM;AAAA,MACtB,wBAAwB,MAAM,YAAY;AAAA,IAC5C;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,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,SAAS;AAAA,QAC9B;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAc,aACZ,SACA,aACA,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,QAAQ,OAAO,IAAI;AACzB;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;AACA,cAAI,YAAY,kBAAkB;AAChC,kBAAM,YAAY,iBAAiB,OAAO,OAAO,IAAI;AAAA,UACvD;AACA;AAAA,QACF;AACA,aAAK,OAAO;AAAA,UACV,mDAAmD,MAAM,SAAS;AAAA,UAClE;AAAA,QACF;AACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AACF;;;AC7OA,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,SAAS;AAC9C,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,QAAM,QAAQ,KAAK,UAAU;AAAA,IAC3B,WAAW,MAAM;AAAA,IACjB,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM;AAAA,EACjB,CAAC;AAED,SAAO,EAAE,OAAO,KAAK,OAAO,QAAQ;AACtC;;;AFnCO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YACU,WACA,SACA,cAAc,IACtB;AAHQ;AACA;AACA;AAAA,EACP;AAAA,EAEH,MAAM,MACJ,IACA,MACiD;AACjD,UAAM,SAASC,QAAO;AACtB,UAAM,UAAU;AAAA,MACd;AAAA,MACA,YAAY;AAAA,MACZ,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,MAClB;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,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,QAAI,OAAO,eAAe,YAAY;AACpC,YAAM,YAAY;AAAA,QAChB,QAAQ,IAAI;AAAA,QACZ,YAAY,IAAI;AAAA,QAChB,cAAc,IAAI;AAAA,QAClB,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,IAAI;AAAA,QAClB,YAAY,IAAI;AAAA,MAClB;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,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,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,mBAAmB,MAAM;AAAA,MACzB,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,SAAS;AAAA,MAAI;AAAA,MAAO,MACpE,KAAK,UAAU,QAAQ,OAAO;AAAA,IAChC;AAAA,EACF;AACF;;;AGxLA,SAAS,MAAMC,eAAc;AAKtB,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,OAAO,KAAK,MAAM,QAAQ,KAAK;AAErC,UAAM,SAAS,QAAQ,SAAS;AAChC,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL;AAAA,MACA,aAAa,QAAQ,mBAAmB,KAAK;AAAA,MAC7C,SAAS,QAAQ,eAAe,KAAKA,QAAO;AAAA,MAC5C,WAAW,KAAK;AAAA,MAChB,UAAU,QAAQ,gBAAgB,KAAK;AAAA,MACvC,YAAY,KAAK,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,MACtD,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,SAAS,KAAK;AAAA,MACd,UAAU,QAAQ,WAAW,KAAK;AAAA,MAClC,iBAAiB,QAAQ,kBAAkB,KAAK;AAAA,MAChD,iBAAiB,QAAQ,uBAAuB,KAAK;AAAA,MACrD,KAAK,QAAQ,UAAU,KAAK;AAAA,IAC9B;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,WAAW,KAAK;AAAA,MAChB,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;;;ACxGO,IAAM,4BAAN,cAAwC,UAAU;AAAA,EACvD,YACE,WACA,mBACA,cACA;AACA;AAAA,MACE,qCAAqC,SAAS,qBAC1B,iBAAiB,UAAU,YAAY;AAAA,IAC7D;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ACZO,IAAM,gCAAN,cAA4C,UAAU;AAAA,EAC3D,YAAY,WAAmB,WAAmB,QAAgB;AAChE;AAAA,MACE,+BAA+B,SAAS,SAAS,SAAS,MAAM,MAAM;AAAA,IACxE;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ACKO,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;AAC3C,iBAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,YAAY,EAAE,GAAG;AACjE,YAAI,IAAI,IAAI,SAAS,GAAG;AACtB,gBAAM,WAAW,IAAI,IAAI,SAAS;AAClC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,SAAS,YAAY;AAAA,YACrB,YAAY;AAAA,UACd;AAAA,QACF;AACA,cAAM,UAAU,YAAY,iBAAiB,SAAS;AACtD,YAAI,SAAS,SAAS,SAAS,MAAM;AACnC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AACA,YAAI,IAAI,WAAW,EAAE,aAAa,SAAS,QAAQ,CAAC;AAAA,MACtD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AClDO,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"]}
|