@saga-bus/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors/index.ts","../src/dsl/HandlerBuilder.ts","../src/dsl/SagaDefinitionImpl.ts","../src/dsl/SagaMachineBuilder.ts","../src/types/messages.ts","../src/runtime/SagaContextImpl.ts","../src/runtime/utils.ts","../src/runtime/SagaOrchestrator.ts","../src/runtime/MiddlewarePipeline.ts","../src/runtime/DefaultLogger.ts","../src/runtime/DefaultErrorHandler.ts","../src/runtime/RetryHandler.ts","../src/runtime/BusImpl.ts"],"sourcesContent":["/**\n * Thrown when optimistic concurrency check fails.\n */\nexport class ConcurrencyError extends Error {\n readonly sagaId: string;\n readonly expectedVersion: number;\n readonly actualVersion?: number;\n\n constructor(\n sagaId: string,\n expectedVersion: number,\n actualVersion?: number\n ) {\n const message = actualVersion !== undefined\n ? `Concurrency conflict for saga ${sagaId}: expected version ${expectedVersion}, got ${actualVersion}`\n : `Concurrency conflict for saga ${sagaId}: expected version ${expectedVersion}`;\n\n super(message);\n this.name = \"ConcurrencyError\";\n this.sagaId = sagaId;\n this.expectedVersion = expectedVersion;\n this.actualVersion = actualVersion;\n }\n}\n\n/**\n * Marker class for transient errors that should be retried.\n */\nexport class TransientError extends Error {\n override readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = \"TransientError\";\n this.cause = cause;\n }\n\n static wrap(error: Error): TransientError {\n return new TransientError(error.message, error);\n }\n}\n\n/**\n * Thrown when message validation fails.\n */\nexport class ValidationError extends Error {\n readonly field?: string;\n readonly value?: unknown;\n\n constructor(message: string, field?: string, value?: unknown) {\n super(message);\n this.name = \"ValidationError\";\n this.field = field;\n this.value = value;\n }\n}\n\n/**\n * Thrown when a saga timeout expires.\n * Can be used in handlers to detect timeout scenarios.\n */\nexport class SagaTimeoutError extends Error {\n readonly sagaId: string;\n readonly sagaName: string;\n readonly correlationId: string;\n readonly timeoutMs: number;\n\n constructor(\n sagaId: string,\n sagaName: string,\n correlationId: string,\n timeoutMs: number\n ) {\n super(\n `Saga timeout expired: ${sagaName} (${sagaId}) after ${timeoutMs}ms`\n );\n this.name = \"SagaTimeoutError\";\n this.sagaId = sagaId;\n this.sagaName = sagaName;\n this.correlationId = correlationId;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Context attached to processing errors for better observability.\n */\nexport interface SagaErrorContext {\n readonly sagaName: string;\n readonly correlationId: string;\n readonly sagaId?: string;\n readonly messageType: string;\n readonly messageId: string;\n}\n\n/**\n * Wraps errors that occur during saga processing with context.\n * Used by BusImpl to provide richer error context to error handlers.\n */\nexport class SagaProcessingError extends Error {\n readonly context: SagaErrorContext;\n override readonly cause: Error;\n\n constructor(cause: Error, context: SagaErrorContext) {\n super(`Error processing message in ${context.sagaName}: ${cause.message}`);\n this.name = \"SagaProcessingError\";\n this.cause = cause;\n this.context = context;\n }\n\n /**\n * Check if an error is a SagaProcessingError and extract context.\n */\n static extractContext(error: unknown): SagaErrorContext | null {\n if (error instanceof SagaProcessingError) {\n return error.context;\n }\n return null;\n }\n}\n","import type { BaseMessage, SagaState } from \"../types/index.js\";\nimport type {\n SagaHandler,\n StateGuard,\n HandlerRegistration,\n} from \"./types.js\";\nimport type { SagaMachineBuilder } from \"./SagaMachineBuilder.js\";\n\n/**\n * Builder for configuring a message handler with optional state guards.\n */\nexport class HandlerBuilder<\n TState extends SagaState,\n TMessages extends BaseMessage,\n TCurrentMessage extends TMessages\n> {\n private guard?: StateGuard<TState>;\n\n constructor(\n private readonly parent: SagaMachineBuilder<TState, TMessages>,\n private readonly messageType: TCurrentMessage[\"type\"]\n ) {}\n\n /**\n * Add a state guard that must pass for the handler to execute.\n * Multiple guards can be chained with multiple .when() calls.\n */\n when(\n guard: StateGuard<TState>\n ): HandlerBuilder<TState, TMessages, TCurrentMessage> {\n if (this.guard) {\n // Chain guards with AND logic\n const existingGuard = this.guard;\n this.guard = (state) => existingGuard(state) && guard(state);\n } else {\n this.guard = guard;\n }\n return this;\n }\n\n /**\n * Register the handler function and return to the parent builder.\n */\n handle(\n handler: SagaHandler<TState, TCurrentMessage>\n ): SagaMachineBuilder<TState, TMessages> {\n const registration: HandlerRegistration<TState, TCurrentMessage> = {\n messageType: this.messageType,\n guard: this.guard,\n handler,\n };\n\n return this.parent._registerHandler(\n registration as HandlerRegistration<TState, TMessages>\n );\n }\n}\n","import type {\n BaseMessage,\n SagaState,\n SagaContext,\n SagaCorrelation,\n SagaDefinition,\n SagaHandlerResult,\n} from \"../types/index.js\";\nimport type {\n CorrelationConfig,\n HandlerRegistration,\n InitialStateFactory,\n} from \"./types.js\";\n\n/**\n * Concrete implementation of SagaDefinition produced by the builder.\n */\nexport class SagaDefinitionImpl<\n TState extends SagaState,\n TMessages extends BaseMessage\n> implements SagaDefinition<TState, TMessages>\n{\n readonly name: string;\n readonly handledMessageTypes: ReadonlyArray<TMessages[\"type\"]>;\n\n private readonly correlations: Map<string, CorrelationConfig<TMessages>>;\n private readonly wildcardCorrelation?: CorrelationConfig<TMessages>;\n private readonly handlers: Map<\n string,\n Array<HandlerRegistration<TState, TMessages>>\n >;\n private readonly initialFactory?: InitialStateFactory<TState, TMessages>;\n\n constructor(config: {\n name: string;\n correlations: Map<string, CorrelationConfig<TMessages>>;\n wildcardCorrelation?: CorrelationConfig<TMessages>;\n handlers: Map<string, Array<HandlerRegistration<TState, TMessages>>>;\n initialFactory?: InitialStateFactory<TState, TMessages>;\n }) {\n this.name = config.name;\n this.correlations = config.correlations;\n this.wildcardCorrelation = config.wildcardCorrelation;\n this.handlers = config.handlers;\n this.initialFactory = config.initialFactory;\n\n // Collect all handled message types\n const types = new Set<string>();\n for (const type of this.correlations.keys()) {\n types.add(type);\n }\n for (const type of this.handlers.keys()) {\n types.add(type);\n }\n this.handledMessageTypes = Array.from(types) as TMessages[\"type\"][];\n }\n\n getCorrelation<T extends TMessages>(message: T): SagaCorrelation<T> {\n // Try specific correlation first\n const specific = this.correlations.get(message.type);\n if (specific) {\n return {\n canStart: specific.canStart,\n getCorrelationId: (msg: T) =>\n (specific.getCorrelationId as (m: T) => string | null)(msg),\n };\n }\n\n // Fall back to wildcard\n if (this.wildcardCorrelation) {\n return {\n canStart: this.wildcardCorrelation.canStart,\n getCorrelationId: (msg: T) =>\n (this.wildcardCorrelation!.getCorrelationId as (m: T) => string | null)(msg),\n };\n }\n\n // No correlation found - return a non-starting, non-correlating result\n return {\n canStart: false,\n getCorrelationId: () => null,\n };\n }\n\n async createInitialState<T extends TMessages>(\n message: T,\n ctx: SagaContext\n ): Promise<TState> {\n if (!this.initialFactory) {\n throw new Error(\n `No initial state factory defined for saga \"${this.name}\"`\n );\n }\n\n return this.initialFactory(message as TMessages, ctx);\n }\n\n async handle<T extends TMessages>(\n message: T,\n state: TState,\n ctx: SagaContext\n ): Promise<SagaHandlerResult<TState>> {\n const registrations = this.handlers.get(message.type);\n\n if (!registrations || registrations.length === 0) {\n // No handlers for this message type - return state unchanged\n return { newState: state };\n }\n\n // Find the first handler whose guard passes (or has no guard)\n for (const registration of registrations) {\n if (!registration.guard || registration.guard(state)) {\n return registration.handler(message as TMessages, state, ctx);\n }\n }\n\n // No handler matched (all guards failed) - return state unchanged\n return { newState: state };\n }\n}\n","import type {\n BaseMessage,\n SagaState,\n SagaDefinition,\n} from \"../types/index.js\";\nimport type {\n CorrelateOptions,\n CorrelationConfig,\n HandlerRegistration,\n InitialStateFactory,\n} from \"./types.js\";\nimport { HandlerBuilder } from \"./HandlerBuilder.js\";\nimport { SagaDefinitionImpl } from \"./SagaDefinitionImpl.js\";\n\n/**\n * Fluent builder for creating saga definitions.\n *\n * @example\n * ```typescript\n * const saga = createSagaMachine<OrderState, OrderMessages>()\n * .name(\"OrderSaga\")\n * .correlate(\"OrderSubmitted\", msg => msg.orderId, { canStart: true })\n * .correlate(\"*\", msg => msg.orderId)\n * .initial<OrderSubmitted>((msg, ctx) => ({ ... }))\n * .on(\"PaymentCaptured\").when(s => s.status === \"pending\").handle(...)\n * .build();\n * ```\n */\nexport class SagaMachineBuilder<\n TState extends SagaState,\n TMessages extends BaseMessage\n> {\n private sagaName?: string;\n private readonly correlations = new Map<\n string,\n CorrelationConfig<TMessages>\n >();\n private wildcardCorrelation?: CorrelationConfig<TMessages>;\n private readonly handlers = new Map<\n string,\n Array<HandlerRegistration<TState, TMessages>>\n >();\n private initialFactory?: InitialStateFactory<TState, TMessages>;\n\n /**\n * Set the saga name.\n */\n name(sagaName: string): this {\n this.sagaName = sagaName;\n return this;\n }\n\n /**\n * Define how to correlate messages to saga instances.\n *\n * @param messageType - The message type to correlate, or \"*\" for wildcard\n * @param getCorrelationId - Function to extract correlation ID from message\n * @param options - Correlation options (e.g., canStart)\n */\n correlate<TType extends TMessages[\"type\"] | \"*\">(\n messageType: TType,\n getCorrelationId: TType extends \"*\"\n ? (message: TMessages) => string | null\n : (\n message: Extract<TMessages, { type: TType }>\n ) => string | null,\n options: CorrelateOptions = {}\n ): this {\n const config: CorrelationConfig<TMessages> = {\n canStart: options.canStart ?? false,\n getCorrelationId: getCorrelationId as (\n message: TMessages\n ) => string | null,\n };\n\n if (messageType === \"*\") {\n this.wildcardCorrelation = config;\n } else {\n this.correlations.set(messageType, config);\n }\n\n return this;\n }\n\n /**\n * Define the initial state factory for new saga instances.\n *\n * @param factory - Function to create initial state from the starting message\n */\n initial<TStartMessage extends TMessages>(\n factory: InitialStateFactory<TState, TStartMessage>\n ): this {\n this.initialFactory = factory as InitialStateFactory<TState, TMessages>;\n return this;\n }\n\n /**\n * Start defining a handler for a specific message type.\n *\n * @param messageType - The message type to handle\n * @returns A HandlerBuilder for chaining .when() and .handle()\n */\n on<TType extends TMessages[\"type\"]>(\n messageType: TType\n ): HandlerBuilder<TState, TMessages, Extract<TMessages, { type: TType }>> {\n return new HandlerBuilder<\n TState,\n TMessages,\n Extract<TMessages, { type: TType }>\n >(this, messageType);\n }\n\n /**\n * Internal method called by HandlerBuilder to register a handler.\n * @internal\n */\n _registerHandler(\n registration: HandlerRegistration<TState, TMessages>\n ): this {\n const existing = this.handlers.get(registration.messageType);\n if (existing) {\n existing.push(registration);\n } else {\n this.handlers.set(registration.messageType, [registration]);\n }\n return this;\n }\n\n /**\n * Build the saga definition.\n *\n * @throws Error if required configuration is missing\n */\n build(): SagaDefinition<TState, TMessages> {\n if (!this.sagaName) {\n throw new Error(\"Saga name is required. Call .name() before .build()\");\n }\n\n // Validate that at least one correlation can start\n let hasStartingCorrelation = false;\n for (const config of this.correlations.values()) {\n if (config.canStart) {\n hasStartingCorrelation = true;\n break;\n }\n }\n if (this.wildcardCorrelation?.canStart) {\n hasStartingCorrelation = true;\n }\n\n if (!hasStartingCorrelation) {\n throw new Error(\n `Saga \"${this.sagaName}\" has no correlation with canStart: true`\n );\n }\n\n if (!this.initialFactory) {\n throw new Error(\n `Saga \"${this.sagaName}\" requires an initial state factory. Call .initial() before .build()`\n );\n }\n\n return new SagaDefinitionImpl<TState, TMessages>({\n name: this.sagaName,\n correlations: this.correlations,\n wildcardCorrelation: this.wildcardCorrelation,\n handlers: this.handlers,\n initialFactory: this.initialFactory,\n });\n }\n}\n\n/**\n * Create a new saga machine builder.\n *\n * @example\n * ```typescript\n * const saga = createSagaMachine<OrderState, OrderMessages>()\n * .name(\"OrderSaga\")\n * .correlate(\"OrderSubmitted\", msg => msg.orderId, { canStart: true })\n * .initial<OrderSubmitted>((msg, ctx) => ({ ... }))\n * .on(\"PaymentCaptured\").handle(...)\n * .build();\n * ```\n */\nexport function createSagaMachine<\n TState extends SagaState,\n TMessages extends BaseMessage\n>(): SagaMachineBuilder<TState, TMessages> {\n return new SagaMachineBuilder<TState, TMessages>();\n}\n","/**\n * Base interface for all messages in the saga bus.\n * Every message must have a `type` discriminator.\n */\nexport interface BaseMessage {\n readonly type: string;\n}\n\n/**\n * Envelope wrapping a message with metadata for transport.\n */\nexport interface MessageEnvelope<T extends BaseMessage = BaseMessage> {\n /** Unique identifier for this message instance */\n readonly id: string;\n /** Message type discriminator (mirrors payload.type) */\n readonly type: T[\"type\"];\n /** The actual message payload */\n readonly payload: T;\n /** Transport and application headers */\n readonly headers: Readonly<Record<string, string>>;\n /** When the message was created */\n readonly timestamp: Date;\n /** Optional partition key for ordered delivery */\n readonly partitionKey?: string;\n}\n\n/**\n * System message type for saga timeout expiration.\n * Automatically published when a saga's timeout expires.\n */\nexport interface SagaTimeoutExpired extends BaseMessage {\n readonly type: \"SagaTimeoutExpired\";\n /** ID of the saga that timed out */\n readonly sagaId: string;\n /** Name of the saga that timed out */\n readonly sagaName: string;\n /** Correlation ID of the saga */\n readonly correlationId: string;\n /** The timeout duration that was configured (in ms) */\n readonly timeoutMs: number;\n /** When the timeout was originally set */\n readonly timeoutSetAt: Date;\n}\n\n/** Well-known message type constant for saga timeout */\nexport const SAGA_TIMEOUT_MESSAGE_TYPE = \"SagaTimeoutExpired\" as const;\n","import type {\n SagaContext,\n MessageEnvelope,\n BaseMessage,\n Transport,\n TransportPublishOptions,\n SagaStateMetadata,\n TimeoutBounds,\n} from \"../types/index.js\";\n\n/** Default timeout bounds */\nexport const DEFAULT_TIMEOUT_BOUNDS: Required<TimeoutBounds> = {\n minMs: 1000, // 1 second minimum\n maxMs: 604800000, // 7 days maximum\n};\n\nexport interface SagaContextImplOptions {\n sagaName: string;\n sagaId: string;\n correlationId: string;\n envelope: MessageEnvelope;\n transport: Transport;\n defaultEndpoint?: string;\n /** Current saga metadata (for reading existing timeout) */\n currentMetadata?: SagaStateMetadata;\n /** Timeout bounds to validate against */\n timeoutBounds?: TimeoutBounds;\n}\n\n/**\n * Pending timeout changes to be applied to saga state.\n */\nexport interface PendingTimeoutChange {\n type: \"set\" | \"clear\";\n timeoutMs?: number;\n timeoutExpiresAt?: Date;\n}\n\n/**\n * Concrete implementation of SagaContext.\n */\nexport class SagaContextImpl implements SagaContext {\n readonly sagaName: string;\n readonly sagaId: string;\n readonly correlationId: string;\n readonly envelope: MessageEnvelope;\n readonly metadata: Record<string, unknown> = {};\n\n private readonly transport: Transport;\n private readonly defaultEndpoint?: string;\n private readonly timeoutBounds: Required<TimeoutBounds>;\n private _isCompleted = false;\n private _currentMetadata?: SagaStateMetadata;\n private _pendingTimeoutChange?: PendingTimeoutChange;\n\n constructor(options: SagaContextImplOptions) {\n this.sagaName = options.sagaName;\n this.sagaId = options.sagaId;\n this.correlationId = options.correlationId;\n this.envelope = options.envelope;\n this.transport = options.transport;\n this.defaultEndpoint = options.defaultEndpoint;\n this._currentMetadata = options.currentMetadata;\n this.timeoutBounds = {\n minMs: options.timeoutBounds?.minMs ?? DEFAULT_TIMEOUT_BOUNDS.minMs,\n maxMs: options.timeoutBounds?.maxMs ?? DEFAULT_TIMEOUT_BOUNDS.maxMs,\n };\n }\n\n async publish<TMessage extends BaseMessage>(\n message: TMessage,\n options?: Partial<TransportPublishOptions>\n ): Promise<void> {\n const endpoint = options?.endpoint ?? this.defaultEndpoint ?? message.type;\n\n await this.transport.publish(message, {\n endpoint,\n ...options,\n });\n }\n\n async schedule<TMessage extends BaseMessage>(\n message: TMessage,\n delayMs: number,\n options?: Partial<TransportPublishOptions>\n ): Promise<void> {\n const endpoint = options?.endpoint ?? this.defaultEndpoint ?? message.type;\n\n await this.transport.publish(message, {\n endpoint,\n delayMs,\n ...options,\n });\n }\n\n complete(): void {\n this._isCompleted = true;\n }\n\n setMetadata(key: string, value: unknown): void {\n this.metadata[key] = value;\n }\n\n getMetadata<T = unknown>(key: string): T | undefined {\n return this.metadata[key] as T | undefined;\n }\n\n /**\n * Check if complete() was called.\n */\n get isCompleted(): boolean {\n return this._isCompleted;\n }\n\n setTimeout(delayMs: number): void {\n if (delayMs <= 0) {\n throw new Error(\"Timeout delay must be positive\");\n }\n if (delayMs < this.timeoutBounds.minMs) {\n throw new Error(\n `Timeout delay ${delayMs}ms is below minimum allowed (${this.timeoutBounds.minMs}ms)`\n );\n }\n if (delayMs > this.timeoutBounds.maxMs) {\n throw new Error(\n `Timeout delay ${delayMs}ms exceeds maximum allowed (${this.timeoutBounds.maxMs}ms)`\n );\n }\n const now = new Date();\n this._pendingTimeoutChange = {\n type: \"set\",\n timeoutMs: delayMs,\n timeoutExpiresAt: new Date(now.getTime() + delayMs),\n };\n }\n\n clearTimeout(): void {\n this._pendingTimeoutChange = {\n type: \"clear\",\n };\n }\n\n getTimeoutRemaining(): number | null {\n // If there's a pending change, use that\n if (this._pendingTimeoutChange) {\n if (this._pendingTimeoutChange.type === \"clear\") {\n return null;\n }\n if (this._pendingTimeoutChange.timeoutExpiresAt) {\n const remaining =\n this._pendingTimeoutChange.timeoutExpiresAt.getTime() - Date.now();\n return Math.max(0, remaining);\n }\n }\n\n // Otherwise use current metadata\n if (this._currentMetadata?.timeoutExpiresAt) {\n const remaining =\n this._currentMetadata.timeoutExpiresAt.getTime() - Date.now();\n return Math.max(0, remaining);\n }\n\n return null;\n }\n\n /**\n * Get any pending timeout change to be applied to saga state.\n * Used by SagaOrchestrator when updating state.\n */\n get pendingTimeoutChange(): PendingTimeoutChange | undefined {\n return this._pendingTimeoutChange;\n }\n\n /**\n * Update the current metadata reference (called after state is loaded/created).\n */\n updateCurrentMetadata(metadata: SagaStateMetadata): void {\n this._currentMetadata = metadata;\n }\n}\n","import { randomUUID } from \"node:crypto\";\n\n/**\n * Generate a unique saga ID.\n */\nexport function generateSagaId(): string {\n return randomUUID();\n}\n\n/**\n * Generate a unique message ID.\n */\nexport function generateMessageId(): string {\n return randomUUID();\n}\n\n/**\n * Create a new Date for timestamps.\n */\nexport function now(): Date {\n return new Date();\n}\n","import type {\n BaseMessage,\n MessageEnvelope,\n SagaDefinition,\n SagaState,\n SagaStore,\n SagaPipelineContext,\n Transport,\n Logger,\n SagaTimeoutExpired,\n TimeoutBounds,\n CorrelationFailureHandler,\n} from \"../types/index.js\";\nimport { SAGA_TIMEOUT_MESSAGE_TYPE } from \"../types/index.js\";\nimport { ConcurrencyError, SagaProcessingError } from \"../errors/index.js\";\nimport { SagaContextImpl } from \"./SagaContextImpl.js\";\nimport { MiddlewarePipeline } from \"./MiddlewarePipeline.js\";\nimport { generateSagaId, now } from \"./utils.js\";\n\nexport interface SagaOrchestratorOptions<\n TState extends SagaState,\n TMessages extends BaseMessage\n> {\n definition: SagaDefinition<TState, TMessages>;\n store: SagaStore<TState>;\n transport: Transport;\n pipeline: MiddlewarePipeline;\n logger: Logger;\n /** Default endpoint for publishing messages (including timeout messages) */\n defaultEndpoint?: string;\n /** Timeout bounds to validate against */\n timeoutBounds?: TimeoutBounds;\n /** Handler for messages that fail correlation */\n onCorrelationFailure?: CorrelationFailureHandler;\n}\n\n/**\n * Result of processing a message that failed correlation.\n */\nexport interface CorrelationFailureResult {\n readonly failed: true;\n readonly action: \"drop\" | \"dlq\";\n readonly messageType: string;\n}\n\n/**\n * Orchestrates saga execution for a single saga definition.\n */\nexport class SagaOrchestrator<\n TState extends SagaState,\n TMessages extends BaseMessage\n> {\n private readonly definition: SagaDefinition<TState, TMessages>;\n private readonly store: SagaStore<TState>;\n private readonly transport: Transport;\n private readonly pipeline: MiddlewarePipeline;\n private readonly logger: Logger;\n private readonly defaultEndpoint?: string;\n private readonly timeoutBounds?: TimeoutBounds;\n private readonly onCorrelationFailure?: CorrelationFailureHandler;\n\n constructor(options: SagaOrchestratorOptions<TState, TMessages>) {\n this.definition = options.definition;\n this.store = options.store;\n this.transport = options.transport;\n this.pipeline = options.pipeline;\n this.logger = options.logger;\n this.defaultEndpoint = options.defaultEndpoint;\n this.timeoutBounds = options.timeoutBounds;\n this.onCorrelationFailure = options.onCorrelationFailure;\n }\n\n /**\n * Process an incoming message.\n * @returns CorrelationFailureResult if message failed correlation, undefined otherwise\n */\n async processMessage(envelope: MessageEnvelope<TMessages>): Promise<CorrelationFailureResult | undefined> {\n const message = envelope.payload;\n const correlation = this.definition.getCorrelation(message);\n const correlationId = correlation.getCorrelationId(message);\n\n if (!correlationId) {\n this.logger.warn(\"Could not correlate message\", {\n sagaName: this.definition.name,\n messageType: message.type,\n messageId: envelope.id,\n });\n\n // Call the correlation failure handler if provided\n let action: \"drop\" | \"dlq\" = \"drop\";\n if (this.onCorrelationFailure) {\n action = await this.onCorrelationFailure({\n envelope,\n sagaName: this.definition.name,\n messageType: message.type,\n });\n }\n\n return {\n failed: true,\n action,\n messageType: message.type,\n };\n }\n\n // Load existing saga state BEFORE pipeline executes\n // This allows middleware (e.g., tracing) to access stored trace context\n const existingState = await this.store.getByCorrelationId(\n this.definition.name,\n correlationId\n );\n\n // Create pipeline context with mutable trace context\n let traceContext: { traceParent: string; traceState: string | null } | undefined;\n\n const pipelineCtx: SagaPipelineContext = {\n envelope,\n sagaName: this.definition.name,\n correlationId,\n existingState, // Provide existing state to middleware\n metadata: {},\n setTraceContext(traceParent: string, traceState: string | null) {\n traceContext = { traceParent, traceState };\n pipelineCtx.traceContext = traceContext;\n },\n };\n\n try {\n await this.pipeline.execute(pipelineCtx, async () => {\n await this.handleMessage(envelope, correlationId, correlation.canStart, existingState, pipelineCtx);\n });\n } catch (error) {\n pipelineCtx.error = error;\n // Wrap the error with context for better observability\n const wrappedError = new SagaProcessingError(\n error instanceof Error ? error : new Error(String(error)),\n {\n sagaName: this.definition.name,\n correlationId,\n sagaId: pipelineCtx.sagaId,\n messageType: message.type,\n messageId: envelope.id,\n }\n );\n throw wrappedError;\n }\n }\n\n private async handleMessage(\n envelope: MessageEnvelope<TMessages>,\n correlationId: string,\n canStart: boolean,\n existingState: TState | null,\n pipelineCtx: SagaPipelineContext\n ): Promise<void> {\n const message = envelope.payload;\n\n // Use the pre-loaded existing state\n let state = existingState;\n\n let sagaId: string;\n\n if (!state) {\n // No existing saga\n if (!canStart) {\n this.logger.debug(\"Message cannot start saga and no existing saga found\", {\n sagaName: this.definition.name,\n messageType: message.type,\n correlationId,\n });\n return;\n }\n\n // Create new saga\n sagaId = generateSagaId();\n\n const ctx = new SagaContextImpl({\n sagaName: this.definition.name,\n sagaId,\n correlationId,\n envelope,\n transport: this.transport,\n timeoutBounds: this.timeoutBounds,\n });\n\n state = await this.definition.createInitialState(message, ctx);\n\n // Ensure metadata is set correctly, including trace context if set by middleware\n state = {\n ...state,\n metadata: {\n ...state.metadata,\n sagaId,\n version: 0,\n createdAt: now(),\n updatedAt: now(),\n isCompleted: false,\n traceParent: pipelineCtx.traceContext?.traceParent ?? null,\n traceState: pipelineCtx.traceContext?.traceState ?? null,\n },\n };\n\n // Insert the new saga\n await this.store.insert(this.definition.name, correlationId, state);\n\n this.logger.info(\"Created new saga instance\", {\n sagaName: this.definition.name,\n sagaId,\n correlationId,\n messageType: message.type,\n });\n } else {\n sagaId = state.metadata.sagaId;\n }\n\n // Update pipeline context\n pipelineCtx.sagaId = sagaId;\n pipelineCtx.preState = state;\n\n // Check if saga is already completed\n if (state.metadata.isCompleted) {\n this.logger.debug(\"Ignoring message for completed saga\", {\n sagaName: this.definition.name,\n sagaId,\n messageType: message.type,\n });\n return;\n }\n\n // Create handler context with current metadata for timeout tracking\n const ctx = new SagaContextImpl({\n sagaName: this.definition.name,\n sagaId,\n correlationId,\n envelope,\n transport: this.transport,\n defaultEndpoint: this.defaultEndpoint,\n currentMetadata: state.metadata,\n timeoutBounds: this.timeoutBounds,\n });\n\n // Execute handler\n const result = await this.definition.handle(message, state, ctx);\n\n // Determine completion\n const isCompleted = result.isCompleted ?? ctx.isCompleted;\n\n // Build new metadata with timeout changes\n const expectedVersion = state.metadata.version;\n const pendingTimeout = ctx.pendingTimeoutChange;\n\n let timeoutMs = state.metadata.timeoutMs;\n let timeoutExpiresAt = state.metadata.timeoutExpiresAt;\n\n if (pendingTimeout) {\n if (pendingTimeout.type === \"clear\") {\n timeoutMs = null;\n timeoutExpiresAt = null;\n } else if (pendingTimeout.type === \"set\") {\n timeoutMs = pendingTimeout.timeoutMs ?? null;\n timeoutExpiresAt = pendingTimeout.timeoutExpiresAt ?? null;\n }\n }\n\n // Update state with new metadata\n const newState: TState = {\n ...result.newState,\n metadata: {\n ...result.newState.metadata,\n version: expectedVersion + 1,\n updatedAt: now(),\n isCompleted,\n timeoutMs,\n timeoutExpiresAt,\n },\n };\n\n // Update pipeline context\n pipelineCtx.postState = newState;\n pipelineCtx.handlerResult = result;\n\n // Persist the updated state\n try {\n await this.store.update(this.definition.name, newState, expectedVersion);\n } catch (error) {\n if (error instanceof ConcurrencyError) {\n this.logger.warn(\"Concurrency conflict, message will be retried\", {\n sagaName: this.definition.name,\n sagaId,\n expectedVersion,\n actualVersion: error.actualVersion,\n });\n }\n throw error;\n }\n\n // Schedule timeout message if timeout was set (and saga not completed)\n if (pendingTimeout?.type === \"set\" && !isCompleted && pendingTimeout.timeoutMs) {\n await this.scheduleTimeoutMessage(\n sagaId,\n correlationId,\n pendingTimeout.timeoutMs,\n pendingTimeout.timeoutExpiresAt ?? new Date()\n );\n }\n\n if (isCompleted) {\n this.logger.info(\"Saga completed\", {\n sagaName: this.definition.name,\n sagaId,\n correlationId,\n });\n } else {\n this.logger.debug(\"Saga state updated\", {\n sagaName: this.definition.name,\n sagaId,\n version: newState.metadata.version,\n });\n }\n }\n\n /**\n * Schedule a timeout message for delayed delivery.\n */\n private async scheduleTimeoutMessage(\n sagaId: string,\n correlationId: string,\n timeoutMs: number,\n timeoutExpiresAt: Date\n ): Promise<void> {\n const timeoutMessage: SagaTimeoutExpired = {\n type: SAGA_TIMEOUT_MESSAGE_TYPE,\n sagaId,\n sagaName: this.definition.name,\n correlationId,\n timeoutMs,\n timeoutSetAt: new Date(timeoutExpiresAt.getTime() - timeoutMs),\n };\n\n const endpoint = this.defaultEndpoint ?? SAGA_TIMEOUT_MESSAGE_TYPE;\n\n await this.transport.publish(timeoutMessage, {\n endpoint,\n delayMs: timeoutMs,\n key: correlationId, // Use correlation ID for ordering\n });\n\n this.logger.debug(\"Scheduled timeout message\", {\n sagaName: this.definition.name,\n sagaId,\n correlationId,\n timeoutMs,\n timeoutExpiresAt: timeoutExpiresAt.toISOString(),\n });\n }\n\n /**\n * Get the saga name.\n */\n get name(): string {\n return this.definition.name;\n }\n\n /**\n * Get the handled message types.\n */\n get handledMessageTypes(): ReadonlyArray<string> {\n return this.definition.handledMessageTypes;\n }\n}\n","import type { SagaMiddleware, SagaPipelineContext } from \"../types/index.js\";\n\n/**\n * Executes middleware in order, calling next() to proceed.\n */\nexport class MiddlewarePipeline {\n private readonly middleware: SagaMiddleware[];\n\n constructor(middleware: SagaMiddleware[] = []) {\n this.middleware = middleware;\n }\n\n /**\n * Execute the pipeline with a core handler at the end.\n */\n async execute(\n ctx: SagaPipelineContext,\n coreHandler: () => Promise<void>\n ): Promise<void> {\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index < this.middleware.length) {\n const mw = this.middleware[index];\n index++;\n if (mw) {\n await mw(ctx, next);\n }\n } else {\n // All middleware executed, run core handler\n await coreHandler();\n }\n };\n\n await next();\n }\n}\n","import type { Logger } from \"../types/index.js\";\n\n/**\n * Default console-based logger implementation.\n */\nexport class DefaultLogger implements Logger {\n private readonly prefix: string;\n\n constructor(prefix = \"[saga-bus]\") {\n this.prefix = prefix;\n }\n\n debug(message: string, meta?: Record<string, unknown>): void {\n if (meta) {\n console.debug(`${this.prefix} ${message}`, meta);\n } else {\n console.debug(`${this.prefix} ${message}`);\n }\n }\n\n info(message: string, meta?: Record<string, unknown>): void {\n if (meta) {\n console.info(`${this.prefix} ${message}`, meta);\n } else {\n console.info(`${this.prefix} ${message}`);\n }\n }\n\n warn(message: string, meta?: Record<string, unknown>): void {\n if (meta) {\n console.warn(`${this.prefix} ${message}`, meta);\n } else {\n console.warn(`${this.prefix} ${message}`);\n }\n }\n\n error(message: string, meta?: Record<string, unknown>): void {\n if (meta) {\n console.error(`${this.prefix} ${message}`, meta);\n } else {\n console.error(`${this.prefix} ${message}`);\n }\n }\n}\n","import type { ErrorHandler, SagaPipelineContext } from \"../types/index.js\";\nimport { ConcurrencyError, TransientError } from \"../errors/index.js\";\n\n/**\n * List of error types that are considered transient and should be retried.\n */\nconst TRANSIENT_ERROR_PATTERNS = [\n /ECONNREFUSED/i,\n /ECONNRESET/i,\n /ETIMEDOUT/i,\n /ENOTFOUND/i,\n /timeout/i,\n /connection.*refused/i,\n /connection.*reset/i,\n /network/i,\n /socket hang up/i,\n /EPIPE/i,\n /EHOSTUNREACH/i,\n];\n\n/**\n * Check if an error is transient based on its message.\n */\nfunction isTransientError(error: unknown): boolean {\n // Explicit TransientError\n if (error instanceof TransientError) {\n return true;\n }\n\n // ConcurrencyError is transient (optimistic locking failure)\n if (error instanceof ConcurrencyError) {\n return true;\n }\n\n // Check error message against patterns\n if (error instanceof Error) {\n const message = error.message;\n return TRANSIENT_ERROR_PATTERNS.some((pattern) => pattern.test(message));\n }\n\n return false;\n}\n\n/**\n * Default error handler implementation.\n * Classifies errors as transient (retry) or permanent (DLQ).\n */\nexport class DefaultErrorHandler implements ErrorHandler {\n async handle(\n error: unknown,\n _ctx: SagaPipelineContext\n ): Promise<\"retry\" | \"dlq\" | \"drop\"> {\n // Transient errors should be retried\n if (isTransientError(error)) {\n return \"retry\";\n }\n\n // Permanent errors go to DLQ\n return \"dlq\";\n }\n}\n\n/**\n * Create a custom error handler with additional transient patterns.\n */\nexport function createErrorHandler(options?: {\n additionalTransientPatterns?: RegExp[];\n customClassifier?: (error: unknown, ctx: SagaPipelineContext) => \"retry\" | \"dlq\" | \"drop\" | null;\n}): ErrorHandler {\n const additionalPatterns = options?.additionalTransientPatterns ?? [];\n const customClassifier = options?.customClassifier;\n\n return {\n async handle(error: unknown, ctx: SagaPipelineContext) {\n // Try custom classifier first\n if (customClassifier) {\n const result = customClassifier(error, ctx);\n if (result !== null) {\n return result;\n }\n }\n\n // Check standard transient errors\n if (isTransientError(error)) {\n return \"retry\";\n }\n\n // Check additional patterns\n if (error instanceof Error) {\n const message = error.message;\n if (additionalPatterns.some((pattern) => pattern.test(message))) {\n return \"retry\";\n }\n }\n\n return \"dlq\";\n },\n };\n}\n","import type {\n WorkerRetryPolicy,\n MessageEnvelope,\n Transport,\n Logger,\n} from \"../types/index.js\";\n\n/**\n * Header names for retry tracking.\n */\nexport const RETRY_HEADERS = {\n ATTEMPT: \"x-saga-attempt\",\n FIRST_SEEN: \"x-saga-first-seen\",\n ORIGINAL_ENDPOINT: \"x-saga-original-endpoint\",\n ERROR_MESSAGE: \"x-saga-error-message\",\n ERROR_TYPE: \"x-saga-error-type\",\n} as const;\n\n/**\n * Default retry policy.\n */\nexport const DEFAULT_RETRY_POLICY: WorkerRetryPolicy = {\n maxAttempts: 3,\n baseDelayMs: 1000,\n maxDelayMs: 30000,\n backoff: \"exponential\",\n};\n\n/**\n * Default DLQ naming function.\n */\nexport function defaultDlqNaming(endpoint: string): string {\n return `${endpoint}.dlq`;\n}\n\n/**\n * Calculate delay based on retry policy and attempt number.\n */\nexport function calculateDelay(\n policy: WorkerRetryPolicy,\n attempt: number\n): number {\n let delay: number;\n\n if (policy.backoff === \"linear\") {\n delay = policy.baseDelayMs * attempt;\n } else {\n // Exponential backoff: base * 2^(attempt-1)\n delay = policy.baseDelayMs * Math.pow(2, attempt - 1);\n }\n\n // Cap at max delay\n return Math.min(delay, policy.maxDelayMs);\n}\n\n/**\n * Extract attempt count from message headers.\n */\nexport function getAttemptCount(envelope: MessageEnvelope): number {\n const attempt = envelope.headers[RETRY_HEADERS.ATTEMPT];\n if (attempt) {\n const parsed = parseInt(attempt, 10);\n return isNaN(parsed) ? 1 : parsed;\n }\n return 1;\n}\n\n/**\n * Get the first-seen timestamp from headers.\n */\nexport function getFirstSeen(envelope: MessageEnvelope): Date {\n const firstSeen = envelope.headers[RETRY_HEADERS.FIRST_SEEN];\n if (firstSeen) {\n return new Date(firstSeen);\n }\n return envelope.timestamp;\n}\n\nexport interface RetryHandlerOptions {\n transport: Transport;\n logger: Logger;\n defaultPolicy: WorkerRetryPolicy;\n dlqNaming: (endpoint: string) => string;\n}\n\n/**\n * Handles retry logic and DLQ routing.\n */\nexport class RetryHandler {\n private readonly transport: Transport;\n private readonly logger: Logger;\n private readonly defaultPolicy: WorkerRetryPolicy;\n private readonly dlqNaming: (endpoint: string) => string;\n\n constructor(options: RetryHandlerOptions) {\n this.transport = options.transport;\n this.logger = options.logger;\n this.defaultPolicy = options.defaultPolicy;\n this.dlqNaming = options.dlqNaming;\n }\n\n /**\n * Handle a failed message - either retry or send to DLQ.\n *\n * @returns true if message was retried, false if sent to DLQ\n */\n async handleFailure(\n envelope: MessageEnvelope,\n endpoint: string,\n error: unknown,\n policy: WorkerRetryPolicy = this.defaultPolicy\n ): Promise<boolean> {\n const attempt = getAttemptCount(envelope);\n const firstSeen = getFirstSeen(envelope);\n\n if (attempt < policy.maxAttempts) {\n // Retry\n const delay = calculateDelay(policy, attempt);\n const nextAttempt = attempt + 1;\n\n this.logger.info(\"Retrying message\", {\n messageId: envelope.id,\n messageType: envelope.type,\n endpoint,\n attempt: nextAttempt,\n maxAttempts: policy.maxAttempts,\n delayMs: delay,\n });\n\n // Re-publish with updated headers\n const retryHeaders: Record<string, string> = {\n ...envelope.headers,\n [RETRY_HEADERS.ATTEMPT]: String(nextAttempt),\n [RETRY_HEADERS.FIRST_SEEN]: firstSeen.toISOString(),\n [RETRY_HEADERS.ORIGINAL_ENDPOINT]: envelope.headers[RETRY_HEADERS.ORIGINAL_ENDPOINT] ?? endpoint,\n };\n\n await this.transport.publish(envelope.payload, {\n endpoint,\n headers: retryHeaders,\n delayMs: delay,\n key: envelope.partitionKey,\n });\n\n return true;\n }\n\n // Max attempts exceeded - send to DLQ\n await this.sendToDlq(envelope, endpoint, error);\n return false;\n }\n\n /**\n * Send a message to the dead-letter queue.\n */\n async sendToDlq(\n envelope: MessageEnvelope,\n originalEndpoint: string,\n error: unknown\n ): Promise<void> {\n const dlqEndpoint = this.dlqNaming(originalEndpoint);\n const attempt = getAttemptCount(envelope);\n const firstSeen = getFirstSeen(envelope);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorType = error instanceof Error ? error.name : \"UnknownError\";\n\n this.logger.warn(\"Sending message to DLQ\", {\n messageId: envelope.id,\n messageType: envelope.type,\n originalEndpoint,\n dlqEndpoint,\n attempts: attempt,\n firstSeen: firstSeen.toISOString(),\n error: errorMessage,\n });\n\n const dlqHeaders: Record<string, string> = {\n ...envelope.headers,\n [RETRY_HEADERS.ATTEMPT]: String(attempt),\n [RETRY_HEADERS.FIRST_SEEN]: firstSeen.toISOString(),\n [RETRY_HEADERS.ORIGINAL_ENDPOINT]: envelope.headers[RETRY_HEADERS.ORIGINAL_ENDPOINT] ?? originalEndpoint,\n [RETRY_HEADERS.ERROR_MESSAGE]: errorMessage,\n [RETRY_HEADERS.ERROR_TYPE]: errorType,\n };\n\n await this.transport.publish(envelope.payload, {\n endpoint: dlqEndpoint,\n headers: dlqHeaders,\n key: envelope.partitionKey,\n });\n }\n}\n","import type {\n Bus,\n BusConfig,\n BaseMessage,\n TransportPublishOptions,\n SagaState,\n Logger,\n ErrorHandler,\n WorkerRetryPolicy,\n} from \"../types/index.js\";\nimport { SagaOrchestrator } from \"./SagaOrchestrator.js\";\nimport { MiddlewarePipeline } from \"./MiddlewarePipeline.js\";\nimport { DefaultLogger } from \"./DefaultLogger.js\";\nimport { DefaultErrorHandler } from \"./DefaultErrorHandler.js\";\nimport { SagaProcessingError } from \"../errors/index.js\";\nimport {\n RetryHandler,\n DEFAULT_RETRY_POLICY,\n defaultDlqNaming,\n getAttemptCount,\n} from \"./RetryHandler.js\";\n\n/**\n * Main bus implementation with retry and DLQ support.\n */\nexport class BusImpl implements Bus {\n private readonly config: BusConfig;\n private readonly logger: Logger;\n private readonly errorHandler: ErrorHandler;\n private readonly pipeline: MiddlewarePipeline;\n private readonly orchestrators: SagaOrchestrator<SagaState, BaseMessage>[];\n private readonly retryHandler: RetryHandler;\n private readonly defaultRetryPolicy: WorkerRetryPolicy;\n private started = false;\n\n constructor(config: BusConfig) {\n this.config = config;\n this.logger = config.logger ?? new DefaultLogger();\n this.errorHandler = config.errorHandler ?? new DefaultErrorHandler();\n this.pipeline = new MiddlewarePipeline(config.middleware ? [...config.middleware] : []);\n\n // Set up retry configuration\n this.defaultRetryPolicy = config.worker?.retryPolicy ?? DEFAULT_RETRY_POLICY;\n const dlqNaming = config.worker?.dlqNaming ?? defaultDlqNaming;\n\n this.retryHandler = new RetryHandler({\n transport: config.transport,\n logger: this.logger,\n defaultPolicy: this.defaultRetryPolicy,\n dlqNaming,\n });\n\n // Create orchestrators for each registered saga\n this.orchestrators = config.sagas.map((registration) => {\n // Resolve store: per-saga store takes precedence over default store\n const store = registration.store ?? config.store;\n if (!store) {\n throw new Error(\n `Saga \"${registration.definition.name}\" has no store. ` +\n `Provide a store in the saga registration or set a default store in BusConfig.`\n );\n }\n\n return new SagaOrchestrator({\n definition: registration.definition,\n store,\n transport: config.transport,\n pipeline: this.pipeline,\n logger: this.logger,\n timeoutBounds: config.worker?.timeoutBounds,\n onCorrelationFailure: config.worker?.onCorrelationFailure,\n });\n });\n }\n\n async start(): Promise<void> {\n if (this.started) {\n return;\n }\n\n this.logger.info(\"Starting saga bus...\");\n\n // Start the transport\n await this.config.transport.start();\n\n // Subscribe to endpoints for each saga's message types\n const subscribed = new Set<string>();\n\n for (const orchestrator of this.orchestrators) {\n for (const messageType of orchestrator.handledMessageTypes) {\n const endpoint = messageType;\n const subscriptionKey = endpoint;\n\n if (subscribed.has(subscriptionKey)) {\n continue;\n }\n subscribed.add(subscriptionKey);\n\n const concurrency =\n this.config.worker?.sagas?.[orchestrator.name]?.concurrency ??\n this.config.worker?.defaultConcurrency ??\n 1;\n\n await this.config.transport.subscribe(\n { endpoint, concurrency },\n async (envelope) => {\n const handlers = this.orchestrators.filter((o) =>\n o.handledMessageTypes.includes(envelope.type)\n );\n\n for (const handler of handlers) {\n // Get the retry policy for this specific saga\n const retryPolicy =\n this.config.worker?.sagas?.[handler.name]?.retryPolicy ??\n this.defaultRetryPolicy;\n\n try {\n const result = await handler.processMessage(envelope);\n\n // Handle correlation failures\n if (result?.failed) {\n if (result.action === \"dlq\") {\n await this.retryHandler.sendToDlq(\n envelope,\n endpoint,\n new Error(`Correlation failed for message type ${result.messageType}`)\n );\n }\n // action === \"drop\" means we just drop the message (default behavior)\n continue;\n }\n } catch (error) {\n // Extract context from SagaProcessingError if available\n const errorContext = SagaProcessingError.extractContext(error);\n const originalError = error instanceof SagaProcessingError ? error.cause : error;\n\n // Log the error with full context\n this.logger.error(\"Error processing message\", {\n sagaName: handler.name,\n messageType: envelope.type,\n messageId: envelope.id,\n correlationId: errorContext?.correlationId,\n sagaId: errorContext?.sagaId,\n attempt: getAttemptCount(envelope),\n error: originalError instanceof Error ? originalError.message : String(originalError),\n });\n\n // Classify the error - pass the original error and rich context\n const action = await this.errorHandler.handle(originalError, {\n envelope,\n sagaName: handler.name,\n correlationId: errorContext?.correlationId ?? \"\",\n metadata: {\n sagaId: errorContext?.sagaId,\n },\n error: originalError,\n setTraceContext: () => {}, // No-op for error context\n });\n\n if (action === \"retry\") {\n await this.retryHandler.handleFailure(\n envelope,\n endpoint,\n error,\n retryPolicy\n );\n } else if (action === \"dlq\") {\n await this.retryHandler.sendToDlq(envelope, endpoint, error);\n }\n // action === \"drop\" means we just drop the message\n\n // Don't re-throw - we've handled the error\n }\n }\n }\n );\n\n this.logger.debug(\"Subscribed to endpoint\", {\n endpoint,\n messageType,\n concurrency,\n });\n }\n }\n\n this.started = true;\n this.logger.info(\"Saga bus started\", {\n sagaCount: this.orchestrators.length,\n endpointCount: subscribed.size,\n });\n }\n\n async stop(): Promise<void> {\n if (!this.started) {\n return;\n }\n\n this.logger.info(\"Stopping saga bus...\");\n\n // Stop the transport (handles graceful shutdown)\n await this.config.transport.stop();\n\n this.started = false;\n this.logger.info(\"Saga bus stopped\");\n }\n\n isRunning(): boolean {\n return this.started;\n }\n\n async publish<TMessage extends BaseMessage>(\n message: TMessage,\n options?: Partial<TransportPublishOptions>\n ): Promise<void> {\n const endpoint = options?.endpoint ?? message.type;\n\n await this.config.transport.publish(message, {\n endpoint,\n ...options,\n });\n }\n}\n\n/**\n * Create a new bus instance.\n */\nexport function createBus(config: BusConfig): Bus {\n return new BusImpl(config);\n}\n"],"mappings":"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","names":["now","ctx"]}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@saga-bus/core",
3
+ "version": "0.1.0",
4
+ "description": "Core types, DSL, and runtime for saga-bus message orchestration",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/deanforan/saga-bus.git",
26
+ "directory": "packages/core"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/deanforan/saga-bus/issues"
30
+ },
31
+ "homepage": "https://github.com/deanforan/saga-bus#readme",
32
+ "keywords": [
33
+ "saga",
34
+ "message-bus",
35
+ "orchestration",
36
+ "state-machine",
37
+ "typescript"
38
+ ],
39
+ "devDependencies": {
40
+ "@types/node": "^20.0.0",
41
+ "tsup": "^8.0.0",
42
+ "typescript": "^5.9.2",
43
+ "vitest": "^3.0.0",
44
+ "@repo/eslint-config": "0.0.0",
45
+ "@repo/typescript-config": "0.0.0"
46
+ },
47
+ "peerDependencies": {
48
+ "typescript": ">=5.5.0"
49
+ },
50
+ "scripts": {
51
+ "build": "tsup",
52
+ "dev": "tsup --watch",
53
+ "lint": "eslint src/",
54
+ "check-types": "tsc --noEmit",
55
+ "test": "vitest run",
56
+ "test:watch": "vitest"
57
+ }
58
+ }