{"version":3,"sources":["../src/index.ts","../src/core/constants.ts","../src/core/config-presets.ts","../src/core/config.ts","../src/core/connection.ts","../src/core/duration.ts","../src/core/subject.ts","../src/core/errors.ts","../src/core/health-check.ts","../src/core/presets.ts","../src/core/structured-logger.ts","../src/core/schema-validator.ts","../src/core/circuit-breaker.ts","../src/core/validation.ts","../src/publisher/publisher.ts","../src/publisher/envelope-builder.ts","../src/publisher/subject-builder.ts","../src/publisher/publish-validator.ts","../src/publisher/publish-result.ts","../src/publisher/fluent-batch.ts","../src/publisher/batch-publisher.ts","../src/subscribers/consumer.ts","../src/middleware/chain.ts","../src/topology/topology-manager.ts","../src/dlq/dlq-handler.ts","../src/subscribers/registry.ts","../src/subscribers/message-processor.ts","../src/subscribers/subscriber.ts","../src/subscribers/graceful-shutdown.ts","../src/types.ts","../src/subscribers/error-handler.ts","../src/dlq/dlq-consumer.ts","../src/middleware/logging.ts","../src/middleware/retry-logger.ts","../src/testing/test-harness.ts","../src/testing/index.ts","../src/outbox/types.ts","../src/outbox/outbox-publisher.ts","../src/outbox/memory-outbox-repository.ts","../src/outbox/sql-schemas.ts","../src/inbox/types.ts","../src/inbox/inbox-processor.ts","../src/inbox/memory-inbox-repository.ts","../src/inbox/sql-schemas.ts"],"sourcesContent":["// Core\nexport { default as config } from './core/config';\nexport { default as connection } from './core/connection';\nexport { parseDuration, toNanos, fromNanos } from './core/duration';\nexport { Subject } from './core/subject';\nexport {\n  NatsPubsubError,\n  ConnectionError,\n  PublishError,\n  SubscriptionError,\n  TopologyError,\n  DlqError,\n  ConfigurationError,\n  TimeoutError,\n} from './core/errors';\nexport { HealthCheck, HealthCheckResult, ComponentHealth } from './core/health-check';\nexport { Presets } from './core/presets';\nexport { StructuredLogger, LoggerFactory } from './core/structured-logger';\nexport type { LogLevel, LogEntry } from './core/structured-logger';\nexport {\n  SchemaValidator,\n  createValidator,\n  validateSchema,\n  CommonSchemas,\n  createMessageSchema,\n} from './core/schema-validator';\nexport type { ValidationResult, ValidationErrorDetail } from './core/schema-validator';\nexport {\n  CircuitBreaker,\n  CircuitBreakerError,\n  createCircuitBreaker,\n  CircuitState,\n} from './core/circuit-breaker';\nexport type { CircuitBreakerOptions, CircuitBreakerStats } from './core/circuit-breaker';\n\n// Validation\nexport {\n  validate,\n  validateConfig,\n  validateMetadata,\n  createValidatedSubscriber,\n  ValidationError,\n  EventMetadataSchema,\n  ConfigSchema,\n  z,\n} from './core/validation';\n\n// Publisher\nexport { Publisher, default as publisher } from './publisher/publisher';\nexport { FluentBatchPublisher, FluentBatchPublishResult } from './publisher/fluent-batch';\nexport { BatchPublisher, BatchPublishResult } from './publisher/batch-publisher';\n\n// Consumer\nexport { Consumer, default as consumer } from './subscribers/consumer';\n\n// Subscriber\nexport { subscriber, Subscriber } from './subscribers/subscriber';\nexport { GracefulShutdown } from './subscribers/graceful-shutdown';\nexport type { GracefulShutdownOptions } from './subscribers/graceful-shutdown';\nexport { ErrorHandler } from './subscribers/error-handler';\n\n// DLQ\nexport { DlqHandler } from './dlq/dlq-handler';\nexport {\n  DlqConsumer,\n  DlqMessage,\n  DlqHandler as IDlqHandler,\n  PersistentDlqStore,\n  LoggingDlqHandler,\n  AlertDlqHandler,\n  StorageDlqHandler,\n  default as dlqConsumer,\n} from './dlq/dlq-consumer';\n\n// Topology\nexport { TopologyManager } from './topology/topology-manager';\n\n// Registry\nexport { Registry } from './subscribers/registry';\n\n// Middleware\nexport { MiddlewareChain } from './middleware/chain';\nexport { LoggingMiddleware, default as loggingMiddleware } from './middleware/logging';\nexport { RetryLoggerMiddleware, default as retryLoggerMiddleware } from './middleware/retry-logger';\n\n// Types\nexport * from './types';\nexport type {\n  MessageContext,\n  ErrorAction,\n  ErrorContext,\n  RetryStrategy,\n  CircuitBreakerConfig,\n  DlqConfig,\n} from './types';\n\n// Testing utilities\nexport * from './testing';\n\n// Outbox Pattern (Reliable Message Publishing)\nexport * from './outbox';\n\n// Inbox Pattern (Idempotent Message Processing)\nexport * from './inbox';\n\n// Main API\nimport config from './core/config';\nimport publisher from './publisher/publisher';\nimport consumer from './subscribers/consumer';\nimport connection from './core/connection';\nimport { TopologyManager } from './topology/topology-manager';\nimport { HealthCheck } from './core/health-check';\nimport { FluentBatchPublisher } from './publisher/fluent-batch';\n\n/**\n * Main NatsPubsub API\n * Provides a unified interface for all NatsPubsub functionality\n */\nexport const NatsPubsub = {\n  // Configuration\n  configure: config.configure.bind(config),\n  getConfig: () => config.get(),\n  validate: () => config.validate(),\n\n  // Connection & Topology\n  connect: connection.connect.bind(connection),\n  disconnect: connection.disconnect.bind(connection),\n  ensureConnection: connection.ensureConnection.bind(connection),\n\n  // Health checks\n  healthCheck: HealthCheck.check.bind(HealthCheck),\n  quickHealthCheck: HealthCheck.quickCheck.bind(HealthCheck),\n  healthCheckMiddleware: HealthCheck.middleware.bind(HealthCheck),\n  quickHealthCheckMiddleware: HealthCheck.quickMiddleware.bind(HealthCheck),\n\n  /**\n   * Ensure JetStream topology is set up\n   * Creates necessary streams and consumers\n   */\n  async ensureTopology(): Promise<void> {\n    await connection.ensureConnection();\n    const nc = connection.getConnection();\n    const jsm = await nc.jetstreamManager();\n    const topologyManager = new TopologyManager();\n    await topologyManager.ensureTopology(jsm);\n  },\n\n  /**\n   * Setup and connect in one call\n   * Combines configure + ensureTopology for simpler initialization\n   *\n   * @example\n   * await NatsPubsub.setup({\n   *   env: 'production',\n   *   appName: 'my-service',\n   *   natsUrls: 'nats://nats.example.com:4222'\n   * });\n   */\n  async setup(options?: Parameters<typeof config.configure>[0]): Promise<void> {\n    if (options) {\n      config.configure(options);\n    }\n    config.validate();\n    await this.ensureTopology();\n  },\n\n  // Publishing\n  publish: publisher.publish.bind(publisher),\n\n  /**\n   * Create a batch publisher for publishing multiple messages efficiently\n   *\n   * @example\n   * ```typescript\n   * const result = await NatsPubsub.batch()\n   *   .add('user.created', { id: 1, name: 'Alice' })\n   *   .add('notification.sent', { userId: 1 })\n   *   .withOptions({ traceId: 'batch-123' })\n   *   .publish();\n   * ```\n   */\n  batch(): FluentBatchPublisher {\n    return new FluentBatchPublisher(publisher);\n  },\n\n  // Subscribing\n  registerSubscriber: consumer.registerSubscriber.bind(consumer),\n  use: consumer.use.bind(consumer),\n  start: consumer.start.bind(consumer),\n  stop: consumer.stop.bind(consumer),\n\n  // Configuration helpers\n  get useDlq(): boolean {\n    return config.get().useDlq ?? true;\n  },\n\n  get useOutbox(): boolean {\n    return config.get().useOutbox ?? false;\n  },\n\n  get useInbox(): boolean {\n    return config.get().useInbox ?? false;\n  },\n};\n\nexport default NatsPubsub;\n","/**\n * Centralized constants for the library\n * Extracts magic numbers and strings into named, documented constants\n */\n\n/**\n * Timeout-related constants\n */\nexport const Timeouts = {\n  /** Default acknowledgment wait time in milliseconds */\n  ACK_WAIT_DEFAULT: 30_000, // 30 seconds\n\n  /** Default idle wait time in milliseconds */\n  IDLE_WAIT_DEFAULT: 100, // 100ms\n\n  /** Default connection timeout in milliseconds */\n  CONNECTION_TIMEOUT: 5_000, // 5 seconds\n\n  /** Default request timeout for management operations */\n  MANAGEMENT_TIMEOUT: 10_000, // 10 seconds\n\n  /** Default message processing timeout */\n  PROCESSING_TIMEOUT: 60_000, // 60 seconds\n} as const;\n\n/**\n * Retry strategy constants\n */\nexport const Retry = {\n  /** Default exponential backoff delays in milliseconds */\n  DEFAULT_BACKOFF: [1_000, 5_000, 15_000, 30_000, 60_000] as const,\n\n  /** Maximum number of delivery attempts before sending to DLQ */\n  MAX_ATTEMPTS: 5,\n\n  /** Base delay for transient errors (milliseconds) */\n  TRANSIENT_BASE_DELAY: 500,\n\n  /** Base delay for persistent errors (milliseconds) */\n  PERSISTENT_BASE_DELAY: 2_000,\n\n  /** Maximum backoff delay cap (milliseconds) */\n  MAX_BACKOFF_CAP: 60_000, // 60 seconds\n} as const;\n\n/**\n * Dead Letter Queue constants\n */\nexport const DLQ = {\n  /** Default retention period for DLQ messages (30 days in nanoseconds) */\n  RETENTION_PERIOD: 30 * 24 * 60 * 60 * 1_000_000_000,\n\n  /** DLQ stream suffix */\n  STREAM_SUFFIX: '-dlq',\n\n  /** Maximum attempts before moving to DLQ */\n  MAX_ATTEMPTS: 3,\n} as const;\n\n/**\n * Stream and consumer configuration constants\n */\nexport const Stream = {\n  /** Default stream retention policy */\n  RETENTION_POLICY: 'limits' as const, // limits, interest, workqueue\n\n  /** Default storage type */\n  STORAGE_TYPE: 'file' as const, // file or memory\n\n  /** Default max message age (7 days in nanoseconds) */\n  MAX_AGE: 7 * 24 * 60 * 60 * 1_000_000_000,\n\n  /** Default max messages per stream */\n  MAX_MESSAGES: 1_000_000,\n\n  /** Default max bytes per stream (1GB) */\n  MAX_BYTES: 1_073_741_824,\n} as const;\n\n/**\n * Consumer configuration constants\n */\nexport const Consumer = {\n  /** Default concurrency level */\n  DEFAULT_CONCURRENCY: 5,\n\n  /** Minimum concurrency */\n  MIN_CONCURRENCY: 1,\n\n  /** Maximum concurrency (prevents resource exhaustion) */\n  MAX_CONCURRENCY: 1000,\n\n  /** Default batch size for pull consumers */\n  BATCH_SIZE: 10,\n\n  /** Maximum batch size */\n  MAX_BATCH_SIZE: 256,\n} as const;\n\n/**\n * Subject pattern constants\n */\nexport const Subject = {\n  /** Wildcard for matching one level */\n  SINGLE_LEVEL_WILDCARD: '*',\n\n  /** Wildcard for matching multiple levels */\n  MULTI_LEVEL_WILDCARD: '>',\n\n  /** Subject token separator */\n  SEPARATOR: '.',\n\n  /** Maximum subject length */\n  MAX_LENGTH: 255,\n} as const;\n\n/**\n * Envelope schema constants\n */\nexport const Envelope = {\n  /** Current schema version */\n  SCHEMA_VERSION: 1,\n\n  /** Required envelope fields */\n  REQUIRED_FIELDS: ['event_id', 'schema_version', 'producer', 'occurred_at'] as const,\n\n  /** Topic envelope required fields */\n  TOPIC_REQUIRED_FIELDS: [\n    'event_id',\n    'schema_version',\n    'producer',\n    'occurred_at',\n    'topic',\n    'message',\n  ] as const,\n\n  /** Event envelope required fields (legacy) */\n  EVENT_REQUIRED_FIELDS: [\n    'event_id',\n    'schema_version',\n    'producer',\n    'occurred_at',\n    'domain',\n    'resource',\n    'action',\n    'payload',\n  ] as const,\n} as const;\n\n/**\n * Error classification constants\n */\nexport const Errors = {\n  /** Errors that should not be retried */\n  UNRECOVERABLE_ERRORS: ['TypeError', 'ReferenceError', 'SyntaxError', 'ValidationError'] as const,\n\n  /** Errors indicating malformed messages */\n  MALFORMED_ERRORS: ['SyntaxError', 'JSON.parse error'] as const,\n\n  /** Transient errors that should be retried */\n  TRANSIENT_ERRORS: [\n    'TimeoutError',\n    'ConnectionError',\n    'ECONNREFUSED',\n    'ETIMEDOUT',\n    'ENOTFOUND',\n  ] as const,\n} as const;\n\n/**\n * Logging constants\n */\nexport const Logging = {\n  /** Default log level */\n  DEFAULT_LEVEL: 'info' as const,\n\n  /** Available log levels */\n  LEVELS: ['debug', 'info', 'warn', 'error', 'fatal'] as const,\n\n  /** Structured log field names */\n  FIELDS: {\n    EVENT_ID: 'event_id',\n    TRACE_ID: 'trace_id',\n    SUBJECT: 'subject',\n    TOPIC: 'topic',\n    DELIVERY_COUNT: 'delivery_count',\n    ELAPSED_MS: 'elapsed_ms',\n    ERROR_CLASS: 'error_class',\n    ERROR_MESSAGE: 'error_message',\n  } as const,\n} as const;\n\n/**\n * Health check constants\n */\nexport const HealthCheck = {\n  /** Quick check timeout (milliseconds) */\n  QUICK_TIMEOUT: 5_000,\n\n  /** Full check timeout (milliseconds) */\n  FULL_TIMEOUT: 30_000,\n\n  /** Health check statuses */\n  HEALTHY: 'healthy' as const,\n  DEGRADED: 'degraded' as const,\n  UNHEALTHY: 'unhealthy' as const,\n} as const;\n\n/**\n * Circuit breaker constants\n */\nexport const CircuitBreaker = {\n  /** Default failure threshold */\n  FAILURE_THRESHOLD: 5,\n\n  /** Default success threshold for half-open state */\n  SUCCESS_THRESHOLD: 2,\n\n  /** Default timeout before attempting recovery (milliseconds) */\n  TIMEOUT: 60_000,\n\n  /** States */\n  CLOSED: 'closed' as const,\n  OPEN: 'open' as const,\n  HALF_OPEN: 'half_open' as const,\n} as const;\n","/**\n * Configuration presets for common deployment scenarios\n * Provides smart defaults for development, production, and testing environments\n */\n\nimport type { NatsPubsubConfig } from '../types';\nimport { Consumer, Retry, Timeouts, DLQ } from './constants';\n\nexport type PresetName = 'development' | 'production' | 'testing';\n\n/**\n * Configuration preset definitions\n */\nexport class ConfigPresets {\n  /**\n   * Apply a preset to a configuration object\n   *\n   * @param config - Partial configuration object to modify\n   * @param preset - Preset name (development, production, testing)\n   * @returns Configuration with preset applied\n   */\n  static apply(config: Partial<NatsPubsubConfig>, preset: PresetName): Partial<NatsPubsubConfig> {\n    switch (preset) {\n      case 'development':\n        return this.applyDevelopment(config);\n      case 'production':\n        return this.applyProduction(config);\n      case 'testing':\n        return this.applyTesting(config);\n      default:\n        throw new Error(`Unknown preset: ${preset}. Available: development, production, testing`);\n    }\n  }\n\n  /**\n   * Get preset description\n   *\n   * @param preset - Preset name\n   * @returns Description of the preset\n   */\n  static description(preset: PresetName): string {\n    return PRESET_DESCRIPTIONS[preset] || `Unknown preset: ${preset}`;\n  }\n\n  /**\n   * List all available presets\n   *\n   * @returns Array of available preset names\n   */\n  static availablePresets(): PresetName[] {\n    return ['development', 'production', 'testing'];\n  }\n\n  /**\n   * Development preset - optimized for local development\n   * - Verbose logging for debugging\n   * - Lower concurrency to avoid resource exhaustion\n   * - DLQ enabled for debugging failed messages\n   * - Shorter timeouts for faster feedback\n   */\n  private static applyDevelopment(config: Partial<NatsPubsubConfig>): Partial<NatsPubsubConfig> {\n    return {\n      ...config,\n      env: config.env || 'development',\n      concurrency: Consumer.DEFAULT_CONCURRENCY,\n      maxDeliver: 3, // Fail faster in development\n      ackWait: 10_000, // 10 seconds - shorter for faster feedback\n      backoff: [500, 2_000, 5_000], // Faster retries\n      useDlq: true,\n      dlqMaxAttempts: 2, // Fail to DLQ faster for debugging\n    };\n  }\n\n  /**\n   * Production preset - optimized for reliability and performance\n   * - Error-level logging to reduce noise\n   * - Higher concurrency for throughput\n   * - DLQ enabled for failure recovery\n   * - Longer timeouts for stability\n   */\n  private static applyProduction(config: Partial<NatsPubsubConfig>): Partial<NatsPubsubConfig> {\n    return {\n      ...config,\n      env: config.env || 'production',\n      concurrency: 20, // Higher throughput\n      maxDeliver: Retry.MAX_ATTEMPTS,\n      ackWait: Timeouts.ACK_WAIT_DEFAULT,\n      backoff: [...Retry.DEFAULT_BACKOFF],\n      useDlq: true,\n      dlqMaxAttempts: DLQ.MAX_ATTEMPTS,\n    };\n  }\n\n  /**\n   * Testing preset - optimized for test suite performance\n   * - Minimal logging to avoid test output noise\n   * - Low concurrency for deterministic behavior\n   * - DLQ disabled (tests should verify behavior directly)\n   * - Fast timeouts\n   */\n  private static applyTesting(config: Partial<NatsPubsubConfig>): Partial<NatsPubsubConfig> {\n    return {\n      ...config,\n      env: config.env || 'test',\n      concurrency: 1, // Synchronous processing\n      maxDeliver: 2, // Fail fast in tests\n      ackWait: 1_000, // Fast timeout\n      backoff: [100, 500], // Minimal retries\n      useDlq: false, // Disabled for speed\n      dlqMaxAttempts: 1,\n    };\n  }\n}\n\n/**\n * Preset descriptions for documentation\n */\nconst PRESET_DESCRIPTIONS: Record<PresetName, string> = {\n  development: 'Optimized for local development with verbose logging and fast feedback',\n  production: 'Optimized for reliability and performance in production environments',\n  testing: 'Optimized for test suite performance with synchronous processing',\n};\n","import { NatsPubsubConfig, Logger } from '../types';\nimport { Consumer, Retry, Timeouts, DLQ } from './constants';\nimport { ConfigPresets, PresetName } from './config-presets';\n\n/**\n * Configuration validation error\n */\nexport class ConfigurationError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'ConfigurationError';\n    Object.setPrototypeOf(this, ConfigurationError.prototype);\n  }\n}\n\nclass Config {\n  private config: NatsPubsubConfig;\n  private preset?: PresetName;\n\n  constructor() {\n    this.config = {\n      natsUrls: 'nats://localhost:4222',\n      env: process.env.NODE_ENV || 'development',\n      appName: process.env.APP_NAME || 'app',\n      concurrency: Consumer.DEFAULT_CONCURRENCY,\n      maxDeliver: Retry.MAX_ATTEMPTS,\n      ackWait: Timeouts.ACK_WAIT_DEFAULT,\n      backoff: [...Retry.DEFAULT_BACKOFF],\n      useOutbox: false,\n      useInbox: false,\n      useDlq: true,\n      perMessageConcurrency: Consumer.DEFAULT_CONCURRENCY,\n      subscriberTimeoutMs: Timeouts.PROCESSING_TIMEOUT,\n      dlqMaxAttempts: DLQ.MAX_ATTEMPTS,\n    };\n  }\n\n  public configure(options: Partial<NatsPubsubConfig>): void {\n    this.config = { ...this.config, ...options };\n    this.validate();\n  }\n\n  /**\n   * Configure with a preset\n   *\n   * @param preset - Preset name (development, production, testing)\n   * @param overrides - Optional overrides to apply after preset\n   */\n  public configureWithPreset(preset: PresetName, overrides?: Partial<NatsPubsubConfig>): void {\n    this.preset = preset;\n    const presetConfig = ConfigPresets.apply(this.config, preset);\n    this.config = { ...this.config, ...presetConfig, ...overrides } as NatsPubsubConfig;\n    this.validate();\n  }\n\n  /**\n   * Get the current preset name\n   */\n  public getPreset(): PresetName | undefined {\n    return this.preset;\n  }\n\n  public get(): NatsPubsubConfig {\n    return this.config;\n  }\n\n  public get streamName(): string {\n    return this.config.streamName || `${this.config.env}-events-stream`;\n  }\n\n  /**\n   * DLQ subject for failed messages\n   */\n  public get dlqSubject(): string {\n    return this.config.dlqSubject || `${this.config.env}.${this.config.appName}.dlq`;\n  }\n\n  /**\n   * Build event subject\n   * Format: {env}.{app_name}.{domain}.{resource}.{action}\n   *\n   * @param domain - Business domain\n   * @param resource - Resource type\n   * @param action - Event action\n   * @returns NATS subject string\n   */\n  public eventSubject(domain: string, resource: string, action: string): string {\n    return `${this.config.env}.${this.config.appName}.${domain}.${resource}.${action}`;\n  }\n\n  public get logger(): Logger {\n    if (this.config.logger) {\n      return this.config.logger;\n    }\n    // Default console logger\n    return {\n      debug: (message: string, meta?: Record<string, unknown>) => {\n        if (process.env.NODE_ENV !== 'production') {\n          console.debug(message, meta || '');\n        }\n      },\n      info: (message: string, meta?: Record<string, unknown>) => console.info(message, meta || ''),\n      warn: (message: string, meta?: Record<string, unknown>) => console.warn(message, meta || ''),\n      error: (message: string, meta?: Record<string, unknown>) =>\n        console.error(message, meta || ''),\n    };\n  }\n\n  /**\n   * Validate configuration values\n   * Throws ConfigurationError if invalid\n   */\n  public validate(): void {\n    this.validateRequiredFields();\n    this.validateNumericRanges();\n    this.validateUrls();\n  }\n\n  /**\n   * Validate required configuration fields\n   */\n  private validateRequiredFields(): void {\n    if (!this.config.appName || this.config.appName.trim() === '') {\n      throw new ConfigurationError('appName cannot be blank');\n    }\n\n    if (!this.config.env || this.config.env.trim() === '') {\n      throw new ConfigurationError('env cannot be blank');\n    }\n\n    if (!this.config.natsUrls || this.config.natsUrls.length === 0) {\n      throw new ConfigurationError('natsUrls cannot be empty');\n    }\n  }\n\n  /**\n   * Validate numeric configuration values are within acceptable ranges\n   */\n  private validateNumericRanges(): void {\n    if (this.config.concurrency !== undefined && this.config.concurrency <= 0) {\n      throw new ConfigurationError('concurrency must be positive');\n    }\n\n    // Validate concurrency bounds\n    if (this.config.concurrency !== undefined) {\n      if (this.config.concurrency < Consumer.MIN_CONCURRENCY) {\n        throw new ConfigurationError(\n          `concurrency must be at least ${Consumer.MIN_CONCURRENCY}, got ${this.config.concurrency}`\n        );\n      }\n      if (this.config.concurrency > Consumer.MAX_CONCURRENCY) {\n        throw new ConfigurationError(\n          `concurrency cannot exceed ${Consumer.MAX_CONCURRENCY}, got ${this.config.concurrency}`\n        );\n      }\n    }\n\n    if (this.config.maxDeliver !== undefined && this.config.maxDeliver <= 0) {\n      throw new ConfigurationError('maxDeliver must be positive');\n    }\n\n    if (this.config.dlqMaxAttempts !== undefined && this.config.dlqMaxAttempts <= 0) {\n      throw new ConfigurationError('dlqMaxAttempts must be positive');\n    }\n\n    if (this.config.ackWait !== undefined && this.config.ackWait <= 0) {\n      throw new ConfigurationError('ackWait must be positive');\n    }\n\n    if (this.config.perMessageConcurrency !== undefined && this.config.perMessageConcurrency <= 0) {\n      throw new ConfigurationError('perMessageConcurrency must be positive');\n    }\n\n    if (this.config.subscriberTimeoutMs !== undefined && this.config.subscriberTimeoutMs < 0) {\n      throw new ConfigurationError('subscriberTimeoutMs must be non-negative');\n    }\n\n    if (this.config.backoff) {\n      if (!Array.isArray(this.config.backoff)) {\n        throw new ConfigurationError('backoff must be an array');\n      }\n\n      if (this.config.backoff.some((ms) => ms <= 0)) {\n        throw new ConfigurationError('backoff values must be positive');\n      }\n    }\n  }\n\n  /**\n   * Validate NATS URLs format\n   */\n  private validateUrls(): void {\n    const urls = Array.isArray(this.config.natsUrls)\n      ? this.config.natsUrls\n      : [this.config.natsUrls];\n\n    for (const url of urls) {\n      if (!/^nats:\\/\\//i.test(url)) {\n        throw new ConfigurationError(`Invalid NATS URL: ${url}`);\n      }\n    }\n  }\n}\n\nexport default new Config();\n","import { connect, NatsConnection, JetStreamClient } from 'nats';\nimport { ConnectionManager } from '../types';\nimport config from './config';\n\nclass Connection implements ConnectionManager {\n  public connection: NatsConnection | null = null;\n  public jetstream: JetStreamClient | null = null;\n  private connecting: Promise<void> | null = null;\n\n  async connect(): Promise<void> {\n    if (this.connecting) {\n      return this.connecting;\n    }\n\n    if (this.connection) {\n      return;\n    }\n\n    this.connecting = this._connect();\n    await this.connecting;\n    this.connecting = null;\n  }\n\n  private async _connect(): Promise<void> {\n    const cfg = config.get();\n    const logger = config.logger;\n\n    try {\n      logger.info('Connecting to NATS...', { urls: cfg.natsUrls });\n\n      const servers = Array.isArray(cfg.natsUrls) ? cfg.natsUrls : [cfg.natsUrls];\n\n      this.connection = await connect({\n        servers,\n        name: cfg.appName,\n        maxReconnectAttempts: -1, // Unlimited reconnects\n        reconnectTimeWait: 1000, // 1 second\n        waitOnFirstConnect: true,\n      });\n\n      logger.info('Connected to NATS successfully');\n\n      this.jetstream = this.connection.jetstream();\n      logger.info('JetStream client initialized');\n\n      // Handle connection events\n      this.setupEventHandlers();\n    } catch (error) {\n      logger.error('Failed to connect to NATS', { error });\n      throw error;\n    }\n  }\n\n  private setupEventHandlers(): void {\n    if (!this.connection) return;\n\n    const logger = config.logger;\n\n    (async () => {\n      for await (const status of this.connection!.status()) {\n        switch (status.type) {\n          case 'disconnect':\n            logger.warn('Disconnected from NATS');\n            break;\n          case 'reconnect':\n            logger.info('Reconnected to NATS');\n            break;\n          case 'reconnecting':\n            logger.info('Reconnecting to NATS...');\n            break;\n          case 'error':\n            logger.error('NATS connection error', { error: status.data });\n            break;\n        }\n      }\n    })();\n  }\n\n  async disconnect(): Promise<void> {\n    const logger = config.logger;\n\n    if (this.connection) {\n      logger.info('Closing NATS connection...');\n      await this.connection.drain();\n      await this.connection.close();\n      this.connection = null;\n      this.jetstream = null;\n      logger.info('NATS connection closed');\n    }\n  }\n\n  async ensureConnection(): Promise<void> {\n    if (!this.connection || this.connection.isClosed()) {\n      await this.connect();\n    }\n  }\n\n  getJetStream(): JetStreamClient {\n    if (!this.jetstream) {\n      throw new Error('JetStream not initialized. Call connect() first.');\n    }\n    return this.jetstream;\n  }\n\n  getConnection(): NatsConnection {\n    if (!this.connection) {\n      throw new Error('Connection not initialized. Call connect() first.');\n    }\n    return this.connection;\n  }\n}\n\nexport default new Connection();\n","/**\n * Parse duration strings like \"30s\", \"5m\", \"1h\" into milliseconds\n */\nexport function parseDuration(duration: string | number): number {\n  if (typeof duration === 'number') {\n    return duration;\n  }\n\n  const match = duration.match(/^(\\d+)(ms|s|m|h)$/);\n  if (!match) {\n    throw new Error(`Invalid duration format: ${duration}`);\n  }\n\n  const value = parseInt(match[1], 10);\n  const unit = match[2];\n\n  switch (unit) {\n    case 'ms':\n      return value;\n    case 's':\n      return value * 1000;\n    case 'm':\n      return value * 60 * 1000;\n    case 'h':\n      return value * 60 * 60 * 1000;\n    default:\n      throw new Error(`Unknown duration unit: ${unit}`);\n  }\n}\n\n/**\n * Convert milliseconds to nanoseconds (for NATS JetStream)\n */\nexport function toNanos(ms: number): number {\n  return ms * 1_000_000;\n}\n\n/**\n * Convert nanoseconds to milliseconds\n */\nexport function fromNanos(nanos: number): number {\n  return nanos / 1_000_000;\n}\n\n/**\n * Parse duration strings and convert to nanoseconds\n * Supports: ns, us, ms, s, m, h\n */\nexport function parseNanos(duration: string | number): number {\n  if (typeof duration === 'number') {\n    return duration;\n  }\n\n  // Handle numeric strings\n  const numericValue = parseFloat(duration);\n  if (!isNaN(numericValue) && duration === numericValue.toString()) {\n    return numericValue;\n  }\n\n  const match = duration.match(/^(\\d+(?:\\.\\d+)?)(ns|us|ms|s|m|h)$/);\n  if (!match) {\n    throw new Error(`Invalid duration format: ${duration}`);\n  }\n\n  const value = parseFloat(match[1]);\n  const unit = match[2];\n\n  switch (unit) {\n    case 'ns':\n      return value;\n    case 'us':\n      return value * 1000;\n    case 'ms':\n      return value * 1_000_000;\n    case 's':\n      return value * 1_000_000_000;\n    case 'm':\n      return value * 60 * 1_000_000_000;\n    case 'h':\n      return value * 60 * 60 * 1_000_000_000;\n    default:\n      throw new Error(`Unknown duration unit: ${unit}`);\n  }\n}\n","/**\n * Subject utility class for building and parsing NATS subjects\n *\n * This class centralizes all subject/topic logic to eliminate duplication\n * and provide a single source of truth for subject formatting.\n *\n * Subject patterns:\n * - Topic-based: {env}.{appName}.{topic}\n * - Event-based: {env}.events.{domain}.{resource}.{action}\n * - DLQ: {env}.dlq\n */\nexport class Subject {\n  /**\n   * Build a subject for topic-based messaging\n   *\n   * @param env - Environment (e.g., 'production', 'staging', 'development')\n   * @param appName - Application name\n   * @param topic - Topic name (supports hierarchical topics with dots)\n   * @returns Formatted NATS subject\n   *\n   * @example\n   * ```typescript\n   * Subject.forTopic('production', 'myapp', 'user.created')\n   * // Returns: 'production.myapp.user.created'\n   *\n   * Subject.forTopic('production', 'myapp', 'notifications.email')\n   * // Returns: 'production.myapp.notifications.email'\n   * ```\n   */\n  static forTopic(env: string, appName: string, topic: string): string {\n    const normalizedTopic = this.normalizeName(topic);\n    return `${env}.${appName}.${normalizedTopic}`;\n  }\n\n  /**\n   * Build a subject for event-based messaging (domain/resource/action)\n   *\n   * @param env - Environment\n   * @param domain - Business domain (e.g., 'users', 'orders')\n   * @param resource - Resource type (e.g., 'user', 'order')\n   * @param action - Event action (e.g., 'created', 'updated', 'deleted')\n   * @returns Formatted NATS subject\n   *\n   * @example\n   * ```typescript\n   * Subject.forEvent('production', 'users', 'user', 'created')\n   * // Returns: 'production.events.users.user.created'\n   * ```\n   */\n  static forEvent(env: string, domain: string, resource: string, action: string): string {\n    const normalizedDomain = this.normalizeName(domain);\n    const normalizedResource = this.normalizeName(resource);\n    const normalizedAction = this.normalizeName(action);\n\n    return `${env}.events.${normalizedDomain}.${normalizedResource}.${normalizedAction}`;\n  }\n\n  /**\n   * Build a DLQ (Dead Letter Queue) subject\n   *\n   * @param env - Environment\n   * @returns Formatted NATS DLQ subject\n   *\n   * @example\n   * ```typescript\n   * Subject.forDlq('production')\n   * // Returns: 'production.dlq'\n   * ```\n   */\n  static forDlq(env: string): string {\n    return `${env}.dlq`;\n  }\n\n  /**\n   * Build a wildcard subject pattern for subscribing to all events\n   *\n   * @param env - Environment\n   * @returns Subject pattern with NATS wildcard\n   *\n   * @example\n   * ```typescript\n   * Subject.allEvents('production')\n   * // Returns: 'production.events.>'\n   * ```\n   */\n  static allEvents(env: string): string {\n    return `${env}.events.>`;\n  }\n\n  /**\n   * Parse a topic-based subject into its components\n   *\n   * @param subject - NATS subject string\n   * @returns Object with env, appName, and topic, or null if invalid format\n   *\n   * @example\n   * ```typescript\n   * Subject.parseTopic('production.myapp.user.created')\n   * // Returns: { env: 'production', appName: 'myapp', topic: 'user.created' }\n   * ```\n   */\n  static parseTopic(subject: string): {\n    env: string;\n    appName: string;\n    topic: string;\n  } | null {\n    const parts = subject.split('.');\n\n    if (parts.length < 3) {\n      return null;\n    }\n\n    const [env, appName, ...topicParts] = parts;\n    return {\n      env,\n      appName,\n      topic: topicParts.join('.'),\n    };\n  }\n\n  /**\n   * Parse an event-based subject into its components\n   *\n   * @param subject - NATS subject string\n   * @returns Object with env, domain, resource, and action, or null if invalid format\n   *\n   * @example\n   * ```typescript\n   * Subject.parseEvent('production.events.users.user.created')\n   * // Returns: { env: 'production', domain: 'users', resource: 'user', action: 'created' }\n   * ```\n   */\n  static parseEvent(subject: string): {\n    env: string;\n    domain: string;\n    resource: string;\n    action: string;\n  } | null {\n    const parts = subject.split('.');\n\n    if (parts.length !== 5 || parts[1] !== 'events') {\n      return null;\n    }\n\n    return {\n      env: parts[0],\n      domain: parts[2],\n      resource: parts[3],\n      action: parts[4],\n    };\n  }\n\n  /**\n   * Check if a subject is a topic-based subject\n   *\n   * @param subject - NATS subject string\n   * @returns true if subject follows topic pattern\n   *\n   * @example\n   * ```typescript\n   * Subject.isTopic('production.myapp.user.created') // true\n   * Subject.isTopic('production.events.users.user.created') // false\n   * ```\n   */\n  static isTopic(subject: string): boolean {\n    const parts = subject.split('.');\n    return parts.length >= 3 && parts[1] !== 'events';\n  }\n\n  /**\n   * Check if a subject is an event-based subject\n   *\n   * @param subject - NATS subject string\n   * @returns true if subject follows event pattern\n   *\n   * @example\n   * ```typescript\n   * Subject.isEvent('production.events.users.user.created') // true\n   * Subject.isEvent('production.myapp.user.created') // false\n   * ```\n   */\n  static isEvent(subject: string): boolean {\n    const parts = subject.split('.');\n    return parts.length >= 5 && parts[1] === 'events';\n  }\n\n  /**\n   * Normalize a name for use in subjects\n   *\n   * Converts to lowercase and replaces special characters with underscores.\n   * Preserves dots (.), NATS wildcards (> and *), and hyphens (-).\n   *\n   * @param name - Name to normalize\n   * @returns Normalized name safe for NATS subjects\n   *\n   * @example\n   * ```typescript\n   * Subject.normalizeName('User Created') // 'user_created'\n   * Subject.normalizeName('user.created') // 'user.created' (dots preserved)\n   * Subject.normalizeName('users.*') // 'users.*' (wildcards preserved)\n   * ```\n   */\n  static normalizeName(name: string): string {\n    return name.toLowerCase().replace(/[^a-z0-9_.>*-]/g, '_');\n  }\n\n  /**\n   * Check if a subject pattern matches a concrete subject\n   *\n   * Supports NATS wildcards:\n   * - * matches a single token\n   * - > matches one or more tokens (tail wildcard)\n   *\n   * @param pattern - Subject pattern (may contain wildcards)\n   * @param subject - Concrete subject to test\n   * @returns true if pattern matches subject\n   *\n   * @example\n   * ```typescript\n   * Subject.matches('production.*.created', 'production.user.created') // true\n   * Subject.matches('production.>', 'production.myapp.user.created') // true\n   * Subject.matches('production.events.*', 'production.events.users') // true\n   * Subject.matches('production.events.*', 'production.events.users.user') // false\n   * ```\n   */\n  static matches(pattern: string, subject: string): boolean {\n    const patternTokens = pattern.split('.');\n    const subjectTokens = subject.split('.');\n\n    let index = 0;\n\n    while (index < patternTokens.length && index < subjectTokens.length) {\n      const patternToken = patternTokens[index];\n\n      if (patternToken === '>') {\n        // Tail wildcard matches everything remaining\n        return true;\n      }\n\n      if (patternToken === '*') {\n        // Single token wildcard, continue to next token\n        index++;\n        continue;\n      }\n\n      // Exact match required\n      if (patternToken !== subjectTokens[index]) {\n        return false;\n      }\n\n      index++;\n    }\n\n    // Exact match or remaining '>' wildcard\n    if (index === patternTokens.length && index === subjectTokens.length) {\n      return true;\n    }\n\n    // Check if pattern has remaining '>' wildcard\n    return patternTokens[index] === '>' || patternTokens.slice(index).includes('>');\n  }\n\n  /**\n   * Validate a subject string\n   *\n   * Checks if a subject follows valid NATS subject rules:\n   * - Not empty\n   * - Contains only valid characters (a-z, 0-9, ., -, _, *, >)\n   * - Doesn't start or end with a dot\n   * - No consecutive dots\n   * - Wildcards in valid positions\n   *\n   * @param subject - Subject string to validate\n   * @returns true if subject is valid\n   *\n   * @example\n   * ```typescript\n   * Subject.isValid('production.myapp.user') // true\n   * Subject.isValid('production..myapp') // false (consecutive dots)\n   * Subject.isValid('.production.myapp') // false (starts with dot)\n   * Subject.isValid('production.*.user') // true (wildcard valid)\n   * ```\n   */\n  static isValid(subject: string): boolean {\n    if (!subject || subject.length === 0) {\n      return false;\n    }\n\n    // Can't start or end with a dot\n    if (subject.startsWith('.') || subject.endsWith('.')) {\n      return false;\n    }\n\n    // No consecutive dots\n    if (subject.includes('..')) {\n      return false;\n    }\n\n    // Only valid characters: a-z, 0-9, dot, hyphen, underscore, wildcards\n    if (!/^[a-z0-9._*>-]+$/i.test(subject)) {\n      return false;\n    }\n\n    // Tail wildcard (>) must be the last token\n    const tokens = subject.split('.');\n    const tailIndex = tokens.indexOf('>');\n    if (tailIndex !== -1 && tailIndex !== tokens.length - 1) {\n      return false;\n    }\n\n    return true;\n  }\n}\n","/**\n * Base error class for NatsPubsub\n */\nexport class NatsPubsubError extends Error {\n  public readonly context?: Record<string, unknown>;\n  public readonly resolution?: string;\n\n  constructor(message: string, context?: Record<string, unknown>, resolution?: string) {\n    super(message);\n    this.name = 'NatsPubsubError';\n    this.context = context;\n    this.resolution = resolution;\n    Object.setPrototypeOf(this, NatsPubsubError.prototype);\n  }\n}\n\n/**\n * Connection-related errors\n *\n * Common causes:\n * - NATS server not running\n * - Incorrect connection URL\n * - Network issues\n * - Authentication failures\n */\nexport class ConnectionError extends NatsPubsubError {\n  constructor(message: string, context?: Record<string, unknown>, resolution?: string) {\n    const defaultResolution =\n      resolution ||\n      'Verify NATS server is running with JetStream enabled: nats-server -js\\n' +\n        'Check NATS_URLS configuration and network connectivity';\n    super(message, context, defaultResolution);\n    this.name = 'ConnectionError';\n    Object.setPrototypeOf(this, ConnectionError.prototype);\n  }\n}\n\n/**\n * Publishing-related errors\n *\n * Common causes:\n * - Stream not found\n * - Permission denied\n * - Message too large\n * - Connection lost\n */\nexport class PublishError extends NatsPubsubError {\n  constructor(message: string, context?: Record<string, unknown>, resolution?: string) {\n    super(message, context, resolution);\n    this.name = 'PublishError';\n    Object.setPrototypeOf(this, PublishError.prototype);\n  }\n}\n\n/**\n * Subscription-related errors\n *\n * Common causes:\n * - Consumer not found\n * - Stream not found\n * - Permission denied\n * - Invalid subject pattern\n */\nexport class SubscriptionError extends NatsPubsubError {\n  constructor(message: string, context?: Record<string, unknown>, resolution?: string) {\n    super(message, context, resolution);\n    this.name = 'SubscriptionError';\n    Object.setPrototypeOf(this, SubscriptionError.prototype);\n  }\n}\n\n/**\n * Schema validation errors\n *\n * Thrown when message payload doesn't match expected schema\n */\nexport class ValidationError extends NatsPubsubError {\n  public readonly validationErrors?: unknown;\n\n  constructor(message: string, validationErrors?: unknown, context?: Record<string, unknown>) {\n    const resolution = 'Check message payload matches expected schema. Review publisher code.';\n    super(message, context, resolution);\n    this.name = 'ValidationError';\n    this.validationErrors = validationErrors;\n    Object.setPrototypeOf(this, ValidationError.prototype);\n  }\n}\n\n/**\n * Topology-related errors\n *\n * Common causes:\n * - Stream subjects overlap\n * - Invalid stream configuration\n * - JetStream disabled\n */\nexport class TopologyError extends NatsPubsubError {\n  constructor(message: string, context?: Record<string, unknown>, resolution?: string) {\n    const defaultResolution =\n      resolution ||\n      'Check stream configuration for subject overlaps.\\n' +\n        'Verify JetStream is enabled: nats account info';\n    super(message, context, defaultResolution);\n    this.name = 'TopologyError';\n    Object.setPrototypeOf(this, TopologyError.prototype);\n  }\n}\n\n/**\n * DLQ (Dead Letter Queue) related errors\n *\n * Thrown when DLQ operations fail\n */\nexport class DlqError extends NatsPubsubError {\n  constructor(message: string, context?: Record<string, unknown>, resolution?: string) {\n    super(message, context, resolution);\n    this.name = 'DlqError';\n    Object.setPrototypeOf(this, DlqError.prototype);\n  }\n}\n\n/**\n * Configuration-related errors\n *\n * Thrown when configuration is invalid or missing\n */\nexport class ConfigurationError extends NatsPubsubError {\n  constructor(message: string, context?: Record<string, unknown>, resolution?: string) {\n    const defaultResolution =\n      resolution ||\n      'Review your NatsPubsub.configure() call.\\n' +\n        'Ensure required fields (natsUrls, env, appName) are set.';\n    super(message, context, defaultResolution);\n    this.name = 'ConfigurationError';\n    Object.setPrototypeOf(this, ConfigurationError.prototype);\n  }\n}\n\n/**\n * Timeout errors\n *\n * Thrown when operations exceed configured timeout\n */\nexport class TimeoutError extends NatsPubsubError {\n  public readonly timeoutMs: number;\n\n  constructor(message: string, timeoutMs: number, context?: Record<string, unknown>) {\n    const resolution = `Operation timed out after ${timeoutMs}ms. Consider increasing ackWait or optimizing subscriber logic.`;\n    super(message, context, resolution);\n    this.name = 'TimeoutError';\n    this.timeoutMs = timeoutMs;\n    Object.setPrototypeOf(this, TimeoutError.prototype);\n  }\n}\n","import connection from './connection';\nimport config from './config';\n\nexport interface HealthCheckResult {\n  /** Overall health status */\n  status: 'healthy' | 'degraded' | 'unhealthy';\n  /** Timestamp of the health check */\n  timestamp: string;\n  /** NatsPubsub version */\n  version: string;\n  /** Individual component health */\n  components: {\n    nats: ComponentHealth;\n    config: ComponentHealth;\n    consumers?: ComponentHealth;\n  };\n  /** Additional details */\n  details?: Record<string, unknown>;\n}\n\nexport interface ComponentHealth {\n  /** Component status */\n  status: 'up' | 'down' | 'degraded';\n  /** Component details */\n  details?: Record<string, unknown>;\n  /** Error message if down */\n  error?: string;\n}\n\n/**\n * Health check utility for NatsPubsub\n * Provides information about system health and connectivity\n */\nexport class HealthCheck {\n  /**\n   * Perform a comprehensive health check\n   *\n   * @example\n   * ```typescript\n   * const health = await HealthCheck.check();\n   * console.log(`Status: ${health.status}`);\n   * console.log(`NATS: ${health.components.nats.status}`);\n   * ```\n   */\n  static async check(): Promise<HealthCheckResult> {\n    const timestamp = new Date().toISOString();\n    const components: HealthCheckResult['components'] = {\n      nats: await this.checkNats(),\n      config: this.checkConfig(),\n    };\n\n    // Determine overall status\n    const componentStatuses = Object.values(components).map((c) => c.status);\n    let overallStatus: 'healthy' | 'degraded' | 'unhealthy';\n\n    if (componentStatuses.every((s) => s === 'up')) {\n      overallStatus = 'healthy';\n    } else if (componentStatuses.some((s) => s === 'down')) {\n      overallStatus = 'unhealthy';\n    } else {\n      overallStatus = 'degraded';\n    }\n\n    return {\n      status: overallStatus,\n      timestamp,\n      version: this.getVersion(),\n      components,\n    };\n  }\n\n  /**\n   * Quick health check - just returns status\n   * Faster than full check, suitable for load balancer health endpoints\n   */\n  static async quickCheck(): Promise<{ status: 'ok' | 'error' }> {\n    try {\n      const nc = connection.getConnection();\n      if (!nc) {\n        return { status: 'error' };\n      }\n\n      // Check if connection is alive\n      const isConnected = !nc.isClosed();\n      return { status: isConnected ? 'ok' : 'error' };\n    } catch {\n      return { status: 'error' };\n    }\n  }\n\n  /**\n   * Check NATS connection health\n   */\n  private static async checkNats(): Promise<ComponentHealth> {\n    try {\n      const nc = connection.getConnection();\n\n      if (!nc) {\n        return {\n          status: 'down',\n          error: 'No connection established',\n        };\n      }\n\n      if (nc.isClosed()) {\n        return {\n          status: 'down',\n          error: 'Connection is closed',\n        };\n      }\n\n      // Get connection stats\n      const stats = nc.stats();\n      const info = nc.info;\n\n      return {\n        status: 'up',\n        details: {\n          connected: true,\n          server: info?.host,\n          version: info?.version,\n          inMsgs: stats.inMsgs,\n          outMsgs: stats.outMsgs,\n          inBytes: stats.inBytes,\n          outBytes: stats.outBytes,\n        },\n      };\n    } catch (error) {\n      return {\n        status: 'down',\n        error: error instanceof Error ? error.message : 'Unknown error',\n      };\n    }\n  }\n\n  /**\n   * Check configuration health\n   */\n  private static checkConfig(): ComponentHealth {\n    try {\n      const cfg = config.get();\n\n      // Check required fields\n      const hasRequiredFields = cfg.natsUrls && cfg.env && cfg.appName;\n\n      if (!hasRequiredFields) {\n        return {\n          status: 'down',\n          error: 'Missing required configuration fields',\n        };\n      }\n\n      return {\n        status: 'up',\n        details: {\n          env: cfg.env,\n          appName: cfg.appName,\n          natsUrls: cfg.natsUrls,\n          concurrency: cfg.concurrency,\n          useDlq: cfg.useDlq,\n        },\n      };\n    } catch (error) {\n      return {\n        status: 'down',\n        error: error instanceof Error ? error.message : 'Configuration error',\n      };\n    }\n  }\n\n  /**\n   * Get NatsPubsub version\n   */\n  private static getVersion(): string {\n    // This would typically come from package.json\n    // For now, return a static version\n    return '0.1.0';\n  }\n\n  /**\n   * Create an Express middleware for health check endpoint\n   *\n   * @example\n   * ```typescript\n   * import express from 'express';\n   * import { HealthCheck } from 'nats-pubsub';\n   *\n   * const app = express();\n   * app.get('/health', HealthCheck.middleware());\n   * ```\n   */\n  static middleware() {\n    return async (_req: any, res: any) => {\n      try {\n        const health = await this.check();\n        const statusCode =\n          health.status === 'healthy' ? 200 : health.status === 'degraded' ? 200 : 503;\n\n        res.status(statusCode).json(health);\n      } catch (error) {\n        res.status(503).json({\n          status: 'unhealthy',\n          timestamp: new Date().toISOString(),\n          error: error instanceof Error ? error.message : 'Health check failed',\n        });\n      }\n    };\n  }\n\n  /**\n   * Create a quick health check middleware (for load balancers)\n   *\n   * @example\n   * ```typescript\n   * app.get('/health/ready', HealthCheck.quickMiddleware());\n   * ```\n   */\n  static quickMiddleware() {\n    return async (_req: any, res: any) => {\n      try {\n        const result = await this.quickCheck();\n        const statusCode = result.status === 'ok' ? 200 : 503;\n\n        res.status(statusCode).json(result);\n      } catch {\n        res.status(503).json({ status: 'error' });\n      }\n    };\n  }\n}\n\nexport default HealthCheck;\n","import { NatsPubsubConfig } from '../types';\n\n/**\n * Configuration preset options\n */\nexport interface PresetOptions {\n  appName: string;\n  natsUrls: string | string[];\n  auth?: {\n    type?: 'token' | 'credentials' | 'nkey';\n    token?: string;\n    credentials?: string;\n    nkey?: string;\n  };\n}\n\n/**\n * Development preset with sensible defaults for local development\n *\n * Features:\n * - Lower concurrency for easier debugging\n * - Shorter timeouts for faster feedback\n * - DLQ enabled for error visibility\n * - Debug logging\n *\n * @param options - Basic configuration options\n * @returns Development configuration\n *\n * @example\n * ```typescript\n * await NatsPubsub.setup(Presets.development({\n *   appName: 'my-service',\n *   natsUrls: 'nats://localhost:4222'\n * }));\n * ```\n */\nexport function development(options: PresetOptions): Partial<NatsPubsubConfig> {\n  return {\n    appName: options.appName,\n    natsUrls: options.natsUrls,\n    env: 'development',\n\n    // Lower concurrency for easier debugging\n    concurrency: 5,\n    perMessageConcurrency: 3,\n\n    // Faster feedback during development\n    maxDeliver: 3,\n    ackWait: 15000, // 15 seconds\n    backoff: [1000, 3000, 5000], // Shorter backoff\n\n    // DLQ enabled for visibility\n    useDlq: true,\n    dlqMaxAttempts: 2,\n\n    // Inbox/Outbox typically not needed in dev\n    useInbox: false,\n    useOutbox: false,\n\n    // Shorter timeouts\n    subscriberTimeoutMs: 15000,\n  };\n}\n\n/**\n * Production preset optimized for reliability and performance\n *\n * Features:\n * - Higher concurrency for throughput\n * - Longer timeouts for network latency\n * - Aggressive retry strategy\n * - DLQ enabled for operational safety\n * - Info-level logging\n *\n * @param options - Basic configuration options\n * @returns Production configuration\n *\n * @example\n * ```typescript\n * await NatsPubsub.setup(Presets.production({\n *   appName: 'my-service',\n *   natsUrls: process.env.NATS_CLUSTER_URLS!.split(','),\n *   auth: {\n *     type: 'token',\n *     token: process.env.NATS_TOKEN\n *   }\n * }));\n * ```\n */\nexport function production(options: PresetOptions): Partial<NatsPubsubConfig> {\n  return {\n    appName: options.appName,\n    natsUrls: options.natsUrls,\n    env: 'production',\n\n    // Higher concurrency for throughput\n    concurrency: 20,\n    perMessageConcurrency: 5,\n\n    // More aggressive retry strategy\n    maxDeliver: 5,\n    ackWait: 30000, // 30 seconds\n    backoff: [1000, 5000, 15000, 30000, 60000], // Exponential backoff\n\n    // DLQ enabled for operational safety\n    useDlq: true,\n    dlqMaxAttempts: 3,\n\n    // Consider enabling for transactional guarantees\n    useInbox: false,\n    useOutbox: false,\n\n    // Longer timeouts for network latency\n    subscriberTimeoutMs: 30000,\n  };\n}\n\n/**\n * Staging preset balanced between development and production\n *\n * Features:\n * - Moderate concurrency\n * - Production-like retry strategy\n * - DLQ enabled\n * - Debug logging for troubleshooting\n *\n * @param options - Basic configuration options\n * @returns Staging configuration\n *\n * @example\n * ```typescript\n * await NatsPubsub.setup(Presets.staging({\n *   appName: 'my-service',\n *   natsUrls: 'nats://staging-nats:4222'\n * }));\n * ```\n */\nexport function staging(options: PresetOptions): Partial<NatsPubsubConfig> {\n  return {\n    appName: options.appName,\n    natsUrls: options.natsUrls,\n    env: 'staging',\n\n    // Moderate concurrency\n    concurrency: 10,\n    perMessageConcurrency: 5,\n\n    // Production-like retry strategy\n    maxDeliver: 5,\n    ackWait: 30000,\n    backoff: [1000, 5000, 15000, 30000, 60000],\n\n    // DLQ enabled\n    useDlq: true,\n    dlqMaxAttempts: 3,\n\n    // Inbox/Outbox optional\n    useInbox: false,\n    useOutbox: false,\n\n    subscriberTimeoutMs: 30000,\n  };\n}\n\n/**\n * Testing preset optimized for unit and integration tests\n *\n * Features:\n * - Minimal concurrency\n * - Very short timeouts for fast tests\n * - No retries for deterministic behavior\n * - DLQ disabled\n *\n * @param options - Basic configuration options\n * @returns Testing configuration\n *\n * @example\n * ```typescript\n * await NatsPubsub.setup(Presets.testing({\n *   appName: 'test-service',\n *   natsUrls: 'nats://localhost:4222'\n * }));\n * ```\n */\nexport function testing(options: PresetOptions): Partial<NatsPubsubConfig> {\n  return {\n    appName: options.appName,\n    natsUrls: options.natsUrls,\n    env: 'test',\n\n    // Minimal concurrency\n    concurrency: 1,\n    perMessageConcurrency: 1,\n\n    // No retries for deterministic behavior\n    maxDeliver: 1,\n    ackWait: 5000, // 5 seconds\n    backoff: [],\n\n    // DLQ disabled for simpler testing\n    useDlq: false,\n    dlqMaxAttempts: 0,\n\n    // Inbox/Outbox disabled\n    useInbox: false,\n    useOutbox: false,\n\n    // Short timeouts for fast tests\n    subscriberTimeoutMs: 5000,\n  };\n}\n\n/**\n * Configuration presets for common environments\n */\nexport const Presets = {\n  development,\n  production,\n  staging,\n  testing,\n};\n","/**\n * Log level type\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * Log entry structure\n */\nexport interface LogEntry {\n  timestamp: string;\n  level: string;\n  message: string;\n  pid: number;\n  [key: string]: unknown;\n}\n\n/**\n * Structured logger for machine-parseable JSON logs\n */\nexport class StructuredLogger {\n  private readonly context: Record<string, unknown>;\n\n  private static readonly LEVELS: Record<LogLevel, number> = {\n    debug: 0,\n    info: 1,\n    warn: 2,\n    error: 3,\n    fatal: 4,\n  };\n\n  constructor(\n    private readonly level: LogLevel = 'info',\n    context: Record<string, unknown> = {}\n  ) {\n    this.context = context;\n  }\n\n  /**\n   * Log at debug level\n   */\n  debug(message: string, metadata: Record<string, unknown> = {}): void {\n    this.log('debug', message, metadata);\n  }\n\n  /**\n   * Log at info level\n   */\n  info(message: string, metadata: Record<string, unknown> = {}): void {\n    this.log('info', message, metadata);\n  }\n\n  /**\n   * Log at warn level\n   */\n  warn(message: string, metadata: Record<string, unknown> = {}): void {\n    this.log('warn', message, metadata);\n  }\n\n  /**\n   * Log at error level\n   */\n  error(message: string, metadata: Record<string, unknown> = {}): void {\n    this.log('error', message, metadata);\n  }\n\n  /**\n   * Log at fatal level\n   */\n  fatal(message: string, metadata: Record<string, unknown> = {}): void {\n    this.log('fatal', message, metadata);\n  }\n\n  /**\n   * Create child logger with additional context\n   */\n  withContext(childContext: Record<string, unknown>): StructuredLogger {\n    return new StructuredLogger(this.level, {\n      ...this.context,\n      ...childContext,\n    });\n  }\n\n  /**\n   * Log a message\n   */\n  private log(severity: LogLevel, message: string, metadata: Record<string, unknown>): void {\n    if (StructuredLogger.LEVELS[severity] < StructuredLogger.LEVELS[this.level]) {\n      return;\n    }\n\n    const logEntry = this.buildLogEntry(severity, message, metadata);\n\n    try {\n      console.log(JSON.stringify(logEntry));\n    } catch {\n      // Fallback to plain text if JSON fails\n      console.log(`[${severity}] ${message}`);\n    }\n  }\n\n  /**\n   * Build structured log entry\n   */\n  private buildLogEntry(\n    severity: LogLevel,\n    message: string,\n    metadata: Record<string, unknown>\n  ): LogEntry {\n    return {\n      timestamp: new Date().toISOString(),\n      level: severity.toUpperCase(),\n      message,\n      pid: process.pid,\n      ...this.context,\n      ...metadata,\n    };\n  }\n}\n\n/**\n * Logger factory for creating structured loggers\n */\nexport class LoggerFactory {\n  /**\n   * Create a structured logger from configuration\n   */\n  static createFromConfig(config: {\n    logLevel?: LogLevel;\n    appName?: string;\n    env?: string;\n  }): StructuredLogger {\n    const level = config.logLevel || 'info';\n\n    return new StructuredLogger(level, {\n      app_name: config.appName,\n      env: config.env,\n    });\n  }\n\n  /**\n   * Create a logger for a specific component\n   */\n  static forComponent(\n    component: string,\n    config: { logLevel?: LogLevel; appName?: string; env?: string }\n  ): StructuredLogger {\n    return this.createFromConfig(config).withContext({ component });\n  }\n}\n","import { z } from 'zod';\nimport { ValidationError } from './errors';\n\n/**\n * Schema validator using Zod\n *\n * Provides runtime validation for messages with full TypeScript type inference.\n *\n * @example\n * ```typescript\n * const UserSchema = z.object({\n *   id: z.string().uuid(),\n *   name: z.string().min(1),\n *   email: z.string().email()\n * });\n *\n * const validator = new SchemaValidator(UserSchema);\n * const result = validator.validate(data);\n *\n * if (!result.success) {\n *   console.error(result.errors);\n * }\n * ```\n */\nexport class SchemaValidator<T extends z.ZodType> {\n  constructor(private schema: T) {}\n\n  /**\n   * Validate data against schema\n   *\n   * @param data - Data to validate\n   * @returns Validation result\n   */\n  validate(data: unknown): ValidationResult<z.infer<T>> {\n    try {\n      const parsed = this.schema.parse(data);\n      return {\n        success: true,\n        data: parsed,\n      };\n    } catch (error) {\n      if (error instanceof z.ZodError) {\n        return {\n          success: false,\n          errors: error.issues.map((err: z.ZodIssue) => ({\n            path: err.path.join('.'),\n            message: err.message,\n            code: err.code,\n          })),\n          zodError: error,\n        };\n      }\n\n      return {\n        success: false,\n        errors: [\n          {\n            path: '',\n            message: error instanceof Error ? error.message : String(error),\n            code: 'unknown',\n          },\n        ],\n      };\n    }\n  }\n\n  /**\n   * Validate and throw on error\n   *\n   * @param data - Data to validate\n   * @returns Parsed data\n   * @throws ValidationError if validation fails\n   */\n  validateOrThrow(data: unknown): z.infer<T> {\n    const result = this.validate(data);\n\n    if (!result.success) {\n      throw new ValidationError(\n        `Schema validation failed: ${result.errors.map((e) => `${e.path}: ${e.message}`).join(', ')}`,\n        result.errors\n      );\n    }\n\n    return result.data;\n  }\n\n  /**\n   * Validate partially (for updates)\n   *\n   * @param data - Data to validate\n   * @returns Validation result\n   */\n  validatePartial(data: unknown): ValidationResult<Partial<z.infer<T>>> {\n    try {\n      // Cast to any to access partial() method - only works with ZodObject types\n      const partialSchema = (this.schema as any).partial() as z.ZodType<Partial<z.infer<T>>>;\n      const parsed = partialSchema.parse(data);\n      return {\n        success: true,\n        data: parsed,\n      };\n    } catch (error) {\n      if (error instanceof z.ZodError) {\n        return {\n          success: false,\n          errors: error.issues.map((err: z.ZodIssue) => ({\n            path: err.path.join('.'),\n            message: err.message,\n            code: err.code,\n          })),\n          zodError: error,\n        };\n      }\n\n      return {\n        success: false,\n        errors: [\n          {\n            path: '',\n            message: error instanceof Error ? error.message : String(error),\n            code: 'unknown',\n          },\n        ],\n      };\n    }\n  }\n\n  /**\n   * Get the underlying Zod schema\n   *\n   * @returns Zod schema\n   */\n  getSchema(): T {\n    return this.schema;\n  }\n}\n\n/**\n * Validation result\n */\nexport type ValidationResult<T> =\n  | {\n      success: true;\n      data: T;\n    }\n  | {\n      success: false;\n      errors: ValidationErrorDetail[];\n      zodError?: z.ZodError;\n    };\n\n/**\n * Validation error detail\n */\nexport interface ValidationErrorDetail {\n  path: string;\n  message: string;\n  code: string;\n}\n\n/**\n * Create a schema validator\n *\n * @param schema - Zod schema\n * @returns Schema validator instance\n *\n * @example\n * ```typescript\n * const validator = createValidator(z.object({ id: z.string() }));\n * const result = validator.validate(data);\n * ```\n */\nexport function createValidator<T extends z.ZodType>(schema: T): SchemaValidator<T> {\n  return new SchemaValidator(schema);\n}\n\n/**\n * Validate data against a schema\n *\n * @param schema - Zod schema\n * @param data - Data to validate\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateSchema(UserSchema, userData);\n * if (result.success) {\n *   console.log(result.data);\n * }\n * ```\n */\nexport function validateSchema<T extends z.ZodType>(\n  schema: T,\n  data: unknown\n): ValidationResult<z.infer<T>> {\n  const validator = new SchemaValidator(schema);\n  return validator.validate(data);\n}\n\n/**\n * Common schemas for reuse\n */\nexport const CommonSchemas = {\n  /**\n   * UUID string\n   */\n  uuid: z.string().uuid(),\n\n  /**\n   * Email address\n   */\n  email: z.string().email(),\n\n  /**\n   * URL\n   */\n  url: z.string().url(),\n\n  /**\n   * ISO 8601 date string\n   */\n  isoDate: z.string().datetime(),\n\n  /**\n   * Positive integer\n   */\n  positiveInt: z.number().int().positive(),\n\n  /**\n   * Non-empty string\n   */\n  nonEmptyString: z.string().min(1),\n\n  /**\n   * Trace ID (hex string)\n   */\n  traceId: z.string().regex(/^[0-9a-fA-F]+$/),\n\n  /**\n   * Topic name (alphanumeric with dots, dashes, underscores)\n   */\n  topic: z.string().regex(/^[a-zA-Z0-9._-]+$/),\n};\n\n/**\n * Create a message schema with standard fields\n *\n * @param payloadSchema - Schema for the message payload\n * @returns Complete message schema\n *\n * @example\n * ```typescript\n * const UserCreatedMessageSchema = createMessageSchema(\n *   z.object({\n *     id: z.string().uuid(),\n *     name: z.string(),\n *     email: z.string().email()\n *   })\n * );\n * ```\n */\nexport function createMessageSchema<T extends z.ZodType>(payloadSchema: T) {\n  return z.object({\n    payload: payloadSchema,\n    metadata: z\n      .object({\n        eventId: CommonSchemas.uuid.optional(),\n        traceId: z.string().optional(),\n        correlationId: z.string().optional(),\n        occurredAt: z.date().optional(),\n      })\n      .optional(),\n  });\n}\n","/**\n * Circuit breaker states\n */\nexport enum CircuitState {\n  /** Circuit is closed, requests flow normally */\n  CLOSED = 'closed',\n  /** Circuit is open, requests are rejected */\n  OPEN = 'open',\n  /** Circuit is half-open, testing if service recovered */\n  HALF_OPEN = 'half_open',\n}\n\n/**\n * Circuit breaker configuration\n */\nexport interface CircuitBreakerOptions {\n  /** Number of failures before opening circuit */\n  threshold: number;\n  /** Time to keep circuit open in milliseconds */\n  timeout: number;\n  /** Number of test calls in half-open state */\n  halfOpenMaxCalls: number;\n  /** Name for logging/monitoring */\n  name?: string;\n}\n\n/**\n * Circuit breaker statistics\n */\nexport interface CircuitBreakerStats {\n  state: CircuitState;\n  failures: number;\n  successes: number;\n  rejections: number;\n  lastFailureTime?: Date;\n  lastSuccessTime?: Date;\n  lastStateChange?: Date;\n}\n\n/**\n * Circuit breaker implementation\n *\n * Prevents cascading failures by failing fast when a dependency is unhealthy.\n *\n * States:\n * - CLOSED: Normal operation, requests flow through\n * - OPEN: Too many failures, requests are rejected immediately\n * - HALF_OPEN: Testing if service recovered, limited requests allowed\n *\n * @example\n * ```typescript\n * const breaker = new CircuitBreaker({\n *   threshold: 5,\n *   timeout: 60000,\n *   halfOpenMaxCalls: 3\n * });\n *\n * try {\n *   await breaker.execute(async () => {\n *     return await callExternalService();\n *   });\n * } catch (error) {\n *   if (error instanceof CircuitBreakerError) {\n *     console.log('Circuit is open!');\n *   }\n * }\n * ```\n */\nexport class CircuitBreaker {\n  private state: CircuitState = CircuitState.CLOSED;\n  private failureCount: number = 0;\n  private successCount: number = 0;\n  private rejectionCount: number = 0;\n  private lastFailureTime?: Date;\n  private lastSuccessTime?: Date;\n  private lastStateChange?: Date;\n  private halfOpenCalls: number = 0;\n  private openTimeout?: NodeJS.Timeout;\n\n  constructor(private options: CircuitBreakerOptions) {\n    this.validateOptions();\n  }\n\n  /**\n   * Execute a function with circuit breaker protection\n   *\n   * @param fn - Async function to execute\n   * @returns Result of the function\n   * @throws CircuitBreakerError if circuit is open\n   */\n  async execute<T>(fn: () => Promise<T>): Promise<T> {\n    // Check if circuit is open\n    if (this.state === CircuitState.OPEN) {\n      this.rejectionCount++;\n      throw new CircuitBreakerError(\n        `Circuit breaker '${this.options.name || 'default'}' is OPEN`,\n        this.getStats()\n      );\n    }\n\n    // Check half-open call limit\n    if (\n      this.state === CircuitState.HALF_OPEN &&\n      this.halfOpenCalls >= this.options.halfOpenMaxCalls\n    ) {\n      this.rejectionCount++;\n      throw new CircuitBreakerError(\n        `Circuit breaker '${this.options.name || 'default'}' is HALF_OPEN and at max calls`,\n        this.getStats()\n      );\n    }\n\n    // Track half-open calls\n    if (this.state === CircuitState.HALF_OPEN) {\n      this.halfOpenCalls++;\n    }\n\n    try {\n      const result = await fn();\n      this.onSuccess();\n      return result;\n    } catch (error) {\n      this.onFailure();\n      throw error;\n    }\n  }\n\n  /**\n   * Handle successful execution\n   */\n  private onSuccess(): void {\n    this.successCount++;\n    this.lastSuccessTime = new Date();\n\n    if (this.state === CircuitState.HALF_OPEN) {\n      // If enough successful calls in half-open, close the circuit\n      if (this.halfOpenCalls >= this.options.halfOpenMaxCalls) {\n        this.closeCircuit();\n      }\n    } else if (this.state === CircuitState.CLOSED) {\n      // Reset failure count on success\n      this.failureCount = 0;\n    }\n  }\n\n  /**\n   * Handle failed execution\n   */\n  private onFailure(): void {\n    this.failureCount++;\n    this.lastFailureTime = new Date();\n\n    if (this.state === CircuitState.HALF_OPEN) {\n      // Any failure in half-open immediately reopens the circuit\n      this.openCircuit();\n    } else if (this.state === CircuitState.CLOSED) {\n      // Check if threshold exceeded\n      if (this.failureCount >= this.options.threshold) {\n        this.openCircuit();\n      }\n    }\n  }\n\n  /**\n   * Open the circuit\n   */\n  private openCircuit(): void {\n    this.state = CircuitState.OPEN;\n    this.lastStateChange = new Date();\n    this.halfOpenCalls = 0;\n\n    // Clear any existing timeout\n    if (this.openTimeout) {\n      clearTimeout(this.openTimeout);\n    }\n\n    // Set timeout to transition to half-open\n    this.openTimeout = setTimeout(() => {\n      this.halfOpenCircuit();\n    }, this.options.timeout);\n  }\n\n  /**\n   * Transition to half-open state\n   */\n  private halfOpenCircuit(): void {\n    this.state = CircuitState.HALF_OPEN;\n    this.lastStateChange = new Date();\n    this.halfOpenCalls = 0;\n  }\n\n  /**\n   * Close the circuit\n   */\n  private closeCircuit(): void {\n    this.state = CircuitState.CLOSED;\n    this.lastStateChange = new Date();\n    this.failureCount = 0;\n    this.halfOpenCalls = 0;\n\n    if (this.openTimeout) {\n      clearTimeout(this.openTimeout);\n      this.openTimeout = undefined;\n    }\n  }\n\n  /**\n   * Get current circuit breaker state\n   *\n   * @returns Current state\n   */\n  getState(): CircuitState {\n    return this.state;\n  }\n\n  /**\n   * Get circuit breaker statistics\n   *\n   * @returns Statistics object\n   */\n  getStats(): CircuitBreakerStats {\n    return {\n      state: this.state,\n      failures: this.failureCount,\n      successes: this.successCount,\n      rejections: this.rejectionCount,\n      lastFailureTime: this.lastFailureTime,\n      lastSuccessTime: this.lastSuccessTime,\n      lastStateChange: this.lastStateChange,\n    };\n  }\n\n  /**\n   * Manually reset the circuit breaker\n   */\n  reset(): void {\n    this.state = CircuitState.CLOSED;\n    this.failureCount = 0;\n    this.successCount = 0;\n    this.rejectionCount = 0;\n    this.halfOpenCalls = 0;\n    this.lastFailureTime = undefined;\n    this.lastSuccessTime = undefined;\n    this.lastStateChange = new Date();\n\n    if (this.openTimeout) {\n      clearTimeout(this.openTimeout);\n      this.openTimeout = undefined;\n    }\n  }\n\n  /**\n   * Check if circuit is open\n   *\n   * @returns True if circuit is open\n   */\n  isOpen(): boolean {\n    return this.state === CircuitState.OPEN;\n  }\n\n  /**\n   * Check if circuit is closed\n   *\n   * @returns True if circuit is closed\n   */\n  isClosed(): boolean {\n    return this.state === CircuitState.CLOSED;\n  }\n\n  /**\n   * Check if circuit is half-open\n   *\n   * @returns True if circuit is half-open\n   */\n  isHalfOpen(): boolean {\n    return this.state === CircuitState.HALF_OPEN;\n  }\n\n  /**\n   * Validate configuration options\n   */\n  private validateOptions(): void {\n    if (this.options.threshold <= 0) {\n      throw new Error('Circuit breaker threshold must be positive');\n    }\n    if (this.options.timeout <= 0) {\n      throw new Error('Circuit breaker timeout must be positive');\n    }\n    if (this.options.halfOpenMaxCalls <= 0) {\n      throw new Error('Circuit breaker halfOpenMaxCalls must be positive');\n    }\n  }\n\n  /**\n   * Cleanup resources\n   */\n  destroy(): void {\n    if (this.openTimeout) {\n      clearTimeout(this.openTimeout);\n      this.openTimeout = undefined;\n    }\n  }\n}\n\n/**\n * Circuit breaker error\n */\nexport class CircuitBreakerError extends Error {\n  constructor(\n    message: string,\n    public stats: CircuitBreakerStats\n  ) {\n    super(message);\n    this.name = 'CircuitBreakerError';\n  }\n}\n\n/**\n * Create a circuit breaker instance\n *\n * @param options - Circuit breaker options\n * @returns Circuit breaker instance\n *\n * @example\n * ```typescript\n * const breaker = createCircuitBreaker({\n *   threshold: 5,\n *   timeout: 60000,\n *   halfOpenMaxCalls: 3,\n *   name: 'payment-service'\n * });\n * ```\n */\nexport function createCircuitBreaker(options: CircuitBreakerOptions): CircuitBreaker {\n  return new CircuitBreaker(options);\n}\n","/**\n * Runtime validation utilities using Zod\n *\n * Provides schema-based validation for messages, configuration, and metadata.\n * Enables type-safe runtime validation with helpful error messages.\n *\n * @module validation\n */\n\nimport { z } from 'zod';\nimport { EventMetadata, NatsPubsubConfig } from '../types';\n\n/**\n * Zod schema for event metadata validation\n */\nexport const EventMetadataSchema = z.object({\n  event_id: z.string().min(1, 'Event ID is required'),\n  subject: z.string().min(1, 'Subject is required'),\n  domain: z.string().min(1, 'Domain is required'),\n  resource: z.string().min(1, 'Resource is required'),\n  action: z.string().min(1, 'Action is required'),\n  stream: z.string().optional(),\n  stream_seq: z.number().int().positive().optional(),\n  deliveries: z.number().int().positive().optional(),\n  trace_id: z.string().optional(),\n});\n\n/**\n * Zod schema for NATS PubSub configuration validation\n */\nexport const ConfigSchema = z.object({\n  natsUrls: z.union([z.string(), z.array(z.string())]),\n  env: z.string().min(1, 'Environment is required'),\n  appName: z.string().min(1, 'Application name is required'),\n  concurrency: z.number().int().positive().optional(),\n  maxDeliver: z.number().int().positive().optional(),\n  ackWait: z.number().int().positive().optional(),\n  backoff: z.array(z.number().int().positive()).optional(),\n  useOutbox: z.boolean().optional(),\n  useInbox: z.boolean().optional(),\n  useDlq: z.boolean().optional(),\n  streamName: z.string().optional(),\n  dlqSubject: z.string().optional(),\n  metrics: z\n    .object({\n      recordDlqMessage: z.function(),\n    })\n    .passthrough()\n    .optional(),\n  perMessageConcurrency: z.number().int().positive().optional(),\n  subscriberTimeoutMs: z.number().int().positive().optional(),\n  dlqMaxAttempts: z.number().int().positive().optional(),\n  logger: z\n    .object({\n      debug: z.function(),\n      info: z.function(),\n      warn: z.function(),\n      error: z.function(),\n    })\n    .passthrough()\n    .optional(),\n}) as z.ZodType<NatsPubsubConfig>;\n\n/**\n * Validation error class for schema validation failures\n */\nexport class ValidationError extends Error {\n  constructor(\n    message: string,\n    public issues: z.ZodIssue[]\n  ) {\n    super(message);\n    this.name = 'ValidationError';\n  }\n}\n\n/**\n * Validates data against a Zod schema\n *\n * @template T - The type of the schema\n * @param schema - Zod schema to validate against\n * @param data - Data to validate\n * @param errorMessage - Optional custom error message\n * @returns The validated and typed data\n * @throws ValidationError if validation fails\n *\n * @example\n * ```typescript\n * const UserSchema = z.object({\n *   id: z.string(),\n *   name: z.string().min(1),\n *   email: z.string().email(),\n * });\n *\n * const user = validate(UserSchema, rawData, 'Invalid user data');\n * // user is now typed as { id: string; name: string; email: string }\n * ```\n */\nexport function validate<T extends z.ZodType>(\n  schema: T,\n  data: unknown,\n  errorMessage?: string\n): z.infer<T> {\n  const result = schema.safeParse(data);\n\n  if (!result.success) {\n    const message =\n      errorMessage || `Validation failed: ${result.error.issues.map((i) => i.message).join(', ')}`;\n    throw new ValidationError(message, result.error.issues);\n  }\n\n  return result.data;\n}\n\n/**\n * Creates a type-safe subscriber with runtime message validation\n *\n * @template TMessage - The schema type for the message\n * @param messageSchema - Zod schema for validating incoming messages\n * @param handler - Handler function that receives validated messages\n * @returns A subscriber call function with runtime validation\n *\n * @example\n * ```typescript\n * const UserCreatedSchema = z.object({\n *   id: z.string(),\n *   name: z.string(),\n *   email: z.string().email(),\n * });\n *\n * class UserSubscriber extends Subscriber {\n *   private validatedHandle = createValidatedSubscriber(\n *     UserCreatedSchema,\n *     async (message, metadata) => {\n *       // message is typed and validated!\n *       console.log(message.email); // TypeScript knows this is a string\n *     }\n *   );\n *\n *   async handle(message: Record<string, unknown>, metadata: EventMetadata) {\n *     return this.validatedHandle(message, metadata);\n *   }\n * }\n * ```\n */\nexport function createValidatedSubscriber<T extends z.ZodType>(\n  messageSchema: T,\n  handler: (message: z.infer<T>, metadata: EventMetadata) => Promise<void>\n): (message: Record<string, unknown>, metadata: EventMetadata) => Promise<void> {\n  return async (message: Record<string, unknown>, metadata: EventMetadata): Promise<void> => {\n    const validatedMessage = validate(\n      messageSchema,\n      message,\n      `Invalid message format for subject ${metadata.subject}`\n    );\n    return handler(validatedMessage, metadata);\n  };\n}\n\n/**\n * Validates configuration at runtime\n *\n * @param config - Configuration object to validate\n * @returns Validated configuration\n * @throws ValidationError if configuration is invalid\n *\n * @example\n * ```typescript\n * const config = validateConfig({\n *   natsUrls: 'nats://localhost:4222',\n *   env: 'development',\n *   appName: 'my-app',\n * });\n * ```\n */\nexport function validateConfig(config: unknown): NatsPubsubConfig {\n  return validate(ConfigSchema, config, 'Invalid NatsPubsub configuration');\n}\n\n/**\n * Validates event metadata at runtime\n *\n * @param metadata - Metadata object to validate\n * @returns Validated metadata\n * @throws ValidationError if metadata is invalid\n *\n * @example\n * ```typescript\n * const metadata = validateMetadata(rawMetadata);\n * ```\n */\nexport function validateMetadata(metadata: unknown): EventMetadata {\n  return validate(EventMetadataSchema, metadata, 'Invalid event metadata');\n}\n\n// Re-export Zod for convenience\nexport { z } from 'zod';\n","import { JetStreamClient, headers as natsHeaders } from 'nats';\nimport connection from '../core/connection';\nimport config from '../core/config';\nimport { EnvelopeBuilder } from './envelope-builder';\nimport { SubjectBuilder } from './subject-builder';\nimport { PublishValidator } from './publish-validator';\nimport { PublishResultBuilder } from './publish-result';\nimport {\n  TopicPublishOptions,\n  DomainResourceActionParams,\n  MultiTopicParams,\n  MultiTopicPublishResult,\n} from './types';\n\n// Re-export types for backward compatibility\nexport { TopicMessage, TopicPublishOptions } from './types';\n\n/**\n * Logger interface for dependency injection\n */\nexport interface Logger {\n  debug(message: string, meta?: Record<string, unknown>): void;\n  info(message: string, meta?: Record<string, unknown>): void;\n  error(message: string, meta?: Record<string, unknown>): void;\n  warn(message: string, meta?: Record<string, unknown>): void;\n}\n\n/**\n * Connection manager interface for dependency injection\n */\nexport interface ConnectionManager {\n  ensureConnection(): Promise<void>;\n  getJetStream(): JetStreamClient;\n}\n\n/**\n * Publisher - Handles message publishing to NATS JetStream\n *\n * This class follows SOLID principles and best practices:\n * - Single Responsibility: Coordinates publishing operations\n * - Open/Closed: Easy to extend with new publish strategies\n * - Liskov Substitution: Can be replaced with mock implementations\n * - Interface Segregation: Uses focused interfaces\n * - Dependency Inversion: Depends on abstractions (interfaces)\n *\n * Design Patterns:\n * - Dependency Injection: All dependencies are injected\n * - Strategy Pattern: Different publish strategies (topic, multi-topic, domain/resource/action)\n * - Builder Pattern: Uses builder classes for construction\n *\n * @example Basic usage\n * ```typescript\n * const publisher = new Publisher();\n * await publisher.publishToTopic('notifications', { message: 'Hello' });\n * ```\n *\n * @example With dependency injection\n * ```typescript\n * const publisher = new Publisher(\n *   customConnection,\n *   customLogger,\n *   customEnvelopeBuilder,\n *   customSubjectBuilder,\n *   customValidator\n * );\n * ```\n */\nexport class Publisher {\n  private readonly connectionManager: ConnectionManager;\n  private readonly logger: Logger;\n  private readonly envelopeBuilder: EnvelopeBuilder;\n  private readonly subjectBuilder: SubjectBuilder;\n  private readonly validator: PublishValidator;\n\n  /**\n   * Create a new Publisher instance\n   *\n   * @param connectionManager - Connection manager (defaults to global connection)\n   * @param logger - Logger instance (defaults to global config.logger)\n   * @param envelopeBuilder - Envelope builder (created from config if not provided)\n   * @param subjectBuilder - Subject builder (created from config if not provided)\n   * @param validator - Validator instance (created if not provided)\n   */\n  constructor(\n    connectionManager?: ConnectionManager,\n    logger?: Logger,\n    envelopeBuilder?: EnvelopeBuilder,\n    subjectBuilder?: SubjectBuilder,\n    validator?: PublishValidator\n  ) {\n    this.connectionManager = connectionManager || connection;\n    this.logger = logger || config.logger;\n\n    if (envelopeBuilder && subjectBuilder) {\n      this.envelopeBuilder = envelopeBuilder;\n      this.subjectBuilder = subjectBuilder;\n    } else {\n      const cfg = config.get();\n      this.envelopeBuilder = envelopeBuilder || new EnvelopeBuilder(cfg.appName);\n      this.subjectBuilder = subjectBuilder || new SubjectBuilder(cfg.env, cfg.appName);\n    }\n\n    this.validator = validator || new PublishValidator();\n  }\n\n  /**\n   * Publish a message to a specific topic\n   *\n   * Topics are the foundation of the pubsub system. Use dot notation for\n   * hierarchical topics and wildcards (* and >) for pattern matching.\n   *\n   * @param topic - Topic name (e.g., 'notifications', 'users.user.created')\n   * @param message - Message payload\n   * @param options - Additional publish options\n   *\n   * @example\n   * ```typescript\n   * // Simple topic\n   * await publisher.publishToTopic('notifications', { type: 'email' });\n   *\n   * // Hierarchical topic\n   * await publisher.publishToTopic('notifications.email', { to: 'user@example.com' });\n   *\n   * // With options\n   * await publisher.publishToTopic('analytics', { event: 'page_view' }, {\n   *   trace_id: 'trace-123',\n   *   message_type: 'urgent'\n   * });\n   * ```\n   */\n  async publishToTopic(\n    topic: string,\n    message: Record<string, unknown>,\n    options: TopicPublishOptions = {}\n  ): Promise<void> {\n    // Validate inputs\n    this.validator.validateTopic(topic);\n    this.validator.validateMessage(message);\n\n    // Ensure connection\n    await this.connectionManager.ensureConnection();\n    const js = this.connectionManager.getJetStream();\n\n    // Build envelope and subject\n    const envelope = this.envelopeBuilder.build(topic, message, options);\n    const subject = this.subjectBuilder.buildTopicSubject(topic);\n\n    try {\n      this.logger.debug('Publishing to topic', {\n        subject,\n        topic,\n        event_id: envelope.event_id,\n      });\n\n      // Build NATS headers\n      const hdrs = natsHeaders();\n      hdrs.set('Nats-Msg-Id', envelope.event_id);\n      hdrs.set('topic', topic);\n\n      if (options.trace_id) {\n        hdrs.set('trace_id', options.trace_id);\n      }\n\n      // Publish to NATS\n      await js.publish(subject, JSON.stringify(envelope), {\n        msgID: envelope.event_id,\n        headers: hdrs,\n      });\n\n      this.logger.info('Topic message published successfully', {\n        subject,\n        topic,\n        event_id: envelope.event_id,\n      });\n    } catch (error) {\n      this.logger.error('Failed to publish topic message', {\n        subject,\n        topic,\n        event_id: envelope.event_id,\n        error,\n      });\n      throw error;\n    }\n  }\n\n  /**\n   * Publish to multiple topics at once\n   *\n   * Broadcasts the same message to multiple topics. Useful for cross-cutting\n   * concerns like audit logs and notifications.\n   *\n   * @param topics - Array of topic names\n   * @param message - Message payload\n   * @param options - Additional publish options\n   * @returns Results object with statistics\n   *\n   * @example\n   * ```typescript\n   * const result = await publisher.publishToTopics(\n   *   ['notifications.email', 'audit.user_events'],\n   *   { action: 'user_login', user_id: 123 }\n   * );\n   * console.log(`Published to ${result.successCount} topics`);\n   * ```\n   */\n  async publishToTopics(\n    topics: string[],\n    message: Record<string, unknown>,\n    options: TopicPublishOptions = {}\n  ): Promise<MultiTopicPublishResult> {\n    // Validate inputs\n    this.validator.validateTopicsArray(topics);\n    this.validator.validateMessage(message);\n\n    const results: Record<string, boolean> = {};\n\n    await Promise.all(\n      topics.map(async (topic) => {\n        try {\n          await this.publishToTopic(topic, message, options);\n          results[topic] = true;\n        } catch {\n          results[topic] = false;\n        }\n      })\n    );\n\n    return PublishResultBuilder.fromTopicResults(results);\n  }\n\n  /**\n   * Polymorphic publish method that supports both topic-based and domain/resource/action patterns\n   *\n   * @overload\n   * Publish to a single topic\n   * @param topic - Topic name\n   * @param message - Message payload\n   * @param options - Optional publish options\n   *\n   * @overload\n   * Publish to multiple topics\n   * @param params - Object with topics array and message\n   * @param params.topics - Array of topic names\n   * @param params.message - Message payload\n   * @param options - Optional publish options\n   *\n   * @overload\n   * Publish using domain/resource/action pattern\n   * @param params - Object with domain, resource, action, and payload\n   * @param params.domain - Business domain\n   * @param params.resource - Resource type\n   * @param params.action - Event action\n   * @param params.payload - Event payload\n   * @param options - Optional publish options\n   *\n   * @example Topic-based (single)\n   * ```typescript\n   * await publisher.publish('notifications.email', { to: 'user@example.com' });\n   * ```\n   *\n   * @example Topic-based (multiple)\n   * ```typescript\n   * await publisher.publish({\n   *   topics: ['notifications', 'audit'],\n   *   message: { action: 'login' }\n   * });\n   * ```\n   *\n   * @example Domain/Resource/Action\n   * ```typescript\n   * await publisher.publish({\n   *   domain: 'users',\n   *   resource: 'user',\n   *   action: 'created',\n   *   payload: { id: 123, name: 'John' }\n   * });\n   * ```\n   */\n  async publish(\n    topicOrParams: string | MultiTopicParams | DomainResourceActionParams,\n    messageOrOptions?: Record<string, unknown> | TopicPublishOptions,\n    options?: TopicPublishOptions\n  ): Promise<void | MultiTopicPublishResult> {\n    // Case 1: Topic-based single topic - publish(topic, message, options?)\n    if (typeof topicOrParams === 'string') {\n      const topic = topicOrParams;\n      const message = messageOrOptions as Record<string, unknown>;\n      const opts = options || {};\n      return this.publishToTopic(topic, message, opts);\n    }\n\n    // Case 2: Multiple topics - publish({ topics: [...], message: {...} }, options?)\n    if ('topics' in topicOrParams && 'message' in topicOrParams) {\n      this.validator.validateMultiTopicParams(topicOrParams);\n      const opts = (messageOrOptions as TopicPublishOptions) || {};\n      return this.publishToTopics(topicOrParams.topics, topicOrParams.message, opts);\n    }\n\n    // Case 3: Domain/Resource/Action - publish({ domain, resource, action, payload }, options?)\n    if ('domain' in topicOrParams && 'resource' in topicOrParams && 'action' in topicOrParams) {\n      this.validator.validateDomainResourceAction(topicOrParams);\n      return this.publishDomainResourceAction(\n        topicOrParams,\n        messageOrOptions as TopicPublishOptions\n      );\n    }\n\n    throw new Error(\n      'Invalid publish arguments. Use topic string, topics array, or domain/resource/action object.'\n    );\n  }\n\n  /**\n   * Publish using domain/resource/action pattern\n   *\n   * @param params - Domain/resource/action parameters\n   * @param options - Optional publish options\n   */\n  private async publishDomainResourceAction(\n    params: DomainResourceActionParams,\n    options: TopicPublishOptions = {}\n  ): Promise<void> {\n    const { domain, resource, action, payload } = params;\n\n    // Map domain/resource/action to topic\n    const topic = this.subjectBuilder.buildTopicFromDomainResourceAction(domain, resource, action);\n\n    // Build topic publish options including domain/resource/action for backward compatibility\n    const topicOptions: TopicPublishOptions = {\n      ...options,\n      domain,\n      resource,\n      action,\n      resource_id: this.envelopeBuilder.extractResourceId(payload),\n    };\n\n    return this.publishToTopic(topic, payload, topicOptions);\n  }\n}\n\n// Lazy-initialized singleton instance\nlet publisherInstance: Publisher | null = null;\n\nfunction getPublisherInstance(): Publisher {\n  if (!publisherInstance) {\n    publisherInstance = new Publisher();\n  }\n  return publisherInstance;\n}\n\nexport default getPublisherInstance();\n","import { randomUUID } from 'crypto';\nimport { TopicMessage, TopicPublishOptions } from './types';\n\n/**\n * EnvelopeBuilder - Responsible for constructing message envelopes\n *\n * Follows the Builder pattern to create topic message envelopes with proper\n * structure and validation. Encapsulates all envelope construction logic.\n *\n * SOLID Principles:\n * - Single Responsibility: Only builds message envelopes\n * - Open/Closed: Easy to extend with new envelope fields\n */\nexport class EnvelopeBuilder {\n  private readonly appName: string;\n\n  constructor(appName: string) {\n    this.appName = appName;\n  }\n\n  /**\n   * Build a topic message envelope\n   *\n   * @param topic - Topic name\n   * @param message - Message payload\n   * @param options - Additional publish options\n   * @returns Constructed envelope\n   */\n  build(\n    topic: string,\n    message: Record<string, unknown>,\n    options: TopicPublishOptions = {}\n  ): TopicMessage {\n    const eventId = options.event_id || this.generateEventId();\n    const occurredAt = options.occurred_at || new Date();\n\n    const envelope: TopicMessage = {\n      event_id: eventId,\n      schema_version: 1,\n      topic,\n      message_type: options.message_type,\n      producer: this.appName,\n      occurred_at: occurredAt.toISOString(),\n      trace_id: options.trace_id,\n      message,\n    };\n\n    // Add optional domain/resource/action fields for backward compatibility\n    this.addLegacyFields(envelope, options);\n\n    return envelope;\n  }\n\n  /**\n   * Generate a unique event ID\n   */\n  private generateEventId(): string {\n    return randomUUID();\n  }\n\n  /**\n   * Add legacy domain/resource/action fields if provided\n   */\n  private addLegacyFields(envelope: TopicMessage, options: TopicPublishOptions): void {\n    if (options.domain) envelope.domain = options.domain;\n    if (options.resource) envelope.resource = options.resource;\n    if (options.action) envelope.action = options.action;\n    if (options.resource_id) envelope.resource_id = options.resource_id;\n  }\n\n  /**\n   * Extract resource_id from payload if present\n   */\n  extractResourceId(payload: Record<string, unknown>): string | undefined {\n    return (payload.id || payload.ID) as string | undefined;\n  }\n}\n","import { Subject } from '../core/subject';\n\n/**\n * SubjectBuilder - Responsible for constructing NATS subjects\n *\n * Encapsulates all subject construction logic, making it easy to modify\n * subject formatting rules in one place.\n *\n * SOLID Principles:\n * - Single Responsibility: Only builds NATS subjects\n * - Open/Closed: Easy to extend with new subject patterns\n */\nexport class SubjectBuilder {\n  private readonly env: string;\n  private readonly appName: string;\n\n  constructor(env: string, appName: string) {\n    this.env = env;\n    this.appName = appName;\n  }\n\n  /**\n   * Build NATS subject for a topic\n   * Format: {env}.{appName}.{topic}\n   *\n   * @param topic - Topic name\n   * @returns NATS subject string\n   */\n  buildTopicSubject(topic: string): string {\n    return Subject.forTopic(this.env, this.appName, topic);\n  }\n\n  /**\n   * Build NATS subject from domain/resource/action\n   * Maps to topic format: {domain}.{resource}.{action}\n   *\n   * @param domain - Business domain\n   * @param resource - Resource type\n   * @param action - Event action\n   * @returns NATS subject string\n   */\n  buildDomainResourceActionSubject(domain: string, resource: string, action: string): string {\n    const topic = `${domain}.${resource}.${action}`;\n    return this.buildTopicSubject(topic);\n  }\n\n  /**\n   * Get topic from domain/resource/action\n   *\n   * @param domain - Business domain\n   * @param resource - Resource type\n   * @param action - Event action\n   * @returns Topic string\n   */\n  buildTopicFromDomainResourceAction(domain: string, resource: string, action: string): string {\n    return `${domain}.${resource}.${action}`;\n  }\n}\n","import { DomainResourceActionParams, MultiTopicParams } from './types';\n\n/**\n * PublishValidator - Responsible for validating publish parameters\n *\n * Centralizes all validation logic for publish operations, making it\n * easy to maintain and test validation rules.\n *\n * SOLID Principles:\n * - Single Responsibility: Only validates publish parameters\n * - Open/Closed: Easy to add new validation rules\n */\nexport class PublishValidator {\n  /**\n   * Validate topic name\n   *\n   * @param topic - Topic to validate\n   * @throws Error if topic is invalid\n   */\n  validateTopic(topic: string): void {\n    if (!topic || typeof topic !== 'string') {\n      throw new Error('Topic must be a non-empty string');\n    }\n\n    if (topic.trim().length === 0) {\n      throw new Error('Topic cannot be empty or whitespace only');\n    }\n  }\n\n  /**\n   * Validate message payload\n   *\n   * @param message - Message to validate\n   * @throws Error if message is invalid\n   */\n  validateMessage(message: Record<string, unknown>): void {\n    if (!message || typeof message !== 'object') {\n      throw new Error('Message must be an object');\n    }\n\n    if (Array.isArray(message)) {\n      throw new Error('Message cannot be an array');\n    }\n  }\n\n  /**\n   * Validate domain/resource/action parameters\n   *\n   * @param params - Parameters to validate\n   * @throws Error if parameters are invalid\n   */\n  validateDomainResourceAction(params: DomainResourceActionParams): void {\n    const { domain, resource, action, payload } = params;\n\n    if (!domain || typeof domain !== 'string' || domain.trim().length === 0) {\n      throw new Error('Domain must be a non-empty string');\n    }\n\n    if (!resource || typeof resource !== 'string' || resource.trim().length === 0) {\n      throw new Error('Resource must be a non-empty string');\n    }\n\n    if (!action || typeof action !== 'string' || action.trim().length === 0) {\n      throw new Error('Action must be a non-empty string');\n    }\n\n    if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n      throw new Error('Payload must be a non-array object');\n    }\n  }\n\n  /**\n   * Validate multi-topic parameters\n   *\n   * @param params - Parameters to validate\n   * @throws Error if parameters are invalid\n   */\n  validateMultiTopicParams(params: MultiTopicParams): void {\n    const { topics, message } = params;\n\n    if (!Array.isArray(topics)) {\n      throw new Error('Topics must be an array');\n    }\n\n    if (topics.length === 0) {\n      throw new Error('Topics array cannot be empty');\n    }\n\n    // Validate each topic\n    for (const topic of topics) {\n      this.validateTopic(topic);\n    }\n\n    this.validateMessage(message);\n  }\n\n  /**\n   * Validate topics array\n   *\n   * @param topics - Topics to validate\n   * @throws Error if topics are invalid\n   */\n  validateTopicsArray(topics: string[]): void {\n    if (!Array.isArray(topics)) {\n      throw new Error('Topics must be an array');\n    }\n\n    if (topics.length === 0) {\n      throw new Error('Topics array cannot be empty');\n    }\n\n    for (const topic of topics) {\n      this.validateTopic(topic);\n    }\n  }\n}\n","import { MultiTopicPublishResult } from './types';\n\n/**\n * PublishResultBuilder - Helps construct and manage publish results\n *\n * Provides utility methods for building publish result objects with\n * proper structure and statistics.\n *\n * SOLID Principles:\n * - Single Responsibility: Only manages publish results\n * - Open/Closed: Easy to extend with new result types\n */\nexport class PublishResultBuilder {\n  /**\n   * Create a multi-topic publish result from individual results\n   *\n   * @param results - Map of topic to success boolean\n   * @returns Multi-topic publish result with statistics\n   */\n  static fromTopicResults(results: Record<string, boolean>): MultiTopicPublishResult {\n    const successCount = Object.values(results).filter((success) => success).length;\n    const failureCount = Object.values(results).length - successCount;\n\n    return {\n      results,\n      successCount,\n      failureCount,\n    };\n  }\n\n  /**\n   * Create an empty multi-topic result\n   *\n   * @returns Empty multi-topic publish result\n   */\n  static createEmpty(): MultiTopicPublishResult {\n    return {\n      results: {},\n      successCount: 0,\n      failureCount: 0,\n    };\n  }\n\n  /**\n   * Check if all topics published successfully\n   *\n   * @param result - Multi-topic publish result\n   * @returns True if all topics published successfully\n   */\n  static isAllSuccess(result: MultiTopicPublishResult): boolean {\n    return result.failureCount === 0;\n  }\n\n  /**\n   * Check if any topics published successfully\n   *\n   * @param result - Multi-topic publish result\n   * @returns True if at least one topic published successfully\n   */\n  static hasAnySuccess(result: MultiTopicPublishResult): boolean {\n    return result.successCount > 0;\n  }\n\n  /**\n   * Get list of successful topics\n   *\n   * @param result - Multi-topic publish result\n   * @returns Array of successful topic names\n   */\n  static getSuccessfulTopics(result: MultiTopicPublishResult): string[] {\n    return Object.entries(result.results)\n      .filter(([, success]) => success)\n      .map(([topic]) => topic);\n  }\n\n  /**\n   * Get list of failed topics\n   *\n   * @param result - Multi-topic publish result\n   * @returns Array of failed topic names\n   */\n  static getFailedTopics(result: MultiTopicPublishResult): string[] {\n    return Object.entries(result.results)\n      .filter(([, success]) => !success)\n      .map(([topic]) => topic);\n  }\n}\n","import { Publisher } from './publisher';\nimport { TopicPublishOptions } from './types';\nimport config from '../core/config';\n\n/**\n * Result of a batch publish operation\n */\nexport interface FluentBatchPublishResult {\n  /** Total number of messages in the batch */\n  total: number;\n  /** Number of successfully published messages */\n  succeeded: number;\n  /** Number of failed messages */\n  failed: number;\n  /** Detailed results for each message */\n  results: Array<{\n    topic: string;\n    success: boolean;\n    eventId?: string;\n    error?: string;\n  }>;\n}\n\n/**\n * Item in the batch\n */\ninterface BatchItem {\n  topic: string;\n  message: Record<string, unknown>;\n}\n\n/**\n * FluentBatchPublisher provides a modern fluent API for publishing multiple messages efficiently.\n * Messages are published in parallel with optimized error handling.\n *\n * @example\n * ```typescript\n * const result = await NatsPubsub.batch()\n *   .add('user.created', { id: 1, name: 'Alice' })\n *   .add('user.created', { id: 2, name: 'Bob' })\n *   .add('notification.sent', { userId: 1 })\n *   .withOptions({ traceId: 'batch-123' })\n *   .publish();\n *\n * console.log(`Published ${result.succeeded}/${result.total} messages`);\n * ```\n */\nexport class FluentBatchPublisher {\n  private items: BatchItem[] = [];\n  private options: TopicPublishOptions = {};\n  private publisher: Publisher;\n\n  constructor(publisher?: Publisher) {\n    this.publisher = publisher || new Publisher();\n  }\n\n  /**\n   * Add a message to the batch\n   *\n   * @param topic - Topic to publish to\n   * @param message - Message payload\n   * @returns this for chaining\n   */\n  add(topic: string, message: Record<string, unknown>): this {\n    this.items.push({ topic, message });\n    return this;\n  }\n\n  /**\n   * Set options that will be applied to all messages in the batch\n   *\n   * @param options - Publish options (traceId, correlationId, etc.)\n   * @returns this for chaining\n   */\n  withOptions(options: TopicPublishOptions): this {\n    this.options = { ...this.options, ...options };\n    return this;\n  }\n\n  /**\n   * Publish all messages in the batch\n   *\n   * Messages are published in parallel using Promise.allSettled to ensure\n   * all messages are attempted even if some fail.\n   *\n   * @returns FluentBatchPublishResult with success/failure details\n   */\n  async publish(): Promise<FluentBatchPublishResult> {\n    if (this.items.length === 0) {\n      return {\n        total: 0,\n        succeeded: 0,\n        failed: 0,\n        results: [],\n      };\n    }\n\n    const logger = config.get().logger;\n    logger?.debug(`Publishing batch of ${this.items.length} messages`);\n\n    // Publish all messages in parallel\n    const promises = this.items.map(async (item) => {\n      try {\n        await this.publisher.publishToTopic(item.topic, item.message, this.options);\n        return {\n          topic: item.topic,\n          success: true as const,\n          eventId: this.options.event_id,\n        };\n      } catch (error) {\n        logger?.error(`Batch publish failed for topic ${item.topic}:`, { error });\n        return {\n          topic: item.topic,\n          success: false as const,\n          error: error instanceof Error ? error.message : String(error),\n        };\n      }\n    });\n\n    const results = await Promise.allSettled(promises);\n\n    // Process results\n    const mappedResults = results.map((result) => {\n      if (result.status === 'fulfilled') {\n        return result.value;\n      } else {\n        // This shouldn't happen since we catch errors above, but handle it anyway\n        return {\n          topic: 'unknown',\n          success: false as const,\n          error: result.reason instanceof Error ? result.reason.message : String(result.reason),\n        };\n      }\n    });\n\n    const succeeded = mappedResults.filter((r) => r.success).length;\n    const failed = mappedResults.filter((r) => !r.success).length;\n\n    logger?.info(\n      `Batch publish completed: ${succeeded}/${this.items.length} succeeded, ${failed} failed`\n    );\n\n    return {\n      total: this.items.length,\n      succeeded,\n      failed,\n      results: mappedResults,\n    };\n  }\n\n  /**\n   * Clear all items from the batch\n   *\n   * @returns this for chaining\n   */\n  clear(): this {\n    this.items = [];\n    return this;\n  }\n\n  /**\n   * Get the number of items in the batch\n   *\n   * @returns number of items\n   */\n  get size(): number {\n    return this.items.length;\n  }\n}\n","import { Publisher, Logger } from './publisher';\nimport publisherInstance from './publisher';\nimport config from '../core/config';\nimport { PublishOptions } from '../types';\n\nexport interface BatchPublishItem {\n  domain: string;\n  resource: string;\n  action: string;\n  payload: Record<string, unknown>;\n  options?: PublishOptions;\n}\n\nexport interface BatchPublishResult {\n  successful: number;\n  failed: number;\n  errors: Array<{\n    index: number;\n    item: BatchPublishItem;\n    error: string;\n  }>;\n  duration: number;\n}\n\n/**\n * BatchPublisher - Handles batch publishing operations\n *\n * This class follows SOLID principles and best practices:\n * - Single Responsibility: Only handles batch publishing operations\n * - Open/Closed: Easy to extend with new batch strategies\n * - Dependency Inversion: Depends on Publisher abstraction\n *\n * Design Patterns:\n * - Dependency Injection: Publisher and Logger are injected\n * - Facade Pattern: Provides a simpler interface for batch operations\n *\n * @example Basic usage\n * ```typescript\n * const batchPublisher = new BatchPublisher();\n * const result = await batchPublisher.publishBatch(items);\n * console.log(`Published ${result.successful} items`);\n * ```\n *\n * @example With dependency injection\n * ```typescript\n * const batchPublisher = new BatchPublisher(customPublisher, customLogger);\n * ```\n */\nexport class BatchPublisher {\n  private readonly publisher: Publisher;\n  private readonly logger: Logger;\n\n  /**\n   * Create a new BatchPublisher instance\n   *\n   * @param publisher - Publisher instance (defaults to global publisher)\n   * @param logger - Logger instance (defaults to global config.logger)\n   */\n  constructor(publisher?: Publisher, logger?: Logger) {\n    this.publisher = publisher || publisherInstance;\n    this.logger = logger || config.logger;\n  }\n\n  /**\n   * Publish multiple events in a batch\n   *\n   * Continues publishing even if some items fail, providing detailed\n   * results about successes and failures.\n   *\n   * @param items - Array of items to publish\n   * @returns Result with statistics and error details\n   *\n   * @example\n   * ```typescript\n   * const items = [\n   *   { domain: 'users', resource: 'user', action: 'created', payload: { id: 1 } },\n   *   { domain: 'users', resource: 'user', action: 'updated', payload: { id: 2 } }\n   * ];\n   * const result = await batchPublisher.publishBatch(items);\n   * console.log(`Success: ${result.successful}, Failed: ${result.failed}`);\n   * ```\n   */\n  async publishBatch(items: BatchPublishItem[]): Promise<BatchPublishResult> {\n    const startTime = Date.now();\n    const result: BatchPublishResult = {\n      successful: 0,\n      failed: 0,\n      errors: [],\n      duration: 0,\n    };\n\n    // Validate input\n    this.validateBatchItems(items);\n\n    this.logger.info('Publishing batch', {\n      count: items.length,\n    });\n\n    // Publish all items in parallel\n    const promises = items.map(async (item, index) => {\n      try {\n        await this.publishSingleItem(item);\n        result.successful++;\n      } catch (error) {\n        result.failed++;\n        result.errors.push({\n          index,\n          item,\n          error: error instanceof Error ? error.message : 'Unknown error',\n        });\n\n        this.logPublishError(item, index, error);\n      }\n    });\n\n    await Promise.allSettled(promises);\n\n    result.duration = Date.now() - startTime;\n\n    this.logger.info('Batch publish complete', {\n      successful: result.successful,\n      failed: result.failed,\n      duration_ms: result.duration,\n    });\n\n    return result;\n  }\n\n  /**\n   * Publish multiple events with the same domain/resource but different actions\n   *\n   * Useful for publishing multiple related events efficiently.\n   *\n   * @param domain - Business domain\n   * @param resource - Resource type\n   * @param events - Array of events with actions and payloads\n   * @returns Result with statistics and error details\n   *\n   * @example\n   * ```typescript\n   * const result = await batchPublisher.publishMany('users', 'user', [\n   *   { action: 'created', payload: { id: 1, name: 'Alice' } },\n   *   { action: 'updated', payload: { id: 2, name: 'Bob' } }\n   * ]);\n   * ```\n   */\n  async publishMany(\n    domain: string,\n    resource: string,\n    events: Array<{\n      action: string;\n      payload: Record<string, unknown>;\n      options?: PublishOptions;\n    }>\n  ): Promise<BatchPublishResult> {\n    this.validatePublishManyParams(domain, resource, events);\n\n    const items: BatchPublishItem[] = events.map((event) => ({\n      domain,\n      resource,\n      action: event.action,\n      payload: event.payload,\n      options: event.options,\n    }));\n\n    return this.publishBatch(items);\n  }\n\n  /**\n   * Publish the same event to multiple subjects (fanout pattern)\n   *\n   * Useful for broadcasting events to multiple destinations.\n   *\n   * @param destinations - Array of destination subjects\n   * @param payload - Payload to publish\n   * @param options - Optional publish options\n   * @returns Result with statistics and error details\n   *\n   * @example\n   * ```typescript\n   * const result = await batchPublisher.fanout(\n   *   [\n   *     { domain: 'notifications', resource: 'email', action: 'send' },\n   *     { domain: 'audit', resource: 'log', action: 'record' }\n   *   ],\n   *   { message: 'User logged in' }\n   * );\n   * ```\n   */\n  async fanout(\n    destinations: Array<{\n      domain: string;\n      resource: string;\n      action: string;\n    }>,\n    payload: Record<string, unknown>,\n    options?: PublishOptions\n  ): Promise<BatchPublishResult> {\n    this.validateFanoutParams(destinations, payload);\n\n    const items: BatchPublishItem[] = destinations.map((dest) => ({\n      domain: dest.domain,\n      resource: dest.resource,\n      action: dest.action,\n      payload,\n      options,\n    }));\n\n    return this.publishBatch(items);\n  }\n\n  /**\n   * Publish a single batch item\n   *\n   * @param item - Item to publish\n   */\n  private async publishSingleItem(item: BatchPublishItem): Promise<void> {\n    await this.publisher.publish(\n      {\n        domain: item.domain,\n        resource: item.resource,\n        action: item.action,\n        payload: item.payload,\n      },\n      item.options\n    );\n  }\n\n  /**\n   * Log a publish error\n   *\n   * @param item - Item that failed to publish\n   * @param index - Index of the item\n   * @param error - Error that occurred\n   */\n  private logPublishError(item: BatchPublishItem, index: number, error: unknown): void {\n    this.logger.error('Failed to publish batch item', {\n      index,\n      domain: item.domain,\n      resource: item.resource,\n      action: item.action,\n      error: error instanceof Error ? error.message : 'Unknown error',\n    });\n  }\n\n  /**\n   * Validate batch items\n   *\n   * @param items - Items to validate\n   * @throws Error if items are invalid\n   */\n  private validateBatchItems(items: BatchPublishItem[]): void {\n    if (!Array.isArray(items)) {\n      throw new Error('Items must be an array');\n    }\n\n    if (items.length === 0) {\n      throw new Error('Items array cannot be empty');\n    }\n\n    for (const item of items) {\n      this.validateBatchItem(item);\n    }\n  }\n\n  /**\n   * Validate a single batch item\n   *\n   * @param item - Item to validate\n   * @throws Error if item is invalid\n   */\n  private validateBatchItem(item: BatchPublishItem): void {\n    if (!item || typeof item !== 'object') {\n      throw new Error('Batch item must be an object');\n    }\n\n    if (!item.domain || typeof item.domain !== 'string') {\n      throw new Error('Batch item must have a valid domain');\n    }\n\n    if (!item.resource || typeof item.resource !== 'string') {\n      throw new Error('Batch item must have a valid resource');\n    }\n\n    if (!item.action || typeof item.action !== 'string') {\n      throw new Error('Batch item must have a valid action');\n    }\n\n    if (!item.payload || typeof item.payload !== 'object') {\n      throw new Error('Batch item must have a valid payload');\n    }\n  }\n\n  /**\n   * Validate publishMany parameters\n   *\n   * @param domain - Domain to validate\n   * @param resource - Resource to validate\n   * @param events - Events to validate\n   * @throws Error if parameters are invalid\n   */\n  private validatePublishManyParams(\n    domain: string,\n    resource: string,\n    events: Array<{ action: string; payload: Record<string, unknown>; options?: PublishOptions }>\n  ): void {\n    if (!domain || typeof domain !== 'string') {\n      throw new Error('Domain must be a non-empty string');\n    }\n\n    if (!resource || typeof resource !== 'string') {\n      throw new Error('Resource must be a non-empty string');\n    }\n\n    if (!Array.isArray(events) || events.length === 0) {\n      throw new Error('Events must be a non-empty array');\n    }\n  }\n\n  /**\n   * Validate fanout parameters\n   *\n   * @param destinations - Destinations to validate\n   * @param payload - Payload to validate\n   * @throws Error if parameters are invalid\n   */\n  private validateFanoutParams(\n    destinations: Array<{ domain: string; resource: string; action: string }>,\n    payload: Record<string, unknown>\n  ): void {\n    if (!Array.isArray(destinations) || destinations.length === 0) {\n      throw new Error('Destinations must be a non-empty array');\n    }\n\n    if (!payload || typeof payload !== 'object') {\n      throw new Error('Payload must be an object');\n    }\n\n    for (const dest of destinations) {\n      if (!dest.domain || !dest.resource || !dest.action) {\n        throw new Error('Each destination must have domain, resource, and action');\n      }\n    }\n  }\n}\n\nexport default new BatchPublisher();\n","import { AckPolicy, ConsumerConfig, DeliverPolicy, ReplayPolicy } from 'nats';\nimport { Middleware, Subscriber } from '../types';\nimport connection from '../core/connection';\nimport config from '../core/config';\nimport { toNanos } from '../core/duration';\nimport { MiddlewareChain } from '../middleware/chain';\nimport { TopologyManager } from '../topology/topology-manager';\nimport { DlqHandler } from '../dlq/dlq-handler';\nimport { Registry } from './registry';\nimport { MessageProcessor } from './message-processor';\n\n/**\n * Consumer orchestrates message consumption from NATS JetStream\n *\n * This class has been refactored to follow Single Responsibility Principle.\n * It now delegates specific responsibilities to focused modules:\n * - TopologyManager: Stream and DLQ setup\n * - Registry: Subscriber management\n * - MessageProcessor: Message processing logic\n * - DlqHandler: Dead letter queue operations\n *\n * The Consumer class focuses on:\n * - Lifecycle management (start/stop)\n * - Subscription management\n * - Coordinating the specialized modules\n */\nexport class Consumer {\n  private running = false;\n  private readonly middlewareChain: MiddlewareChain = new MiddlewareChain();\n  private readonly topologyManager: TopologyManager = new TopologyManager();\n  private readonly dlqHandler: DlqHandler = new DlqHandler();\n  private readonly registry: Registry = new Registry();\n  private readonly messageProcessor: MessageProcessor;\n\n  constructor() {\n    this.messageProcessor = new MessageProcessor(this.middlewareChain, this.dlqHandler);\n  }\n\n  /**\n   * Register a subscriber to handle messages\n   */\n  registerSubscriber(subscriber: Subscriber): void {\n    this.registry.register(subscriber);\n  }\n\n  /**\n   * Add middleware to the processing chain\n   */\n  use(middleware: Middleware): void {\n    this.middlewareChain.add(middleware);\n  }\n\n  /**\n   * Start consuming messages\n   */\n  async start(): Promise<void> {\n    if (this.running) {\n      throw new Error('Consumer already running');\n    }\n\n    await connection.ensureConnection();\n    const logger = config.logger;\n\n    this.running = true;\n    logger.info('Starting consumer...');\n\n    // Ensure stream topology exists\n    const jsm = await connection.getConnection().jetstreamManager();\n    await this.topologyManager.ensureTopology(jsm);\n\n    // Start subscriptions for each unique subject\n    const subjects = this.registry.getAllSubjects();\n\n    for (const subject of subjects) {\n      this.subscribe(subject);\n    }\n\n    logger.info('Consumer started', { subjects });\n  }\n\n  /**\n   * Stop consuming messages\n   */\n  async stop(): Promise<void> {\n    this.running = false;\n    const logger = config.logger;\n    logger.info('Stopping consumer...');\n    await connection.disconnect();\n    logger.info('Consumer stopped');\n  }\n\n  /**\n   * Subscribe to a subject and process messages\n   */\n  private async subscribe(subject: string): Promise<void> {\n    const js = connection.getJetStream();\n    const cfg = config.get();\n    const streamName = config.streamName;\n    const logger = config.logger;\n\n    const durableName = this.buildDurableName(subject);\n\n    const consumerConfig: Partial<ConsumerConfig> = {\n      durable_name: durableName,\n      ack_policy: AckPolicy.Explicit,\n      deliver_policy: DeliverPolicy.All,\n      replay_policy: ReplayPolicy.Instant,\n      filter_subject: subject,\n      max_deliver: cfg.maxDeliver || 5,\n      ack_wait: toNanos(cfg.ackWait || 30000),\n      max_ack_pending: cfg.concurrency || 10,\n    };\n\n    if (cfg.backoff && cfg.backoff.length > 0) {\n      consumerConfig.backoff = cfg.backoff.map((ms) => toNanos(ms));\n    }\n\n    try {\n      logger.info('Creating consumer subscription', {\n        subject,\n        durable: durableName,\n      });\n\n      const consumer = await js.consumers.get(streamName, durableName);\n      const messages = await consumer.consume({\n        max_messages: cfg.concurrency || 10,\n      });\n\n      logger.info('Consumer subscription created', { subject, durable: durableName });\n\n      // Process messages\n      (async () => {\n        for await (const msg of messages) {\n          if (!this.running) break;\n\n          const subscribers = this.registry.getSubscribers(subject);\n          await this.messageProcessor.processMessage(msg, subscribers);\n        }\n      })();\n    } catch (error) {\n      logger.error('Failed to create consumer subscription', {\n        subject,\n        error,\n      });\n      throw error;\n    }\n  }\n\n  /**\n   * Build durable consumer name from subject\n   */\n  private buildDurableName(subject: string): string {\n    const cfg = config.get();\n    // Replace wildcards and dots with underscores\n    const sanitized = subject.replace(/[.*>]/g, '_');\n    return `${cfg.appName}_${sanitized}`;\n  }\n}\n\nexport default new Consumer();\n","import { EventMetadata, Middleware } from '../types';\n\nexport class MiddlewareChain {\n  private middlewares: Middleware[] = [];\n\n  add(middleware: Middleware): void {\n    this.middlewares.push(middleware);\n  }\n\n  async execute(\n    event: Record<string, unknown>,\n    metadata: EventMetadata,\n    handler: (event: Record<string, unknown>, metadata: EventMetadata) => Promise<void>\n  ): Promise<void> {\n    let index = 0;\n\n    const next = async (): Promise<void> => {\n      if (index < this.middlewares.length) {\n        const middleware = this.middlewares[index++];\n        await middleware.call(event, metadata, next);\n      } else {\n        await handler(event, metadata);\n      }\n    };\n\n    await next();\n  }\n}\n","import { DiscardPolicy, JetStreamManager, RetentionPolicy, StorageType } from 'nats';\nimport config from '../core/config';\nimport { Subject } from '../core/subject';\nimport { toNanos } from '../core/duration';\n\n/**\n * TopologyManager handles JetStream stream and DLQ topology setup\n *\n * Responsibilities:\n * - Create and verify main event stream\n * - Create and verify DLQ stream\n * - Configure retention policies and storage\n */\nexport class TopologyManager {\n  /**\n   * Ensure all required JetStream topology exists\n   * Creates main stream and DLQ stream if configured\n   */\n  async ensureTopology(jsm: JetStreamManager): Promise<void> {\n    await this.ensureMainStream(jsm);\n    await this.ensureDlqStream(jsm);\n  }\n\n  /**\n   * Ensure main event stream exists\n   */\n  private async ensureMainStream(jsm: JetStreamManager): Promise<void> {\n    const cfg = config.get();\n    const streamName = config.streamName;\n    const logger = config.logger;\n\n    try {\n      await jsm.streams.info(streamName);\n      logger.debug('Stream already exists', { stream: streamName });\n    } catch (error: unknown) {\n      const err = error as { code?: string };\n      if (err.code === '404') {\n        logger.info('Creating stream...', { stream: streamName });\n\n        const subjects = [Subject.allEvents(cfg.env)];\n        if (cfg.useDlq) {\n          subjects.push(config.dlqSubject);\n        }\n\n        await jsm.streams.add({\n          name: streamName,\n          subjects,\n          retention: RetentionPolicy.Limits,\n          max_age: toNanos(7 * 24 * 60 * 60 * 1000), // 7 days in nanoseconds\n          storage: StorageType.File,\n          num_replicas: 1,\n          discard: DiscardPolicy.Old,\n        });\n\n        logger.info('Stream created successfully', { stream: streamName });\n      } else {\n        throw error;\n      }\n    }\n  }\n\n  /**\n   * Ensure DLQ stream exists if configured\n   */\n  private async ensureDlqStream(jsm: JetStreamManager): Promise<void> {\n    const cfg = config.get();\n    const streamName = config.streamName;\n    const logger = config.logger;\n\n    if (!cfg.useDlq) {\n      return;\n    }\n\n    const dlqStream = `${streamName}-dlq`;\n    try {\n      await jsm.streams.info(dlqStream);\n      logger.debug('DLQ stream already exists', { stream: dlqStream });\n    } catch (error: unknown) {\n      const err = error as { code?: string };\n      if (err.code === '404') {\n        logger.info('Creating DLQ stream...', {\n          stream: dlqStream,\n          subject: config.dlqSubject,\n        });\n\n        await jsm.streams.add({\n          name: dlqStream,\n          subjects: [config.dlqSubject],\n          retention: RetentionPolicy.Limits,\n          max_age: toNanos(30 * 24 * 60 * 60 * 1000), // 30 days\n          storage: StorageType.File,\n          num_replicas: 1,\n          discard: DiscardPolicy.Old,\n        });\n\n        logger.info('DLQ stream created', { stream: dlqStream });\n      } else {\n        throw error;\n      }\n    }\n  }\n}\n","import { JsMsg, headers as natsHeaders } from 'nats';\nimport connection from '../core/connection';\nimport config from '../core/config';\n\n/**\n * DlqHandler handles dead letter queue operations\n *\n * Responsibilities:\n * - Publish failed messages to DLQ\n * - Handle message failures with retry logic\n * - Manage message acknowledgements\n */\nexport class DlqHandler {\n  /**\n   * Handle a message processing failure\n   *\n   * @param msg - The NATS message that failed\n   * @param error - The error that occurred\n   * @param extra - Additional context to include in DLQ message\n   */\n  async handleFailure(msg: JsMsg, error: unknown, extra?: Record<string, unknown>): Promise<void> {\n    const logger = config.logger;\n    const cfg = config.get();\n    const deliveries = msg.info?.deliveryCount ?? 0;\n    const maxDeliver = cfg.maxDeliver || 5;\n    const exceededMaxDeliver = deliveries >= maxDeliver;\n\n    if (cfg.useDlq) {\n      try {\n        await this.publishToDlq(\n          msg,\n          error,\n          exceededMaxDeliver ? 'max_deliver_exceeded' : 'handler_error',\n          extra\n        );\n        // Only ack after DLQ publish succeeds\n        msg.ack();\n        return;\n      } catch (dlqError) {\n        logger.error('Failed to publish to DLQ', {\n          subject: msg.subject,\n          error: dlqError,\n        });\n        // Fall through to NAK so the message can be retried\n      }\n    }\n\n    if (exceededMaxDeliver || deliveries >= (cfg.dlqMaxAttempts || 3)) {\n      logger.warn('Message exceeded max_deliver; dropping', {\n        subject: msg.subject,\n        deliveries,\n      });\n      msg.term();\n    } else {\n      msg.nak(); // Negative acknowledge for retry\n    }\n  }\n\n  /**\n   * Publish a failed message to the DLQ with context\n   *\n   * @param msg - The NATS message that failed\n   * @param error - The error that occurred\n   * @param reason - Reason for DLQ (e.g., 'max_deliver_exceeded', 'handler_error')\n   * @param extra - Additional context to include\n   */\n  private async publishToDlq(\n    msg: JsMsg,\n    error: unknown,\n    reason: string,\n    extra?: Record<string, unknown>\n  ): Promise<void> {\n    const js = connection.getJetStream();\n    const cfg = config.get();\n    const rawBuffer = msg.data ? Buffer.from(msg.data) : Buffer.alloc(0);\n    const rawPayload = rawBuffer.toString('utf8');\n    let parsedPayload: unknown;\n\n    try {\n      parsedPayload = JSON.parse(rawPayload);\n    } catch {\n      parsedPayload = rawPayload; // Keep raw if not JSON\n    }\n\n    const traceId =\n      (parsedPayload as { trace_id?: string })?.trace_id || msg.headers?.get('trace_id');\n\n    const payload = {\n      event_id:\n        (parsedPayload as { event_id?: string })?.event_id ||\n        msg.headers?.get('nats-msg-id') ||\n        msg.sid.toString(),\n      original_subject: msg.subject,\n      payload: parsedPayload,\n      raw_base64: rawBuffer.toString('base64'),\n      headers: msg.headers ? Object.fromEntries(msg.headers) : undefined,\n      deliveries: msg.info?.deliveryCount ?? 0,\n      reason,\n      error:\n        error instanceof Error ? `${error.name}: ${error.message}` : String(error ?? 'unknown'),\n      occurred_at: new Date().toISOString(),\n      trace_id: traceId || undefined,\n      ...extra,\n    };\n\n    if (!cfg.dlqSubject) {\n      throw new Error('DLQ subject is not configured');\n    }\n\n    const hdrs = natsHeaders();\n    hdrs.set('x-dead-letter', 'true');\n    hdrs.set('x-dlq-reason', reason);\n    hdrs.set('x-deliveries', String(msg.info?.deliveryCount ?? 0));\n    if (payload.event_id) hdrs.set('x-event-id', payload.event_id);\n    if (traceId) hdrs.set('x-trace-id', traceId);\n\n    await js.publish(cfg.dlqSubject, Buffer.from(JSON.stringify(payload)), {\n      headers: hdrs,\n      expect: { streamName: cfg.streamName },\n    });\n    cfg.metrics?.recordDlqMessage?.(msg.subject, reason);\n\n    config.logger.warn('Message moved to DLQ', {\n      subject: msg.subject,\n      deliveries: msg.info?.deliveryCount,\n      reason,\n    });\n  }\n}\n","import { Subscriber } from '../types';\n\n/**\n * Registry manages subscriber registration and lookup\n *\n * Responsibilities:\n * - Register subscribers for subjects\n * - Retrieve subscribers for a subject\n * - Get list of all registered subjects\n */\nexport class Registry {\n  private subscribers: Map<string, Subscriber[]> = new Map();\n\n  /**\n   * Register a subscriber for one or more subjects\n   *\n   * @param subscriber - Subscriber instance to register\n   */\n  register(subscriber: Subscriber): void {\n    for (const subject of subscriber.subjects) {\n      if (!this.subscribers.has(subject)) {\n        this.subscribers.set(subject, []);\n      }\n      this.subscribers.get(subject)!.push(subscriber);\n    }\n  }\n\n  /**\n   * Get all subscribers registered for a specific subject\n   *\n   * @param subject - Subject to look up\n   * @returns Array of subscribers for the subject (empty if none)\n   */\n  getSubscribers(subject: string): Subscriber[] {\n    return this.subscribers.get(subject) || [];\n  }\n\n  /**\n   * Get all registered subjects\n   *\n   * @returns Array of all subject strings\n   */\n  getAllSubjects(): string[] {\n    return Array.from(this.subscribers.keys());\n  }\n\n  /**\n   * Check if a subject has registered subscribers\n   *\n   * @param subject - Subject to check\n   * @returns true if subject has subscribers\n   */\n  hasSubscribers(subject: string): boolean {\n    const subs = this.subscribers.get(subject);\n    return subs !== undefined && subs.length > 0;\n  }\n\n  /**\n   * Get total number of registered subscribers across all subjects\n   *\n   * @returns Total subscriber count\n   */\n  getTotalCount(): number {\n    let count = 0;\n    for (const subs of this.subscribers.values()) {\n      count += subs.length;\n    }\n    return count;\n  }\n\n  /**\n   * Clear all registered subscribers\n   */\n  clear(): void {\n    this.subscribers.clear();\n  }\n}\n","import { JsMsg } from 'nats';\nimport { EventMetadata, Subscriber } from '../types';\nimport config from '../core/config';\nimport { Subject } from '../core/subject';\nimport { MiddlewareChain } from '../middleware/chain';\nimport { DlqHandler } from '../dlq/dlq-handler';\n\n/**\n * MessageProcessor handles message processing logic\n *\n * Responsibilities:\n * - Parse message envelopes\n * - Execute middleware chain\n * - Run subscribers with concurrency control\n * - Handle timeouts\n * - Coordinate with DLQ handler on failures\n */\nexport class MessageProcessor {\n  constructor(\n    private middlewareChain: MiddlewareChain,\n    private dlqHandler: DlqHandler\n  ) {}\n\n  /**\n   * Process a single message through middleware and subscribers\n   *\n   * @param msg - NATS message to process\n   * @param subscribers - Subscribers to execute for this message\n   */\n  async processMessage(msg: JsMsg, subscribers: Subscriber[]): Promise<void> {\n    const logger = config.logger;\n\n    try {\n      const data = JSON.parse(msg.data.toString());\n      const envelope = data;\n\n      const metadata: EventMetadata = {\n        event_id: envelope.event_id,\n        subject: msg.subject,\n        domain: this.extractDomain(msg.subject),\n        resource: envelope.resource_type,\n        action: envelope.event_type,\n        stream: msg.info?.stream,\n        stream_seq: msg.seq,\n        deliveries: msg.info?.deliveryCount,\n        trace_id: envelope.trace_id,\n      };\n\n      logger.debug('Processing message', {\n        subject: msg.subject,\n        event_id: metadata.event_id,\n        deliveries: metadata.deliveries,\n      });\n\n      // Process through each subscriber (run with controlled concurrency)\n      const results = await this.executeSubscribers(envelope.payload, metadata, subscribers);\n\n      const failed = results.filter((r) => r.status === 'rejected') as PromiseRejectedResult[];\n\n      if (failed.length === 0) {\n        // Acknowledge the message\n        msg.ack();\n        logger.debug('Message processed successfully', {\n          subject: msg.subject,\n          event_id: metadata.event_id,\n        });\n        return;\n      }\n\n      // If any subscriber failed, route to DLQ with failed subscriber names\n      const failedNames = failed.map((_, idx) => subscribers[idx].constructor.name);\n      await this.dlqHandler.handleFailure(\n        msg,\n        new Error(`Subscriber failures: ${failedNames.join(',')}`),\n        {\n          failedSubscribers: failedNames,\n        }\n      );\n    } catch (error) {\n      logger.error('Failed to process message', {\n        subject: msg.subject,\n        error,\n      });\n\n      await this.dlqHandler.handleFailure(msg, error);\n    }\n  }\n\n  /**\n   * Execute all subscribers with controlled concurrency\n   */\n  private async executeSubscribers(\n    payload: Record<string, unknown>,\n    metadata: EventMetadata,\n    subscribers: Subscriber[]\n  ): Promise<Array<PromiseSettledResult<{ subscriber: string; durationMs: number }>>> {\n    const cfg = config.get();\n    const limit = Math.max(1, cfg.perMessageConcurrency || subscribers.length || 1);\n    const results: Array<PromiseSettledResult<{ subscriber: string; durationMs: number }>> = [];\n\n    let index = 0;\n    const runNext = async (): Promise<void> => {\n      if (index >= subscribers.length) return;\n      const currentIndex = index++;\n      const subscriber = subscribers[currentIndex];\n      const start = Date.now();\n\n      const exec = async () => {\n        await this.middlewareChain.execute(payload, metadata, async () => {\n          // Ensure subscriber has a handle method\n          if (!subscriber.handle) {\n            throw new Error(\n              `Subscriber ${subscriber.constructor?.name || 'unknown'} missing handle() method`\n            );\n          }\n\n          // Per-subscriber timeout guard\n          if (cfg.subscriberTimeoutMs && cfg.subscriberTimeoutMs > 0) {\n            let timeoutId: NodeJS.Timeout | undefined;\n            try {\n              await Promise.race([\n                subscriber.handle(payload, metadata),\n                new Promise((_, reject) => {\n                  timeoutId = setTimeout(\n                    () => reject(new Error('subscriber_timeout')),\n                    cfg.subscriberTimeoutMs\n                  );\n                  // Use unref() to allow process to exit even if timeout is pending\n                  timeoutId?.unref();\n                }),\n              ]);\n            } finally {\n              // Always clear the timeout to prevent leaks\n              if (timeoutId !== undefined) {\n                clearTimeout(timeoutId);\n              }\n            }\n          } else {\n            await subscriber.handle(payload, metadata);\n          }\n        });\n        return { subscriber: subscriber.constructor.name, durationMs: Date.now() - start };\n      };\n\n      results[currentIndex] = await exec()\n        .then((value) => ({ status: 'fulfilled', value }) as const)\n        .catch((reason) => ({ status: 'rejected', reason }) as const);\n\n      await runNext();\n    };\n\n    const runners = Array.from({ length: Math.min(limit, subscribers.length) }, () => runNext());\n    await Promise.all(runners);\n\n    return results;\n  }\n\n  /**\n   * Extract domain from subject\n   */\n  private extractDomain(subject: string): string {\n    // Try parsing as event-based subject first\n    const eventParsed = Subject.parseEvent(subject);\n    if (eventParsed) {\n      return eventParsed.domain;\n    }\n\n    // Fallback to topic-based parsing\n    const topicParsed = Subject.parseTopic(subject);\n    if (topicParsed) {\n      // For topic-based subjects, use appName as domain\n      return topicParsed.appName;\n    }\n\n    // Fallback: extract third segment for non-standard subjects\n    const parts = subject.split('.');\n    return parts.length >= 3 ? parts[2] : '';\n  }\n}\n","import { EventMetadata, Subscriber as SubscriberInterface, SubscriberOptions } from '../types';\nimport config from '../core/config';\nimport { Subject } from '../core/subject';\n\nexport interface TopicMetadata extends EventMetadata {\n  topic: string;\n}\n\n/**\n * Decorator for creating subscriber classes with type-safe message handling\n * Subscribes to NATS subjects directly\n *\n * @template TMessage - Type of the message payload (defaults to Record<string, unknown>)\n * @template TMetadata - Type of the metadata (defaults to EventMetadata)\n *\n * @example\n * ```typescript\n * interface UserCreatedMessage {\n *   id: string;\n *   name: string;\n *   email: string;\n * }\n *\n * @subscriber<UserCreatedMessage>('production.app.user.created')\n * class UserSubscriber {\n *   async handle(message: UserCreatedMessage, metadata: EventMetadata) {\n *     // message is fully typed!\n *     console.log(message.name.toUpperCase());\n *   }\n * }\n * ```\n */\nexport function subscriber<\n  TMessage extends Record<string, unknown> = Record<string, unknown>,\n  TMetadata extends EventMetadata = EventMetadata,\n>(subjects: string | string[], options?: SubscriberOptions) {\n  return function <\n    T extends new (...args: any[]) => {\n      handle(message: TMessage, metadata: TMetadata): Promise<void>;\n    },\n  >(constructor: T) {\n    const subjectArray = Array.isArray(subjects) ? subjects : [subjects];\n\n    return class extends constructor implements SubscriberInterface {\n      subjects = subjectArray;\n      options = options;\n\n      async handle(event: Record<string, unknown>, metadata: EventMetadata): Promise<void> {\n        // Handle with typed parameters\n        return super.handle(event as TMessage, metadata as TMetadata);\n      }\n    };\n  };\n}\n\n/**\n * Decorator for subscribing to topics with type-safe message handling\n * Topics are the foundation of the pubsub system\n *\n * @template TMessage - Type of the message payload\n * @template TMetadata - Type of the metadata (defaults to TopicMetadata)\n *\n * @param topics - Topic name or array of topic names (e.g., 'notification.email', 'user.*')\n * @param options - Subscription options\n *\n * @example\n * ```typescript\n * interface EmailMessage {\n *   to: string;\n *   subject: string;\n *   body: string;\n * }\n *\n * @topicSubscriber<EmailMessage>('notification.email')\n * class EmailNotificationSubscriber {\n *   async handle(message: EmailMessage, metadata: TopicMetadata) {\n *     // message.to is fully typed!\n *     console.log('Sending to:', message.to);\n *   }\n * }\n *\n * // With wildcards\n * @topicSubscriber('user.*')\n * class AllUserEventsSubscriber {\n *   async handle(message: Record<string, unknown>, metadata: TopicMetadata) {\n *     console.log('User event on topic:', metadata.topic);\n *   }\n * }\n * ```\n */\nexport function topicSubscriber<\n  TMessage extends Record<string, unknown> = Record<string, unknown>,\n  TMetadata extends TopicMetadata = TopicMetadata,\n>(topics: string | string[], options?: SubscriberOptions) {\n  return function <\n    T extends new (...args: any[]) => {\n      handle(message: TMessage, metadata: TMetadata): Promise<void>;\n    },\n  >(constructor: T) {\n    const topicArray = Array.isArray(topics) ? topics : [topics];\n    const cfg = config.get();\n\n    // Build subject patterns for topics using Subject utility\n    const subjects = topicArray.map((topic) => {\n      return Subject.forTopic(cfg.env, cfg.appName, topic);\n    });\n\n    return class extends constructor implements SubscriberInterface {\n      subjects = subjects;\n      options = options;\n\n      async handle(message: Record<string, unknown>, metadata: EventMetadata): Promise<void> {\n        // Handle with typed parameters\n        return super.handle(message as TMessage, metadata as TMetadata);\n      }\n    };\n  };\n}\n\n/**\n * Decorator for subscribing to all subtopics using wildcard (>) with type safety\n *\n * @template TMessage - Type of the message payload\n * @template TMetadata - Type of the metadata (defaults to TopicMetadata)\n *\n * @param topic - Topic name to subscribe to with wildcard\n * @param options - Subscription options\n *\n * @example\n * ```typescript\n * @topicSubscriberWildcard('notification')\n * class AllNotificationSubscriber {\n *   async handle(message: Record<string, unknown>, metadata: TopicMetadata) {\n *     // Receives: notification.email, notification.sms, notification.push, etc.\n *     console.log('Notification on:', metadata.topic);\n *   }\n * }\n * ```\n */\nexport function topicSubscriberWildcard<\n  TMessage extends Record<string, unknown> = Record<string, unknown>,\n  TMetadata extends TopicMetadata = TopicMetadata,\n>(topic: string, options?: SubscriberOptions) {\n  return function <\n    T extends new (...args: any[]) => {\n      handle(message: TMessage, metadata: TMetadata): Promise<void>;\n    },\n  >(constructor: T) {\n    const cfg = config.get();\n    // Use Subject utility to build wildcard pattern\n    const subject = Subject.forTopic(cfg.env, cfg.appName, `${topic}.>`);\n\n    return class extends constructor implements SubscriberInterface {\n      subjects = [subject];\n      options = options;\n\n      async handle(message: Record<string, unknown>, metadata: EventMetadata): Promise<void> {\n        return super.handle(message as TMessage, metadata as TMetadata);\n      }\n    };\n  };\n}\n\n/**\n * Decorator for subscribing to domain/resource/action events with type safety\n * This is a convenience layer that maps to topics internally\n *\n * @template TMessage - Type of the message payload\n * @template TMetadata - Type of the metadata (defaults to TopicMetadata)\n *\n * @param domain - Business domain\n * @param resource - Resource type\n * @param action - Event action (can use '*' wildcard)\n * @param options - Subscription options\n *\n * @example\n * ```typescript\n * interface UserCreatedPayload {\n *   id: string;\n *   name: string;\n *   email: string;\n * }\n *\n * @eventSubscriber<UserCreatedPayload>('user', 'user', 'created')\n * class UserCreatedSubscriber {\n *   async handle(message: UserCreatedPayload, metadata: TopicMetadata) {\n *     // message is fully typed!\n *     console.log('User created:', message.email);\n *   }\n * }\n *\n * // With wildcard action\n * @eventSubscriber('user', 'user', '*')\n * class AllUserEventSubscriber {\n *   async handle(message: Record<string, unknown>, metadata: TopicMetadata) {\n *     console.log('User event:', metadata.action);\n *   }\n * }\n * ```\n */\nexport function eventSubscriber<\n  TMessage extends Record<string, unknown> = Record<string, unknown>,\n  TMetadata extends TopicMetadata = TopicMetadata,\n>(domain: string, resource: string, action: string, options?: SubscriberOptions) {\n  // Map to topic pattern: {domain}.{resource}.{action}\n  const topic = `${domain}.${resource}.${action}`;\n  return topicSubscriber<TMessage, TMetadata>(topic, options);\n}\n\n/**\n * Base class for subscribers with topic support and type-safe message handling\n *\n * Provides helper methods for working with both topic-based and\n * domain/resource/action patterns.\n *\n * @template TMessage - Type of the message payload (defaults to Record<string, unknown>)\n * @template TMetadata - Type of the metadata (defaults to EventMetadata)\n *\n * @example\n * ```typescript\n * interface OrderPlacedMessage {\n *   orderId: string;\n *   userId: string;\n *   total: number;\n * }\n *\n * class OrderSubscriber extends Subscriber<OrderPlacedMessage> {\n *   constructor() {\n *     super('production.shop.order.placed');\n *   }\n *\n *   async handle(message: OrderPlacedMessage, metadata: EventMetadata) {\n *     // message is fully typed!\n *     console.log(`Order ${message.orderId} total: $${message.total}`);\n *   }\n * }\n * ```\n */\nexport abstract class Subscriber<\n  TMessage extends Record<string, unknown> = Record<string, unknown>,\n  TMetadata extends EventMetadata = EventMetadata,\n> implements SubscriberInterface\n{\n  subjects: string[] = [];\n  options?: SubscriberOptions;\n\n  constructor(subjects: string | string[], options?: SubscriberOptions) {\n    this.subjects = Array.isArray(subjects) ? subjects : [subjects];\n    this.options = options;\n  }\n\n  /**\n   * Process a message - must be implemented by subclasses\n   * The message and metadata are typed according to the class generic parameters\n   */\n  abstract handle(message: TMessage, metadata: TMetadata): Promise<void>;\n\n  /**\n   * Check if message is from a specific topic\n   */\n  protected fromTopic(metadata: TopicMetadata, topicName: string): boolean {\n    return metadata.topic === topicName;\n  }\n\n  /**\n   * Check if message is from a specific domain/resource/action\n   */\n  protected fromEvent(\n    metadata: EventMetadata,\n    domain: string,\n    resource: string,\n    action: string\n  ): boolean {\n    return (\n      metadata.domain === domain && metadata.resource === resource && metadata.action === action\n    );\n  }\n\n  /**\n   * Extract topic from NATS subject\n   * Format: {env}.${cfg.appName}.{topic_name}\n   */\n  protected extractTopic(subject: string): string {\n    const parsed = Subject.parseTopic(subject);\n    return parsed ? parsed.topic : '';\n  }\n}\n","import { Consumer } from './consumer';\n\n/**\n * Logger interface for graceful shutdown\n */\ninterface Logger {\n  info(message: string, metadata?: Record<string, unknown>): void;\n  warn(message: string, metadata?: Record<string, unknown>): void;\n  error(message: string, metadata?: Record<string, unknown>): void;\n  debug(message: string, metadata?: Record<string, unknown>): void;\n}\n\n/**\n * Graceful shutdown configuration\n */\nexport interface GracefulShutdownOptions {\n  timeout?: number; // milliseconds\n  logger?: Logger;\n}\n\n/**\n * Graceful shutdown manager for subscribers\n * Handles signal trapping and ensures clean shutdown with message drain\n */\nexport class GracefulShutdown {\n  private readonly timeout: number;\n  private readonly logger?: Logger;\n  private shuttingDown = false;\n  private shutdownStartedAt?: Date;\n\n  private static readonly DEFAULT_TIMEOUT = 30_000; // 30 seconds\n\n  constructor(\n    private readonly consumer: Consumer,\n    options: GracefulShutdownOptions = {}\n  ) {\n    this.timeout = options.timeout || GracefulShutdown.DEFAULT_TIMEOUT;\n    this.logger = options.logger;\n  }\n\n  /**\n   * Start graceful shutdown process\n   * @returns True if shutdown completed gracefully within timeout\n   */\n  async shutdown(): Promise<boolean> {\n    if (this.shuttingDown) {\n      return false;\n    }\n\n    this.shuttingDown = true;\n    this.shutdownStartedAt = new Date();\n\n    this.logger?.info('Starting graceful shutdown', { timeout: this.timeout });\n\n    // Stop accepting new messages\n    await this.stopAcceptingMessages();\n\n    // Wait for in-flight messages\n    const completed = await this.waitForCompletion();\n\n    // Force terminate if needed\n    if (!completed) {\n      await this.forceTerminate();\n    }\n\n    // Close connections\n    await this.closeConnections();\n\n    const elapsed = Date.now() - this.shutdownStartedAt.getTime();\n    this.logger?.info('Graceful shutdown complete', {\n      elapsed,\n      graceful: completed,\n    });\n\n    return completed;\n  }\n\n  /**\n   * Check if shutdown is in progress\n   */\n  isShuttingDown(): boolean {\n    return this.shuttingDown;\n  }\n\n  /**\n   * Install signal handlers for graceful shutdown\n   * Traps SIGTERM and SIGINT\n   */\n  installSignalHandlers(): void {\n    const signals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT'];\n\n    signals.forEach((signal) => {\n      process.on(signal, () => {\n        this.logger?.info(`Received ${signal}, initiating shutdown`);\n        this.shutdown()\n          .then(() => process.exit(0))\n          .catch((error) => {\n            this.logger?.error('Shutdown failed', { error });\n            process.exit(1);\n          });\n      });\n    });\n  }\n\n  /**\n   * Stop accepting new messages\n   */\n  private async stopAcceptingMessages(): Promise<void> {\n    this.logger?.info('Stopping message acceptance');\n    if (typeof (this.consumer as any).pause === 'function') {\n      await (this.consumer as any).pause();\n    }\n  }\n\n  /**\n   * Wait for in-flight messages to complete\n   */\n  private async waitForCompletion(): Promise<boolean> {\n    const deadline = Date.now() + this.timeout;\n\n    while (true) {\n      const inFlight =\n        typeof (this.consumer as any).getInFlightCount === 'function'\n          ? (this.consumer as any).getInFlightCount()\n          : 0;\n\n      if (inFlight === 0) {\n        this.logger?.info('All messages processed');\n        return true;\n      }\n\n      if (Date.now() >= deadline) {\n        this.logger?.warn('Shutdown timeout reached', {\n          inFlight,\n          timeout: this.timeout,\n        });\n        return false;\n      }\n\n      this.logger?.debug('Waiting for messages', {\n        inFlight,\n        remaining: deadline - Date.now(),\n      });\n\n      await this.sleep(500);\n    }\n  }\n\n  /**\n   * Force terminate remaining messages\n   */\n  private async forceTerminate(): Promise<void> {\n    this.logger?.warn('Force terminating remaining messages');\n    if (typeof (this.consumer as any).forceStop === 'function') {\n      await (this.consumer as any).forceStop();\n    }\n  }\n\n  /**\n   * Close connections\n   */\n  private async closeConnections(): Promise<void> {\n    this.logger?.info('Closing connections');\n    if (typeof (this.consumer as any).close === 'function') {\n      await (this.consumer as any).close();\n    }\n  }\n\n  /**\n   * Sleep helper\n   */\n  private sleep(ms: number): Promise<void> {\n    return new Promise((resolve) => setTimeout(resolve, ms));\n  }\n}\n","import { NatsConnection, JetStreamClient } from 'nats';\n\nexport interface NatsPubsubConfig {\n  natsUrls: string | string[];\n  env: string;\n  appName: string;\n  concurrency?: number;\n  maxDeliver?: number;\n  ackWait?: number; // in milliseconds\n  backoff?: number[]; // array of milliseconds\n  useOutbox?: boolean;\n  useInbox?: boolean;\n  useDlq?: boolean;\n  streamName?: string;\n  dlqSubject?: string;\n  // Optional metrics hook for DLQ counting\n  metrics?: {\n    recordDlqMessage(subject: string, reason: string): void;\n  };\n  // Execution controls\n  perMessageConcurrency?: number;\n  subscriberTimeoutMs?: number;\n  dlqMaxAttempts?: number;\n  logger?: Logger;\n}\n\nexport interface Logger {\n  debug(message: string, meta?: Record<string, unknown>): void;\n  info(message: string, meta?: Record<string, unknown>): void;\n  warn(message: string, meta?: Record<string, unknown>): void;\n  error(message: string, meta?: Record<string, unknown>): void;\n}\n\nexport interface EventEnvelope {\n  event_id: string;\n  schema_version: number;\n  event_type: string;\n  producer: string;\n  resource_type: string;\n  resource_id?: string;\n  occurred_at: string;\n  trace_id?: string;\n  payload: Record<string, unknown>;\n}\n\nexport interface EventMetadata {\n  event_id: string;\n  subject: string;\n  domain: string;\n  resource: string;\n  action: string;\n  stream?: string;\n  stream_seq?: number;\n  deliveries?: number;\n  trace_id?: string;\n}\n\n/**\n * Unified message context interface\n * Consolidates all metadata into a single, well-typed context object\n *\n * @example\n * ```typescript\n * @subscribe('notifications.email')\n * class EmailSubscriber {\n *   async handle(message: EmailMessage, context: MessageContext): Promise<void> {\n *     console.log(`Processing event ${context.eventId} with trace ${context.traceId}`);\n *   }\n * }\n * ```\n */\nexport interface MessageContext {\n  /** Unique event identifier (UUID) */\n  eventId: string;\n  /** Full NATS subject (e.g., 'production.myapp.notifications.email') */\n  subject: string;\n  /** Extracted topic from subject (e.g., 'notifications.email') */\n  topic: string;\n  /** Optional distributed tracing ID */\n  traceId?: string;\n  /** Optional correlation ID for request tracking */\n  correlationId?: string;\n  /** Timestamp when the event occurred */\n  occurredAt: Date;\n  /** Number of delivery attempts */\n  deliveries: number;\n  /** JetStream stream name */\n  stream?: string;\n  /** JetStream stream sequence number */\n  streamSeq?: number;\n  /** Application that produced the event */\n  producer?: string;\n  /** Legacy: domain field (for backward compatibility) */\n  domain?: string;\n  /** Legacy: resource field (for backward compatibility) */\n  resource?: string;\n  /** Legacy: action field (for backward compatibility) */\n  action?: string;\n}\n\nexport interface PublishOptions {\n  event_id?: string;\n  trace_id?: string;\n  occurred_at?: Date;\n  correlation_id?: string;\n  ttl?: number; // Time-to-live in milliseconds\n  priority?: number; // Message priority (1-10)\n}\n\n/**\n * Error action enum for fine-grained error handling control\n */\nexport enum ErrorAction {\n  /** Retry the message with backoff strategy */\n  RETRY = 'retry',\n  /** Acknowledge and discard the message (no retry) */\n  DISCARD = 'discard',\n  /** Send message to dead letter queue */\n  DLQ = 'dlq',\n}\n\n/**\n * Error context passed to error handlers\n */\nexport interface ErrorContext {\n  /** The error that occurred */\n  error: Error;\n  /** Error class name */\n  errorClass: string;\n  /** Error message */\n  errorMessage: string;\n  /** The message that failed */\n  message: Record<string, unknown>;\n  /** Message context (deprecated, use metadata) */\n  context?: MessageContext;\n  /** Message metadata */\n  metadata: MessageContext;\n  /** Current attempt number (1-based) */\n  attemptNumber: number;\n  /** Maximum delivery attempts configured */\n  maxAttempts: number;\n  /** Whether this is the last attempt */\n  lastAttempt: boolean;\n  /** Remaining attempts */\n  remainingAttempts: number;\n  /** Whether the error is retryable */\n  retryable: boolean;\n}\n\n/**\n * Retry strategy configuration\n */\nexport interface RetryStrategy {\n  /** Maximum number of retry attempts */\n  maxAttempts: number;\n  /** Backoff strategy: 'exponential', 'linear', or 'fixed' */\n  backoff: 'exponential' | 'linear' | 'fixed';\n  /** Initial delay in milliseconds */\n  initialDelay?: number;\n  /** Maximum delay in milliseconds */\n  maxDelay?: number;\n  /** Multiplier for exponential backoff */\n  multiplier?: number;\n}\n\n/**\n * Circuit breaker configuration\n */\nexport interface CircuitBreakerConfig {\n  /** Enable circuit breaker */\n  enabled: boolean;\n  /** Number of failures before opening circuit */\n  threshold: number;\n  /** Time to keep circuit open in milliseconds */\n  timeout: number;\n  /** Number of test calls in half-open state */\n  halfOpenMaxCalls: number;\n}\n\n/**\n * Dead letter queue configuration\n */\nexport interface DlqConfig {\n  /** Enable DLQ */\n  enabled: boolean;\n  /** Maximum attempts before sending to DLQ */\n  maxAttempts: number;\n  /** Custom DLQ subject pattern */\n  subject?: string;\n}\n\nexport interface SubscriberOptions {\n  /** Number of retry attempts */\n  retry?: number;\n  /** Acknowledgment wait time in milliseconds */\n  ackWait?: number;\n  /** Maximum delivery attempts */\n  maxDeliver?: number;\n  /** Enhanced retry strategy configuration */\n  retryStrategy?: RetryStrategy | number;\n  /** Circuit breaker configuration */\n  circuitBreaker?: CircuitBreakerConfig;\n  /** Dead letter queue configuration */\n  deadLetter?: DlqConfig | boolean;\n  /** Zod schema for message validation */\n  schema?: unknown;\n}\n\nexport interface Subscriber {\n  subjects: string[];\n  options?: SubscriberOptions;\n  /** Handle incoming messages */\n  handle(event: Record<string, unknown>, metadata: EventMetadata): Promise<void>;\n  /** Optional error handler for fine-grained error control */\n  onError?(errorContext: ErrorContext): Promise<ErrorAction>;\n}\n\nexport interface Middleware {\n  call(\n    event: Record<string, unknown>,\n    metadata: EventMetadata,\n    next: () => Promise<void>\n  ): Promise<void>;\n}\n\nexport interface ConnectionManager {\n  connection: NatsConnection | null;\n  jetstream: JetStreamClient | null;\n  connect(): Promise<void>;\n  disconnect(): Promise<void>;\n  ensureConnection(): Promise<void>;\n}\n\nexport type MessageHandler = (\n  event: Record<string, unknown>,\n  metadata: EventMetadata\n) => Promise<void>;\n","import { ErrorAction, ErrorContext, MessageContext } from '../types';\nimport { Errors } from '../core/constants';\nimport config from '../core/config';\n\n/**\n * Subscriber interface with optional error handler\n */\ninterface SubscriberWithErrorHandler {\n  onError?(errorContext: ErrorContext): Promise<ErrorAction> | ErrorAction;\n  [key: string]: unknown;\n}\n\n/**\n * Enhanced error handler with ErrorAction support\n * Integrates per-subscriber error handling strategies\n */\nexport class ErrorHandler {\n  constructor(\n    private readonly subscriber: SubscriberWithErrorHandler,\n    private readonly cfg = config.get()\n  ) {}\n\n  /**\n   * Handle an error from message processing\n   *\n   * @param error The error that occurred\n   * @param message The message payload\n   * @param context Message metadata\n   * @param attemptNumber Current delivery attempt\n   * @returns Error action to take (RETRY, DISCARD, DLQ)\n   */\n  async handleError(\n    error: Error,\n    message: Record<string, unknown>,\n    context: MessageContext,\n    attemptNumber: number\n  ): Promise<ErrorAction> {\n    const errorContext = this.buildErrorContext(error, message, context, attemptNumber);\n\n    // Try subscriber's custom error handler first\n    let action: ErrorAction;\n    if (this.subscriber.onError) {\n      try {\n        action = await this.subscriber.onError(errorContext);\n      } catch (handlerError) {\n        const logger = this.cfg.logger;\n        if (logger && typeof logger.error === 'function') {\n          logger.error(`Subscriber error handler failed: ${handlerError}`, {\n            subscriber: this.subscriber.constructor.name,\n            error: handlerError,\n          });\n        }\n        action = this.determineDefaultAction(errorContext);\n      }\n    } else {\n      action = this.determineDefaultAction(errorContext);\n    }\n\n    return this.normalizeAction(action, errorContext);\n  }\n\n  /**\n   * Build error context object\n   */\n  private buildErrorContext(\n    error: Error,\n    message: Record<string, unknown>,\n    context: MessageContext,\n    attemptNumber: number\n  ): ErrorContext {\n    const maxAttempts = this.cfg.maxDeliver || 5;\n    return {\n      error,\n      errorClass: error.constructor.name,\n      errorMessage: error.message,\n      message,\n      metadata: context,\n      attemptNumber,\n      maxAttempts,\n      lastAttempt: attemptNumber >= maxAttempts,\n      remainingAttempts: Math.max(maxAttempts - attemptNumber, 0),\n      retryable: this.isRetryableError(error),\n    };\n  }\n\n  /**\n   * Determine default action based on error type\n   */\n  private determineDefaultAction(errorContext: ErrorContext): ErrorAction {\n    const { error, lastAttempt } = errorContext;\n\n    // Malformed messages -> Discard immediately\n    if (this.isMalformedError(error)) {\n      return ErrorAction.DISCARD;\n    }\n\n    // Unrecoverable errors -> DLQ immediately\n    if (this.isUnrecoverableError(error)) {\n      return ErrorAction.DLQ;\n    }\n\n    // Last attempt -> DLQ\n    if (lastAttempt) {\n      return ErrorAction.DLQ;\n    }\n\n    // Default -> Retry\n    return ErrorAction.RETRY;\n  }\n\n  /**\n   * Check if error indicates malformed message\n   */\n  private isMalformedError(error: Error): boolean {\n    return Errors.MALFORMED_ERRORS.some((errorName) => error.constructor.name.includes(errorName));\n  }\n\n  /**\n   * Check if error is unrecoverable\n   */\n  private isUnrecoverableError(error: Error): boolean {\n    return Errors.UNRECOVERABLE_ERRORS.some((errorName) =>\n      error.constructor.name.includes(errorName)\n    );\n  }\n\n  /**\n   * Check if error is retryable\n   */\n  private isRetryableError(error: Error): boolean {\n    return Errors.TRANSIENT_ERRORS.some((errorName) => error.constructor.name.includes(errorName));\n  }\n\n  /**\n   * Normalize action to valid ErrorAction\n   */\n  private normalizeAction(action: ErrorAction, errorContext: ErrorContext): ErrorAction {\n    const validActions = Object.values(ErrorAction);\n    if (validActions.includes(action)) {\n      return action;\n    }\n\n    const logger = this.cfg.logger;\n    if (logger && typeof logger.warn === 'function') {\n      logger.warn(`Invalid error action returned: ${action}, using default`, {\n        subscriber: this.subscriber.constructor.name,\n        validActions,\n      });\n    }\n\n    return this.determineDefaultAction(errorContext);\n  }\n}\n","import { Subscriber } from '../subscribers/subscriber';\nimport { EventMetadata } from '../types';\nimport config from '../core/config';\n\nexport interface DlqMessage {\n  event_id: string;\n  original_subject: string;\n  event: Record<string, unknown>;\n  metadata: EventMetadata;\n  error?: string;\n  deliveries?: number;\n  first_seen: Date;\n  last_seen: Date;\n}\n\nexport interface DlqHandler {\n  handle(message: DlqMessage): Promise<void>;\n}\n\nexport interface PersistentDlqStore {\n  save(message: DlqMessage): Promise<void>;\n  list(): Promise<DlqMessage[]>;\n  get(eventId: string): Promise<DlqMessage | undefined>;\n  delete(eventId: string): Promise<void>;\n  clear(): Promise<void>;\n  stats?(): Promise<{\n    total: number;\n    bySubject: Record<string, number>;\n    oldestMessage?: Date;\n    newestMessage?: Date;\n  }>;\n}\n\n/**\n * Dead Letter Queue Consumer\n * Subscribes to DLQ subject and handles poison messages\n */\nexport class DlqConsumer extends Subscriber {\n  private config: typeof config;\n  private handlers: DlqHandler[] = [];\n  private messages: Map<string, DlqMessage> = new Map();\n  private store?: PersistentDlqStore;\n\n  constructor(store?: PersistentDlqStore) {\n    super(config.dlqSubject);\n    this.config = config;\n    this.store = store;\n  }\n\n  /**\n   * Register a custom DLQ handler\n   */\n  addHandler(handler: DlqHandler): void {\n    this.handlers.push(handler);\n  }\n\n  /**\n   * Process DLQ messages\n   */\n  async handle(event: Record<string, unknown>, metadata: EventMetadata): Promise<void> {\n    const dlqMessage: DlqMessage = {\n      event_id: metadata.event_id,\n      original_subject: metadata.subject,\n      event,\n      metadata,\n      deliveries: metadata.deliveries,\n      first_seen: new Date(),\n      last_seen: new Date(),\n    };\n\n    // Update or store message\n    if (this.messages.has(metadata.event_id)) {\n      const existing = this.messages.get(metadata.event_id)!;\n      dlqMessage.first_seen = existing.first_seen;\n    }\n    this.messages.set(metadata.event_id, dlqMessage);\n\n    // Log DLQ message\n    this.config.logger.warn('Message received in DLQ', {\n      event_id: metadata.event_id,\n      original_subject: metadata.subject,\n      deliveries: metadata.deliveries,\n    });\n\n    // Persist if a store is configured\n    if (this.store) {\n      try {\n        await this.store.save(dlqMessage);\n      } catch (error) {\n        this.config.logger.error('Failed to persist DLQ message', {\n          event_id: metadata.event_id,\n          error: error instanceof Error ? error.message : 'Unknown error',\n        });\n      }\n    }\n\n    // Call registered handlers\n    for (const handler of this.handlers) {\n      try {\n        await handler.handle(dlqMessage);\n      } catch (error) {\n        this.config.logger.error('DLQ handler failed', {\n          event_id: metadata.event_id,\n          error: error instanceof Error ? error.message : 'Unknown error',\n        });\n      }\n    }\n  }\n\n  /**\n   * Get all DLQ messages\n   */\n  getMessages(): DlqMessage[] {\n    return Array.from(this.messages.values());\n  }\n\n  /**\n   * Get message by event ID\n   */\n  getMessage(eventId: string): DlqMessage | undefined {\n    return this.messages.get(eventId);\n  }\n\n  /**\n   * Clear all DLQ messages from memory\n   */\n  clearMessages(): void {\n    this.messages.clear();\n    if (this.store) {\n      this.store.clear().catch((error) => {\n        this.config.logger.error('Failed to clear persistent DLQ store', {\n          error: error instanceof Error ? error.message : 'Unknown error',\n        });\n      });\n    }\n  }\n\n  /**\n   * Get statistics about DLQ\n   */\n  getStatistics(): {\n    total: number;\n    bySubject: Record<string, number>;\n    oldestMessage?: Date;\n    newestMessage?: Date;\n  } {\n    const messages = this.getMessages();\n    const bySubject: Record<string, number> = {};\n\n    let oldest: Date | undefined;\n    let newest: Date | undefined;\n\n    for (const message of messages) {\n      // Count by subject\n      bySubject[message.original_subject] = (bySubject[message.original_subject] || 0) + 1;\n\n      // Track oldest and newest\n      if (!oldest || message.first_seen < oldest) {\n        oldest = message.first_seen;\n      }\n      if (!newest || message.last_seen > newest) {\n        newest = message.last_seen;\n      }\n    }\n\n    return {\n      total: messages.length,\n      bySubject,\n      oldestMessage: oldest,\n      newestMessage: newest,\n    };\n  }\n}\n\n/**\n * Example DLQ Handler: Log to external service\n */\nexport class LoggingDlqHandler implements DlqHandler {\n  async handle(message: DlqMessage): Promise<void> {\n    console.error('DLQ Message:', JSON.stringify(message, null, 2));\n  }\n}\n\n/**\n * Example DLQ Handler: Alert operations team\n */\nexport class AlertDlqHandler implements DlqHandler {\n  private alertThreshold: number;\n  private alertedEvents: Set<string> = new Set();\n\n  constructor(threshold: number = 1) {\n    this.alertThreshold = threshold;\n  }\n\n  async handle(message: DlqMessage): Promise<void> {\n    if (this.alertedEvents.has(message.event_id)) {\n      return; // Already alerted\n    }\n\n    if ((message.deliveries || 0) >= this.alertThreshold) {\n      // Note: Integrate with your alerting service (e.g., PagerDuty, Slack, Datadog)\n      // This is a placeholder implementation - replace with your monitoring system\n      console.error(\n        `ALERT: Message ${message.event_id} exceeded ${this.alertThreshold} deliveries`\n      );\n      this.alertedEvents.add(message.event_id);\n    }\n  }\n}\n\n/**\n * Example DLQ Handler: Store to database for manual review\n */\nexport class StorageDlqHandler implements DlqHandler {\n  async handle(message: DlqMessage): Promise<void> {\n    // Note: Implement database storage for your persistence layer\n    // Example implementation:\n    //   await db.dlq_messages.insert({\n    //     event_id: message.event_id,\n    //     payload: message.payload,\n    //     error: message.error,\n    //     created_at: new Date()\n    //   });\n    console.log(`Storing DLQ message ${message.event_id} for manual review`);\n  }\n}\n\nexport default new DlqConsumer();\n","import { EventMetadata, Middleware } from '../types';\nimport config from '../core/config';\n\nexport class LoggingMiddleware implements Middleware {\n  async call(\n    _event: Record<string, unknown>,\n    metadata: EventMetadata,\n    next: () => Promise<void>\n  ): Promise<void> {\n    const logger = config.logger;\n    const startTime = Date.now();\n\n    logger.info('Processing event', {\n      event_id: metadata.event_id,\n      subject: metadata.subject,\n      action: metadata.action,\n    });\n\n    try {\n      await next();\n      const duration = Date.now() - startTime;\n      logger.info('Event processed successfully', {\n        event_id: metadata.event_id,\n        duration_ms: duration,\n      });\n    } catch (error) {\n      const duration = Date.now() - startTime;\n      logger.error('Event processing failed', {\n        event_id: metadata.event_id,\n        duration_ms: duration,\n        error,\n      });\n      throw error;\n    }\n  }\n}\n\nexport default new LoggingMiddleware();\n","import { EventMetadata, Middleware } from '../types';\nimport config from '../core/config';\n\nexport class RetryLoggerMiddleware implements Middleware {\n  async call(\n    _event: Record<string, unknown>,\n    metadata: EventMetadata,\n    next: () => Promise<void>\n  ): Promise<void> {\n    const logger = config.logger;\n\n    if (metadata.deliveries && metadata.deliveries > 1) {\n      logger.warn('Retrying event', {\n        event_id: metadata.event_id,\n        subject: metadata.subject,\n        delivery_count: metadata.deliveries,\n      });\n    }\n\n    await next();\n  }\n}\n\nexport default new RetryLoggerMiddleware();\n","import { Subscriber, EventMetadata } from '../types';\nimport { Consumer } from '../subscribers/consumer';\nimport { Publisher } from '../publisher/publisher';\nimport config from '../core/config';\nimport connection from '../core/connection';\n\n/**\n * Message captured during testing\n */\nexport interface CapturedMessage {\n  topic: string;\n  message: Record<string, unknown>;\n  metadata: EventMetadata;\n  timestamp: Date;\n}\n\n/**\n * DLQ message captured during testing\n */\nexport interface CapturedDlqMessage {\n  originalSubject: string;\n  event: Record<string, unknown>;\n  metadata: EventMetadata;\n  error?: string;\n  reason?: string;\n  timestamp: Date;\n}\n\n/**\n * Options for creating a test harness\n */\nexport interface TestHarnessOptions {\n  /** Subscribers to register */\n  subscribers?: Subscriber[];\n  /** Process messages synchronously (inline mode) */\n  inlineMode?: boolean;\n  /** Auto-start consumer */\n  autoStart?: boolean;\n  /** Mock NATS connection */\n  mockConnection?: boolean;\n}\n\n/**\n * TestHarness provides comprehensive testing utilities for NatsPubsub\n *\n * Features:\n * - Message capture and inspection\n * - Inline/synchronous processing for deterministic tests\n * - DLQ message tracking\n * - Subscriber call tracking\n * - Error simulation\n *\n * @example\n * ```typescript\n * describe('OrderProcessor', () => {\n *   let harness: TestHarness;\n *\n *   beforeEach(async () => {\n *     harness = await TestHarness.create({\n *       subscribers: [OrderSubscriber],\n *       inlineMode: true\n *     });\n *   });\n *\n *   afterEach(async () => {\n *     await harness.cleanup();\n *   });\n *\n *   it('processes orders', async () => {\n *     await harness.publish('order.placed', { id: '123' });\n *     expect(harness.subscriberCalled(OrderSubscriber)).toBe(true);\n *   });\n * });\n * ```\n */\nexport class TestHarness {\n  private messages: CapturedMessage[] = [];\n  private _dlqMessages: CapturedDlqMessage[] = [];\n  private subscriberCalls: Map<string, number> = new Map();\n  private consumer: Consumer;\n  private publisher: Publisher;\n  private errorSimulations: Map<string, Error> = new Map();\n\n  private constructor(options: TestHarnessOptions = {}) {\n    this.consumer = new Consumer();\n    this.publisher = new Publisher();\n\n    // Register subscribers if provided\n    if (options.subscribers) {\n      for (const subscriber of options.subscribers) {\n        this.registerSubscriber(subscriber);\n      }\n    }\n  }\n\n  /**\n   * Create a new test harness\n   *\n   * @param options - Configuration options\n   * @returns Initialized test harness\n   */\n  static async create(options: TestHarnessOptions = {}): Promise<TestHarness> {\n    const harness = new TestHarness(options);\n\n    // Connect and setup topology if not mocking\n    if (!options.mockConnection) {\n      await connection.ensureConnection();\n    }\n\n    // Auto-start consumer if requested\n    if (options.autoStart && !options.inlineMode) {\n      await harness.consumer.start();\n    }\n\n    return harness;\n  }\n\n  /**\n   * Register a subscriber for testing\n   *\n   * @param subscriber - Subscriber to register\n   */\n  registerSubscriber(subscriber: Subscriber): void {\n    // Wrap subscriber to track calls\n    const originalHandle = subscriber.handle.bind(subscriber);\n    const subscriberName = subscriber.constructor.name;\n\n    subscriber.handle = async (event: Record<string, unknown>, metadata: EventMetadata) => {\n      this.trackSubscriberCall(subscriberName);\n\n      // Check for simulated error\n      const error = this.errorSimulations.get(subscriberName);\n      if (error) {\n        throw error;\n      }\n\n      return originalHandle(event, metadata);\n    };\n\n    this.consumer.registerSubscriber(subscriber);\n  }\n\n  /**\n   * Publish a message for testing\n   *\n   * @param topic - Topic to publish to\n   * @param message - Message payload\n   * @param options - Publish options\n   */\n  async publish(topic: string, message: Record<string, unknown>, options?: any): Promise<void> {\n    // Capture message\n    const metadata: EventMetadata = {\n      event_id: options?.event_id || `test-${Date.now()}`,\n      subject: `${config.get().env}.${config.get().appName}.${topic}`,\n      domain: '',\n      resource: '',\n      action: '',\n      deliveries: 1,\n      trace_id: options?.trace_id,\n    };\n\n    this.messages.push({\n      topic,\n      message,\n      metadata,\n      timestamp: new Date(),\n    });\n\n    // Actually publish\n    await this.publisher.publishToTopic(topic, message, options);\n  }\n\n  /**\n   * Get all messages received on a topic\n   *\n   * @param topic - Topic to filter by\n   * @returns Array of captured messages\n   */\n  received(topic: string): CapturedMessage[] {\n    return this.messages.filter((m) => m.topic === topic);\n  }\n\n  /**\n   * Get the last message received on a topic\n   *\n   * @param topic - Topic to filter by\n   * @returns Last captured message or undefined\n   */\n  lastMessage(topic: string): Record<string, unknown> | undefined {\n    const messages = this.received(topic);\n    return messages.length > 0 ? messages[messages.length - 1].message : undefined;\n  }\n\n  /**\n   * Check if a subscriber was called\n   *\n   * @param subscriber - Subscriber class or instance\n   * @returns True if subscriber was called\n   */\n  subscriberCalled(subscriber: any): boolean {\n    const name = typeof subscriber === 'function' ? subscriber.name : subscriber.constructor.name;\n    return (this.subscriberCalls.get(name) || 0) > 0;\n  }\n\n  /**\n   * Get the number of times a subscriber was called\n   *\n   * @param subscriber - Subscriber class or instance\n   * @returns Number of calls\n   */\n  subscriberCallCount(subscriber: any): number {\n    const name = typeof subscriber === 'function' ? subscriber.name : subscriber.constructor.name;\n    return this.subscriberCalls.get(name) || 0;\n  }\n\n  /**\n   * Get all DLQ messages\n   *\n   * @returns Array of captured DLQ messages\n   */\n  dlqMessages(): CapturedDlqMessage[] {\n    return this._dlqMessages;\n  }\n\n  /**\n   * Get the last DLQ message\n   *\n   * @returns Last DLQ message or undefined\n   */\n  lastDlqMessage(): CapturedDlqMessage | undefined {\n    return this._dlqMessages.length > 0\n      ? this._dlqMessages[this._dlqMessages.length - 1]\n      : undefined;\n  }\n\n  /**\n   * Simulate an error for a subscriber\n   *\n   * @param subscriber - Subscriber class or instance\n   * @param error - Error to throw\n   */\n  simulateError(subscriber: any, error: Error): void {\n    const name = typeof subscriber === 'function' ? subscriber.name : subscriber.constructor.name;\n    this.errorSimulations.set(name, error);\n  }\n\n  /**\n   * Clear simulated error for a subscriber\n   *\n   * @param subscriber - Subscriber class or instance\n   */\n  clearSimulatedError(subscriber: any): void {\n    const name = typeof subscriber === 'function' ? subscriber.name : subscriber.constructor.name;\n    this.errorSimulations.delete(name);\n  }\n\n  /**\n   * Clear all captured data\n   */\n  clear(): void {\n    this.messages = [];\n    this._dlqMessages = [];\n    this.subscriberCalls.clear();\n    this.errorSimulations.clear();\n  }\n\n  /**\n   * Cleanup and disconnect\n   */\n  async cleanup(): Promise<void> {\n    await this.consumer.stop();\n    this.clear();\n  }\n\n  /**\n   * Track a subscriber call\n   */\n  private trackSubscriberCall(subscriberName: string): void {\n    const count = this.subscriberCalls.get(subscriberName) || 0;\n    this.subscriberCalls.set(subscriberName, count + 1);\n  }\n\n  /**\n   * Wait for a condition to be true\n   *\n   * @param condition - Function that returns true when condition is met\n   * @param timeoutMs - Timeout in milliseconds\n   * @param intervalMs - Polling interval in milliseconds\n   */\n  async waitFor(\n    condition: () => boolean,\n    timeoutMs: number = 5000,\n    intervalMs: number = 100\n  ): Promise<void> {\n    const startTime = Date.now();\n\n    while (Date.now() - startTime < timeoutMs) {\n      if (condition()) {\n        return;\n      }\n      await new Promise((resolve) => setTimeout(resolve, intervalMs));\n    }\n\n    throw new Error(`Condition not met within ${timeoutMs}ms`);\n  }\n\n  /**\n   * Wait for a subscriber to be called\n   *\n   * @param subscriber - Subscriber class or instance\n   * @param timeoutMs - Timeout in milliseconds\n   */\n  async waitForSubscriber(subscriber: any, timeoutMs: number = 5000): Promise<void> {\n    await this.waitFor(() => this.subscriberCalled(subscriber), timeoutMs);\n  }\n\n  /**\n   * Wait for messages on a topic\n   *\n   * @param topic - Topic to wait for\n   * @param count - Expected number of messages\n   * @param timeoutMs - Timeout in milliseconds\n   */\n  async waitForMessages(topic: string, count: number = 1, timeoutMs: number = 5000): Promise<void> {\n    await this.waitFor(() => this.received(topic).length >= count, timeoutMs);\n  }\n}\n","/**\n * Testing utilities for nats-pubsub\n *\n * Provides test helpers, mocks, and utilities for testing subscribers,\n * publishers, and message handlers without requiring a real NATS server.\n *\n * @example\n * ```typescript\n * import { createMockMetadata, createMockMessage, MockPublisher } from 'nats-pubsub/testing';\n *\n * describe('MySubscriber', () => {\n *   it('processes messages', async () => {\n *     const subscriber = new MySubscriber();\n *     const message = createMockMessage({ id: '123', name: 'Test' });\n *     const metadata = createMockMetadata({ action: 'created' });\n *\n *     await subscriber.call(message, metadata);\n *     // assertions...\n *   });\n * });\n * ```\n */\n\nimport { EventMetadata, PublishOptions, Logger } from '../types';\n\n/**\n * Creates mock event metadata for testing\n *\n * @param overrides - Partial metadata to override defaults\n * @returns Complete EventMetadata object with sensible defaults\n *\n * @example\n * ```typescript\n * const metadata = createMockMetadata({\n *   action: 'created',\n *   domain: 'users',\n *   resource: 'user',\n * });\n * ```\n */\nexport function createMockMetadata(overrides?: Partial<EventMetadata>): EventMetadata {\n  return {\n    event_id: 'test-event-id',\n    subject: 'test.app.domain.resource.action',\n    domain: 'domain',\n    resource: 'resource',\n    action: 'action',\n    stream: 'TEST_STREAM',\n    stream_seq: 1,\n    deliveries: 1,\n    trace_id: 'test-trace-id',\n    ...overrides,\n  };\n}\n\n/**\n * Creates a mock message payload for testing\n *\n * @param data - Message data\n * @returns Message as Record<string, unknown>\n *\n * @example\n * ```typescript\n * const message = createMockMessage({ id: '123', name: 'Alice' });\n * ```\n */\nexport function createMockMessage(data: Record<string, unknown>): Record<string, unknown> {\n  return { ...data };\n}\n\n/**\n * Mock publisher for testing without real NATS connection\n * Tracks all published messages for assertions\n *\n * @example\n * ```typescript\n * const publisher = new MockPublisher();\n * await publisher.publish('notifications.email', { to: 'test@example.com' });\n *\n * expect(publisher.published).toHaveLength(1);\n * expect(publisher.published[0]).toMatchObject({\n *   topic: 'notifications.email',\n *   message: { to: 'test@example.com' }\n * });\n * ```\n */\nexport class MockPublisher {\n  public published: Array<{\n    topic?: string;\n    topics?: string[];\n    message: Record<string, unknown>;\n    options?: PublishOptions;\n    domain?: string;\n    resource?: string;\n    action?: string;\n  }> = [];\n\n  async publish(\n    topicOrOptions:\n      | string\n      | {\n          topics?: string[];\n          domain?: string;\n          resource?: string;\n          action?: string;\n          message?: Record<string, unknown>;\n          payload?: Record<string, unknown>;\n        },\n    messageOrOptions?: Record<string, unknown> | PublishOptions,\n    options?: PublishOptions\n  ): Promise<void> {\n    if (typeof topicOrOptions === 'string') {\n      // Topic-based publish\n      this.published.push({\n        topic: topicOrOptions,\n        message: messageOrOptions as Record<string, unknown>,\n        options,\n      });\n    } else {\n      // Object-based publish\n      const payload = topicOrOptions.payload || topicOrOptions.message || {};\n      this.published.push({\n        topics: topicOrOptions.topics,\n        domain: topicOrOptions.domain,\n        resource: topicOrOptions.resource,\n        action: topicOrOptions.action,\n        message: payload,\n        options: messageOrOptions as PublishOptions,\n      });\n    }\n  }\n\n  /**\n   * Clear all published messages\n   */\n  clear(): void {\n    this.published = [];\n  }\n\n  /**\n   * Get last published message\n   */\n  getLastPublished() {\n    return this.published[this.published.length - 1];\n  }\n\n  /**\n   * Find published messages by topic\n   */\n  findByTopic(topic: string) {\n    return this.published.filter((p) => p.topic === topic);\n  }\n\n  /**\n   * Find published messages by domain/resource/action\n   */\n  findByEvent(domain: string, resource: string, action: string) {\n    return this.published.filter(\n      (p) => p.domain === domain && p.resource === resource && p.action === action\n    );\n  }\n}\n\n/**\n * Mock logger for testing without console output\n * Captures all log calls for assertions\n *\n * @example\n * ```typescript\n * const logger = new MockLogger();\n * logger.info('Test message', { key: 'value' });\n *\n * expect(logger.logs.info).toHaveLength(1);\n * expect(logger.logs.info[0].message).toBe('Test message');\n * ```\n */\nexport class MockLogger implements Logger {\n  public logs: {\n    debug: Array<{ message: string; meta?: Record<string, unknown> }>;\n    info: Array<{ message: string; meta?: Record<string, unknown> }>;\n    warn: Array<{ message: string; meta?: Record<string, unknown> }>;\n    error: Array<{ message: string; meta?: Record<string, unknown> }>;\n  } = {\n    debug: [],\n    info: [],\n    warn: [],\n    error: [],\n  };\n\n  debug(message: string, meta?: Record<string, unknown>): void {\n    this.logs.debug.push({ message, meta });\n  }\n\n  info(message: string, meta?: Record<string, unknown>): void {\n    this.logs.info.push({ message, meta });\n  }\n\n  warn(message: string, meta?: Record<string, unknown>): void {\n    this.logs.warn.push({ message, meta });\n  }\n\n  error(message: string, meta?: Record<string, unknown>): void {\n    this.logs.error.push({ message, meta });\n  }\n\n  /**\n   * Clear all logged messages\n   */\n  clear(): void {\n    this.logs = {\n      debug: [],\n      info: [],\n      warn: [],\n      error: [],\n    };\n  }\n\n  /**\n   * Get all logs as a flat array\n   */\n  getAllLogs() {\n    return [\n      ...this.logs.debug.map((l) => ({ level: 'debug', ...l })),\n      ...this.logs.info.map((l) => ({ level: 'info', ...l })),\n      ...this.logs.warn.map((l) => ({ level: 'warn', ...l })),\n      ...this.logs.error.map((l) => ({ level: 'error', ...l })),\n    ];\n  }\n}\n\n/**\n * Wait for a condition to be true (useful for async tests)\n *\n * @param condition - Function that returns true when condition is met\n * @param timeoutMs - Maximum time to wait in milliseconds (default: 5000)\n * @param intervalMs - Polling interval in milliseconds (default: 100)\n * @returns Promise that resolves when condition is true\n * @throws Error if timeout is reached\n *\n * @example\n * ```typescript\n * const publisher = new MockPublisher();\n * await someAsyncOperation(publisher);\n * await waitFor(() => publisher.published.length > 0, 1000);\n * ```\n */\nexport async function waitFor(\n  condition: () => boolean,\n  timeoutMs: number = 5000,\n  intervalMs: number = 100\n): Promise<void> {\n  const startTime = Date.now();\n\n  while (!condition()) {\n    if (Date.now() - startTime > timeoutMs) {\n      throw new Error(`Timeout waiting for condition after ${timeoutMs}ms`);\n    }\n    await new Promise((resolve) => setTimeout(resolve, intervalMs));\n  }\n}\n\n/**\n * Create a spy function that tracks calls\n * Similar to jest.fn() but framework-agnostic\n *\n * @example\n * ```typescript\n * const spy = createSpy();\n * await subscriber.call(message, metadata);\n * expect(spy.calls).toHaveLength(1);\n * ```\n */\nexport function createSpy<T extends (...args: any[]) => any>(\n  implementation?: T\n): T & { calls: any[][]; reset: () => void } {\n  const calls: any[][] = [];\n\n  const spy = ((...args: any[]) => {\n    calls.push(args);\n    return implementation?.(...args);\n  }) as T & { calls: any[][]; reset: () => void };\n\n  spy.calls = calls;\n  spy.reset = () => {\n    calls.length = 0;\n  };\n\n  return spy;\n}\n\n/**\n * Sleep utility for tests\n *\n * @param ms - Milliseconds to sleep\n * @returns Promise that resolves after the specified time\n *\n * @example\n * ```typescript\n * await sleep(100); // Wait 100ms\n * ```\n */\nexport async function sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Create a test suite helper with common setup/teardown\n *\n * @example\n * ```typescript\n * const testSuite = createTestSuite({\n *   beforeEach: async () => ({ publisher: new MockPublisher() }),\n *   afterEach: async (ctx) => ctx.publisher.clear(),\n * });\n *\n * it('test case', async () => {\n *   const { publisher } = await testSuite.setup();\n *   // ... test code\n *   await testSuite.teardown({ publisher });\n * });\n * ```\n */\nexport function createTestSuite<T>(options: {\n  beforeEach?: () => Promise<T> | T;\n  afterEach?: (context: T) => Promise<void> | void;\n  beforeAll?: () => Promise<void> | void;\n  afterAll?: () => Promise<void> | void;\n}) {\n  return {\n    async setup(): Promise<T> {\n      if (options.beforeAll) {\n        await options.beforeAll();\n      }\n      if (options.beforeEach) {\n        return await options.beforeEach();\n      }\n      return {} as T;\n    },\n    async teardown(context: T): Promise<void> {\n      if (options.afterEach) {\n        await options.afterEach(context);\n      }\n      if (options.afterAll) {\n        await options.afterAll();\n      }\n    },\n  };\n}\n\n// Export TestHarness\nexport { TestHarness } from './test-harness';\nexport type { TestHarnessOptions, CapturedMessage, CapturedDlqMessage } from './test-harness';\n","/**\n * Types for Outbox pattern implementation\n *\n * The Outbox pattern ensures reliable message delivery by:\n * 1. Persisting the message to storage before publishing\n * 2. Publishing to NATS\n * 3. Marking as sent in storage\n *\n * This prevents message loss if the application crashes between publishing and commit\n */\n\n/**\n * Status of an outbox event\n */\nexport enum OutboxStatus {\n  /** Event is pending and ready to be published */\n  PENDING = 'pending',\n  /** Event is currently being published */\n  PUBLISHING = 'publishing',\n  /** Event has been successfully published */\n  SENT = 'sent',\n  /** Event failed to publish after retries */\n  FAILED = 'failed',\n}\n\n/**\n * Outbox event stored in the repository\n */\nexport interface OutboxEvent {\n  /** Unique event identifier (UUID) */\n  eventId: string;\n  /** NATS subject to publish to */\n  subject: string;\n  /** Message envelope (JSON-serialized) */\n  payload: string;\n  /** NATS headers (JSON-serialized) */\n  headers: string;\n  /** Current status */\n  status: OutboxStatus;\n  /** Number of publish attempts */\n  attempts: number;\n  /** Last error message if failed */\n  lastError?: string;\n  /** When the event was enqueued */\n  enqueuedAt: Date;\n  /** When the event was sent (null if not sent) */\n  sentAt?: Date;\n  /** When the event was created */\n  createdAt: Date;\n  /** When the event was last updated */\n  updatedAt: Date;\n}\n\n/**\n * Parameters for creating a new outbox event\n */\nexport interface CreateOutboxEventParams {\n  eventId: string;\n  subject: string;\n  payload: string;\n  headers: string;\n  enqueuedAt?: Date;\n}\n\n/**\n * Options for querying outbox events\n */\nexport interface FindOutboxEventsOptions {\n  status?: OutboxStatus;\n  limit?: number;\n  olderThan?: Date;\n}\n\n/**\n * Repository interface for Outbox pattern\n * Implementations should handle database operations\n */\nexport interface OutboxRepository {\n  /**\n   * Find or create an outbox event by event ID\n   * Used for idempotency - prevents duplicate events\n   */\n  findOrCreate(params: CreateOutboxEventParams): Promise<OutboxEvent>;\n\n  /**\n   * Find an outbox event by event ID\n   */\n  findByEventId(eventId: string): Promise<OutboxEvent | null>;\n\n  /**\n   * Find pending events ready to be published\n   */\n  findPending(options?: FindOutboxEventsOptions): Promise<OutboxEvent[]>;\n\n  /**\n   * Mark an event as publishing (in-progress)\n   */\n  markAsPublishing(eventId: string): Promise<void>;\n\n  /**\n   * Mark an event as successfully sent\n   */\n  markAsSent(eventId: string): Promise<void>;\n\n  /**\n   * Mark an event as failed with error message\n   */\n  markAsFailed(eventId: string, error: string): Promise<void>;\n\n  /**\n   * Increment attempt count for an event\n   */\n  incrementAttempts(eventId: string): Promise<void>;\n\n  /**\n   * Delete successfully sent events older than retention period\n   * Used for cleanup/maintenance\n   */\n  cleanup(olderThan: Date): Promise<number>;\n\n  /**\n   * Reset stale publishing events back to pending\n   * Events stuck in \"publishing\" state for too long\n   */\n  resetStalePublishing(olderThan: Date): Promise<number>;\n\n  /**\n   * Mark a batch of events as sent (for performance)\n   */\n  markBatchAsSent(eventIds: string[]): Promise<number>;\n\n  /**\n   * Mark a batch of events as failed (for performance)\n   */\n  markBatchAsFailed(eventIds: string[], error: string): Promise<number>;\n}\n\n/**\n * Result of a publish operation\n */\nexport interface PublishResult {\n  success: boolean;\n  eventId: string;\n  subject: string;\n  reason?: string;\n  details?: string;\n  error?: Error;\n}\n","import { OutboxRepository, OutboxStatus, PublishResult, CreateOutboxEventParams } from './types';\nimport { Logger } from '../types';\nimport config from '../core/config';\n\n/**\n * OutboxPublisher - Handles publishing messages using the Outbox pattern\n *\n * The Outbox pattern ensures reliable message delivery by:\n * 1. Persisting the message to the database before publishing\n * 2. Publishing to NATS\n * 3. Marking as sent in the database\n *\n * This prevents message loss if the application crashes between publishing and commit\n *\n * Design Patterns:\n * - Repository Pattern: Abstracts database operations\n * - Template Method: Defines the publish flow\n * - Dependency Injection: Repository and logger are injected\n *\n * @example\n * ```typescript\n * const publisher = new OutboxPublisher(repository, logger);\n * const result = await publisher.publish({\n *   eventId: 'event-123',\n *   subject: 'production.app.order.created',\n *   payload: JSON.stringify(envelope),\n *   headers: JSON.stringify({ 'nats-msg-id': 'event-123' })\n * }, async () => {\n *   // Actual NATS publish logic\n *   await js.publish(subject, payload);\n * });\n * ```\n */\nexport class OutboxPublisher {\n  private readonly repository: OutboxRepository;\n  private readonly logger: Logger;\n\n  constructor(repository: OutboxRepository, logger?: Logger) {\n    this.repository = repository;\n    this.logger = logger || config.logger;\n  }\n\n  /**\n   * Publish a message using the Outbox pattern\n   *\n   * @param params - Outbox event parameters\n   * @param publishFn - Function that performs the actual NATS publish\n   * @returns PublishResult indicating success or failure\n   */\n  async publish(\n    params: CreateOutboxEventParams,\n    publishFn: () => Promise<void>\n  ): Promise<PublishResult> {\n    const { eventId, subject } = params;\n\n    try {\n      // Step 1: Find or create outbox event (idempotency)\n      const event = await this.repository.findOrCreate(params);\n\n      // Step 2: Check if already sent (idempotency)\n      if (event.status === OutboxStatus.SENT && event.sentAt) {\n        this.logger.info('Outbox event already sent, skipping publish', {\n          eventId,\n          subject,\n          sentAt: event.sentAt,\n        });\n        return {\n          success: true,\n          eventId,\n          subject,\n          details: 'Already sent (idempotent)',\n        };\n      }\n\n      // Step 3: Mark as publishing\n      await this.repository.markAsPublishing(eventId);\n      await this.repository.incrementAttempts(eventId);\n\n      this.logger.debug('Publishing outbox event', {\n        eventId,\n        subject,\n        attempts: event.attempts + 1,\n      });\n\n      // Step 4: Attempt to publish to NATS\n      await publishFn();\n\n      // Step 5: Mark as sent on success\n      await this.repository.markAsSent(eventId);\n\n      this.logger.info('Outbox event published successfully', {\n        eventId,\n        subject,\n      });\n\n      return {\n        success: true,\n        eventId,\n        subject,\n      };\n    } catch (error) {\n      // Step 6: Mark as failed on error\n      const errorMessage = error instanceof Error ? error.message : String(error);\n\n      try {\n        await this.repository.markAsFailed(eventId, errorMessage);\n      } catch (repoError) {\n        this.logger.error('Failed to mark outbox event as failed', {\n          eventId,\n          subject,\n          error: repoError,\n        });\n      }\n\n      this.logger.error('Outbox event publish failed', {\n        eventId,\n        subject,\n        error: errorMessage,\n      });\n\n      return {\n        success: false,\n        eventId,\n        subject,\n        reason: 'publish_failed',\n        details: errorMessage,\n        error: error instanceof Error ? error : new Error(errorMessage),\n      };\n    }\n  }\n\n  /**\n   * Publish a batch of pending events\n   * Useful for background workers processing the outbox\n   *\n   * @param limit - Maximum number of events to process\n   * @returns Array of publish results\n   */\n  async publishPending(\n    limit: number = 100,\n    publishFn: (eventId: string, subject: string, payload: string, headers: string) => Promise<void>\n  ): Promise<PublishResult[]> {\n    const pendingEvents = await this.repository.findPending({ limit });\n\n    this.logger.info('Processing pending outbox events', {\n      count: pendingEvents.length,\n    });\n\n    const results: PublishResult[] = [];\n\n    for (const event of pendingEvents) {\n      const result = await this.publish(\n        {\n          eventId: event.eventId,\n          subject: event.subject,\n          payload: event.payload,\n          headers: event.headers,\n          enqueuedAt: event.enqueuedAt,\n        },\n        async () => {\n          await publishFn(event.eventId, event.subject, event.payload, event.headers);\n        }\n      );\n\n      results.push(result);\n    }\n\n    const successCount = results.filter((r) => r.success).length;\n    const failureCount = results.filter((r) => !r.success).length;\n\n    this.logger.info('Finished processing pending outbox events', {\n      total: results.length,\n      success: successCount,\n      failed: failureCount,\n    });\n\n    return results;\n  }\n\n  /**\n   * Cleanup old sent events\n   * Should be run periodically to prevent unbounded growth\n   *\n   * @param retentionDays - Number of days to retain sent events\n   * @returns Number of events deleted\n   */\n  async cleanup(retentionDays: number = 7): Promise<number> {\n    const olderThan = new Date();\n    olderThan.setDate(olderThan.getDate() - retentionDays);\n\n    const deletedCount = await this.repository.cleanup(olderThan);\n\n    this.logger.info('Cleaned up old outbox events', {\n      deletedCount,\n      retentionDays,\n      olderThan,\n    });\n\n    return deletedCount;\n  }\n\n  /**\n   * Reset stale publishing events\n   * Events stuck in \"publishing\" state for too long are reset to pending\n   *\n   * @param staleDurationMinutes - Duration in minutes to consider an event stale\n   * @returns Number of events reset\n   */\n  async resetStale(staleDurationMinutes: number = 5): Promise<number> {\n    const olderThan = new Date();\n    olderThan.setMinutes(olderThan.getMinutes() - staleDurationMinutes);\n\n    const resetCount = await this.repository.resetStalePublishing(olderThan);\n\n    this.logger.info('Reset stale publishing outbox events', {\n      resetCount,\n      staleDurationMinutes,\n      olderThan,\n    });\n\n    return resetCount;\n  }\n}\n\n/**\n * Create a PublishResult for success\n */\nexport function successResult(eventId: string, subject: string, details?: string): PublishResult {\n  return {\n    success: true,\n    eventId,\n    subject,\n    details,\n  };\n}\n\n/**\n * Create a PublishResult for failure\n */\nexport function failureResult(\n  eventId: string,\n  subject: string,\n  reason: string,\n  details?: string,\n  error?: Error\n): PublishResult {\n  return {\n    success: false,\n    eventId,\n    subject,\n    reason,\n    details,\n    error,\n  };\n}\n","import {\n  OutboxRepository,\n  OutboxEvent,\n  OutboxStatus,\n  CreateOutboxEventParams,\n  FindOutboxEventsOptions,\n} from './types';\n\n/**\n * In-memory implementation of OutboxRepository\n *\n * Useful for:\n * - Testing without database dependencies\n * - Development environments\n * - Simple use cases where persistence isn't critical\n *\n * WARNING: Data is lost when the process restarts!\n * For production use, implement a database-backed repository.\n *\n * @example\n * ```typescript\n * const repository = new MemoryOutboxRepository();\n * const publisher = new OutboxPublisher(repository);\n * ```\n */\nexport class MemoryOutboxRepository implements OutboxRepository {\n  private events: Map<string, OutboxEvent> = new Map();\n\n  async findOrCreate(params: CreateOutboxEventParams): Promise<OutboxEvent> {\n    const existing = this.events.get(params.eventId);\n    if (existing) {\n      return existing;\n    }\n\n    const now = new Date();\n    const event: OutboxEvent = {\n      eventId: params.eventId,\n      subject: params.subject,\n      payload: params.payload,\n      headers: params.headers,\n      status: OutboxStatus.PENDING,\n      attempts: 0,\n      enqueuedAt: params.enqueuedAt || now,\n      createdAt: now,\n      updatedAt: now,\n    };\n\n    this.events.set(event.eventId, event);\n    return event;\n  }\n\n  async findByEventId(eventId: string): Promise<OutboxEvent | null> {\n    return this.events.get(eventId) || null;\n  }\n\n  async findPending(options: FindOutboxEventsOptions = {}): Promise<OutboxEvent[]> {\n    const { status = OutboxStatus.PENDING, limit = 100 } = options;\n\n    const results = Array.from(this.events.values())\n      .filter((event) => {\n        if (event.status !== status) return false;\n        if (options.olderThan && event.enqueuedAt > options.olderThan) return false;\n        return true;\n      })\n      .sort((a, b) => a.enqueuedAt.getTime() - b.enqueuedAt.getTime())\n      .slice(0, limit);\n\n    return results;\n  }\n\n  async markAsPublishing(eventId: string): Promise<void> {\n    const event = this.events.get(eventId);\n    if (!event) {\n      throw new Error(`Event not found: ${eventId}`);\n    }\n\n    event.status = OutboxStatus.PUBLISHING;\n    event.updatedAt = new Date();\n  }\n\n  async markAsSent(eventId: string): Promise<void> {\n    const event = this.events.get(eventId);\n    if (!event) {\n      throw new Error(`Event not found: ${eventId}`);\n    }\n\n    event.status = OutboxStatus.SENT;\n    event.sentAt = new Date();\n    event.updatedAt = new Date();\n  }\n\n  async markAsFailed(eventId: string, error: string): Promise<void> {\n    const event = this.events.get(eventId);\n    if (!event) {\n      throw new Error(`Event not found: ${eventId}`);\n    }\n\n    event.status = OutboxStatus.FAILED;\n    event.lastError = error;\n    event.updatedAt = new Date();\n  }\n\n  async incrementAttempts(eventId: string): Promise<void> {\n    const event = this.events.get(eventId);\n    if (!event) {\n      throw new Error(`Event not found: ${eventId}`);\n    }\n\n    event.attempts += 1;\n    event.updatedAt = new Date();\n  }\n\n  async cleanup(olderThan: Date): Promise<number> {\n    let deletedCount = 0;\n\n    for (const [eventId, event] of this.events.entries()) {\n      if (event.status === OutboxStatus.SENT && event.sentAt && event.sentAt < olderThan) {\n        this.events.delete(eventId);\n        deletedCount++;\n      }\n    }\n\n    return deletedCount;\n  }\n\n  async resetStalePublishing(olderThan: Date): Promise<number> {\n    let resetCount = 0;\n\n    for (const event of this.events.values()) {\n      if (event.status === OutboxStatus.PUBLISHING && event.updatedAt < olderThan) {\n        event.status = OutboxStatus.PENDING;\n        event.lastError = 'Reset from stale publishing state';\n        event.updatedAt = new Date();\n        resetCount++;\n      }\n    }\n\n    return resetCount;\n  }\n\n  async markBatchAsSent(eventIds: string[]): Promise<number> {\n    let count = 0;\n    const now = new Date();\n\n    for (const eventId of eventIds) {\n      const event = this.events.get(eventId);\n      if (event) {\n        event.status = OutboxStatus.SENT;\n        event.sentAt = now;\n        event.updatedAt = now;\n        count++;\n      }\n    }\n\n    return count;\n  }\n\n  async markBatchAsFailed(eventIds: string[], error: string): Promise<number> {\n    let count = 0;\n    const now = new Date();\n\n    for (const eventId of eventIds) {\n      const event = this.events.get(eventId);\n      if (event) {\n        event.status = OutboxStatus.FAILED;\n        event.lastError = error;\n        event.updatedAt = now;\n        count++;\n      }\n    }\n\n    return count;\n  }\n\n  /**\n   * Clear all events (useful for testing)\n   */\n  clear(): void {\n    this.events.clear();\n  }\n\n  /**\n   * Get all events (useful for testing/debugging)\n   */\n  getAll(): OutboxEvent[] {\n    return Array.from(this.events.values());\n  }\n\n  /**\n   * Get event count by status (useful for monitoring)\n   */\n  getCountByStatus(): Record<OutboxStatus, number> {\n    const counts: Record<OutboxStatus, number> = {\n      [OutboxStatus.PENDING]: 0,\n      [OutboxStatus.PUBLISHING]: 0,\n      [OutboxStatus.SENT]: 0,\n      [OutboxStatus.FAILED]: 0,\n    };\n\n    for (const event of this.events.values()) {\n      counts[event.status]++;\n    }\n\n    return counts;\n  }\n}\n","/**\n * SQL schema definitions for Outbox pattern\n *\n * These schemas can be used with any SQL database (PostgreSQL, MySQL, SQLite, etc.)\n * Adapt the syntax as needed for your specific database.\n */\n\n/**\n * PostgreSQL schema for outbox events\n */\nexport const POSTGRES_OUTBOX_SCHEMA = `\nCREATE TABLE IF NOT EXISTS nats_outbox_events (\n  event_id VARCHAR(255) PRIMARY KEY,\n  subject VARCHAR(512) NOT NULL,\n  payload TEXT NOT NULL,\n  headers TEXT NOT NULL,\n  status VARCHAR(50) NOT NULL DEFAULT 'pending',\n  attempts INTEGER NOT NULL DEFAULT 0,\n  last_error TEXT,\n  enqueued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  sent_at TIMESTAMP,\n  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n);\n\n-- Index for finding pending events\nCREATE INDEX IF NOT EXISTS idx_outbox_status_enqueued\n  ON nats_outbox_events(status, enqueued_at)\n  WHERE status IN ('pending', 'publishing');\n\n-- Index for cleanup queries\nCREATE INDEX IF NOT EXISTS idx_outbox_sent_at\n  ON nats_outbox_events(sent_at)\n  WHERE status = 'sent' AND sent_at IS NOT NULL;\n\n-- Index for stale publishing queries\nCREATE INDEX IF NOT EXISTS idx_outbox_stale_publishing\n  ON nats_outbox_events(status, updated_at)\n  WHERE status = 'publishing';\n`;\n\n/**\n * MySQL schema for outbox events\n */\nexport const MYSQL_OUTBOX_SCHEMA = `\nCREATE TABLE IF NOT EXISTS nats_outbox_events (\n  event_id VARCHAR(255) PRIMARY KEY,\n  subject VARCHAR(512) NOT NULL,\n  payload LONGTEXT NOT NULL,\n  headers TEXT NOT NULL,\n  status VARCHAR(50) NOT NULL DEFAULT 'pending',\n  attempts INT NOT NULL DEFAULT 0,\n  last_error TEXT,\n  enqueued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  sent_at TIMESTAMP NULL,\n  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  INDEX idx_outbox_status_enqueued (status, enqueued_at),\n  INDEX idx_outbox_sent_at (sent_at),\n  INDEX idx_outbox_stale_publishing (status, updated_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n`;\n\n/**\n * SQLite schema for outbox events\n */\nexport const SQLITE_OUTBOX_SCHEMA = `\nCREATE TABLE IF NOT EXISTS nats_outbox_events (\n  event_id TEXT PRIMARY KEY,\n  subject TEXT NOT NULL,\n  payload TEXT NOT NULL,\n  headers TEXT NOT NULL,\n  status TEXT NOT NULL DEFAULT 'pending',\n  attempts INTEGER NOT NULL DEFAULT 0,\n  last_error TEXT,\n  enqueued_at TEXT NOT NULL DEFAULT (datetime('now')),\n  sent_at TEXT,\n  created_at TEXT NOT NULL DEFAULT (datetime('now')),\n  updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_outbox_status_enqueued\n  ON nats_outbox_events(status, enqueued_at);\n\nCREATE INDEX IF NOT EXISTS idx_outbox_sent_at\n  ON nats_outbox_events(sent_at);\n\nCREATE INDEX IF NOT EXISTS idx_outbox_stale_publishing\n  ON nats_outbox_events(status, updated_at);\n`;\n\n/**\n * TypeORM entity example\n */\nexport const TYPEORM_OUTBOX_ENTITY = `\nimport { Entity, Column, PrimaryColumn, CreateDateColumn, UpdateDateColumn, Index } from 'typeorm';\n\n@Entity('nats_outbox_events')\n@Index('idx_outbox_status_enqueued', ['status', 'enqueuedAt'])\nexport class OutboxEvent {\n  @PrimaryColumn({ type: 'varchar', length: 255 })\n  eventId!: string;\n\n  @Column({ type: 'varchar', length: 512 })\n  subject!: string;\n\n  @Column({ type: 'text' })\n  payload!: string;\n\n  @Column({ type: 'text' })\n  headers!: string;\n\n  @Column({ type: 'varchar', length: 50, default: 'pending' })\n  status!: string;\n\n  @Column({ type: 'int', default: 0 })\n  attempts!: number;\n\n  @Column({ type: 'text', nullable: true })\n  lastError?: string;\n\n  @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })\n  enqueuedAt!: Date;\n\n  @Column({ type: 'timestamp', nullable: true })\n  sentAt?: Date;\n\n  @CreateDateColumn()\n  createdAt!: Date;\n\n  @UpdateDateColumn()\n  updatedAt!: Date;\n}\n`;\n\n/**\n * Prisma schema example\n */\nexport const PRISMA_OUTBOX_SCHEMA = `\nmodel NatsOutboxEvent {\n  eventId    String   @id @map(\"event_id\") @db.VarChar(255)\n  subject    String   @db.VarChar(512)\n  payload    String   @db.Text\n  headers    String   @db.Text\n  status     String   @default(\"pending\") @db.VarChar(50)\n  attempts   Int      @default(0)\n  lastError  String?  @map(\"last_error\") @db.Text\n  enqueuedAt DateTime @default(now()) @map(\"enqueued_at\")\n  sentAt     DateTime? @map(\"sent_at\")\n  createdAt  DateTime @default(now()) @map(\"created_at\")\n  updatedAt  DateTime @updatedAt @map(\"updated_at\")\n\n  @@index([status, enqueuedAt], map: \"idx_outbox_status_enqueued\")\n  @@index([sentAt], map: \"idx_outbox_sent_at\")\n  @@map(\"nats_outbox_events\")\n}\n`;\n\n/**\n * Knex.js migration example\n */\nexport const KNEX_OUTBOX_MIGRATION = `\nexport async function up(knex: Knex): Promise<void> {\n  await knex.schema.createTable('nats_outbox_events', (table) => {\n    table.string('event_id', 255).primary();\n    table.string('subject', 512).notNullable();\n    table.text('payload').notNullable();\n    table.text('headers').notNullable();\n    table.string('status', 50).notNullable().defaultTo('pending');\n    table.integer('attempts').notNullable().defaultTo(0);\n    table.text('last_error');\n    table.timestamp('enqueued_at').notNullable().defaultTo(knex.fn.now());\n    table.timestamp('sent_at');\n    table.timestamps(true, true);\n\n    table.index(['status', 'enqueued_at'], 'idx_outbox_status_enqueued');\n    table.index(['sent_at'], 'idx_outbox_sent_at');\n    table.index(['status', 'updated_at'], 'idx_outbox_stale_publishing');\n  });\n}\n\nexport async function down(knex: Knex): Promise<void> {\n  await knex.schema.dropTable('nats_outbox_events');\n}\n`;\n","/**\n * Types for Inbox pattern implementation\n *\n * The Inbox pattern ensures idempotent message processing by:\n * 1. Checking if message was already processed\n * 2. Marking message as processing\n * 3. Processing the message\n * 4. Marking as processed\n *\n * This prevents duplicate processing of the same message\n */\n\n/**\n * Status of an inbox event\n */\nexport enum InboxStatus {\n  /** Event is being processed */\n  PROCESSING = 'processing',\n  /** Event has been successfully processed */\n  PROCESSED = 'processed',\n  /** Event failed to process */\n  FAILED = 'failed',\n}\n\n/**\n * Inbox event stored in the repository\n */\nexport interface InboxEvent {\n  /** Unique event identifier (UUID) */\n  eventId: string;\n  /** NATS subject received from */\n  subject: string;\n  /** Message payload (JSON-serialized) */\n  payload: string;\n  /** NATS headers (JSON-serialized) */\n  headers: string;\n  /** JetStream stream name */\n  stream?: string;\n  /** JetStream stream sequence number */\n  streamSeq?: number;\n  /** Number of delivery attempts */\n  deliveries: number;\n  /** Current status */\n  status: InboxStatus;\n  /** Last error message if failed */\n  lastError?: string;\n  /** When the event was received */\n  receivedAt: Date;\n  /** When the event was processed (null if not processed) */\n  processedAt?: Date;\n  /** When the event was created */\n  createdAt: Date;\n  /** When the event was last updated */\n  updatedAt: Date;\n}\n\n/**\n * Parameters for creating a new inbox event\n */\nexport interface CreateInboxEventParams {\n  eventId: string;\n  subject: string;\n  payload: string;\n  headers: string;\n  stream?: string;\n  streamSeq?: number;\n  deliveries: number;\n  receivedAt?: Date;\n}\n\n/**\n * Options for querying inbox events\n */\nexport interface FindInboxEventsOptions {\n  status?: InboxStatus;\n  limit?: number;\n  olderThan?: Date;\n}\n\n/**\n * Repository interface for Inbox pattern\n * Implementations should handle database operations\n */\nexport interface InboxRepository {\n  /**\n   * Find an inbox event by event ID\n   * Returns null if not found\n   */\n  findByEventId(eventId: string): Promise<InboxEvent | null>;\n\n  /**\n   * Find an inbox event by stream sequence\n   * Alternative deduplication key for JetStream\n   */\n  findByStreamSeq(stream: string, seq: number): Promise<InboxEvent | null>;\n\n  /**\n   * Create a new inbox event\n   * Marks it as \"processing\"\n   */\n  create(params: CreateInboxEventParams): Promise<InboxEvent>;\n\n  /**\n   * Find or create an inbox event\n   * Used for idempotency check\n   */\n  findOrCreate(\n    params: CreateInboxEventParams\n  ): Promise<{ event: InboxEvent; alreadyExists: boolean }>;\n\n  /**\n   * Check if an event was already processed\n   */\n  isProcessed(eventId: string): Promise<boolean>;\n\n  /**\n   * Mark an event as successfully processed\n   */\n  markAsProcessed(eventId: string): Promise<void>;\n\n  /**\n   * Mark an event as failed with error message\n   */\n  markAsFailed(eventId: string, error: string): Promise<void>;\n\n  /**\n   * Find events by status\n   */\n  findByStatus(status: InboxStatus, options?: FindInboxEventsOptions): Promise<InboxEvent[]>;\n\n  /**\n   * Delete successfully processed events older than retention period\n   * Used for cleanup/maintenance\n   */\n  cleanup(olderThan: Date): Promise<number>;\n\n  /**\n   * Reset stale processing events back to failed\n   * Events stuck in \"processing\" state for too long\n   */\n  resetStaleProcessing(olderThan: Date): Promise<number>;\n}\n","import { InboxRepository, InboxStatus, CreateInboxEventParams } from './types';\nimport { Logger, MessageContext } from '../types';\nimport config from '../core/config';\n\n/**\n * InboxProcessor - Handles idempotent message processing using the Inbox pattern\n *\n * The Inbox pattern ensures messages are processed exactly once by:\n * 1. Checking if message was already processed (by event_id or stream_seq)\n * 2. Marking message as processing\n * 3. Processing the message\n * 4. Marking as processed\n *\n * This prevents duplicate processing of the same message, which is critical for:\n * - Financial transactions\n * - Order processing\n * - Any operation that shouldn't be repeated\n *\n * Design Patterns:\n * - Repository Pattern: Abstracts database operations\n * - Template Method: Defines the processing flow\n * - Dependency Injection: Repository and logger are injected\n *\n * @example\n * ```typescript\n * const processor = new InboxProcessor(repository, logger);\n * const result = await processor.process(\n *   {\n *     eventId: 'event-123',\n *     subject: 'production.app.order.created',\n *     payload: JSON.stringify(message),\n *     headers: JSON.stringify(natsHeaders),\n *     deliveries: 1\n *   },\n *   async (message, context) => {\n *     // Your message processing logic\n *     await orderService.createOrder(message);\n *   },\n *   context\n * );\n * ```\n */\nexport class InboxProcessor {\n  private readonly repository: InboxRepository;\n  private readonly logger: Logger;\n\n  constructor(repository: InboxRepository, logger?: Logger) {\n    this.repository = repository;\n    this.logger = logger || config.logger;\n  }\n\n  /**\n   * Process a message using the Inbox pattern\n   *\n   * @param params - Inbox event parameters\n   * @param processFn - Function that processes the message\n   * @param context - Message context\n   * @returns Boolean indicating if message was processed (false if already processed)\n   */\n  async process(\n    params: CreateInboxEventParams,\n    processFn: (message: Record<string, unknown>, context: MessageContext) => Promise<void>,\n    context: MessageContext\n  ): Promise<boolean> {\n    const { eventId, subject } = params;\n\n    try {\n      // Step 1: Find or create inbox event (idempotency check)\n      const { event, alreadyExists } = await this.repository.findOrCreate(params);\n\n      // Step 2: Check if already processed (idempotency)\n      if (alreadyExists && event.status === InboxStatus.PROCESSED && event.processedAt) {\n        this.logger.info('Inbox event already processed, skipping', {\n          eventId,\n          subject,\n          processedAt: event.processedAt,\n        });\n        return false; // Already processed, don't process again\n      }\n\n      this.logger.debug('Processing inbox event', {\n        eventId,\n        subject,\n        deliveries: params.deliveries,\n      });\n\n      // Step 3: Parse and process the message\n      const message = JSON.parse(params.payload);\n      await processFn(message, context);\n\n      // Step 4: Mark as processed on success\n      await this.repository.markAsProcessed(eventId);\n\n      this.logger.info('Inbox event processed successfully', {\n        eventId,\n        subject,\n      });\n\n      return true; // Successfully processed\n    } catch (error) {\n      // Step 5: Mark as failed on error\n      const errorMessage = error instanceof Error ? error.message : String(error);\n\n      try {\n        await this.repository.markAsFailed(eventId, errorMessage);\n      } catch (repoError) {\n        this.logger.error('Failed to mark inbox event as failed', {\n          eventId,\n          subject,\n          error: repoError,\n        });\n      }\n\n      this.logger.error('Inbox event processing failed', {\n        eventId,\n        subject,\n        error: errorMessage,\n      });\n\n      // Re-throw to allow caller to handle (e.g., NAK the message)\n      throw error;\n    }\n  }\n\n  /**\n   * Check if a message was already processed\n   * Useful for quick idempotency checks before expensive operations\n   *\n   * @param eventId - Event identifier\n   * @returns Boolean indicating if already processed\n   */\n  async isProcessed(eventId: string): Promise<boolean> {\n    return await this.repository.isProcessed(eventId);\n  }\n\n  /**\n   * Cleanup old processed events\n   * Should be run periodically to prevent unbounded growth\n   *\n   * @param retentionDays - Number of days to retain processed events\n   * @returns Number of events deleted\n   */\n  async cleanup(retentionDays: number = 30): Promise<number> {\n    const olderThan = new Date();\n    olderThan.setDate(olderThan.getDate() - retentionDays);\n\n    const deletedCount = await this.repository.cleanup(olderThan);\n\n    this.logger.info('Cleaned up old inbox events', {\n      deletedCount,\n      retentionDays,\n      olderThan,\n    });\n\n    return deletedCount;\n  }\n\n  /**\n   * Reset stale processing events\n   * Events stuck in \"processing\" state for too long are marked as failed\n   *\n   * @param staleDurationMinutes - Duration in minutes to consider an event stale\n   * @returns Number of events reset\n   */\n  async resetStale(staleDurationMinutes: number = 5): Promise<number> {\n    const olderThan = new Date();\n    olderThan.setMinutes(olderThan.getMinutes() - staleDurationMinutes);\n\n    const resetCount = await this.repository.resetStaleProcessing(olderThan);\n\n    this.logger.info('Reset stale processing inbox events', {\n      resetCount,\n      staleDurationMinutes,\n      olderThan,\n    });\n\n    return resetCount;\n  }\n\n  /**\n   * Get failed events for retry or manual intervention\n   *\n   * @param limit - Maximum number of events to return\n   * @returns Array of failed inbox events\n   */\n  async getFailedEvents(limit: number = 100) {\n    return await this.repository.findByStatus(InboxStatus.FAILED, { limit });\n  }\n}\n","import {\n  InboxRepository,\n  InboxEvent,\n  InboxStatus,\n  CreateInboxEventParams,\n  FindInboxEventsOptions,\n} from './types';\n\n/**\n * In-memory implementation of InboxRepository\n *\n * Useful for:\n * - Testing without database dependencies\n * - Development environments\n * - Simple use cases where persistence isn't critical\n *\n * WARNING: Data is lost when the process restarts!\n * For production use, implement a database-backed repository.\n *\n * Deduplication Strategy:\n * - Primary: event_id (unique event identifier)\n * - Secondary: stream + stream_seq (JetStream sequence)\n *\n * @example\n * ```typescript\n * const repository = new MemoryInboxRepository();\n * const processor = new InboxProcessor(repository);\n * ```\n */\nexport class MemoryInboxRepository implements InboxRepository {\n  private events: Map<string, InboxEvent> = new Map();\n  private streamSeqIndex: Map<string, string> = new Map(); // \"stream:seq\" -> eventId\n\n  async findByEventId(eventId: string): Promise<InboxEvent | null> {\n    return this.events.get(eventId) || null;\n  }\n\n  async findByStreamSeq(stream: string, seq: number): Promise<InboxEvent | null> {\n    const key = `${stream}:${seq}`;\n    const eventId = this.streamSeqIndex.get(key);\n    if (!eventId) return null;\n\n    return this.events.get(eventId) || null;\n  }\n\n  async create(params: CreateInboxEventParams): Promise<InboxEvent> {\n    const now = new Date();\n    const event: InboxEvent = {\n      eventId: params.eventId,\n      subject: params.subject,\n      payload: params.payload,\n      headers: params.headers,\n      stream: params.stream,\n      streamSeq: params.streamSeq,\n      deliveries: params.deliveries,\n      status: InboxStatus.PROCESSING,\n      receivedAt: params.receivedAt || now,\n      createdAt: now,\n      updatedAt: now,\n    };\n\n    this.events.set(event.eventId, event);\n\n    // Create stream sequence index if applicable\n    if (event.stream && event.streamSeq !== undefined) {\n      const key = `${event.stream}:${event.streamSeq}`;\n      this.streamSeqIndex.set(key, event.eventId);\n    }\n\n    return event;\n  }\n\n  async findOrCreate(\n    params: CreateInboxEventParams\n  ): Promise<{ event: InboxEvent; alreadyExists: boolean }> {\n    // Try to find by event_id first\n    let existing = await this.findByEventId(params.eventId);\n    if (existing) {\n      return { event: existing, alreadyExists: true };\n    }\n\n    // Try to find by stream sequence if provided\n    if (params.stream && params.streamSeq !== undefined) {\n      existing = await this.findByStreamSeq(params.stream, params.streamSeq);\n      if (existing) {\n        return { event: existing, alreadyExists: true };\n      }\n    }\n\n    // Create new event\n    const event = await this.create(params);\n    return { event, alreadyExists: false };\n  }\n\n  async isProcessed(eventId: string): Promise<boolean> {\n    const event = this.events.get(eventId);\n    return event?.status === InboxStatus.PROCESSED && !!event.processedAt;\n  }\n\n  async markAsProcessed(eventId: string): Promise<void> {\n    const event = this.events.get(eventId);\n    if (!event) {\n      throw new Error(`Event not found: ${eventId}`);\n    }\n\n    event.status = InboxStatus.PROCESSED;\n    event.processedAt = new Date();\n    event.updatedAt = new Date();\n  }\n\n  async markAsFailed(eventId: string, error: string): Promise<void> {\n    const event = this.events.get(eventId);\n    if (!event) {\n      throw new Error(`Event not found: ${eventId}`);\n    }\n\n    event.status = InboxStatus.FAILED;\n    event.lastError = error;\n    event.updatedAt = new Date();\n  }\n\n  async findByStatus(\n    status: InboxStatus,\n    options: FindInboxEventsOptions = {}\n  ): Promise<InboxEvent[]> {\n    const { limit = 100 } = options;\n\n    const results = Array.from(this.events.values())\n      .filter((event) => {\n        if (event.status !== status) return false;\n        if (options.olderThan && event.receivedAt > options.olderThan) return false;\n        return true;\n      })\n      .sort((a, b) => a.receivedAt.getTime() - b.receivedAt.getTime())\n      .slice(0, limit);\n\n    return results;\n  }\n\n  async cleanup(olderThan: Date): Promise<number> {\n    let deletedCount = 0;\n\n    for (const [eventId, event] of this.events.entries()) {\n      if (\n        event.status === InboxStatus.PROCESSED &&\n        event.processedAt &&\n        event.processedAt < olderThan\n      ) {\n        // Remove from main index\n        this.events.delete(eventId);\n\n        // Remove from stream sequence index\n        if (event.stream && event.streamSeq !== undefined) {\n          const key = `${event.stream}:${event.streamSeq}`;\n          this.streamSeqIndex.delete(key);\n        }\n\n        deletedCount++;\n      }\n    }\n\n    return deletedCount;\n  }\n\n  async resetStaleProcessing(olderThan: Date): Promise<number> {\n    let resetCount = 0;\n\n    for (const event of this.events.values()) {\n      if (event.status === InboxStatus.PROCESSING && event.updatedAt < olderThan) {\n        event.status = InboxStatus.FAILED;\n        event.lastError = 'Reset from stale processing state';\n        event.updatedAt = new Date();\n        resetCount++;\n      }\n    }\n\n    return resetCount;\n  }\n\n  /**\n   * Clear all events (useful for testing)\n   */\n  clear(): void {\n    this.events.clear();\n    this.streamSeqIndex.clear();\n  }\n\n  /**\n   * Get all events (useful for testing/debugging)\n   */\n  getAll(): InboxEvent[] {\n    return Array.from(this.events.values());\n  }\n\n  /**\n   * Get event count by status (useful for monitoring)\n   */\n  getCountByStatus(): Record<InboxStatus, number> {\n    const counts: Record<InboxStatus, number> = {\n      [InboxStatus.PROCESSING]: 0,\n      [InboxStatus.PROCESSED]: 0,\n      [InboxStatus.FAILED]: 0,\n    };\n\n    for (const event of this.events.values()) {\n      counts[event.status]++;\n    }\n\n    return counts;\n  }\n}\n","/**\n * SQL schema definitions for Inbox pattern\n *\n * These schemas can be used with any SQL database (PostgreSQL, MySQL, SQLite, etc.)\n * Adapt the syntax as needed for your specific database.\n */\n\n/**\n * PostgreSQL schema for inbox events\n */\nexport const POSTGRES_INBOX_SCHEMA = `\nCREATE TABLE IF NOT EXISTS nats_inbox_events (\n  event_id VARCHAR(255) PRIMARY KEY,\n  subject VARCHAR(512) NOT NULL,\n  payload TEXT NOT NULL,\n  headers TEXT NOT NULL,\n  stream VARCHAR(255),\n  stream_seq BIGINT,\n  deliveries INTEGER NOT NULL DEFAULT 1,\n  status VARCHAR(50) NOT NULL DEFAULT 'processing',\n  last_error TEXT,\n  received_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  processed_at TIMESTAMP,\n  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n);\n\n-- Unique constraint on stream + sequence for JetStream deduplication\nCREATE UNIQUE INDEX IF NOT EXISTS idx_inbox_stream_seq\n  ON nats_inbox_events(stream, stream_seq)\n  WHERE stream IS NOT NULL AND stream_seq IS NOT NULL;\n\n-- Index for finding processed events\nCREATE INDEX IF NOT EXISTS idx_inbox_status_processed\n  ON nats_inbox_events(status, processed_at)\n  WHERE status = 'processed' AND processed_at IS NOT NULL;\n\n-- Index for finding failed events\nCREATE INDEX IF NOT EXISTS idx_inbox_status_failed\n  ON nats_inbox_events(status, received_at)\n  WHERE status = 'failed';\n\n-- Index for stale processing queries\nCREATE INDEX IF NOT EXISTS idx_inbox_stale_processing\n  ON nats_inbox_events(status, updated_at)\n  WHERE status = 'processing';\n`;\n\n/**\n * MySQL schema for inbox events\n */\nexport const MYSQL_INBOX_SCHEMA = `\nCREATE TABLE IF NOT EXISTS nats_inbox_events (\n  event_id VARCHAR(255) PRIMARY KEY,\n  subject VARCHAR(512) NOT NULL,\n  payload LONGTEXT NOT NULL,\n  headers TEXT NOT NULL,\n  stream VARCHAR(255),\n  stream_seq BIGINT,\n  deliveries INT NOT NULL DEFAULT 1,\n  status VARCHAR(50) NOT NULL DEFAULT 'processing',\n  last_error TEXT,\n  received_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  processed_at TIMESTAMP NULL,\n  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  UNIQUE KEY idx_inbox_stream_seq (stream, stream_seq),\n  INDEX idx_inbox_status_processed (status, processed_at),\n  INDEX idx_inbox_status_failed (status, received_at),\n  INDEX idx_inbox_stale_processing (status, updated_at)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n`;\n\n/**\n * SQLite schema for inbox events\n */\nexport const SQLITE_INBOX_SCHEMA = `\nCREATE TABLE IF NOT EXISTS nats_inbox_events (\n  event_id TEXT PRIMARY KEY,\n  subject TEXT NOT NULL,\n  payload TEXT NOT NULL,\n  headers TEXT NOT NULL,\n  stream TEXT,\n  stream_seq INTEGER,\n  deliveries INTEGER NOT NULL DEFAULT 1,\n  status TEXT NOT NULL DEFAULT 'processing',\n  last_error TEXT,\n  received_at TEXT NOT NULL DEFAULT (datetime('now')),\n  processed_at TEXT,\n  created_at TEXT NOT NULL DEFAULT (datetime('now')),\n  updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_inbox_stream_seq\n  ON nats_inbox_events(stream, stream_seq)\n  WHERE stream IS NOT NULL AND stream_seq IS NOT NULL;\n\nCREATE INDEX IF NOT EXISTS idx_inbox_status_processed\n  ON nats_inbox_events(status, processed_at);\n\nCREATE INDEX IF NOT EXISTS idx_inbox_status_failed\n  ON nats_inbox_events(status, received_at);\n\nCREATE INDEX IF NOT EXISTS idx_inbox_stale_processing\n  ON nats_inbox_events(status, updated_at);\n`;\n\n/**\n * TypeORM entity example\n */\nexport const TYPEORM_INBOX_ENTITY = `\nimport { Entity, Column, PrimaryColumn, CreateDateColumn, UpdateDateColumn, Index, Unique } from 'typeorm';\n\n@Entity('nats_inbox_events')\n@Unique('idx_inbox_stream_seq', ['stream', 'streamSeq'])\n@Index('idx_inbox_status_processed', ['status', 'processedAt'])\n@Index('idx_inbox_status_failed', ['status', 'receivedAt'])\nexport class InboxEvent {\n  @PrimaryColumn({ type: 'varchar', length: 255 })\n  eventId!: string;\n\n  @Column({ type: 'varchar', length: 512 })\n  subject!: string;\n\n  @Column({ type: 'text' })\n  payload!: string;\n\n  @Column({ type: 'text' })\n  headers!: string;\n\n  @Column({ type: 'varchar', length: 255, nullable: true })\n  stream?: string;\n\n  @Column({ type: 'bigint', nullable: true })\n  streamSeq?: number;\n\n  @Column({ type: 'int', default: 1 })\n  deliveries!: number;\n\n  @Column({ type: 'varchar', length: 50, default: 'processing' })\n  status!: string;\n\n  @Column({ type: 'text', nullable: true })\n  lastError?: string;\n\n  @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })\n  receivedAt!: Date;\n\n  @Column({ type: 'timestamp', nullable: true })\n  processedAt?: Date;\n\n  @CreateDateColumn()\n  createdAt!: Date;\n\n  @UpdateDateColumn()\n  updatedAt!: Date;\n}\n`;\n\n/**\n * Prisma schema example\n */\nexport const PRISMA_INBOX_SCHEMA = `\nmodel NatsInboxEvent {\n  eventId     String    @id @map(\"event_id\") @db.VarChar(255)\n  subject     String    @db.VarChar(512)\n  payload     String    @db.Text\n  headers     String    @db.Text\n  stream      String?   @db.VarChar(255)\n  streamSeq   BigInt?   @map(\"stream_seq\")\n  deliveries  Int       @default(1)\n  status      String    @default(\"processing\") @db.VarChar(50)\n  lastError   String?   @map(\"last_error\") @db.Text\n  receivedAt  DateTime  @default(now()) @map(\"received_at\")\n  processedAt DateTime? @map(\"processed_at\")\n  createdAt   DateTime  @default(now()) @map(\"created_at\")\n  updatedAt   DateTime  @updatedAt @map(\"updated_at\")\n\n  @@unique([stream, streamSeq], map: \"idx_inbox_stream_seq\")\n  @@index([status, processedAt], map: \"idx_inbox_status_processed\")\n  @@index([status, receivedAt], map: \"idx_inbox_status_failed\")\n  @@map(\"nats_inbox_events\")\n}\n`;\n\n/**\n * Knex.js migration example\n */\nexport const KNEX_INBOX_MIGRATION = `\nexport async function up(knex: Knex): Promise<void> {\n  await knex.schema.createTable('nats_inbox_events', (table) => {\n    table.string('event_id', 255).primary();\n    table.string('subject', 512).notNullable();\n    table.text('payload').notNullable();\n    table.text('headers').notNullable();\n    table.string('stream', 255);\n    table.bigInteger('stream_seq');\n    table.integer('deliveries').notNullable().defaultTo(1);\n    table.string('status', 50).notNullable().defaultTo('processing');\n    table.text('last_error');\n    table.timestamp('received_at').notNullable().defaultTo(knex.fn.now());\n    table.timestamp('processed_at');\n    table.timestamps(true, true);\n\n    table.unique(['stream', 'stream_seq'], { indexName: 'idx_inbox_stream_seq' });\n    table.index(['status', 'processed_at'], 'idx_inbox_status_processed');\n    table.index(['status', 'received_at'], 'idx_inbox_status_failed');\n    table.index(['status', 'updated_at'], 'idx_inbox_stale_processing');\n  });\n}\n\nexport async function down(knex: Knex): Promise<void> {\n  await knex.schema.dropTable('nats_inbox_events');\n}\n`;\n"],"mappings":"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","names":["ConfigurationError","Consumer","ValidationError","ConfigurationError","CircuitState","import_zod","ValidationError","import_nats","natsHeaders","import_nats","import_nats","import_nats","natsHeaders","subscriber","subscriber","Consumer","subscriber","ErrorAction","subscriber","Consumer","subscriber","OutboxStatus","InboxStatus"]}