@drarzter/kafka-client 0.5.6 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -17
- package/dist/{chunk-6B72MJPU.mjs → chunk-TD2AE774.mjs} +198 -127
- package/dist/chunk-TD2AE774.mjs.map +1 -0
- package/dist/core.d.mts +7 -9
- package/dist/core.d.ts +7 -9
- package/dist/core.js +197 -126
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/index.d.mts +3 -13
- package/dist/index.d.ts +3 -13
- package/dist/index.js +198 -135
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -10
- package/dist/index.mjs.map +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/otel.d.ts +1 -1
- package/dist/otel.js +9 -4
- package/dist/otel.js.map +1 -1
- package/dist/otel.mjs +9 -4
- package/dist/otel.mjs.map +1 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{envelope-LeO5e3ob.d.mts → types-DwERZ6ql.d.mts} +96 -83
- package/dist/{envelope-LeO5e3ob.d.ts → types-DwERZ6ql.d.ts} +96 -83
- package/package.json +1 -1
- package/dist/chunk-6B72MJPU.mjs.map +0 -1
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core.ts","../src/client/kafka.client/index.ts","../src/client/message/envelope.ts","../src/client/kafka.client/producer-ops.ts","../src/client/kafka.client/consumer-ops.ts","../src/client/errors.ts","../src/client/consumer/pipeline.ts","../src/client/kafka.client/message-handler.ts","../src/client/consumer/subscribe-retry.ts","../src/client/kafka.client/retry-topic.ts","../src/client/message/topic.ts"],"sourcesContent":["export * from \"./client/kafka.client\";\nexport * from \"./client/message/topic\";\nexport * from \"./client/errors\";\nexport * from \"./client/message/envelope\";\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Kafka = KafkaJS.Kafka;\ntype Producer = KafkaJS.Producer;\ntype Consumer = KafkaJS.Consumer;\ntype Admin = KafkaJS.Admin;\nconst { Kafka: KafkaClass, logLevel: KafkaLogLevel } = KafkaJS;\nimport { TopicDescriptor, SchemaLike } from \"../message/topic\";\nimport type { EventEnvelope } from \"../message/envelope\";\nimport type {\n ClientId,\n GroupId,\n SendOptions,\n BatchMessageItem,\n ConsumerOptions,\n ConsumerHandle,\n TransactionContext,\n TopicMapConstraint,\n IKafkaClient,\n KafkaClientOptions,\n KafkaInstrumentation,\n KafkaLogger,\n BatchMeta,\n} from \"../types\";\n\n// Re-export all types so existing `import { ... } from './kafka.client'` keeps working\nexport * from \"../types\";\n\nimport {\n buildSendPayload,\n resolveTopicName,\n type BuildSendPayloadDeps,\n} from \"./producer-ops\";\nimport {\n getOrCreateConsumer,\n buildSchemaMap,\n type ConsumerOpsDeps,\n} from \"./consumer-ops\";\nimport { handleEachMessage, handleEachBatch } from \"./message-handler\";\nimport type { MessageHandlerDeps } from \"./message-handler\";\nimport { startRetryTopicConsumers } from \"./retry-topic\";\nimport { subscribeWithRetry } from \"../consumer/subscribe-retry\";\nimport { toError } from \"../consumer/pipeline\";\n\n/**\n * Type-safe Kafka client.\n * Wraps @confluentinc/kafka-javascript (librdkafka) with JSON serialization,\n * retries, DLQ, transactions, and interceptors.\n *\n * @typeParam T - Topic-to-message type mapping for compile-time safety.\n */\nexport class KafkaClient<\n T extends TopicMapConstraint<T>,\n> implements IKafkaClient<T> {\n private readonly kafka: Kafka;\n private readonly producer: Producer;\n private txProducer: Producer | undefined;\n private readonly consumers = new Map<string, Consumer>();\n private readonly admin: Admin;\n private readonly logger: KafkaLogger;\n private readonly autoCreateTopicsEnabled: boolean;\n private readonly strictSchemasEnabled: boolean;\n private readonly numPartitions: number;\n private readonly ensuredTopics = new Set<string>();\n private readonly defaultGroupId: string;\n private readonly schemaRegistry = new Map<string, SchemaLike>();\n private readonly runningConsumers = new Map<\n string,\n \"eachMessage\" | \"eachBatch\"\n >();\n private readonly consumerCreationOptions = new Map<\n string,\n { fromBeginning: boolean; autoCommit: boolean }\n >();\n private readonly instrumentation: KafkaInstrumentation[];\n private readonly onMessageLost: KafkaClientOptions[\"onMessageLost\"];\n private readonly onRebalance: KafkaClientOptions[\"onRebalance\"];\n\n private isAdminConnected = false;\n public readonly clientId: ClientId;\n\n constructor(\n clientId: ClientId,\n groupId: GroupId,\n brokers: string[],\n options?: KafkaClientOptions,\n ) {\n this.clientId = clientId;\n this.defaultGroupId = groupId;\n this.logger = options?.logger ?? {\n log: (msg) => console.log(`[KafkaClient:${clientId}] ${msg}`),\n warn: (msg, ...args) =>\n console.warn(`[KafkaClient:${clientId}] ${msg}`, ...args),\n error: (msg, ...args) =>\n console.error(`[KafkaClient:${clientId}] ${msg}`, ...args),\n };\n this.autoCreateTopicsEnabled = options?.autoCreateTopics ?? false;\n this.strictSchemasEnabled = options?.strictSchemas ?? true;\n this.numPartitions = options?.numPartitions ?? 1;\n this.instrumentation = options?.instrumentation ?? [];\n this.onMessageLost = options?.onMessageLost;\n this.onRebalance = options?.onRebalance;\n\n this.kafka = new KafkaClass({\n kafkaJS: {\n clientId: this.clientId,\n brokers,\n logLevel: KafkaLogLevel.ERROR,\n },\n });\n this.producer = this.kafka.producer({\n kafkaJS: {\n acks: -1,\n },\n });\n this.admin = this.kafka.admin();\n }\n\n // ── Send ─────────────────────────────────────────────────────────\n\n /** Send a single typed message. Accepts a topic key or a TopicDescriptor. */\n public async sendMessage<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(descriptor: D, message: D[\"__type\"], options?: SendOptions): Promise<void>;\n public async sendMessage<K extends keyof T>(\n topic: K,\n message: T[K],\n options?: SendOptions,\n ): Promise<void>;\n public async sendMessage(\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ): Promise<void> {\n const payload = await this.preparePayload(topicOrDesc, [\n {\n value: message,\n key: options.key,\n headers: options.headers,\n correlationId: options.correlationId,\n schemaVersion: options.schemaVersion,\n eventId: options.eventId,\n },\n ]);\n await this.producer.send(payload);\n this.notifyAfterSend(payload.topic, payload.messages.length);\n }\n\n /** Send multiple typed messages in one call. Accepts a topic key or a TopicDescriptor. */\n public async sendBatch<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n descriptor: D,\n messages: Array<BatchMessageItem<D[\"__type\"]>>,\n ): Promise<void>;\n public async sendBatch<K extends keyof T>(\n topic: K,\n messages: Array<BatchMessageItem<T[K]>>,\n ): Promise<void>;\n public async sendBatch(\n topicOrDesc: any,\n messages: Array<BatchMessageItem<any>>,\n ): Promise<void> {\n const payload = await this.preparePayload(topicOrDesc, messages);\n await this.producer.send(payload);\n this.notifyAfterSend(payload.topic, payload.messages.length);\n }\n\n /** Execute multiple sends atomically. Commits on success, aborts on error. */\n public async transaction(\n fn: (ctx: TransactionContext<T>) => Promise<void>,\n ): Promise<void> {\n if (!this.txProducer) {\n // transactionalId must be unique per producer instance across the cluster.\n // Two KafkaClient instances sharing the same clientId will share this id,\n // causing Kafka to fence one of the producers. Use distinct clientIds when\n // running multiple instances of the same service.\n this.txProducer = this.kafka.producer({\n kafkaJS: {\n acks: -1,\n idempotent: true,\n transactionalId: `${this.clientId}-tx`,\n maxInFlightRequests: 1,\n },\n });\n await this.txProducer.connect();\n }\n const tx = await this.txProducer.transaction();\n try {\n const ctx: TransactionContext<T> = {\n send: async (\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ) => {\n const payload = await this.preparePayload(topicOrDesc, [\n {\n value: message,\n key: options.key,\n headers: options.headers,\n correlationId: options.correlationId,\n schemaVersion: options.schemaVersion,\n eventId: options.eventId,\n },\n ]);\n await tx.send(payload);\n },\n sendBatch: async (\n topicOrDesc: any,\n messages: BatchMessageItem<any>[],\n ) => {\n await tx.send(await this.preparePayload(topicOrDesc, messages));\n },\n };\n await fn(ctx);\n await tx.commit();\n } catch (error) {\n try {\n await tx.abort();\n } catch (abortError) {\n this.logger.error(\n \"Failed to abort transaction:\",\n toError(abortError).message,\n );\n }\n throw error;\n }\n }\n\n // ── Producer lifecycle ───────────────────────────────────────────\n\n /** Connect the idempotent producer. Called automatically by `KafkaModule.register()`. */\n public async connectProducer(): Promise<void> {\n await this.producer.connect();\n this.logger.log(\"Producer connected\");\n }\n\n public async disconnectProducer(): Promise<void> {\n await this.producer.disconnect();\n this.logger.log(\"Producer disconnected\");\n }\n\n // ── Consumer: eachMessage ────────────────────────────────────────\n\n /** Subscribe to topics and start consuming messages with the given handler. */\n public async startConsumer<K extends Array<keyof T>>(\n topics: K,\n handleMessage: (envelope: EventEnvelope<T[K[number]]>) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startConsumer<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n topics: D[],\n handleMessage: (envelope: EventEnvelope<D[\"__type\"]>) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startConsumer(\n topics: any[],\n handleMessage: (envelope: EventEnvelope<any>) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<ConsumerHandle> {\n if (options.retryTopics && !options.retry) {\n throw new Error(\n \"retryTopics requires retry to be configured — set retry.maxRetries to enable the retry topic chain\",\n );\n }\n\n const { consumer, schemaMap, topicNames, gid, dlq, interceptors, retry } =\n await this.setupConsumer(topics, \"eachMessage\", options);\n\n const deps = this.messageDeps;\n const timeoutMs = options.handlerTimeoutMs;\n\n await consumer.run({\n eachMessage: (payload) =>\n handleEachMessage(\n payload,\n {\n schemaMap,\n handleMessage,\n interceptors,\n dlq,\n retry,\n retryTopics: options.retryTopics,\n timeoutMs,\n wrapWithTimeout: this.wrapWithTimeoutWarning.bind(this),\n },\n deps,\n ),\n });\n\n this.runningConsumers.set(gid, \"eachMessage\");\n\n if (options.retryTopics && retry) {\n await startRetryTopicConsumers(\n topicNames,\n gid,\n handleMessage,\n retry,\n dlq,\n interceptors,\n schemaMap,\n this.retryTopicDeps,\n );\n }\n\n return { groupId: gid, stop: () => this.stopConsumer(gid) };\n }\n\n // ── Consumer: eachBatch ──────────────────────────────────────────\n\n /** Subscribe to topics and consume messages in batches. */\n public async startBatchConsumer<K extends Array<keyof T>>(\n topics: K,\n handleBatch: (\n envelopes: EventEnvelope<T[K[number]]>[],\n meta: BatchMeta,\n ) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startBatchConsumer<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n topics: D[],\n handleBatch: (\n envelopes: EventEnvelope<D[\"__type\"]>[],\n meta: BatchMeta,\n ) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startBatchConsumer(\n topics: any[],\n handleBatch: (\n envelopes: EventEnvelope<any>[],\n meta: BatchMeta,\n ) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<ConsumerHandle> {\n const { consumer, schemaMap, gid, dlq, interceptors, retry } =\n await this.setupConsumer(topics, \"eachBatch\", options);\n\n const deps = this.messageDeps;\n const timeoutMs = options.handlerTimeoutMs;\n\n await consumer.run({\n eachBatch: (payload) =>\n handleEachBatch(\n payload,\n {\n schemaMap,\n handleBatch,\n interceptors,\n dlq,\n retry,\n timeoutMs,\n wrapWithTimeout: this.wrapWithTimeoutWarning.bind(this),\n },\n deps,\n ),\n });\n\n this.runningConsumers.set(gid, \"eachBatch\");\n\n return { groupId: gid, stop: () => this.stopConsumer(gid) };\n }\n\n // ── Consumer lifecycle ───────────────────────────────────────────\n\n public async stopConsumer(groupId?: string): Promise<void> {\n if (groupId !== undefined) {\n const consumer = this.consumers.get(groupId);\n if (!consumer) {\n this.logger.warn(\n `stopConsumer: no active consumer for group \"${groupId}\"`,\n );\n return;\n }\n await consumer.disconnect().catch(() => {});\n this.consumers.delete(groupId);\n this.runningConsumers.delete(groupId);\n this.consumerCreationOptions.delete(groupId);\n this.logger.log(`Consumer disconnected: group \"${groupId}\"`);\n } else {\n const tasks = Array.from(this.consumers.values()).map((c) =>\n c.disconnect().catch(() => {}),\n );\n await Promise.allSettled(tasks);\n this.consumers.clear();\n this.runningConsumers.clear();\n this.consumerCreationOptions.clear();\n this.logger.log(\"All consumers disconnected\");\n }\n }\n\n /**\n * Query consumer group lag per partition.\n * Lag = broker high-watermark − last committed offset.\n * A committed offset of -1 (nothing committed yet) counts as full lag.\n */\n public async getConsumerLag(\n groupId?: string,\n ): Promise<Array<{ topic: string; partition: number; lag: number }>> {\n const gid = groupId ?? this.defaultGroupId;\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n\n const committedByTopic = await this.admin.fetchOffsets({ groupId: gid });\n const result: Array<{ topic: string; partition: number; lag: number }> = [];\n\n for (const { topic, partitions } of committedByTopic) {\n const brokerOffsets = await this.admin.fetchTopicOffsets(topic);\n\n for (const { partition, offset } of partitions) {\n const broker = brokerOffsets.find((o) => o.partition === partition);\n if (!broker) continue;\n\n const committed = parseInt(offset, 10);\n const high = parseInt(broker.high, 10);\n // committed === -1 means the group has never committed for this partition\n const lag = committed === -1 ? high : Math.max(0, high - committed);\n result.push({ topic, partition, lag });\n }\n }\n\n return result;\n }\n\n /** Check broker connectivity and return status, clientId, and available topics. */\n public async checkStatus(): Promise<{\n status: \"up\";\n clientId: string;\n topics: string[];\n }> {\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n const topics = await this.admin.listTopics();\n return { status: \"up\", clientId: this.clientId, topics };\n }\n\n public getClientId(): ClientId {\n return this.clientId;\n }\n\n /** Gracefully disconnect producer, all consumers, and admin. */\n public async disconnect(): Promise<void> {\n const tasks: Promise<void>[] = [this.producer.disconnect()];\n if (this.txProducer) {\n tasks.push(this.txProducer.disconnect());\n this.txProducer = undefined;\n }\n for (const consumer of this.consumers.values()) {\n tasks.push(consumer.disconnect());\n }\n if (this.isAdminConnected) {\n tasks.push(this.admin.disconnect());\n this.isAdminConnected = false;\n }\n await Promise.allSettled(tasks);\n this.consumers.clear();\n this.runningConsumers.clear();\n this.consumerCreationOptions.clear();\n this.logger.log(\"All connections closed\");\n }\n\n // ── Private helpers ──────────────────────────────────────────────\n\n private async preparePayload(\n topicOrDesc: any,\n messages: Array<BatchMessageItem<any>>,\n ) {\n const payload = await buildSendPayload(\n topicOrDesc,\n messages,\n this.producerOpsDeps,\n );\n await this.ensureTopic(payload.topic);\n return payload;\n }\n\n // afterSend is called once per message — symmetric with beforeSend in buildSendPayload.\n private notifyAfterSend(topic: string, count: number): void {\n for (let i = 0; i < count; i++) {\n for (const inst of this.instrumentation) {\n inst.afterSend?.(topic);\n }\n }\n }\n\n /**\n * Start a timer that logs a warning if `fn` hasn't resolved within `timeoutMs`.\n * The handler itself is not cancelled — the warning is diagnostic only.\n */\n private wrapWithTimeoutWarning<R>(\n fn: () => Promise<R>,\n timeoutMs: number,\n topic: string,\n ): Promise<R> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const promise = fn().finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n timer = setTimeout(() => {\n this.logger.warn(\n `Handler for topic \"${topic}\" has not resolved after ${timeoutMs}ms — possible stuck handler`,\n );\n }, timeoutMs);\n return promise;\n }\n\n private async ensureTopic(topic: string): Promise<void> {\n if (!this.autoCreateTopicsEnabled || this.ensuredTopics.has(topic)) return;\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n await this.admin.createTopics({\n topics: [{ topic, numPartitions: this.numPartitions }],\n });\n this.ensuredTopics.add(topic);\n }\n\n /** Shared consumer setup: groupId check, schema map, connect, subscribe. */\n private async setupConsumer(\n topics: any[],\n mode: \"eachMessage\" | \"eachBatch\",\n options: ConsumerOptions<T>,\n ) {\n const {\n groupId: optGroupId,\n fromBeginning = false,\n retry,\n dlq = false,\n interceptors = [],\n schemas: optionSchemas,\n } = options;\n\n const gid = optGroupId || this.defaultGroupId;\n const existingMode = this.runningConsumers.get(gid);\n const oppositeMode = mode === \"eachMessage\" ? \"eachBatch\" : \"eachMessage\";\n if (existingMode === oppositeMode) {\n throw new Error(\n `Cannot use ${mode} on consumer group \"${gid}\" — it is already running with ${oppositeMode}. ` +\n `Use a different groupId for this consumer.`,\n );\n }\n\n const consumer = getOrCreateConsumer(\n gid,\n fromBeginning,\n options.autoCommit ?? true,\n this.consumerOpsDeps,\n );\n const schemaMap = buildSchemaMap(\n topics,\n this.schemaRegistry,\n optionSchemas,\n );\n\n const topicNames = (topics as any[]).map((t: any) => resolveTopicName(t));\n\n // Ensure topics exist before subscribing — librdkafka errors on unknown topics\n for (const t of topicNames) {\n await this.ensureTopic(t);\n }\n if (dlq) {\n for (const t of topicNames) {\n await this.ensureTopic(`${t}.dlq`);\n }\n }\n\n await consumer.connect();\n await subscribeWithRetry(\n consumer,\n topicNames,\n this.logger,\n options.subscribeRetry,\n );\n\n this.logger.log(\n `${mode === \"eachBatch\" ? \"Batch consumer\" : \"Consumer\"} subscribed to topics: ${topicNames.join(\", \")}`,\n );\n\n return { consumer, schemaMap, topicNames, gid, dlq, interceptors, retry };\n }\n\n // ── Deps object getters ──────────────────────────────────────────\n\n private get producerOpsDeps(): BuildSendPayloadDeps {\n return {\n schemaRegistry: this.schemaRegistry,\n strictSchemasEnabled: this.strictSchemasEnabled,\n instrumentation: this.instrumentation,\n };\n }\n\n private get consumerOpsDeps(): ConsumerOpsDeps {\n return {\n consumers: this.consumers,\n consumerCreationOptions: this.consumerCreationOptions,\n kafka: this.kafka,\n onRebalance: this.onRebalance,\n logger: this.logger,\n };\n }\n\n private get messageDeps(): MessageHandlerDeps {\n return {\n logger: this.logger,\n producer: this.producer,\n instrumentation: this.instrumentation,\n onMessageLost: this.onMessageLost,\n };\n }\n\n private get retryTopicDeps() {\n return {\n logger: this.logger,\n producer: this.producer,\n instrumentation: this.instrumentation,\n onMessageLost: this.onMessageLost,\n ensureTopic: (t: string) => this.ensureTopic(t),\n getOrCreateConsumer: (gid: string, fb: boolean, ac: boolean) =>\n getOrCreateConsumer(gid, fb, ac, this.consumerOpsDeps),\n runningConsumers: this.runningConsumers,\n };\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { randomUUID } from \"node:crypto\";\nimport type { MessageHeaders } from \"../types\";\n\n// ── Header keys ──────────────────────────────────────────────────────\n\nexport const HEADER_EVENT_ID = \"x-event-id\";\nexport const HEADER_CORRELATION_ID = \"x-correlation-id\";\nexport const HEADER_TIMESTAMP = \"x-timestamp\";\nexport const HEADER_SCHEMA_VERSION = \"x-schema-version\";\nexport const HEADER_TRACEPARENT = \"traceparent\";\n\n// ── EventEnvelope ────────────────────────────────────────────────────\n\n/**\n * Typed wrapper combining a parsed message payload with Kafka metadata\n * and envelope headers.\n *\n * On **send**, the library auto-generates envelope headers\n * (`x-event-id`, `x-correlation-id`, `x-timestamp`, `x-schema-version`).\n *\n * On **consume**, the library extracts those headers and assembles\n * an `EventEnvelope` that is passed to the handler.\n */\nexport interface EventEnvelope<T> {\n /** Deserialized + validated message body. */\n payload: T;\n /** Topic the message was produced to / consumed from. */\n topic: string;\n /** Kafka partition (consume-side only, `-1` on send). */\n partition: number;\n /** Kafka offset (consume-side only, empty string on send). */\n offset: string;\n /** ISO-8601 timestamp set by the producer. */\n timestamp: string;\n /** Unique ID for this event (UUID v4). */\n eventId: string;\n /** Correlation ID — auto-propagated via AsyncLocalStorage. */\n correlationId: string;\n /** Schema version of the payload. */\n schemaVersion: number;\n /** W3C Trace Context `traceparent` header (set by OTel instrumentation). */\n traceparent?: string;\n /** All decoded Kafka headers for extensibility. */\n headers: MessageHeaders;\n}\n\n// ── AsyncLocalStorage context ────────────────────────────────────────\n\ninterface EnvelopeCtx {\n correlationId: string;\n traceparent?: string;\n}\n\nconst envelopeStorage = new AsyncLocalStorage<EnvelopeCtx>();\n\n/** Read the current envelope context (correlationId / traceparent) from ALS. */\nexport function getEnvelopeContext(): EnvelopeCtx | undefined {\n return envelopeStorage.getStore();\n}\n\n/** Execute `fn` inside an envelope context so nested sends inherit correlationId. */\nexport function runWithEnvelopeContext<R>(ctx: EnvelopeCtx, fn: () => R): R {\n return envelopeStorage.run(ctx, fn);\n}\n\n// ── Header helpers ───────────────────────────────────────────────────\n\n/** Options accepted by `buildEnvelopeHeaders`. */\nexport interface EnvelopeHeaderOptions {\n correlationId?: string;\n schemaVersion?: number;\n eventId?: string;\n headers?: MessageHeaders;\n}\n\n/**\n * Generate envelope headers for the send path.\n *\n * Priority for `correlationId`:\n * explicit option → ALS context → new UUID.\n */\nexport function buildEnvelopeHeaders(\n options: EnvelopeHeaderOptions = {},\n): MessageHeaders {\n const ctx = getEnvelopeContext();\n\n const correlationId =\n options.correlationId ?? ctx?.correlationId ?? randomUUID();\n const eventId = options.eventId ?? randomUUID();\n const timestamp = new Date().toISOString();\n const schemaVersion = String(options.schemaVersion ?? 1);\n\n const envelope: MessageHeaders = {\n [HEADER_EVENT_ID]: eventId,\n [HEADER_CORRELATION_ID]: correlationId,\n [HEADER_TIMESTAMP]: timestamp,\n [HEADER_SCHEMA_VERSION]: schemaVersion,\n };\n\n // Propagate traceparent from ALS if present (OTel may override via instrumentation)\n if (ctx?.traceparent) {\n envelope[HEADER_TRACEPARENT] = ctx.traceparent;\n }\n\n // User-provided headers win on conflict\n return { ...envelope, ...options.headers };\n}\n\n/**\n * Decode kafkajs headers (`Record<string, Buffer | string | undefined>`)\n * into plain `Record<string, string>`.\n */\nexport function decodeHeaders(\n raw:\n | Record<string, Buffer | string | (Buffer | string)[] | undefined>\n | undefined,\n): MessageHeaders {\n if (!raw) return {};\n const result: MessageHeaders = {};\n for (const [key, value] of Object.entries(raw)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n result[key] = value\n .map((v) => (Buffer.isBuffer(v) ? v.toString() : v))\n .join(\",\");\n } else {\n result[key] = Buffer.isBuffer(value) ? value.toString() : value;\n }\n }\n return result;\n}\n\n/**\n * Build an `EventEnvelope` from a consumed kafkajs message.\n * Tolerates missing envelope headers — generates defaults so messages\n * from non-envelope producers still work.\n */\nexport function extractEnvelope<T>(\n payload: T,\n headers: MessageHeaders,\n topic: string,\n partition: number,\n offset: string,\n): EventEnvelope<T> {\n return {\n payload,\n topic,\n partition,\n offset,\n eventId: headers[HEADER_EVENT_ID] ?? randomUUID(),\n correlationId: headers[HEADER_CORRELATION_ID] ?? randomUUID(),\n timestamp: headers[HEADER_TIMESTAMP] ?? new Date().toISOString(),\n schemaVersion: Number(headers[HEADER_SCHEMA_VERSION] ?? 1),\n traceparent: headers[HEADER_TRACEPARENT],\n headers,\n };\n}\n","import { buildEnvelopeHeaders } from \"../message/envelope\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n BatchMessageItem,\n KafkaInstrumentation,\n MessageHeaders,\n} from \"../types\";\n\nexport function resolveTopicName(topicOrDescriptor: unknown): string {\n if (typeof topicOrDescriptor === \"string\") return topicOrDescriptor;\n if (\n topicOrDescriptor &&\n typeof topicOrDescriptor === \"object\" &&\n \"__topic\" in topicOrDescriptor\n ) {\n return (topicOrDescriptor as { __topic: string }).__topic;\n }\n return String(topicOrDescriptor);\n}\n\nexport function registerSchema(\n topicOrDesc: any,\n schemaRegistry: Map<string, SchemaLike>,\n): void {\n if (topicOrDesc?.__schema) {\n const topic = resolveTopicName(topicOrDesc);\n schemaRegistry.set(topic, topicOrDesc.__schema);\n }\n}\n\nexport async function validateMessage(\n topicOrDesc: any,\n message: any,\n deps: {\n schemaRegistry: Map<string, SchemaLike>;\n strictSchemasEnabled: boolean;\n },\n): Promise<any> {\n if (topicOrDesc?.__schema) {\n return await topicOrDesc.__schema.parse(message);\n }\n if (deps.strictSchemasEnabled && typeof topicOrDesc === \"string\") {\n const schema = deps.schemaRegistry.get(topicOrDesc);\n if (schema) return await schema.parse(message);\n }\n return message;\n}\n\nexport type BuildSendPayloadDeps = {\n schemaRegistry: Map<string, SchemaLike>;\n strictSchemasEnabled: boolean;\n instrumentation: KafkaInstrumentation[];\n};\n\nexport async function buildSendPayload(\n topicOrDesc: any,\n messages: Array<BatchMessageItem<any>>,\n deps: BuildSendPayloadDeps,\n): Promise<{\n topic: string;\n messages: Array<{\n value: string;\n key: string | null;\n headers: MessageHeaders;\n }>;\n}> {\n registerSchema(topicOrDesc, deps.schemaRegistry);\n const topic = resolveTopicName(topicOrDesc);\n const builtMessages = await Promise.all(\n messages.map(async (m) => {\n const envelopeHeaders = buildEnvelopeHeaders({\n correlationId: m.correlationId,\n schemaVersion: m.schemaVersion,\n eventId: m.eventId,\n headers: m.headers,\n });\n\n // beforeSend: let instrumentation mutate headers (e.g. OTel injects traceparent)\n for (const inst of deps.instrumentation) {\n inst.beforeSend?.(topic, envelopeHeaders);\n }\n\n return {\n value: JSON.stringify(\n await validateMessage(topicOrDesc, m.value, deps),\n ),\n key: m.key ?? null,\n headers: envelopeHeaders,\n };\n }),\n );\n return { topic, messages: builtMessages };\n}\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Consumer = KafkaJS.Consumer;\ntype Kafka = KafkaJS.Kafka;\nimport type { SchemaLike } from \"../message/topic\";\nimport type { KafkaClientOptions, KafkaLogger } from \"../types\";\nimport { resolveTopicName } from \"./producer-ops\";\n\nexport type ConsumerOpsDeps = {\n consumers: Map<string, Consumer>;\n consumerCreationOptions: Map<\n string,\n { fromBeginning: boolean; autoCommit: boolean }\n >;\n kafka: Kafka;\n onRebalance: KafkaClientOptions[\"onRebalance\"];\n logger: KafkaLogger;\n};\n\nexport function getOrCreateConsumer(\n groupId: string,\n fromBeginning: boolean,\n autoCommit: boolean,\n deps: ConsumerOpsDeps,\n): Consumer {\n const { consumers, consumerCreationOptions, kafka, onRebalance, logger } =\n deps;\n\n if (consumers.has(groupId)) {\n const prev = consumerCreationOptions.get(groupId)!;\n if (\n prev.fromBeginning !== fromBeginning ||\n prev.autoCommit !== autoCommit\n ) {\n logger.warn(\n `Consumer group \"${groupId}\" already exists with options ` +\n `(fromBeginning: ${prev.fromBeginning}, autoCommit: ${prev.autoCommit}) — ` +\n `new options (fromBeginning: ${fromBeginning}, autoCommit: ${autoCommit}) ignored. ` +\n `Use a different groupId to apply different options.`,\n );\n }\n return consumers.get(groupId)!;\n }\n\n consumerCreationOptions.set(groupId, { fromBeginning, autoCommit });\n\n const config: Parameters<typeof kafka.consumer>[0] = {\n kafkaJS: { groupId, fromBeginning, autoCommit },\n };\n\n if (onRebalance) {\n const cb = onRebalance;\n // rebalance_cb is called by librdkafka on every partition assign/revoke.\n // err.code -175 = ERR__ASSIGN_PARTITIONS, -174 = ERR__REVOKE_PARTITIONS.\n // The library handles the actual assign/unassign in its finally block regardless\n // of what this callback does, so we only need it for the side-effect notification.\n (config as any)[\"rebalance_cb\"] = (err: any, assignment: any[]) => {\n const type = err.code === -175 ? \"assign\" : \"revoke\";\n try {\n cb(\n type,\n assignment.map((p) => ({ topic: p.topic, partition: p.partition })),\n );\n } catch (e) {\n logger.warn(`onRebalance callback threw: ${(e as Error).message}`);\n }\n };\n }\n\n const consumer = kafka.consumer(config);\n consumers.set(groupId, consumer);\n return consumer;\n}\n\nexport function buildSchemaMap(\n topics: any[],\n schemaRegistry: Map<string, SchemaLike>,\n optionSchemas?: Map<string, SchemaLike>,\n): Map<string, SchemaLike> {\n const schemaMap = new Map<string, SchemaLike>();\n for (const t of topics) {\n if (t?.__schema) {\n const name = resolveTopicName(t);\n schemaMap.set(name, t.__schema);\n schemaRegistry.set(name, t.__schema);\n }\n }\n if (optionSchemas) {\n for (const [k, v] of optionSchemas) {\n schemaMap.set(k, v);\n schemaRegistry.set(k, v);\n }\n }\n return schemaMap;\n}\n","/** Error thrown when a consumer message handler fails. */\nexport class KafkaProcessingError extends Error {\n declare readonly cause?: Error;\n\n constructor(\n message: string,\n public readonly topic: string,\n public readonly originalMessage: unknown,\n options?: { cause?: Error },\n ) {\n super(message, options);\n this.name = \"KafkaProcessingError\";\n if (options?.cause) this.cause = options.cause;\n }\n}\n\n/** Error thrown when schema validation fails on send or consume. */\nexport class KafkaValidationError extends Error {\n declare readonly cause?: Error;\n\n constructor(\n public readonly topic: string,\n public readonly originalMessage: unknown,\n options?: { cause?: Error },\n ) {\n super(`Schema validation failed for topic \"${topic}\"`, options);\n this.name = \"KafkaValidationError\";\n if (options?.cause) this.cause = options.cause;\n }\n}\n\n/** Error thrown when all retry attempts are exhausted for a message. */\nexport class KafkaRetryExhaustedError extends KafkaProcessingError {\n constructor(\n topic: string,\n originalMessage: unknown,\n public readonly attempts: number,\n options?: { cause?: Error },\n ) {\n super(\n `Message processing failed after ${attempts} attempts on topic \"${topic}\"`,\n topic,\n originalMessage,\n options,\n );\n this.name = \"KafkaRetryExhaustedError\";\n }\n}\n","import type { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Producer = KafkaJS.Producer;\nimport type { EventEnvelope } from \"../message/envelope\";\nimport { extractEnvelope } from \"../message/envelope\";\nimport { KafkaRetryExhaustedError, KafkaValidationError } from \"../errors\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n ConsumerInterceptor,\n KafkaInstrumentation,\n KafkaLogger,\n MessageHeaders,\n MessageLostContext,\n RetryOptions,\n TopicMapConstraint,\n} from \"../types\";\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nexport function toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ── JSON parsing ────────────────────────────────────────────────────\n\n/** Parse raw message as JSON. Returns null on failure (logs error). */\nexport function parseJsonMessage(\n raw: string,\n topic: string,\n logger: KafkaLogger,\n): any | null {\n try {\n return JSON.parse(raw);\n } catch (error) {\n logger.error(\n `Failed to parse message from topic ${topic}:`,\n toError(error).stack,\n );\n return null;\n }\n}\n\n// ── Schema validation ───────────────────────────────────────────────\n\n/**\n * Validate a parsed message against the schema map.\n * On failure: logs error, sends to DLQ if enabled, calls interceptor.onError.\n * Returns validated message or null.\n */\nexport async function validateWithSchema<T extends TopicMapConstraint<T>>(\n message: any,\n raw: string,\n topic: string,\n schemaMap: Map<string, SchemaLike>,\n interceptors: ConsumerInterceptor<T>[],\n dlq: boolean,\n deps: {\n logger: KafkaLogger;\n producer: Producer;\n onMessageLost?: (ctx: MessageLostContext) => void | Promise<void>;\n originalHeaders?: MessageHeaders;\n },\n): Promise<any | null> {\n const schema = schemaMap.get(topic);\n if (!schema) return message;\n\n try {\n return await schema.parse(message);\n } catch (error) {\n const err = toError(error);\n const validationError = new KafkaValidationError(topic, message, {\n cause: err,\n });\n deps.logger.error(\n `Schema validation failed for topic ${topic}:`,\n err.message,\n );\n if (dlq) {\n await sendToDlq(topic, raw, deps, {\n error: validationError,\n attempt: 0,\n originalHeaders: deps.originalHeaders,\n });\n } else {\n await deps.onMessageLost?.({\n topic,\n error: validationError,\n attempt: 0,\n headers: deps.originalHeaders ?? {},\n });\n }\n // Validation errors don't have an envelope yet — call onError with a minimal envelope\n const errorEnvelope = extractEnvelope(\n message,\n deps.originalHeaders ?? {},\n topic,\n -1,\n \"\",\n );\n for (const interceptor of interceptors) {\n await interceptor.onError?.(errorEnvelope, validationError);\n }\n return null;\n }\n}\n\n// ── DLQ ─────────────────────────────────────────────────────────────\n\nexport interface DlqMetadata {\n error: Error;\n attempt: number;\n /** Original Kafka message headers — forwarded to DLQ to preserve correlationId, traceparent, etc. */\n originalHeaders?: MessageHeaders;\n}\n\nexport async function sendToDlq(\n topic: string,\n rawMessage: string,\n deps: { logger: KafkaLogger; producer: Producer },\n meta?: DlqMetadata,\n): Promise<void> {\n const dlqTopic = `${topic}.dlq`;\n const headers: MessageHeaders = {\n ...(meta?.originalHeaders ?? {}),\n \"x-dlq-original-topic\": topic,\n \"x-dlq-failed-at\": new Date().toISOString(),\n \"x-dlq-error-message\": meta?.error.message ?? \"unknown\",\n \"x-dlq-error-stack\": meta?.error.stack?.slice(0, 2000) ?? \"\",\n \"x-dlq-attempt-count\": String(meta?.attempt ?? 0),\n };\n try {\n await deps.producer.send({\n topic: dlqTopic,\n messages: [{ value: rawMessage, headers }],\n });\n deps.logger.warn(`Message sent to DLQ: ${dlqTopic}`);\n } catch (error) {\n deps.logger.error(\n `Failed to send message to DLQ ${dlqTopic}:`,\n toError(error).stack,\n );\n }\n}\n\n// ── Retry topic routing ─────────────────────────────────────────────\n\n/** Headers stamped on messages sent to a `<topic>.retry` topic. */\nexport const RETRY_HEADER_ATTEMPT = \"x-retry-attempt\";\nexport const RETRY_HEADER_AFTER = \"x-retry-after\";\nexport const RETRY_HEADER_MAX_RETRIES = \"x-retry-max-retries\";\nexport const RETRY_HEADER_ORIGINAL_TOPIC = \"x-retry-original-topic\";\n\n/**\n * Send raw messages to the retry topic `<originalTopic>.retry`.\n * Stamps scheduling headers so the retry consumer knows when and how many times to retry.\n */\nexport async function sendToRetryTopic(\n originalTopic: string,\n rawMessages: string[],\n attempt: number,\n maxRetries: number,\n delayMs: number,\n originalHeaders: MessageHeaders,\n deps: { logger: KafkaLogger; producer: Producer },\n): Promise<void> {\n const retryTopic = `${originalTopic}.retry`;\n // Strip any stale retry headers from a previous hop so they don't leak through.\n const {\n [RETRY_HEADER_ATTEMPT]: _a,\n [RETRY_HEADER_AFTER]: _b,\n [RETRY_HEADER_MAX_RETRIES]: _c,\n [RETRY_HEADER_ORIGINAL_TOPIC]: _d,\n ...userHeaders\n } = originalHeaders;\n const headers: MessageHeaders = {\n ...userHeaders,\n [RETRY_HEADER_ATTEMPT]: String(attempt),\n [RETRY_HEADER_AFTER]: String(Date.now() + delayMs),\n [RETRY_HEADER_MAX_RETRIES]: String(maxRetries),\n [RETRY_HEADER_ORIGINAL_TOPIC]: originalTopic,\n };\n try {\n for (const raw of rawMessages) {\n await deps.producer.send({\n topic: retryTopic,\n messages: [{ value: raw, headers }],\n });\n }\n deps.logger.warn(\n `Message queued in retry topic ${retryTopic} (attempt ${attempt}/${maxRetries})`,\n );\n } catch (error) {\n deps.logger.error(\n `Failed to send message to retry topic ${retryTopic}:`,\n toError(error).stack,\n );\n }\n}\n\n// ── Pipeline helpers ─────────────────────────────────────────────────\n\nasync function broadcastToInterceptors<T extends TopicMapConstraint<T>>(\n envelopes: EventEnvelope<any>[],\n interceptors: ConsumerInterceptor<T>[],\n cb: (\n interceptor: ConsumerInterceptor<T>,\n env: EventEnvelope<any>,\n ) => Promise<void> | void | undefined,\n): Promise<void> {\n for (const env of envelopes) {\n for (const interceptor of interceptors) {\n await cb(interceptor, env);\n }\n }\n}\n\n/**\n * Run `fn` through the full instrumentation and interceptor lifecycle:\n * beforeConsume → interceptor.before → fn → interceptor.after → cleanup\n *\n * On error: fires `onConsumeError` and cleanup, then returns the error.\n * The caller is responsible for calling `notifyInterceptorsOnError` (with\n * a possibly-wrapped error) and deciding what happens next.\n *\n * Returns `null` on success, the caught `Error` on failure.\n */\nexport async function runHandlerWithPipeline<T extends TopicMapConstraint<T>>(\n fn: () => Promise<void>,\n envelopes: EventEnvelope<any>[],\n interceptors: ConsumerInterceptor<T>[],\n instrumentation: KafkaInstrumentation[],\n): Promise<Error | null> {\n const cleanups: (() => void)[] = [];\n\n try {\n for (const env of envelopes) {\n for (const inst of instrumentation) {\n const cleanup = inst.beforeConsume?.(env);\n if (typeof cleanup === \"function\") cleanups.push(cleanup);\n }\n }\n for (const env of envelopes) {\n for (const interceptor of interceptors) {\n await interceptor.before?.(env);\n }\n }\n\n await fn();\n\n for (const env of envelopes) {\n for (const interceptor of interceptors) {\n await interceptor.after?.(env);\n }\n }\n for (const cleanup of cleanups) cleanup();\n\n return null;\n } catch (error) {\n const err = toError(error);\n for (const env of envelopes) {\n for (const inst of instrumentation) {\n inst.onConsumeError?.(env, err);\n }\n }\n for (const cleanup of cleanups) cleanup();\n return err;\n }\n}\n\n/**\n * Call `interceptor.onError` for every envelope with the given error.\n * Separated from `runHandlerWithPipeline` so callers can wrap the raw error\n * (e.g. in `KafkaRetryExhaustedError`) before notifying interceptors.\n */\nexport async function notifyInterceptorsOnError<\n T extends TopicMapConstraint<T>,\n>(\n envelopes: EventEnvelope<any>[],\n interceptors: ConsumerInterceptor<T>[],\n error: Error,\n): Promise<void> {\n await broadcastToInterceptors(envelopes, interceptors, (i, env) =>\n i.onError?.(env, error),\n );\n}\n\n// ── Retry pipeline ──────────────────────────────────────────────────\n\nexport interface ExecuteWithRetryContext<T extends TopicMapConstraint<T>> {\n envelope: EventEnvelope<any> | EventEnvelope<any>[];\n rawMessages: string[];\n interceptors: ConsumerInterceptor<T>[];\n dlq: boolean;\n retry?: RetryOptions;\n isBatch?: boolean;\n /**\n * When `true`, failed messages are routed to `<topic>.retry` instead of being\n * retried in-process. All backoff and subsequent attempts are handled by the\n * companion retry consumer started by `startRetryTopicConsumers`.\n */\n retryTopics?: boolean;\n}\n\n/**\n * Execute a handler with retry, interceptors, instrumentation, and DLQ support.\n * Used by both single-message and batch consumers.\n */\nexport async function executeWithRetry<T extends TopicMapConstraint<T>>(\n fn: () => Promise<void>,\n ctx: ExecuteWithRetryContext<T>,\n deps: {\n logger: KafkaLogger;\n producer: Producer;\n instrumentation: KafkaInstrumentation[];\n onMessageLost?: (ctx: MessageLostContext) => void | Promise<void>;\n },\n): Promise<void> {\n const {\n envelope,\n rawMessages,\n interceptors,\n dlq,\n retry,\n isBatch,\n retryTopics,\n } = ctx;\n // With retryTopics mode the main consumer tries exactly once — retry consumer takes over.\n const maxAttempts = retryTopics ? 1 : retry ? retry.maxRetries + 1 : 1;\n const backoffMs = retry?.backoffMs ?? 1000;\n const maxBackoffMs = retry?.maxBackoffMs ?? 30_000;\n const envelopes = Array.isArray(envelope) ? envelope : [envelope];\n const topic = envelopes[0]?.topic ?? \"unknown\";\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const error = await runHandlerWithPipeline(\n fn,\n envelopes,\n interceptors,\n deps.instrumentation,\n );\n if (!error) return;\n\n const isLastAttempt = attempt === maxAttempts;\n const reportedError =\n isLastAttempt && maxAttempts > 1\n ? new KafkaRetryExhaustedError(\n topic,\n envelopes.map((e) => e.payload),\n maxAttempts,\n { cause: error },\n )\n : error;\n\n await notifyInterceptorsOnError(envelopes, interceptors, reportedError);\n\n deps.logger.error(\n `Error processing ${isBatch ? \"batch\" : \"message\"} from topic ${topic} (attempt ${attempt}/${maxAttempts}):`,\n error.stack,\n );\n\n if (retryTopics && retry) {\n // Route to retry topic — retry consumer handles backoff and further attempts.\n // Always use attempt 1 here (main consumer never retries in-process).\n const cap = Math.min(backoffMs, maxBackoffMs);\n const delay = Math.floor(Math.random() * cap);\n await sendToRetryTopic(\n topic,\n rawMessages,\n 1,\n retry.maxRetries,\n delay,\n envelopes[0]?.headers ?? {},\n deps,\n );\n } else if (isLastAttempt) {\n if (dlq) {\n const dlqMeta: DlqMetadata = {\n error,\n attempt,\n originalHeaders: envelopes[0]?.headers,\n };\n for (const raw of rawMessages) {\n await sendToDlq(topic, raw, deps, dlqMeta);\n }\n } else {\n await deps.onMessageLost?.({\n topic,\n error,\n attempt,\n headers: envelopes[0]?.headers ?? {},\n });\n }\n } else {\n // Exponential backoff with full jitter to avoid thundering herd\n const cap = Math.min(backoffMs * 2 ** (attempt - 1), maxBackoffMs);\n await sleep(Math.random() * cap);\n }\n }\n}\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Producer = KafkaJS.Producer;\nimport {\n decodeHeaders,\n extractEnvelope,\n runWithEnvelopeContext,\n} from \"../message/envelope\";\nimport type { EventEnvelope } from \"../message/envelope\";\nimport {\n parseJsonMessage,\n validateWithSchema,\n executeWithRetry,\n} from \"../consumer/pipeline\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n BatchMeta,\n ConsumerInterceptor,\n KafkaClientOptions,\n KafkaInstrumentation,\n KafkaLogger,\n RetryOptions,\n} from \"../types\";\n\nexport type MessageHandlerDeps = {\n logger: KafkaLogger;\n producer: Producer;\n instrumentation: KafkaInstrumentation[];\n onMessageLost: KafkaClientOptions[\"onMessageLost\"];\n};\n\nexport type EachMessageOpts = {\n schemaMap: Map<string, SchemaLike>;\n handleMessage: (envelope: EventEnvelope<any>) => Promise<void>;\n interceptors: ConsumerInterceptor<any>[];\n dlq: boolean;\n retry: RetryOptions | undefined;\n retryTopics: boolean | undefined;\n timeoutMs: number | undefined;\n wrapWithTimeout: <R>(\n fn: () => Promise<R>,\n ms: number,\n topic: string,\n ) => Promise<R>;\n};\n\n/** Parse, validate and extract an envelope from a single raw Kafka message. Returns null to skip. */\nasync function parseSingleMessage(\n message: {\n value: Buffer | null;\n headers?: Record<string, any>;\n offset: string;\n },\n topic: string,\n partition: number,\n schemaMap: Map<string, SchemaLike>,\n interceptors: ConsumerInterceptor<any>[],\n dlq: boolean,\n deps: MessageHandlerDeps,\n): Promise<EventEnvelope<any> | null> {\n if (!message.value) {\n deps.logger.warn(`Received empty message from topic ${topic}`);\n return null;\n }\n\n const raw = message.value.toString();\n const parsed = parseJsonMessage(raw, topic, deps.logger);\n if (parsed === null) return null;\n\n const headers = decodeHeaders(message.headers);\n const validated = await validateWithSchema(\n parsed,\n raw,\n topic,\n schemaMap,\n interceptors,\n dlq,\n { ...deps, originalHeaders: headers },\n );\n if (validated === null) return null;\n\n return extractEnvelope(validated, headers, topic, partition, message.offset);\n}\n\nexport async function handleEachMessage(\n payload: {\n topic: string;\n partition: number;\n message: {\n value: Buffer | null;\n headers?: Record<string, any>;\n offset: string;\n };\n },\n opts: EachMessageOpts,\n deps: MessageHandlerDeps,\n): Promise<void> {\n const { topic, partition, message } = payload;\n const {\n schemaMap,\n handleMessage,\n interceptors,\n dlq,\n retry,\n retryTopics,\n timeoutMs,\n wrapWithTimeout,\n } = opts;\n\n const envelope = await parseSingleMessage(\n message,\n topic,\n partition,\n schemaMap,\n interceptors,\n dlq,\n deps,\n );\n if (envelope === null) return;\n\n await executeWithRetry(\n () => {\n const fn = () =>\n runWithEnvelopeContext(\n {\n correlationId: envelope.correlationId,\n traceparent: envelope.traceparent,\n },\n () => handleMessage(envelope),\n );\n return timeoutMs ? wrapWithTimeout(fn, timeoutMs, topic) : fn();\n },\n {\n envelope,\n rawMessages: [message.value!.toString()],\n interceptors,\n dlq,\n retry,\n retryTopics,\n },\n deps,\n );\n}\n\nexport type EachBatchOpts = {\n schemaMap: Map<string, SchemaLike>;\n handleBatch: (\n envelopes: EventEnvelope<any>[],\n meta: BatchMeta,\n ) => Promise<void>;\n interceptors: ConsumerInterceptor<any>[];\n dlq: boolean;\n retry: RetryOptions | undefined;\n timeoutMs: number | undefined;\n wrapWithTimeout: <R>(\n fn: () => Promise<R>,\n ms: number,\n topic: string,\n ) => Promise<R>;\n};\n\nexport async function handleEachBatch(\n payload: {\n batch: {\n topic: string;\n partition: number;\n highWatermark: string;\n messages: Array<{\n value: Buffer | null;\n headers?: Record<string, any>;\n offset: string;\n }>;\n };\n heartbeat(): Promise<void>;\n resolveOffset(offset: string): void;\n commitOffsetsIfNecessary(): Promise<void>;\n },\n opts: EachBatchOpts,\n deps: MessageHandlerDeps,\n): Promise<void> {\n const { batch, heartbeat, resolveOffset, commitOffsetsIfNecessary } = payload;\n const {\n schemaMap,\n handleBatch,\n interceptors,\n dlq,\n retry,\n timeoutMs,\n wrapWithTimeout,\n } = opts;\n\n const envelopes: EventEnvelope<any>[] = [];\n const rawMessages: string[] = [];\n\n for (const message of batch.messages) {\n const envelope = await parseSingleMessage(\n message,\n batch.topic,\n batch.partition,\n schemaMap,\n interceptors,\n dlq,\n deps,\n );\n if (envelope === null) continue;\n envelopes.push(envelope);\n rawMessages.push(message.value!.toString());\n }\n\n if (envelopes.length === 0) return;\n\n const meta: BatchMeta = {\n partition: batch.partition,\n highWatermark: batch.highWatermark,\n heartbeat,\n resolveOffset,\n commitOffsetsIfNecessary,\n };\n\n await executeWithRetry(\n () => {\n const fn = () => handleBatch(envelopes, meta);\n return timeoutMs ? wrapWithTimeout(fn, timeoutMs, batch.topic) : fn();\n },\n {\n envelope: envelopes,\n rawMessages: batch.messages\n .filter((m) => m.value)\n .map((m) => m.value!.toString()),\n interceptors,\n dlq,\n retry,\n isBatch: true,\n },\n deps,\n );\n}\n","import type { KafkaJS } from \"@confluentinc/kafka-javascript\";\nimport type { KafkaLogger, SubscribeRetryOptions } from \"../types\";\nimport { toError, sleep } from \"./pipeline\";\n\nexport async function subscribeWithRetry(\n consumer: KafkaJS.Consumer,\n topics: string[],\n logger: KafkaLogger,\n retryOpts?: SubscribeRetryOptions,\n): Promise<void> {\n const maxAttempts = retryOpts?.retries ?? 5;\n const backoffMs = retryOpts?.backoffMs ?? 5000;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n await consumer.subscribe({ topics });\n return;\n } catch (error) {\n if (attempt === maxAttempts) throw error;\n const msg = toError(error).message;\n logger.warn(\n `Failed to subscribe to [${topics.join(\", \")}] (attempt ${attempt}/${maxAttempts}): ${msg}. Retrying in ${backoffMs}ms...`,\n );\n await sleep(backoffMs);\n }\n }\n}\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Consumer = KafkaJS.Consumer;\ntype Producer = KafkaJS.Producer;\nimport {\n decodeHeaders,\n extractEnvelope,\n runWithEnvelopeContext,\n} from \"../message/envelope\";\nimport type { EventEnvelope } from \"../message/envelope\";\nimport {\n parseJsonMessage,\n validateWithSchema,\n runHandlerWithPipeline,\n notifyInterceptorsOnError,\n sendToDlq,\n sendToRetryTopic,\n sleep,\n RETRY_HEADER_ATTEMPT,\n RETRY_HEADER_AFTER,\n RETRY_HEADER_MAX_RETRIES,\n RETRY_HEADER_ORIGINAL_TOPIC,\n} from \"../consumer/pipeline\";\nimport { KafkaRetryExhaustedError } from \"../errors\";\nimport { subscribeWithRetry } from \"../consumer/subscribe-retry\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n ConsumerInterceptor,\n KafkaClientOptions,\n KafkaInstrumentation,\n KafkaLogger,\n} from \"../types\";\n\nexport type RetryTopicDeps = {\n logger: KafkaLogger;\n producer: Producer;\n instrumentation: KafkaInstrumentation[];\n onMessageLost: KafkaClientOptions[\"onMessageLost\"];\n ensureTopic: (topic: string) => Promise<void>;\n getOrCreateConsumer: (\n groupId: string,\n fromBeginning: boolean,\n autoCommit: boolean,\n ) => Consumer;\n runningConsumers: Map<string, \"eachMessage\" | \"eachBatch\">;\n};\n\n/**\n * Poll `consumer.assignment()` until the consumer has received at least one\n * partition for the given topics, then return. Logs a warning and returns\n * (rather than throwing) on timeout so that a slow broker does not break\n * the caller — in the worst case a message sent immediately after would be\n * missed, which is the same behaviour as before this guard was added.\n */\nexport async function waitForPartitionAssignment(\n consumer: Consumer,\n topics: string[],\n logger: KafkaLogger,\n timeoutMs = 10_000,\n): Promise<void> {\n const topicSet = new Set(topics);\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n const assigned: { topic: string; partition: number }[] =\n consumer.assignment();\n if (assigned.some((a) => topicSet.has(a.topic))) return;\n } catch {\n // consumer.assignment() throws if not yet in CONNECTED state — keep polling\n }\n await sleep(200);\n }\n logger.warn(\n `Retry consumer did not receive partition assignments for [${topics.join(\", \")}] within ${timeoutMs}ms`,\n );\n}\n\n/**\n * Auto-start companion consumers on `<topic>.retry` for each original topic.\n * Called by `startConsumer` when `retryTopics: true`.\n *\n * Flow per message:\n * 1. Sleep until `x-retry-after` (scheduled by the main consumer or previous retry hop)\n * 2. Call the original handler\n * 3. On failure: if retries remain → re-send to `<originalTopic>.retry` with incremented attempt\n * if exhausted → DLQ or onMessageLost\n */\nexport async function startRetryTopicConsumers(\n originalTopics: string[],\n originalGroupId: string,\n handleMessage: (envelope: EventEnvelope<any>) => Promise<void>,\n retry: { maxRetries: number; backoffMs?: number; maxBackoffMs?: number },\n dlq: boolean,\n interceptors: ConsumerInterceptor<any>[],\n schemaMap: Map<string, SchemaLike>,\n deps: RetryTopicDeps,\n): Promise<void> {\n const {\n logger,\n producer,\n instrumentation,\n onMessageLost,\n ensureTopic,\n getOrCreateConsumer,\n runningConsumers,\n } = deps;\n\n const retryTopicNames = originalTopics.map((t) => `${t}.retry`);\n const retryGroupId = `${originalGroupId}-retry`;\n const backoffMs = retry.backoffMs ?? 1_000;\n const maxBackoffMs = retry.maxBackoffMs ?? 30_000;\n const pipelineDeps = { logger, producer, instrumentation, onMessageLost };\n\n for (const rt of retryTopicNames) {\n await ensureTopic(rt);\n }\n\n const consumer = getOrCreateConsumer(retryGroupId, false, true);\n await consumer.connect();\n await subscribeWithRetry(consumer, retryTopicNames, logger);\n\n await consumer.run({\n eachMessage: async ({ topic: retryTopic, partition, message }) => {\n if (!message.value) return;\n\n const raw = message.value.toString();\n const parsed = parseJsonMessage(raw, retryTopic, logger);\n if (parsed === null) return;\n\n const headers = decodeHeaders(message.headers);\n const originalTopic =\n (headers[RETRY_HEADER_ORIGINAL_TOPIC] as string | undefined) ??\n retryTopic.replace(/\\.retry$/, \"\");\n const currentAttempt = parseInt(\n (headers[RETRY_HEADER_ATTEMPT] as string | undefined) ?? \"1\",\n 10,\n );\n const maxRetries = parseInt(\n (headers[RETRY_HEADER_MAX_RETRIES] as string | undefined) ??\n String(retry.maxRetries),\n 10,\n );\n const retryAfter = parseInt(\n (headers[RETRY_HEADER_AFTER] as string | undefined) ?? \"0\",\n 10,\n );\n\n // Pause only this partition for the scheduled delay so that other\n // topic-partitions on the same retry consumer continue processing.\n const remaining = retryAfter - Date.now();\n if (remaining > 0) {\n consumer.pause([{ topic: retryTopic, partitions: [partition] }]);\n await sleep(remaining);\n consumer.resume([{ topic: retryTopic, partitions: [partition] }]);\n }\n\n // Validate schema against original topic's schema (if any)\n const validated = await validateWithSchema(\n parsed,\n raw,\n originalTopic,\n schemaMap,\n interceptors,\n dlq,\n { ...pipelineDeps, originalHeaders: headers },\n );\n if (validated === null) return;\n\n // Build envelope with originalTopic so correlationId/traceparent are correct\n const envelope = extractEnvelope(\n validated,\n headers,\n originalTopic,\n partition,\n message.offset,\n );\n\n const error = await runHandlerWithPipeline(\n () =>\n runWithEnvelopeContext(\n {\n correlationId: envelope.correlationId,\n traceparent: envelope.traceparent,\n },\n () => handleMessage(envelope),\n ),\n [envelope],\n interceptors,\n instrumentation,\n );\n\n if (error) {\n const nextAttempt = currentAttempt + 1;\n const exhausted = currentAttempt >= maxRetries;\n const reportedError =\n exhausted && maxRetries > 1\n ? new KafkaRetryExhaustedError(\n originalTopic,\n [envelope.payload],\n maxRetries,\n { cause: error },\n )\n : error;\n\n await notifyInterceptorsOnError(\n [envelope],\n interceptors,\n reportedError,\n );\n\n logger.error(\n `Retry consumer error for ${originalTopic} (attempt ${currentAttempt}/${maxRetries}):`,\n error.stack,\n );\n\n if (!exhausted) {\n // currentAttempt is the hop that just failed (1-based).\n // Before hop N+1 we want backoffMs * 2^N, so exponent = currentAttempt.\n const cap = Math.min(backoffMs * 2 ** currentAttempt, maxBackoffMs);\n const delay = Math.floor(Math.random() * cap);\n await sendToRetryTopic(\n originalTopic,\n [raw],\n nextAttempt,\n maxRetries,\n delay,\n headers,\n pipelineDeps,\n );\n } else if (dlq) {\n await sendToDlq(originalTopic, raw, pipelineDeps, {\n error,\n // +1 to account for the main consumer's initial attempt before\n // routing to the retry topic, making this consistent with the\n // in-process retry path where attempt counts all tries.\n attempt: currentAttempt + 1,\n originalHeaders: headers,\n });\n } else {\n await onMessageLost?.({\n topic: originalTopic,\n error,\n attempt: currentAttempt,\n headers,\n });\n }\n }\n },\n });\n\n runningConsumers.set(retryGroupId, \"eachMessage\");\n\n // Block until the retry consumer has received at least one partition assignment.\n // consumer.run() starts the group-join protocol asynchronously; without this wait,\n // the caller may send a message to the original topic before the retry consumer\n // has established its \"latest\" offset on the (initially empty) retry partition,\n // causing it to skip any retry messages produced in that window.\n await waitForPartitionAssignment(consumer, retryTopicNames, logger);\n\n logger.log(\n `Retry topic consumers started for: ${originalTopics.join(\", \")} (group: ${retryGroupId})`,\n );\n}\n","/**\n * Any validation library with a `.parse()` method.\n * Works with Zod, Valibot, ArkType, or any custom validator.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n * const schema: SchemaLike<{ id: string }> = z.object({ id: z.string() });\n * ```\n */\nexport interface SchemaLike<T = any> {\n parse(data: unknown): T | Promise<T>;\n}\n\n/** Infer the output type from a SchemaLike. */\nexport type InferSchema<S extends SchemaLike> =\n S extends SchemaLike<infer T> ? T : never;\n\n/**\n * A typed topic descriptor that pairs a topic name with its message type.\n * Created via the `topic()` factory function.\n *\n * @typeParam N - The literal topic name string.\n * @typeParam M - The message payload type for this topic.\n */\nexport interface TopicDescriptor<\n N extends string = string,\n M extends Record<string, any> = Record<string, any>,\n> {\n readonly __topic: N;\n /** @internal Phantom type — never has a real value at runtime. */\n readonly __type: M;\n /** Runtime schema validator. Present only when created via `topic().schema()`. */\n readonly __schema?: SchemaLike<M>;\n}\n\n/**\n * Define a typed topic descriptor.\n *\n * @example\n * ```ts\n * // Without schema — type provided explicitly:\n * const OrderCreated = topic('order.created')<{ orderId: string; amount: number }>();\n *\n * // With schema — type inferred from schema:\n * const OrderCreated = topic('order.created').schema(z.object({\n * orderId: z.string(),\n * amount: z.number(),\n * }));\n *\n * // Use with KafkaClient:\n * await kafka.sendMessage(OrderCreated, { orderId: '123', amount: 100 });\n *\n * // Use with @SubscribeTo:\n * @SubscribeTo(OrderCreated)\n * async handleOrder(msg) { ... }\n * ```\n */\nexport function topic<N extends string>(name: N) {\n const fn = <M extends Record<string, any>>(): TopicDescriptor<N, M> => ({\n __topic: name,\n __type: undefined as unknown as M,\n });\n\n fn.schema = <S extends SchemaLike<Record<string, any>>>(\n schema: S,\n ): TopicDescriptor<N, InferSchema<S>> => ({\n __topic: name,\n __type: undefined as unknown as InferSchema<S>,\n __schema: schema as unknown as SchemaLike<InferSchema<S>>,\n });\n\n return fn;\n}\n\n/**\n * Build a topic-message map type from a union of TopicDescriptors.\n *\n * @example\n * ```ts\n * const OrderCreated = topic('order.created')<{ orderId: string }>();\n * const OrderCompleted = topic('order.completed')<{ completedAt: string }>();\n *\n * type MyTopics = TopicsFrom<typeof OrderCreated | typeof OrderCompleted>;\n * // { 'order.created': { orderId: string }; 'order.completed': { completedAt: string } }\n * ```\n */\nexport type TopicsFrom<D extends TopicDescriptor<any, any>> = {\n [K in D as K[\"__topic\"]]: K[\"__type\"];\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,8BAAwB;;;ACAxB,8BAAkC;AAClC,yBAA2B;AAKpB,IAAM,kBAAkB;AACxB,IAAM,wBAAwB;AAC9B,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAC9B,IAAM,qBAAqB;AA4ClC,IAAM,kBAAkB,IAAI,0CAA+B;AAGpD,SAAS,qBAA8C;AAC5D,SAAO,gBAAgB,SAAS;AAClC;AAGO,SAAS,uBAA0B,KAAkB,IAAgB;AAC1E,SAAO,gBAAgB,IAAI,KAAK,EAAE;AACpC;AAkBO,SAAS,qBACd,UAAiC,CAAC,GAClB;AAChB,QAAM,MAAM,mBAAmB;AAE/B,QAAM,gBACJ,QAAQ,iBAAiB,KAAK,qBAAiB,+BAAW;AAC5D,QAAM,UAAU,QAAQ,eAAW,+BAAW;AAC9C,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,QAAM,gBAAgB,OAAO,QAAQ,iBAAiB,CAAC;AAEvD,QAAM,WAA2B;AAAA,IAC/B,CAAC,eAAe,GAAG;AAAA,IACnB,CAAC,qBAAqB,GAAG;AAAA,IACzB,CAAC,gBAAgB,GAAG;AAAA,IACpB,CAAC,qBAAqB,GAAG;AAAA,EAC3B;AAGA,MAAI,KAAK,aAAa;AACpB,aAAS,kBAAkB,IAAI,IAAI;AAAA,EACrC;AAGA,SAAO,EAAE,GAAG,UAAU,GAAG,QAAQ,QAAQ;AAC3C;AAMO,SAAS,cACd,KAGgB;AAChB,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,QAAM,SAAyB,CAAC;AAChC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,QAAI,UAAU,OAAW;AACzB,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAO,GAAG,IAAI,MACX,IAAI,CAAC,MAAO,OAAO,SAAS,CAAC,IAAI,EAAE,SAAS,IAAI,CAAE,EAClD,KAAK,GAAG;AAAA,IACb,OAAO;AACL,aAAO,GAAG,IAAI,OAAO,SAAS,KAAK,IAAI,MAAM,SAAS,IAAI;AAAA,IAC5D;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,gBACd,SACA,SACAA,QACA,WACA,QACkB;AAClB,SAAO;AAAA,IACL;AAAA,IACA,OAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,QAAQ,eAAe,SAAK,+BAAW;AAAA,IAChD,eAAe,QAAQ,qBAAqB,SAAK,+BAAW;AAAA,IAC5D,WAAW,QAAQ,gBAAgB,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC/D,eAAe,OAAO,QAAQ,qBAAqB,KAAK,CAAC;AAAA,IACzD,aAAa,QAAQ,kBAAkB;AAAA,IACvC;AAAA,EACF;AACF;;;ACrJO,SAAS,iBAAiB,mBAAoC;AACnE,MAAI,OAAO,sBAAsB,SAAU,QAAO;AAClD,MACE,qBACA,OAAO,sBAAsB,YAC7B,aAAa,mBACb;AACA,WAAQ,kBAA0C;AAAA,EACpD;AACA,SAAO,OAAO,iBAAiB;AACjC;AAEO,SAAS,eACd,aACA,gBACM;AACN,MAAI,aAAa,UAAU;AACzB,UAAMC,SAAQ,iBAAiB,WAAW;AAC1C,mBAAe,IAAIA,QAAO,YAAY,QAAQ;AAAA,EAChD;AACF;AAEA,eAAsB,gBACpB,aACA,SACA,MAIc;AACd,MAAI,aAAa,UAAU;AACzB,WAAO,MAAM,YAAY,SAAS,MAAM,OAAO;AAAA,EACjD;AACA,MAAI,KAAK,wBAAwB,OAAO,gBAAgB,UAAU;AAChE,UAAM,SAAS,KAAK,eAAe,IAAI,WAAW;AAClD,QAAI,OAAQ,QAAO,MAAM,OAAO,MAAM,OAAO;AAAA,EAC/C;AACA,SAAO;AACT;AAQA,eAAsB,iBACpB,aACA,UACA,MAQC;AACD,iBAAe,aAAa,KAAK,cAAc;AAC/C,QAAMA,SAAQ,iBAAiB,WAAW;AAC1C,QAAM,gBAAgB,MAAM,QAAQ;AAAA,IAClC,SAAS,IAAI,OAAO,MAAM;AACxB,YAAM,kBAAkB,qBAAqB;AAAA,QAC3C,eAAe,EAAE;AAAA,QACjB,eAAe,EAAE;AAAA,QACjB,SAAS,EAAE;AAAA,QACX,SAAS,EAAE;AAAA,MACb,CAAC;AAGD,iBAAW,QAAQ,KAAK,iBAAiB;AACvC,aAAK,aAAaA,QAAO,eAAe;AAAA,MAC1C;AAEA,aAAO;AAAA,QACL,OAAO,KAAK;AAAA,UACV,MAAM,gBAAgB,aAAa,EAAE,OAAO,IAAI;AAAA,QAClD;AAAA,QACA,KAAK,EAAE,OAAO;AAAA,QACd,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,EAAE,OAAAA,QAAO,UAAU,cAAc;AAC1C;;;AC1EO,SAAS,oBACd,SACA,eACA,YACA,MACU;AACV,QAAM,EAAE,WAAW,yBAAyB,OAAO,aAAa,OAAO,IACrE;AAEF,MAAI,UAAU,IAAI,OAAO,GAAG;AAC1B,UAAM,OAAO,wBAAwB,IAAI,OAAO;AAChD,QACE,KAAK,kBAAkB,iBACvB,KAAK,eAAe,YACpB;AACA,aAAO;AAAA,QACL,mBAAmB,OAAO,iDACL,KAAK,aAAa,iBAAiB,KAAK,UAAU,wCACtC,aAAa,iBAAiB,UAAU;AAAA,MAE3E;AAAA,IACF;AACA,WAAO,UAAU,IAAI,OAAO;AAAA,EAC9B;AAEA,0BAAwB,IAAI,SAAS,EAAE,eAAe,WAAW,CAAC;AAElE,QAAM,SAA+C;AAAA,IACnD,SAAS,EAAE,SAAS,eAAe,WAAW;AAAA,EAChD;AAEA,MAAI,aAAa;AACf,UAAM,KAAK;AAKX,IAAC,OAAe,cAAc,IAAI,CAAC,KAAU,eAAsB;AACjE,YAAM,OAAO,IAAI,SAAS,OAAO,WAAW;AAC5C,UAAI;AACF;AAAA,UACE;AAAA,UACA,WAAW,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,WAAW,EAAE,UAAU,EAAE;AAAA,QACpE;AAAA,MACF,SAAS,GAAG;AACV,eAAO,KAAK,+BAAgC,EAAY,OAAO,EAAE;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,SAAS,MAAM;AACtC,YAAU,IAAI,SAAS,QAAQ;AAC/B,SAAO;AACT;AAEO,SAAS,eACd,QACA,gBACA,eACyB;AACzB,QAAM,YAAY,oBAAI,IAAwB;AAC9C,aAAW,KAAK,QAAQ;AACtB,QAAI,GAAG,UAAU;AACf,YAAM,OAAO,iBAAiB,CAAC;AAC/B,gBAAU,IAAI,MAAM,EAAE,QAAQ;AAC9B,qBAAe,IAAI,MAAM,EAAE,QAAQ;AAAA,IACrC;AAAA,EACF;AACA,MAAI,eAAe;AACjB,eAAW,CAAC,GAAG,CAAC,KAAK,eAAe;AAClC,gBAAU,IAAI,GAAG,CAAC;AAClB,qBAAe,IAAI,GAAG,CAAC;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;;;AC5FO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YACE,SACgBC,QACA,iBAChB,SACA;AACA,UAAM,SAAS,OAAO;AAJN,iBAAAA;AACA;AAIhB,SAAK,OAAO;AACZ,QAAI,SAAS,MAAO,MAAK,QAAQ,QAAQ;AAAA,EAC3C;AACF;AAGO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YACkBA,QACA,iBAChB,SACA;AACA,UAAM,uCAAuCA,MAAK,KAAK,OAAO;AAJ9C,iBAAAA;AACA;AAIhB,SAAK,OAAO;AACZ,QAAI,SAAS,MAAO,MAAK,QAAQ,QAAQ;AAAA,EAC3C;AACF;AAGO,IAAM,2BAAN,cAAuC,qBAAqB;AAAA,EACjE,YACEA,QACA,iBACgB,UAChB,SACA;AACA;AAAA,MACE,mCAAmC,QAAQ,uBAAuBA,MAAK;AAAA,MACvEA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AARgB;AAShB,SAAK,OAAO;AAAA,EACd;AACF;;;AC7BO,SAAS,QAAQ,OAAuB;AAC7C,SAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACjE;AAEO,SAAS,MAAM,IAA2B;AAC/C,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAKO,SAAS,iBACd,KACAC,QACA,QACY;AACZ,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,SAAS,OAAO;AACd,WAAO;AAAA,MACL,sCAAsCA,MAAK;AAAA,MAC3C,QAAQ,KAAK,EAAE;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AACF;AASA,eAAsB,mBACpB,SACA,KACAA,QACA,WACA,cACA,KACA,MAMqB;AACrB,QAAM,SAAS,UAAU,IAAIA,MAAK;AAClC,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI;AACF,WAAO,MAAM,OAAO,MAAM,OAAO;AAAA,EACnC,SAAS,OAAO;AACd,UAAM,MAAM,QAAQ,KAAK;AACzB,UAAM,kBAAkB,IAAI,qBAAqBA,QAAO,SAAS;AAAA,MAC/D,OAAO;AAAA,IACT,CAAC;AACD,SAAK,OAAO;AAAA,MACV,sCAAsCA,MAAK;AAAA,MAC3C,IAAI;AAAA,IACN;AACA,QAAI,KAAK;AACP,YAAM,UAAUA,QAAO,KAAK,MAAM;AAAA,QAChC,OAAO;AAAA,QACP,SAAS;AAAA,QACT,iBAAiB,KAAK;AAAA,MACxB,CAAC;AAAA,IACH,OAAO;AACL,YAAM,KAAK,gBAAgB;AAAA,QACzB,OAAAA;AAAA,QACA,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS,KAAK,mBAAmB,CAAC;AAAA,MACpC,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA,KAAK,mBAAmB,CAAC;AAAA,MACzBA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,eAAW,eAAe,cAAc;AACtC,YAAM,YAAY,UAAU,eAAe,eAAe;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AACF;AAWA,eAAsB,UACpBA,QACA,YACA,MACA,MACe;AACf,QAAM,WAAW,GAAGA,MAAK;AACzB,QAAM,UAA0B;AAAA,IAC9B,GAAI,MAAM,mBAAmB,CAAC;AAAA,IAC9B,wBAAwBA;AAAA,IACxB,oBAAmB,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC1C,uBAAuB,MAAM,MAAM,WAAW;AAAA,IAC9C,qBAAqB,MAAM,MAAM,OAAO,MAAM,GAAG,GAAI,KAAK;AAAA,IAC1D,uBAAuB,OAAO,MAAM,WAAW,CAAC;AAAA,EAClD;AACA,MAAI;AACF,UAAM,KAAK,SAAS,KAAK;AAAA,MACvB,OAAO;AAAA,MACP,UAAU,CAAC,EAAE,OAAO,YAAY,QAAQ,CAAC;AAAA,IAC3C,CAAC;AACD,SAAK,OAAO,KAAK,wBAAwB,QAAQ,EAAE;AAAA,EACrD,SAAS,OAAO;AACd,SAAK,OAAO;AAAA,MACV,iCAAiC,QAAQ;AAAA,MACzC,QAAQ,KAAK,EAAE;AAAA,IACjB;AAAA,EACF;AACF;AAKO,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB;AAC3B,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AAM3C,eAAsB,iBACpB,eACA,aACA,SACA,YACA,SACA,iBACA,MACe;AACf,QAAM,aAAa,GAAG,aAAa;AAEnC,QAAM;AAAA,IACJ,CAAC,oBAAoB,GAAG;AAAA,IACxB,CAAC,kBAAkB,GAAG;AAAA,IACtB,CAAC,wBAAwB,GAAG;AAAA,IAC5B,CAAC,2BAA2B,GAAG;AAAA,IAC/B,GAAG;AAAA,EACL,IAAI;AACJ,QAAM,UAA0B;AAAA,IAC9B,GAAG;AAAA,IACH,CAAC,oBAAoB,GAAG,OAAO,OAAO;AAAA,IACtC,CAAC,kBAAkB,GAAG,OAAO,KAAK,IAAI,IAAI,OAAO;AAAA,IACjD,CAAC,wBAAwB,GAAG,OAAO,UAAU;AAAA,IAC7C,CAAC,2BAA2B,GAAG;AAAA,EACjC;AACA,MAAI;AACF,eAAW,OAAO,aAAa;AAC7B,YAAM,KAAK,SAAS,KAAK;AAAA,QACvB,OAAO;AAAA,QACP,UAAU,CAAC,EAAE,OAAO,KAAK,QAAQ,CAAC;AAAA,MACpC,CAAC;AAAA,IACH;AACA,SAAK,OAAO;AAAA,MACV,iCAAiC,UAAU,aAAa,OAAO,IAAI,UAAU;AAAA,IAC/E;AAAA,EACF,SAAS,OAAO;AACd,SAAK,OAAO;AAAA,MACV,yCAAyC,UAAU;AAAA,MACnD,QAAQ,KAAK,EAAE;AAAA,IACjB;AAAA,EACF;AACF;AAIA,eAAe,wBACb,WACA,cACA,IAIe;AACf,aAAW,OAAO,WAAW;AAC3B,eAAW,eAAe,cAAc;AACtC,YAAM,GAAG,aAAa,GAAG;AAAA,IAC3B;AAAA,EACF;AACF;AAYA,eAAsB,uBACpB,IACA,WACA,cACA,iBACuB;AACvB,QAAM,WAA2B,CAAC;AAElC,MAAI;AACF,eAAW,OAAO,WAAW;AAC3B,iBAAW,QAAQ,iBAAiB;AAClC,cAAM,UAAU,KAAK,gBAAgB,GAAG;AACxC,YAAI,OAAO,YAAY,WAAY,UAAS,KAAK,OAAO;AAAA,MAC1D;AAAA,IACF;AACA,eAAW,OAAO,WAAW;AAC3B,iBAAW,eAAe,cAAc;AACtC,cAAM,YAAY,SAAS,GAAG;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,GAAG;AAET,eAAW,OAAO,WAAW;AAC3B,iBAAW,eAAe,cAAc;AACtC,cAAM,YAAY,QAAQ,GAAG;AAAA,MAC/B;AAAA,IACF;AACA,eAAW,WAAW,SAAU,SAAQ;AAExC,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,MAAM,QAAQ,KAAK;AACzB,eAAW,OAAO,WAAW;AAC3B,iBAAW,QAAQ,iBAAiB;AAClC,aAAK,iBAAiB,KAAK,GAAG;AAAA,MAChC;AAAA,IACF;AACA,eAAW,WAAW,SAAU,SAAQ;AACxC,WAAO;AAAA,EACT;AACF;AAOA,eAAsB,0BAGpB,WACA,cACA,OACe;AACf,QAAM;AAAA,IAAwB;AAAA,IAAW;AAAA,IAAc,CAAC,GAAG,QACzD,EAAE,UAAU,KAAK,KAAK;AAAA,EACxB;AACF;AAuBA,eAAsB,iBACpB,IACA,KACA,MAMe;AACf,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,cAAc,cAAc,IAAI,QAAQ,MAAM,aAAa,IAAI;AACrE,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,eAAe,OAAO,gBAAgB;AAC5C,QAAM,YAAY,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ;AAChE,QAAMA,SAAQ,UAAU,CAAC,GAAG,SAAS;AAErC,WAAS,UAAU,GAAG,WAAW,aAAa,WAAW;AACvD,UAAM,QAAQ,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AACA,QAAI,CAAC,MAAO;AAEZ,UAAM,gBAAgB,YAAY;AAClC,UAAM,gBACJ,iBAAiB,cAAc,IAC3B,IAAI;AAAA,MACFA;AAAA,MACA,UAAU,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,MAC9B;AAAA,MACA,EAAE,OAAO,MAAM;AAAA,IACjB,IACA;AAEN,UAAM,0BAA0B,WAAW,cAAc,aAAa;AAEtE,SAAK,OAAO;AAAA,MACV,oBAAoB,UAAU,UAAU,SAAS,eAAeA,MAAK,aAAa,OAAO,IAAI,WAAW;AAAA,MACxG,MAAM;AAAA,IACR;AAEA,QAAI,eAAe,OAAO;AAGxB,YAAM,MAAM,KAAK,IAAI,WAAW,YAAY;AAC5C,YAAM,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAC5C,YAAM;AAAA,QACJA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA,UAAU,CAAC,GAAG,WAAW,CAAC;AAAA,QAC1B;AAAA,MACF;AAAA,IACF,WAAW,eAAe;AACxB,UAAI,KAAK;AACP,cAAM,UAAuB;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,iBAAiB,UAAU,CAAC,GAAG;AAAA,QACjC;AACA,mBAAW,OAAO,aAAa;AAC7B,gBAAM,UAAUA,QAAO,KAAK,MAAM,OAAO;AAAA,QAC3C;AAAA,MACF,OAAO;AACL,cAAM,KAAK,gBAAgB;AAAA,UACzB,OAAAA;AAAA,UACA;AAAA,UACA;AAAA,UACA,SAAS,UAAU,CAAC,GAAG,WAAW,CAAC;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,YAAM,MAAM,KAAK,IAAI,YAAY,MAAM,UAAU,IAAI,YAAY;AACjE,YAAM,MAAM,KAAK,OAAO,IAAI,GAAG;AAAA,IACjC;AAAA,EACF;AACF;;;ACnWA,eAAe,mBACb,SAKAC,QACA,WACA,WACA,cACA,KACA,MACoC;AACpC,MAAI,CAAC,QAAQ,OAAO;AAClB,SAAK,OAAO,KAAK,qCAAqCA,MAAK,EAAE;AAC7D,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,QAAQ,MAAM,SAAS;AACnC,QAAM,SAAS,iBAAiB,KAAKA,QAAO,KAAK,MAAM;AACvD,MAAI,WAAW,KAAM,QAAO;AAE5B,QAAM,UAAU,cAAc,QAAQ,OAAO;AAC7C,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,GAAG,MAAM,iBAAiB,QAAQ;AAAA,EACtC;AACA,MAAI,cAAc,KAAM,QAAO;AAE/B,SAAO,gBAAgB,WAAW,SAASA,QAAO,WAAW,QAAQ,MAAM;AAC7E;AAEA,eAAsB,kBACpB,SASA,MACA,MACe;AACf,QAAM,EAAE,OAAAA,QAAO,WAAW,QAAQ,IAAI;AACtC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,aAAa,KAAM;AAEvB,QAAM;AAAA,IACJ,MAAM;AACJ,YAAM,KAAK,MACT;AAAA,QACE;AAAA,UACE,eAAe,SAAS;AAAA,UACxB,aAAa,SAAS;AAAA,QACxB;AAAA,QACA,MAAM,cAAc,QAAQ;AAAA,MAC9B;AACF,aAAO,YAAY,gBAAgB,IAAI,WAAWA,MAAK,IAAI,GAAG;AAAA,IAChE;AAAA,IACA;AAAA,MACE;AAAA,MACA,aAAa,CAAC,QAAQ,MAAO,SAAS,CAAC;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAmBA,eAAsB,gBACpB,SAeA,MACA,MACe;AACf,QAAM,EAAE,OAAO,WAAW,eAAe,yBAAyB,IAAI;AACtE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,YAAkC,CAAC;AACzC,QAAM,cAAwB,CAAC;AAE/B,aAAW,WAAW,MAAM,UAAU;AACpC,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,aAAa,KAAM;AACvB,cAAU,KAAK,QAAQ;AACvB,gBAAY,KAAK,QAAQ,MAAO,SAAS,CAAC;AAAA,EAC5C;AAEA,MAAI,UAAU,WAAW,EAAG;AAE5B,QAAM,OAAkB;AAAA,IACtB,WAAW,MAAM;AAAA,IACjB,eAAe,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM;AAAA,IACJ,MAAM;AACJ,YAAM,KAAK,MAAM,YAAY,WAAW,IAAI;AAC5C,aAAO,YAAY,gBAAgB,IAAI,WAAW,MAAM,KAAK,IAAI,GAAG;AAAA,IACtE;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,aAAa,MAAM,SAChB,OAAO,CAAC,MAAM,EAAE,KAAK,EACrB,IAAI,CAAC,MAAM,EAAE,MAAO,SAAS,CAAC;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX;AAAA,IACA;AAAA,EACF;AACF;;;ACvOA,eAAsB,mBACpB,UACA,QACA,QACA,WACe;AACf,QAAM,cAAc,WAAW,WAAW;AAC1C,QAAM,YAAY,WAAW,aAAa;AAE1C,WAAS,UAAU,GAAG,WAAW,aAAa,WAAW;AACvD,QAAI;AACF,YAAM,SAAS,UAAU,EAAE,OAAO,CAAC;AACnC;AAAA,IACF,SAAS,OAAO;AACd,UAAI,YAAY,YAAa,OAAM;AACnC,YAAM,MAAM,QAAQ,KAAK,EAAE;AAC3B,aAAO;AAAA,QACL,2BAA2B,OAAO,KAAK,IAAI,CAAC,cAAc,OAAO,IAAI,WAAW,MAAM,GAAG,iBAAiB,SAAS;AAAA,MACrH;AACA,YAAM,MAAM,SAAS;AAAA,IACvB;AAAA,EACF;AACF;;;AC2BA,eAAsB,2BACpB,UACA,QACA,QACA,YAAY,KACG;AACf,QAAM,WAAW,IAAI,IAAI,MAAM;AAC/B,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,QAAI;AACF,YAAM,WACJ,SAAS,WAAW;AACtB,UAAI,SAAS,KAAK,CAAC,MAAM,SAAS,IAAI,EAAE,KAAK,CAAC,EAAG;AAAA,IACnD,QAAQ;AAAA,IAER;AACA,UAAM,MAAM,GAAG;AAAA,EACjB;AACA,SAAO;AAAA,IACL,6DAA6D,OAAO,KAAK,IAAI,CAAC,YAAY,SAAS;AAAA,EACrG;AACF;AAYA,eAAsB,yBACpB,gBACA,iBACA,eACA,OACA,KACA,cACA,WACA,MACe;AACf,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAAC;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,kBAAkB,eAAe,IAAI,CAAC,MAAM,GAAG,CAAC,QAAQ;AAC9D,QAAM,eAAe,GAAG,eAAe;AACvC,QAAM,YAAY,MAAM,aAAa;AACrC,QAAM,eAAe,MAAM,gBAAgB;AAC3C,QAAM,eAAe,EAAE,QAAQ,UAAU,iBAAiB,cAAc;AAExE,aAAW,MAAM,iBAAiB;AAChC,UAAM,YAAY,EAAE;AAAA,EACtB;AAEA,QAAM,WAAWA,qBAAoB,cAAc,OAAO,IAAI;AAC9D,QAAM,SAAS,QAAQ;AACvB,QAAM,mBAAmB,UAAU,iBAAiB,MAAM;AAE1D,QAAM,SAAS,IAAI;AAAA,IACjB,aAAa,OAAO,EAAE,OAAO,YAAY,WAAW,QAAQ,MAAM;AAChE,UAAI,CAAC,QAAQ,MAAO;AAEpB,YAAM,MAAM,QAAQ,MAAM,SAAS;AACnC,YAAM,SAAS,iBAAiB,KAAK,YAAY,MAAM;AACvD,UAAI,WAAW,KAAM;AAErB,YAAM,UAAU,cAAc,QAAQ,OAAO;AAC7C,YAAM,gBACH,QAAQ,2BAA2B,KACpC,WAAW,QAAQ,YAAY,EAAE;AACnC,YAAM,iBAAiB;AAAA,QACpB,QAAQ,oBAAoB,KAA4B;AAAA,QACzD;AAAA,MACF;AACA,YAAM,aAAa;AAAA,QAChB,QAAQ,wBAAwB,KAC/B,OAAO,MAAM,UAAU;AAAA,QACzB;AAAA,MACF;AACA,YAAM,aAAa;AAAA,QAChB,QAAQ,kBAAkB,KAA4B;AAAA,QACvD;AAAA,MACF;AAIA,YAAM,YAAY,aAAa,KAAK,IAAI;AACxC,UAAI,YAAY,GAAG;AACjB,iBAAS,MAAM,CAAC,EAAE,OAAO,YAAY,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;AAC/D,cAAM,MAAM,SAAS;AACrB,iBAAS,OAAO,CAAC,EAAE,OAAO,YAAY,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;AAAA,MAClE;AAGA,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,EAAE,GAAG,cAAc,iBAAiB,QAAQ;AAAA,MAC9C;AACA,UAAI,cAAc,KAAM;AAGxB,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV;AAEA,YAAM,QAAQ,MAAM;AAAA,QAClB,MACE;AAAA,UACE;AAAA,YACE,eAAe,SAAS;AAAA,YACxB,aAAa,SAAS;AAAA,UACxB;AAAA,UACA,MAAM,cAAc,QAAQ;AAAA,QAC9B;AAAA,QACF,CAAC,QAAQ;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAEA,UAAI,OAAO;AACT,cAAM,cAAc,iBAAiB;AACrC,cAAM,YAAY,kBAAkB;AACpC,cAAM,gBACJ,aAAa,aAAa,IACtB,IAAI;AAAA,UACF;AAAA,UACA,CAAC,SAAS,OAAO;AAAA,UACjB;AAAA,UACA,EAAE,OAAO,MAAM;AAAA,QACjB,IACA;AAEN,cAAM;AAAA,UACJ,CAAC,QAAQ;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAEA,eAAO;AAAA,UACL,4BAA4B,aAAa,aAAa,cAAc,IAAI,UAAU;AAAA,UAClF,MAAM;AAAA,QACR;AAEA,YAAI,CAAC,WAAW;AAGd,gBAAM,MAAM,KAAK,IAAI,YAAY,KAAK,gBAAgB,YAAY;AAClE,gBAAM,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAC5C,gBAAM;AAAA,YACJ;AAAA,YACA,CAAC,GAAG;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,WAAW,KAAK;AACd,gBAAM,UAAU,eAAe,KAAK,cAAc;AAAA,YAChD;AAAA;AAAA;AAAA;AAAA,YAIA,SAAS,iBAAiB;AAAA,YAC1B,iBAAiB;AAAA,UACnB,CAAC;AAAA,QACH,OAAO;AACL,gBAAM,gBAAgB;AAAA,YACpB,OAAO;AAAA,YACP;AAAA,YACA,SAAS;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,mBAAiB,IAAI,cAAc,aAAa;AAOhD,QAAM,2BAA2B,UAAU,iBAAiB,MAAM;AAElE,SAAO;AAAA,IACL,sCAAsC,eAAe,KAAK,IAAI,CAAC,YAAY,YAAY;AAAA,EACzF;AACF;;;ARhQA,IAAM,EAAE,OAAO,YAAY,UAAU,cAAc,IAAI;AA6ChD,IAAM,cAAN,MAEsB;AAAA,EACV;AAAA,EACA;AAAA,EACT;AAAA,EACS,YAAY,oBAAI,IAAsB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB,oBAAI,IAAY;AAAA,EAChC;AAAA,EACA,iBAAiB,oBAAI,IAAwB;AAAA,EAC7C,mBAAmB,oBAAI,IAGtC;AAAA,EACe,0BAA0B,oBAAI,IAG7C;AAAA,EACe;AAAA,EACA;AAAA,EACA;AAAA,EAET,mBAAmB;AAAA,EACX;AAAA,EAEhB,YACE,UACA,SACA,SACA,SACA;AACA,SAAK,WAAW;AAChB,SAAK,iBAAiB;AACtB,SAAK,SAAS,SAAS,UAAU;AAAA,MAC/B,KAAK,CAAC,QAAQ,QAAQ,IAAI,gBAAgB,QAAQ,KAAK,GAAG,EAAE;AAAA,MAC5D,MAAM,CAAC,QAAQ,SACb,QAAQ,KAAK,gBAAgB,QAAQ,KAAK,GAAG,IAAI,GAAG,IAAI;AAAA,MAC1D,OAAO,CAAC,QAAQ,SACd,QAAQ,MAAM,gBAAgB,QAAQ,KAAK,GAAG,IAAI,GAAG,IAAI;AAAA,IAC7D;AACA,SAAK,0BAA0B,SAAS,oBAAoB;AAC5D,SAAK,uBAAuB,SAAS,iBAAiB;AACtD,SAAK,gBAAgB,SAAS,iBAAiB;AAC/C,SAAK,kBAAkB,SAAS,mBAAmB,CAAC;AACpD,SAAK,gBAAgB,SAAS;AAC9B,SAAK,cAAc,SAAS;AAE5B,SAAK,QAAQ,IAAI,WAAW;AAAA,MAC1B,SAAS;AAAA,QACP,UAAU,KAAK;AAAA,QACf;AAAA,QACA,UAAU,cAAc;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,SAAK,WAAW,KAAK,MAAM,SAAS;AAAA,MAClC,SAAS;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AACD,SAAK,QAAQ,KAAK,MAAM,MAAM;AAAA,EAChC;AAAA,EAaA,MAAa,YACX,aACA,SACA,UAAuB,CAAC,GACT;AACf,UAAM,UAAU,MAAM,KAAK,eAAe,aAAa;AAAA,MACrD;AAAA,QACE,OAAO;AAAA,QACP,KAAK,QAAQ;AAAA,QACb,SAAS,QAAQ;AAAA,QACjB,eAAe,QAAQ;AAAA,QACvB,eAAe,QAAQ;AAAA,QACvB,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC;AACD,UAAM,KAAK,SAAS,KAAK,OAAO;AAChC,SAAK,gBAAgB,QAAQ,OAAO,QAAQ,SAAS,MAAM;AAAA,EAC7D;AAAA,EAaA,MAAa,UACX,aACA,UACe;AACf,UAAM,UAAU,MAAM,KAAK,eAAe,aAAa,QAAQ;AAC/D,UAAM,KAAK,SAAS,KAAK,OAAO;AAChC,SAAK,gBAAgB,QAAQ,OAAO,QAAQ,SAAS,MAAM;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAa,YACX,IACe;AACf,QAAI,CAAC,KAAK,YAAY;AAKpB,WAAK,aAAa,KAAK,MAAM,SAAS;AAAA,QACpC,SAAS;AAAA,UACP,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,iBAAiB,GAAG,KAAK,QAAQ;AAAA,UACjC,qBAAqB;AAAA,QACvB;AAAA,MACF,CAAC;AACD,YAAM,KAAK,WAAW,QAAQ;AAAA,IAChC;AACA,UAAM,KAAK,MAAM,KAAK,WAAW,YAAY;AAC7C,QAAI;AACF,YAAM,MAA6B;AAAA,QACjC,MAAM,OACJ,aACA,SACA,UAAuB,CAAC,MACrB;AACH,gBAAM,UAAU,MAAM,KAAK,eAAe,aAAa;AAAA,YACrD;AAAA,cACE,OAAO;AAAA,cACP,KAAK,QAAQ;AAAA,cACb,SAAS,QAAQ;AAAA,cACjB,eAAe,QAAQ;AAAA,cACvB,eAAe,QAAQ;AAAA,cACvB,SAAS,QAAQ;AAAA,YACnB;AAAA,UACF,CAAC;AACD,gBAAM,GAAG,KAAK,OAAO;AAAA,QACvB;AAAA,QACA,WAAW,OACT,aACA,aACG;AACH,gBAAM,GAAG,KAAK,MAAM,KAAK,eAAe,aAAa,QAAQ,CAAC;AAAA,QAChE;AAAA,MACF;AACA,YAAM,GAAG,GAAG;AACZ,YAAM,GAAG,OAAO;AAAA,IAClB,SAAS,OAAO;AACd,UAAI;AACF,cAAM,GAAG,MAAM;AAAA,MACjB,SAAS,YAAY;AACnB,aAAK,OAAO;AAAA,UACV;AAAA,UACA,QAAQ,UAAU,EAAE;AAAA,QACtB;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,MAAa,kBAAiC;AAC5C,UAAM,KAAK,SAAS,QAAQ;AAC5B,SAAK,OAAO,IAAI,oBAAoB;AAAA,EACtC;AAAA,EAEA,MAAa,qBAAoC;AAC/C,UAAM,KAAK,SAAS,WAAW;AAC/B,SAAK,OAAO,IAAI,uBAAuB;AAAA,EACzC;AAAA,EAiBA,MAAa,cACX,QACA,eACA,UAA8B,CAAC,GACN;AACzB,QAAI,QAAQ,eAAe,CAAC,QAAQ,OAAO;AACzC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,EAAE,UAAU,WAAW,YAAY,KAAK,KAAK,cAAc,MAAM,IACrE,MAAM,KAAK,cAAc,QAAQ,eAAe,OAAO;AAEzD,UAAM,OAAO,KAAK;AAClB,UAAM,YAAY,QAAQ;AAE1B,UAAM,SAAS,IAAI;AAAA,MACjB,aAAa,CAAC,YACZ;AAAA,QACE;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,aAAa,QAAQ;AAAA,UACrB;AAAA,UACA,iBAAiB,KAAK,uBAAuB,KAAK,IAAI;AAAA,QACxD;AAAA,QACA;AAAA,MACF;AAAA,IACJ,CAAC;AAED,SAAK,iBAAiB,IAAI,KAAK,aAAa;AAE5C,QAAI,QAAQ,eAAe,OAAO;AAChC,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,KAAK,MAAM,MAAM,KAAK,aAAa,GAAG,EAAE;AAAA,EAC5D;AAAA,EAuBA,MAAa,mBACX,QACA,aAIA,UAA8B,CAAC,GACN;AACzB,UAAM,EAAE,UAAU,WAAW,KAAK,KAAK,cAAc,MAAM,IACzD,MAAM,KAAK,cAAc,QAAQ,aAAa,OAAO;AAEvD,UAAM,OAAO,KAAK;AAClB,UAAM,YAAY,QAAQ;AAE1B,UAAM,SAAS,IAAI;AAAA,MACjB,WAAW,CAAC,YACV;AAAA,QACE;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,iBAAiB,KAAK,uBAAuB,KAAK,IAAI;AAAA,QACxD;AAAA,QACA;AAAA,MACF;AAAA,IACJ,CAAC;AAED,SAAK,iBAAiB,IAAI,KAAK,WAAW;AAE1C,WAAO,EAAE,SAAS,KAAK,MAAM,MAAM,KAAK,aAAa,GAAG,EAAE;AAAA,EAC5D;AAAA;AAAA,EAIA,MAAa,aAAa,SAAiC;AACzD,QAAI,YAAY,QAAW;AACzB,YAAM,WAAW,KAAK,UAAU,IAAI,OAAO;AAC3C,UAAI,CAAC,UAAU;AACb,aAAK,OAAO;AAAA,UACV,+CAA+C,OAAO;AAAA,QACxD;AACA;AAAA,MACF;AACA,YAAM,SAAS,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAC1C,WAAK,UAAU,OAAO,OAAO;AAC7B,WAAK,iBAAiB,OAAO,OAAO;AACpC,WAAK,wBAAwB,OAAO,OAAO;AAC3C,WAAK,OAAO,IAAI,iCAAiC,OAAO,GAAG;AAAA,IAC7D,OAAO;AACL,YAAM,QAAQ,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE;AAAA,QAAI,CAAC,MACrD,EAAE,WAAW,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC/B;AACA,YAAM,QAAQ,WAAW,KAAK;AAC9B,WAAK,UAAU,MAAM;AACrB,WAAK,iBAAiB,MAAM;AAC5B,WAAK,wBAAwB,MAAM;AACnC,WAAK,OAAO,IAAI,4BAA4B;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,eACX,SACmE;AACnE,UAAM,MAAM,WAAW,KAAK;AAC5B,QAAI,CAAC,KAAK,kBAAkB;AAC1B,YAAM,KAAK,MAAM,QAAQ;AACzB,WAAK,mBAAmB;AAAA,IAC1B;AAEA,UAAM,mBAAmB,MAAM,KAAK,MAAM,aAAa,EAAE,SAAS,IAAI,CAAC;AACvE,UAAM,SAAmE,CAAC;AAE1E,eAAW,EAAE,OAAAC,QAAO,WAAW,KAAK,kBAAkB;AACpD,YAAM,gBAAgB,MAAM,KAAK,MAAM,kBAAkBA,MAAK;AAE9D,iBAAW,EAAE,WAAW,OAAO,KAAK,YAAY;AAC9C,cAAM,SAAS,cAAc,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AAClE,YAAI,CAAC,OAAQ;AAEb,cAAM,YAAY,SAAS,QAAQ,EAAE;AACrC,cAAM,OAAO,SAAS,OAAO,MAAM,EAAE;AAErC,cAAM,MAAM,cAAc,KAAK,OAAO,KAAK,IAAI,GAAG,OAAO,SAAS;AAClE,eAAO,KAAK,EAAE,OAAAA,QAAO,WAAW,IAAI,CAAC;AAAA,MACvC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAa,cAIV;AACD,QAAI,CAAC,KAAK,kBAAkB;AAC1B,YAAM,KAAK,MAAM,QAAQ;AACzB,WAAK,mBAAmB;AAAA,IAC1B;AACA,UAAM,SAAS,MAAM,KAAK,MAAM,WAAW;AAC3C,WAAO,EAAE,QAAQ,MAAM,UAAU,KAAK,UAAU,OAAO;AAAA,EACzD;AAAA,EAEO,cAAwB;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAa,aAA4B;AACvC,UAAM,QAAyB,CAAC,KAAK,SAAS,WAAW,CAAC;AAC1D,QAAI,KAAK,YAAY;AACnB,YAAM,KAAK,KAAK,WAAW,WAAW,CAAC;AACvC,WAAK,aAAa;AAAA,IACpB;AACA,eAAW,YAAY,KAAK,UAAU,OAAO,GAAG;AAC9C,YAAM,KAAK,SAAS,WAAW,CAAC;AAAA,IAClC;AACA,QAAI,KAAK,kBAAkB;AACzB,YAAM,KAAK,KAAK,MAAM,WAAW,CAAC;AAClC,WAAK,mBAAmB;AAAA,IAC1B;AACA,UAAM,QAAQ,WAAW,KAAK;AAC9B,SAAK,UAAU,MAAM;AACrB,SAAK,iBAAiB,MAAM;AAC5B,SAAK,wBAAwB,MAAM;AACnC,SAAK,OAAO,IAAI,wBAAwB;AAAA,EAC1C;AAAA;AAAA,EAIA,MAAc,eACZ,aACA,UACA;AACA,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AACA,UAAM,KAAK,YAAY,QAAQ,KAAK;AACpC,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,gBAAgBA,QAAe,OAAqB;AAC1D,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,iBAAW,QAAQ,KAAK,iBAAiB;AACvC,aAAK,YAAYA,MAAK;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,uBACN,IACA,WACAA,QACY;AACZ,QAAI;AACJ,UAAM,UAAU,GAAG,EAAE,QAAQ,MAAM;AACjC,UAAI,UAAU,OAAW,cAAa,KAAK;AAAA,IAC7C,CAAC;AACD,YAAQ,WAAW,MAAM;AACvB,WAAK,OAAO;AAAA,QACV,sBAAsBA,MAAK,4BAA4B,SAAS;AAAA,MAClE;AAAA,IACF,GAAG,SAAS;AACZ,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,YAAYA,QAA8B;AACtD,QAAI,CAAC,KAAK,2BAA2B,KAAK,cAAc,IAAIA,MAAK,EAAG;AACpE,QAAI,CAAC,KAAK,kBAAkB;AAC1B,YAAM,KAAK,MAAM,QAAQ;AACzB,WAAK,mBAAmB;AAAA,IAC1B;AACA,UAAM,KAAK,MAAM,aAAa;AAAA,MAC5B,QAAQ,CAAC,EAAE,OAAAA,QAAO,eAAe,KAAK,cAAc,CAAC;AAAA,IACvD,CAAC;AACD,SAAK,cAAc,IAAIA,MAAK;AAAA,EAC9B;AAAA;AAAA,EAGA,MAAc,cACZ,QACA,MACA,SACA;AACA,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB;AAAA,MACA,MAAM;AAAA,MACN,eAAe,CAAC;AAAA,MAChB,SAAS;AAAA,IACX,IAAI;AAEJ,UAAM,MAAM,cAAc,KAAK;AAC/B,UAAM,eAAe,KAAK,iBAAiB,IAAI,GAAG;AAClD,UAAM,eAAe,SAAS,gBAAgB,cAAc;AAC5D,QAAI,iBAAiB,cAAc;AACjC,YAAM,IAAI;AAAA,QACR,cAAc,IAAI,uBAAuB,GAAG,uCAAkC,YAAY;AAAA,MAE5F;AAAA,IACF;AAEA,UAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA,QAAQ,cAAc;AAAA,MACtB,KAAK;AAAA,IACP;AACA,UAAM,YAAY;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AAEA,UAAM,aAAc,OAAiB,IAAI,CAAC,MAAW,iBAAiB,CAAC,CAAC;AAGxE,eAAW,KAAK,YAAY;AAC1B,YAAM,KAAK,YAAY,CAAC;AAAA,IAC1B;AACA,QAAI,KAAK;AACP,iBAAW,KAAK,YAAY;AAC1B,cAAM,KAAK,YAAY,GAAG,CAAC,MAAM;AAAA,MACnC;AAAA,IACF;AAEA,UAAM,SAAS,QAAQ;AACvB,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,QAAQ;AAAA,IACV;AAEA,SAAK,OAAO;AAAA,MACV,GAAG,SAAS,cAAc,mBAAmB,UAAU,0BAA0B,WAAW,KAAK,IAAI,CAAC;AAAA,IACxG;AAEA,WAAO,EAAE,UAAU,WAAW,YAAY,KAAK,KAAK,cAAc,MAAM;AAAA,EAC1E;AAAA;AAAA,EAIA,IAAY,kBAAwC;AAClD,WAAO;AAAA,MACL,gBAAgB,KAAK;AAAA,MACrB,sBAAsB,KAAK;AAAA,MAC3B,iBAAiB,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,IAAY,kBAAmC;AAC7C,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,yBAAyB,KAAK;AAAA,MAC9B,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA,EAEA,IAAY,cAAkC;AAC5C,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB,KAAK;AAAA,MACtB,eAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,IAAY,iBAAiB;AAC3B,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,iBAAiB,KAAK;AAAA,MACtB,eAAe,KAAK;AAAA,MACpB,aAAa,CAAC,MAAc,KAAK,YAAY,CAAC;AAAA,MAC9C,qBAAqB,CAAC,KAAa,IAAa,OAC9C,oBAAoB,KAAK,IAAI,IAAI,KAAK,eAAe;AAAA,MACvD,kBAAkB,KAAK;AAAA,IACzB;AAAA,EACF;AACF;;;AS5jBO,SAAS,MAAwB,MAAS;AAC/C,QAAM,KAAK,OAA6D;AAAA,IACtE,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,KAAG,SAAS,CACV,YACwC;AAAA,IACxC,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAEA,SAAO;AACT;","names":["topic","topic","topic","topic","topic","getOrCreateConsumer","topic"]}
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/client/kafka.client/index.ts","../src/client/message/envelope.ts","../src/client/errors.ts","../src/client/kafka.client/producer-ops.ts","../src/client/kafka.client/consumer-ops.ts","../src/client/consumer/pipeline.ts","../src/client/kafka.client/message-handler.ts","../src/client/consumer/subscribe-retry.ts","../src/client/kafka.client/retry-topic.ts","../src/client/message/topic.ts"],"sourcesContent":["export * from \"./client/kafka.client\";\nexport * from \"./client/message/topic\";\nexport * from \"./client/errors\";\nexport * from \"./client/message/envelope\";\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Kafka = KafkaJS.Kafka;\ntype Producer = KafkaJS.Producer;\ntype Consumer = KafkaJS.Consumer;\ntype Admin = KafkaJS.Admin;\nconst { Kafka: KafkaClass, logLevel: KafkaLogLevel } = KafkaJS;\nimport { TopicDescriptor, SchemaLike } from \"../message/topic\";\nimport type { EventEnvelope } from \"../message/envelope\";\nimport type {\n ClientId,\n GroupId,\n SendOptions,\n BatchMessageItem,\n ConsumerOptions,\n ConsumerHandle,\n TransactionContext,\n TopicMapConstraint,\n IKafkaClient,\n KafkaClientOptions,\n KafkaInstrumentation,\n KafkaLogger,\n BatchMeta,\n} from \"../types\";\n\n// Re-export all types so existing `import { ... } from './kafka.client'` keeps working\nexport * from \"../types\";\n\nimport {\n buildSendPayload,\n registerSchema,\n resolveTopicName,\n type BuildSendPayloadDeps,\n} from \"./producer-ops\";\nimport {\n getOrCreateConsumer,\n buildSchemaMap,\n type ConsumerOpsDeps,\n} from \"./consumer-ops\";\nimport { handleEachMessage, handleEachBatch } from \"./message-handler\";\nimport type { MessageHandlerDeps } from \"./message-handler\";\nimport { startRetryTopicConsumers } from \"./retry-topic\";\nimport { subscribeWithRetry } from \"../consumer/subscribe-retry\";\nimport { toError } from \"../consumer/pipeline\";\n\n/**\n * Type-safe Kafka client.\n * Wraps @confluentinc/kafka-javascript (librdkafka) with JSON serialization,\n * retries, DLQ, transactions, and interceptors.\n *\n * @typeParam T - Topic-to-message type mapping for compile-time safety.\n */\nexport class KafkaClient<\n T extends TopicMapConstraint<T>,\n> implements IKafkaClient<T> {\n private readonly kafka: Kafka;\n private readonly producer: Producer;\n private txProducer: Producer | undefined;\n private readonly consumers = new Map<string, Consumer>();\n private readonly admin: Admin;\n private readonly logger: KafkaLogger;\n private readonly autoCreateTopicsEnabled: boolean;\n private readonly strictSchemasEnabled: boolean;\n private readonly numPartitions: number;\n private readonly ensuredTopics = new Set<string>();\n private readonly defaultGroupId: string;\n private readonly schemaRegistry = new Map<string, SchemaLike>();\n private readonly runningConsumers = new Map<\n string,\n \"eachMessage\" | \"eachBatch\"\n >();\n private readonly consumerCreationOptions = new Map<\n string,\n { fromBeginning: boolean; autoCommit: boolean }\n >();\n /** Maps each main consumer groupId to its companion retry level groupIds. */\n private readonly companionGroupIds = new Map<string, string[]>();\n private readonly instrumentation: KafkaInstrumentation[];\n private readonly onMessageLost: KafkaClientOptions[\"onMessageLost\"];\n private readonly onRebalance: KafkaClientOptions[\"onRebalance\"];\n\n private isAdminConnected = false;\n public readonly clientId: ClientId;\n\n constructor(\n clientId: ClientId,\n groupId: GroupId,\n brokers: string[],\n options?: KafkaClientOptions,\n ) {\n this.clientId = clientId;\n this.defaultGroupId = groupId;\n this.logger = options?.logger ?? {\n log: (msg) => console.log(`[KafkaClient:${clientId}] ${msg}`),\n warn: (msg, ...args) =>\n console.warn(`[KafkaClient:${clientId}] ${msg}`, ...args),\n error: (msg, ...args) =>\n console.error(`[KafkaClient:${clientId}] ${msg}`, ...args),\n };\n this.autoCreateTopicsEnabled = options?.autoCreateTopics ?? false;\n this.strictSchemasEnabled = options?.strictSchemas ?? true;\n this.numPartitions = options?.numPartitions ?? 1;\n this.instrumentation = options?.instrumentation ?? [];\n this.onMessageLost = options?.onMessageLost;\n this.onRebalance = options?.onRebalance;\n\n this.kafka = new KafkaClass({\n kafkaJS: {\n clientId: this.clientId,\n brokers,\n logLevel: KafkaLogLevel.ERROR,\n },\n });\n this.producer = this.kafka.producer({\n kafkaJS: {\n acks: -1,\n },\n });\n this.admin = this.kafka.admin();\n }\n\n // ── Send ─────────────────────────────────────────────────────────\n\n /** Send a single typed message. Accepts a topic key or a TopicDescriptor. */\n public async sendMessage<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(descriptor: D, message: D[\"__type\"], options?: SendOptions): Promise<void>;\n public async sendMessage<K extends keyof T>(\n topic: K,\n message: T[K],\n options?: SendOptions,\n ): Promise<void>;\n public async sendMessage(\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ): Promise<void> {\n const payload = await this.preparePayload(topicOrDesc, [\n {\n value: message,\n key: options.key,\n headers: options.headers,\n correlationId: options.correlationId,\n schemaVersion: options.schemaVersion,\n eventId: options.eventId,\n },\n ]);\n await this.producer.send(payload);\n this.notifyAfterSend(payload.topic, payload.messages.length);\n }\n\n /** Send multiple typed messages in one call. Accepts a topic key or a TopicDescriptor. */\n public async sendBatch<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n descriptor: D,\n messages: Array<BatchMessageItem<D[\"__type\"]>>,\n ): Promise<void>;\n public async sendBatch<K extends keyof T>(\n topic: K,\n messages: Array<BatchMessageItem<T[K]>>,\n ): Promise<void>;\n public async sendBatch(\n topicOrDesc: any,\n messages: Array<BatchMessageItem<any>>,\n ): Promise<void> {\n const payload = await this.preparePayload(topicOrDesc, messages);\n await this.producer.send(payload);\n this.notifyAfterSend(payload.topic, payload.messages.length);\n }\n\n /** Execute multiple sends atomically. Commits on success, aborts on error. */\n public async transaction(\n fn: (ctx: TransactionContext<T>) => Promise<void>,\n ): Promise<void> {\n if (!this.txProducer) {\n // transactionalId must be unique per producer instance across the cluster.\n // Two KafkaClient instances sharing the same clientId will share this id,\n // causing Kafka to fence one of the producers. Use distinct clientIds when\n // running multiple instances of the same service.\n this.txProducer = this.kafka.producer({\n kafkaJS: {\n acks: -1,\n idempotent: true,\n transactionalId: `${this.clientId}-tx`,\n maxInFlightRequests: 1,\n },\n });\n await this.txProducer.connect();\n }\n const tx = await this.txProducer.transaction();\n try {\n const ctx: TransactionContext<T> = {\n send: async (\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ) => {\n const payload = await this.preparePayload(topicOrDesc, [\n {\n value: message,\n key: options.key,\n headers: options.headers,\n correlationId: options.correlationId,\n schemaVersion: options.schemaVersion,\n eventId: options.eventId,\n },\n ]);\n await tx.send(payload);\n },\n sendBatch: async (\n topicOrDesc: any,\n messages: BatchMessageItem<any>[],\n ) => {\n await tx.send(await this.preparePayload(topicOrDesc, messages));\n },\n };\n await fn(ctx);\n await tx.commit();\n } catch (error) {\n try {\n await tx.abort();\n } catch (abortError) {\n this.logger.error(\n \"Failed to abort transaction:\",\n toError(abortError).message,\n );\n }\n throw error;\n }\n }\n\n // ── Producer lifecycle ───────────────────────────────────────────\n\n /** Connect the idempotent producer. Called automatically by `KafkaModule.register()`. */\n public async connectProducer(): Promise<void> {\n await this.producer.connect();\n this.logger.log(\"Producer connected\");\n }\n\n public async disconnectProducer(): Promise<void> {\n await this.producer.disconnect();\n this.logger.log(\"Producer disconnected\");\n }\n\n // ── Consumer: eachMessage ────────────────────────────────────────\n\n /** Subscribe to topics and start consuming messages with the given handler. */\n public async startConsumer<K extends Array<keyof T>>(\n topics: K,\n handleMessage: (envelope: EventEnvelope<T[K[number]]>) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startConsumer<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n topics: D[],\n handleMessage: (envelope: EventEnvelope<D[\"__type\"]>) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startConsumer(\n topics: any[],\n handleMessage: (envelope: EventEnvelope<any>) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<ConsumerHandle> {\n if (options.retryTopics && !options.retry) {\n throw new Error(\n \"retryTopics requires retry to be configured — set retry.maxRetries to enable the retry topic chain\",\n );\n }\n\n const { consumer, schemaMap, topicNames, gid, dlq, interceptors, retry } =\n await this.setupConsumer(topics, \"eachMessage\", options);\n\n const deps = this.messageDeps;\n const timeoutMs = options.handlerTimeoutMs;\n\n await consumer.run({\n eachMessage: (payload) =>\n handleEachMessage(\n payload,\n {\n schemaMap,\n handleMessage,\n interceptors,\n dlq,\n retry,\n retryTopics: options.retryTopics,\n timeoutMs,\n wrapWithTimeout: this.wrapWithTimeoutWarning.bind(this),\n },\n deps,\n ),\n });\n\n this.runningConsumers.set(gid, \"eachMessage\");\n\n if (options.retryTopics && retry) {\n const companions = await startRetryTopicConsumers(\n topicNames,\n gid,\n handleMessage,\n retry,\n dlq,\n interceptors,\n schemaMap,\n this.retryTopicDeps,\n options.retryTopicAssignmentTimeoutMs,\n );\n this.companionGroupIds.set(gid, companions);\n }\n\n return { groupId: gid, stop: () => this.stopConsumer(gid) };\n }\n\n // ── Consumer: eachBatch ──────────────────────────────────────────\n\n /** Subscribe to topics and consume messages in batches. */\n public async startBatchConsumer<K extends Array<keyof T>>(\n topics: K,\n handleBatch: (\n envelopes: EventEnvelope<T[K[number]]>[],\n meta: BatchMeta,\n ) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startBatchConsumer<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n topics: D[],\n handleBatch: (\n envelopes: EventEnvelope<D[\"__type\"]>[],\n meta: BatchMeta,\n ) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<ConsumerHandle>;\n public async startBatchConsumer(\n topics: any[],\n handleBatch: (\n envelopes: EventEnvelope<any>[],\n meta: BatchMeta,\n ) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<ConsumerHandle> {\n const { consumer, schemaMap, gid, dlq, interceptors, retry } =\n await this.setupConsumer(topics, \"eachBatch\", options);\n\n const deps = this.messageDeps;\n const timeoutMs = options.handlerTimeoutMs;\n\n await consumer.run({\n eachBatch: (payload) =>\n handleEachBatch(\n payload,\n {\n schemaMap,\n handleBatch,\n interceptors,\n dlq,\n retry,\n timeoutMs,\n wrapWithTimeout: this.wrapWithTimeoutWarning.bind(this),\n },\n deps,\n ),\n });\n\n this.runningConsumers.set(gid, \"eachBatch\");\n\n return { groupId: gid, stop: () => this.stopConsumer(gid) };\n }\n\n // ── Consumer lifecycle ───────────────────────────────────────────\n\n public async stopConsumer(groupId?: string): Promise<void> {\n if (groupId !== undefined) {\n const consumer = this.consumers.get(groupId);\n if (!consumer) {\n this.logger.warn(\n `stopConsumer: no active consumer for group \"${groupId}\"`,\n );\n return;\n }\n await consumer.disconnect().catch(() => {});\n this.consumers.delete(groupId);\n this.runningConsumers.delete(groupId);\n this.consumerCreationOptions.delete(groupId);\n this.logger.log(`Consumer disconnected: group \"${groupId}\"`);\n\n // Stop all companion retry level consumers started for this group\n const companions = this.companionGroupIds.get(groupId) ?? [];\n for (const cGroupId of companions) {\n const cConsumer = this.consumers.get(cGroupId);\n if (cConsumer) {\n await cConsumer.disconnect().catch(() => {});\n this.consumers.delete(cGroupId);\n this.runningConsumers.delete(cGroupId);\n this.consumerCreationOptions.delete(cGroupId);\n this.logger.log(`Retry consumer disconnected: group \"${cGroupId}\"`);\n }\n }\n this.companionGroupIds.delete(groupId);\n } else {\n const tasks = Array.from(this.consumers.values()).map((c) =>\n c.disconnect().catch(() => {}),\n );\n await Promise.allSettled(tasks);\n this.consumers.clear();\n this.runningConsumers.clear();\n this.consumerCreationOptions.clear();\n this.companionGroupIds.clear();\n this.logger.log(\"All consumers disconnected\");\n }\n }\n\n /**\n * Query consumer group lag per partition.\n * Lag = broker high-watermark − last committed offset.\n * A committed offset of -1 (nothing committed yet) counts as full lag.\n */\n public async getConsumerLag(\n groupId?: string,\n ): Promise<Array<{ topic: string; partition: number; lag: number }>> {\n const gid = groupId ?? this.defaultGroupId;\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n\n const committedByTopic = await this.admin.fetchOffsets({ groupId: gid });\n const result: Array<{ topic: string; partition: number; lag: number }> = [];\n\n for (const { topic, partitions } of committedByTopic) {\n const brokerOffsets = await this.admin.fetchTopicOffsets(topic);\n\n for (const { partition, offset } of partitions) {\n const broker = brokerOffsets.find((o) => o.partition === partition);\n if (!broker) continue;\n\n const committed = parseInt(offset, 10);\n const high = parseInt(broker.high, 10);\n // committed === -1 means the group has never committed for this partition\n const lag = committed === -1 ? high : Math.max(0, high - committed);\n result.push({ topic, partition, lag });\n }\n }\n\n return result;\n }\n\n /** Check broker connectivity. Never throws — returns a discriminated union. */\n public async checkStatus(): Promise<import(\"../types\").KafkaHealthResult> {\n try {\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n const topics = await this.admin.listTopics();\n return { status: \"up\", clientId: this.clientId, topics };\n } catch (error) {\n return {\n status: \"down\",\n clientId: this.clientId,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n public getClientId(): ClientId {\n return this.clientId;\n }\n\n /** Gracefully disconnect producer, all consumers, and admin. */\n public async disconnect(): Promise<void> {\n const tasks: Promise<void>[] = [this.producer.disconnect()];\n if (this.txProducer) {\n tasks.push(this.txProducer.disconnect());\n this.txProducer = undefined;\n }\n for (const consumer of this.consumers.values()) {\n tasks.push(consumer.disconnect());\n }\n if (this.isAdminConnected) {\n tasks.push(this.admin.disconnect());\n this.isAdminConnected = false;\n }\n await Promise.allSettled(tasks);\n this.consumers.clear();\n this.runningConsumers.clear();\n this.consumerCreationOptions.clear();\n this.companionGroupIds.clear();\n this.logger.log(\"All connections closed\");\n }\n\n // ── Private helpers ──────────────────────────────────────────────\n\n private async preparePayload(\n topicOrDesc: any,\n messages: Array<BatchMessageItem<any>>,\n ) {\n registerSchema(topicOrDesc, this.schemaRegistry);\n const payload = await buildSendPayload(\n topicOrDesc,\n messages,\n this.producerOpsDeps,\n );\n await this.ensureTopic(payload.topic);\n return payload;\n }\n\n // afterSend is called once per message — symmetric with beforeSend in buildSendPayload.\n private notifyAfterSend(topic: string, count: number): void {\n for (let i = 0; i < count; i++) {\n for (const inst of this.instrumentation) {\n inst.afterSend?.(topic);\n }\n }\n }\n\n /**\n * Start a timer that logs a warning if `fn` hasn't resolved within `timeoutMs`.\n * The handler itself is not cancelled — the warning is diagnostic only.\n */\n private wrapWithTimeoutWarning<R>(\n fn: () => Promise<R>,\n timeoutMs: number,\n topic: string,\n ): Promise<R> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const promise = fn().finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n timer = setTimeout(() => {\n this.logger.warn(\n `Handler for topic \"${topic}\" has not resolved after ${timeoutMs}ms — possible stuck handler`,\n );\n }, timeoutMs);\n return promise;\n }\n\n private async ensureTopic(topic: string): Promise<void> {\n if (!this.autoCreateTopicsEnabled || this.ensuredTopics.has(topic)) return;\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n await this.admin.createTopics({\n topics: [{ topic, numPartitions: this.numPartitions }],\n });\n this.ensuredTopics.add(topic);\n }\n\n /** Shared consumer setup: groupId check, schema map, connect, subscribe. */\n private async setupConsumer(\n topics: any[],\n mode: \"eachMessage\" | \"eachBatch\",\n options: ConsumerOptions<T>,\n ) {\n const {\n groupId: optGroupId,\n fromBeginning = false,\n retry,\n dlq = false,\n interceptors = [],\n schemas: optionSchemas,\n } = options;\n\n const gid = optGroupId || this.defaultGroupId;\n const existingMode = this.runningConsumers.get(gid);\n const oppositeMode = mode === \"eachMessage\" ? \"eachBatch\" : \"eachMessage\";\n if (existingMode === oppositeMode) {\n throw new Error(\n `Cannot use ${mode} on consumer group \"${gid}\" — it is already running with ${oppositeMode}. ` +\n `Use a different groupId for this consumer.`,\n );\n }\n\n const consumer = getOrCreateConsumer(\n gid,\n fromBeginning,\n options.autoCommit ?? true,\n this.consumerOpsDeps,\n );\n const schemaMap = buildSchemaMap(\n topics,\n this.schemaRegistry,\n optionSchemas,\n );\n\n const topicNames = (topics as any[]).map((t: any) => resolveTopicName(t));\n\n // Ensure topics exist before subscribing — librdkafka errors on unknown topics\n for (const t of topicNames) {\n await this.ensureTopic(t);\n }\n if (dlq) {\n for (const t of topicNames) {\n await this.ensureTopic(`${t}.dlq`);\n }\n }\n\n await consumer.connect();\n await subscribeWithRetry(\n consumer,\n topicNames,\n this.logger,\n options.subscribeRetry,\n );\n\n this.logger.log(\n `${mode === \"eachBatch\" ? \"Batch consumer\" : \"Consumer\"} subscribed to topics: ${topicNames.join(\", \")}`,\n );\n\n return { consumer, schemaMap, topicNames, gid, dlq, interceptors, retry };\n }\n\n // ── Deps object getters ──────────────────────────────────────────\n\n private get producerOpsDeps(): BuildSendPayloadDeps {\n return {\n schemaRegistry: this.schemaRegistry,\n strictSchemasEnabled: this.strictSchemasEnabled,\n instrumentation: this.instrumentation,\n };\n }\n\n private get consumerOpsDeps(): ConsumerOpsDeps {\n return {\n consumers: this.consumers,\n consumerCreationOptions: this.consumerCreationOptions,\n kafka: this.kafka,\n onRebalance: this.onRebalance,\n logger: this.logger,\n };\n }\n\n private get messageDeps(): MessageHandlerDeps {\n return {\n logger: this.logger,\n producer: this.producer,\n instrumentation: this.instrumentation,\n onMessageLost: this.onMessageLost,\n };\n }\n\n private get retryTopicDeps() {\n return {\n logger: this.logger,\n producer: this.producer,\n instrumentation: this.instrumentation,\n onMessageLost: this.onMessageLost,\n ensureTopic: (t: string) => this.ensureTopic(t),\n getOrCreateConsumer: (gid: string, fb: boolean, ac: boolean) =>\n getOrCreateConsumer(gid, fb, ac, this.consumerOpsDeps),\n runningConsumers: this.runningConsumers,\n };\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { randomUUID } from \"node:crypto\";\nimport type { MessageHeaders } from \"../types\";\n\n// ── Header keys ──────────────────────────────────────────────────────\n\nexport const HEADER_EVENT_ID = \"x-event-id\";\nexport const HEADER_CORRELATION_ID = \"x-correlation-id\";\nexport const HEADER_TIMESTAMP = \"x-timestamp\";\nexport const HEADER_SCHEMA_VERSION = \"x-schema-version\";\nexport const HEADER_TRACEPARENT = \"traceparent\";\n\n// ── EventEnvelope ────────────────────────────────────────────────────\n\n/**\n * Typed wrapper combining a parsed message payload with Kafka metadata\n * and envelope headers.\n *\n * On **send**, the library auto-generates envelope headers\n * (`x-event-id`, `x-correlation-id`, `x-timestamp`, `x-schema-version`).\n *\n * On **consume**, the library extracts those headers and assembles\n * an `EventEnvelope` that is passed to the handler.\n */\nexport interface EventEnvelope<T> {\n /** Deserialized + validated message body. */\n payload: T;\n /** Topic the message was produced to / consumed from. */\n topic: string;\n /** Kafka partition (consume-side only, `-1` on send). */\n partition: number;\n /** Kafka offset (consume-side only, empty string on send). */\n offset: string;\n /** ISO-8601 timestamp set by the producer. */\n timestamp: string;\n /** Unique ID for this event (UUID v4). */\n eventId: string;\n /** Correlation ID — auto-propagated via AsyncLocalStorage. */\n correlationId: string;\n /** Schema version of the payload. */\n schemaVersion: number;\n /** W3C Trace Context `traceparent` header (set by OTel instrumentation). */\n traceparent?: string;\n /** All decoded Kafka headers for extensibility. */\n headers: MessageHeaders;\n}\n\n// ── AsyncLocalStorage context ────────────────────────────────────────\n\ninterface EnvelopeCtx {\n correlationId: string;\n traceparent?: string;\n}\n\nconst envelopeStorage = new AsyncLocalStorage<EnvelopeCtx>();\n\n/** Read the current envelope context (correlationId / traceparent) from ALS. */\nexport function getEnvelopeContext(): EnvelopeCtx | undefined {\n return envelopeStorage.getStore();\n}\n\n/** Execute `fn` inside an envelope context so nested sends inherit correlationId. */\nexport function runWithEnvelopeContext<R>(ctx: EnvelopeCtx, fn: () => R): R {\n return envelopeStorage.run(ctx, fn);\n}\n\n// ── Header helpers ───────────────────────────────────────────────────\n\n/** Options accepted by `buildEnvelopeHeaders`. */\nexport interface EnvelopeHeaderOptions {\n correlationId?: string;\n schemaVersion?: number;\n eventId?: string;\n headers?: MessageHeaders;\n}\n\n/**\n * Generate envelope headers for the send path.\n *\n * Priority for `correlationId`:\n * explicit option → ALS context → new UUID.\n */\nexport function buildEnvelopeHeaders(\n options: EnvelopeHeaderOptions = {},\n): MessageHeaders {\n const ctx = getEnvelopeContext();\n\n const correlationId =\n options.correlationId ?? ctx?.correlationId ?? randomUUID();\n const eventId = options.eventId ?? randomUUID();\n const timestamp = new Date().toISOString();\n const schemaVersion = String(options.schemaVersion ?? 1);\n\n const envelope: MessageHeaders = {\n [HEADER_EVENT_ID]: eventId,\n [HEADER_CORRELATION_ID]: correlationId,\n [HEADER_TIMESTAMP]: timestamp,\n [HEADER_SCHEMA_VERSION]: schemaVersion,\n };\n\n // Propagate traceparent from ALS if present (OTel may override via instrumentation)\n if (ctx?.traceparent) {\n envelope[HEADER_TRACEPARENT] = ctx.traceparent;\n }\n\n // User-provided headers win on conflict\n return { ...envelope, ...options.headers };\n}\n\n/**\n * Decode kafkajs headers (`Record<string, Buffer | string | undefined>`)\n * into plain `Record<string, string>`.\n */\nexport function decodeHeaders(\n raw:\n | Record<string, Buffer | string | (Buffer | string)[] | undefined>\n | undefined,\n): MessageHeaders {\n if (!raw) return {};\n const result: MessageHeaders = {};\n for (const [key, value] of Object.entries(raw)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n result[key] = value\n .map((v) => (Buffer.isBuffer(v) ? v.toString() : v))\n .join(\",\");\n } else {\n result[key] = Buffer.isBuffer(value) ? value.toString() : value;\n }\n }\n return result;\n}\n\n/**\n * Build an `EventEnvelope` from a consumed kafkajs message.\n * Tolerates missing envelope headers — generates defaults so messages\n * from non-envelope producers still work.\n */\nexport function extractEnvelope<T>(\n payload: T,\n headers: MessageHeaders,\n topic: string,\n partition: number,\n offset: string,\n): EventEnvelope<T> {\n return {\n payload,\n topic,\n partition,\n offset,\n eventId: headers[HEADER_EVENT_ID] ?? randomUUID(),\n correlationId: headers[HEADER_CORRELATION_ID] ?? randomUUID(),\n timestamp: headers[HEADER_TIMESTAMP] ?? new Date().toISOString(),\n schemaVersion: Number(headers[HEADER_SCHEMA_VERSION] ?? 1),\n traceparent: headers[HEADER_TRACEPARENT],\n headers,\n };\n}\n","/** Error thrown when a consumer message handler fails. */\nexport class KafkaProcessingError extends Error {\n declare readonly cause?: Error;\n\n constructor(\n message: string,\n public readonly topic: string,\n public readonly originalMessage: unknown,\n options?: { cause?: Error },\n ) {\n super(message, options);\n this.name = \"KafkaProcessingError\";\n if (options?.cause) this.cause = options.cause;\n }\n}\n\n/** Error thrown when schema validation fails on send or consume. */\nexport class KafkaValidationError extends Error {\n declare readonly cause?: Error;\n\n constructor(\n public readonly topic: string,\n public readonly originalMessage: unknown,\n options?: { cause?: Error },\n ) {\n super(`Schema validation failed for topic \"${topic}\"`, options);\n this.name = \"KafkaValidationError\";\n if (options?.cause) this.cause = options.cause;\n }\n}\n\n/** Error thrown when all retry attempts are exhausted for a message. */\nexport class KafkaRetryExhaustedError extends KafkaProcessingError {\n constructor(\n topic: string,\n originalMessage: unknown,\n public readonly attempts: number,\n options?: { cause?: Error },\n ) {\n super(\n `Message processing failed after ${attempts} attempts on topic \"${topic}\"`,\n topic,\n originalMessage,\n options,\n );\n this.name = \"KafkaRetryExhaustedError\";\n }\n}\n","import { buildEnvelopeHeaders } from \"../message/envelope\";\nimport { KafkaValidationError } from \"../errors\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n BatchMessageItem,\n KafkaInstrumentation,\n MessageHeaders,\n} from \"../types\";\n\nexport function resolveTopicName(topicOrDescriptor: unknown): string {\n if (typeof topicOrDescriptor === \"string\") return topicOrDescriptor;\n if (\n topicOrDescriptor &&\n typeof topicOrDescriptor === \"object\" &&\n \"__topic\" in topicOrDescriptor\n ) {\n return (topicOrDescriptor as { __topic: string }).__topic;\n }\n return String(topicOrDescriptor);\n}\n\nexport function registerSchema(\n topicOrDesc: any,\n schemaRegistry: Map<string, SchemaLike>,\n): void {\n if (topicOrDesc?.__schema) {\n const topic = resolveTopicName(topicOrDesc);\n schemaRegistry.set(topic, topicOrDesc.__schema);\n }\n}\n\nexport async function validateMessage(\n topicOrDesc: any,\n message: any,\n deps: {\n schemaRegistry: Map<string, SchemaLike>;\n strictSchemasEnabled: boolean;\n },\n): Promise<any> {\n const topicName = resolveTopicName(topicOrDesc);\n if (topicOrDesc?.__schema) {\n try {\n return await topicOrDesc.__schema.parse(message);\n } catch (error) {\n throw new KafkaValidationError(topicName, message, {\n cause: error instanceof Error ? error : new Error(String(error)),\n });\n }\n }\n if (deps.strictSchemasEnabled && typeof topicOrDesc === \"string\") {\n const schema = deps.schemaRegistry.get(topicOrDesc);\n if (schema) {\n try {\n return await schema.parse(message);\n } catch (error) {\n throw new KafkaValidationError(topicName, message, {\n cause: error instanceof Error ? error : new Error(String(error)),\n });\n }\n }\n }\n return message;\n}\n\nexport type BuildSendPayloadDeps = {\n schemaRegistry: Map<string, SchemaLike>;\n strictSchemasEnabled: boolean;\n instrumentation: KafkaInstrumentation[];\n};\n\nexport async function buildSendPayload(\n topicOrDesc: any,\n messages: Array<BatchMessageItem<any>>,\n deps: BuildSendPayloadDeps,\n): Promise<{\n topic: string;\n messages: Array<{\n value: string;\n key: string | null;\n headers: MessageHeaders;\n }>;\n}> {\n const topic = resolveTopicName(topicOrDesc);\n const builtMessages = await Promise.all(\n messages.map(async (m) => {\n const envelopeHeaders = buildEnvelopeHeaders({\n correlationId: m.correlationId,\n schemaVersion: m.schemaVersion,\n eventId: m.eventId,\n headers: m.headers,\n });\n\n // beforeSend: let instrumentation mutate headers (e.g. OTel injects traceparent)\n for (const inst of deps.instrumentation) {\n inst.beforeSend?.(topic, envelopeHeaders);\n }\n\n return {\n value: JSON.stringify(\n await validateMessage(topicOrDesc, m.value, deps),\n ),\n key: m.key ?? null,\n headers: envelopeHeaders,\n };\n }),\n );\n return { topic, messages: builtMessages };\n}\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Consumer = KafkaJS.Consumer;\ntype Kafka = KafkaJS.Kafka;\nimport type { SchemaLike } from \"../message/topic\";\nimport type { KafkaClientOptions, KafkaLogger } from \"../types\";\nimport { resolveTopicName } from \"./producer-ops\";\n\nexport type ConsumerOpsDeps = {\n consumers: Map<string, Consumer>;\n consumerCreationOptions: Map<\n string,\n { fromBeginning: boolean; autoCommit: boolean }\n >;\n kafka: Kafka;\n onRebalance: KafkaClientOptions[\"onRebalance\"];\n logger: KafkaLogger;\n};\n\nexport function getOrCreateConsumer(\n groupId: string,\n fromBeginning: boolean,\n autoCommit: boolean,\n deps: ConsumerOpsDeps,\n): Consumer {\n const { consumers, consumerCreationOptions, kafka, onRebalance, logger } =\n deps;\n\n if (consumers.has(groupId)) {\n const prev = consumerCreationOptions.get(groupId)!;\n if (\n prev.fromBeginning !== fromBeginning ||\n prev.autoCommit !== autoCommit\n ) {\n logger.warn(\n `Consumer group \"${groupId}\" already exists with options ` +\n `(fromBeginning: ${prev.fromBeginning}, autoCommit: ${prev.autoCommit}) — ` +\n `new options (fromBeginning: ${fromBeginning}, autoCommit: ${autoCommit}) ignored. ` +\n `Use a different groupId to apply different options.`,\n );\n }\n return consumers.get(groupId)!;\n }\n\n consumerCreationOptions.set(groupId, { fromBeginning, autoCommit });\n\n const config: Parameters<typeof kafka.consumer>[0] = {\n kafkaJS: { groupId, fromBeginning, autoCommit },\n };\n\n if (onRebalance) {\n const cb = onRebalance;\n // rebalance_cb is called by librdkafka on every partition assign/revoke.\n // err.code -175 = ERR__ASSIGN_PARTITIONS, -174 = ERR__REVOKE_PARTITIONS.\n // The library handles the actual assign/unassign in its finally block regardless\n // of what this callback does, so we only need it for the side-effect notification.\n (config as any)[\"rebalance_cb\"] = (err: any, assignment: any[]) => {\n const type = err.code === -175 ? \"assign\" : \"revoke\";\n try {\n cb(\n type,\n assignment.map((p) => ({ topic: p.topic, partition: p.partition })),\n );\n } catch (e) {\n logger.warn(`onRebalance callback threw: ${(e as Error).message}`);\n }\n };\n }\n\n const consumer = kafka.consumer(config);\n consumers.set(groupId, consumer);\n return consumer;\n}\n\nexport function buildSchemaMap(\n topics: any[],\n schemaRegistry: Map<string, SchemaLike>,\n optionSchemas?: Map<string, SchemaLike>,\n): Map<string, SchemaLike> {\n const schemaMap = new Map<string, SchemaLike>();\n for (const t of topics) {\n if (t?.__schema) {\n const name = resolveTopicName(t);\n schemaMap.set(name, t.__schema);\n schemaRegistry.set(name, t.__schema);\n }\n }\n if (optionSchemas) {\n for (const [k, v] of optionSchemas) {\n schemaMap.set(k, v);\n schemaRegistry.set(k, v);\n }\n }\n return schemaMap;\n}\n","import type { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Producer = KafkaJS.Producer;\nimport type { EventEnvelope } from \"../message/envelope\";\nimport { extractEnvelope } from \"../message/envelope\";\nimport { KafkaRetryExhaustedError, KafkaValidationError } from \"../errors\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n ConsumerInterceptor,\n KafkaInstrumentation,\n KafkaLogger,\n MessageHeaders,\n MessageLostContext,\n RetryOptions,\n TopicMapConstraint,\n} from \"../types\";\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nexport function toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ── JSON parsing ────────────────────────────────────────────────────\n\n/** Parse raw message as JSON. Returns null on failure (logs error). */\nexport function parseJsonMessage(\n raw: string,\n topic: string,\n logger: KafkaLogger,\n): any | null {\n try {\n return JSON.parse(raw);\n } catch (error) {\n logger.error(\n `Failed to parse message from topic ${topic}:`,\n toError(error).stack,\n );\n return null;\n }\n}\n\n// ── Schema validation ───────────────────────────────────────────────\n\n/**\n * Validate a parsed message against the schema map.\n * On failure: logs error, sends to DLQ if enabled, calls interceptor.onError.\n * Returns validated message or null.\n */\nexport async function validateWithSchema<T extends TopicMapConstraint<T>>(\n message: any,\n raw: string,\n topic: string,\n schemaMap: Map<string, SchemaLike>,\n interceptors: ConsumerInterceptor<T>[],\n dlq: boolean,\n deps: {\n logger: KafkaLogger;\n producer: Producer;\n onMessageLost?: (ctx: MessageLostContext) => void | Promise<void>;\n originalHeaders?: MessageHeaders;\n },\n): Promise<any | null> {\n const schema = schemaMap.get(topic);\n if (!schema) return message;\n\n try {\n return await schema.parse(message);\n } catch (error) {\n const err = toError(error);\n const validationError = new KafkaValidationError(topic, message, {\n cause: err,\n });\n deps.logger.error(\n `Schema validation failed for topic ${topic}:`,\n err.message,\n );\n if (dlq) {\n await sendToDlq(topic, raw, deps, {\n error: validationError,\n attempt: 0,\n originalHeaders: deps.originalHeaders,\n });\n } else {\n await deps.onMessageLost?.({\n topic,\n error: validationError,\n attempt: 0,\n headers: deps.originalHeaders ?? {},\n });\n }\n // Validation errors don't have an envelope yet — call onError with a minimal envelope\n const errorEnvelope = extractEnvelope(\n message,\n deps.originalHeaders ?? {},\n topic,\n -1,\n \"\",\n );\n for (const interceptor of interceptors) {\n await interceptor.onError?.(errorEnvelope, validationError);\n }\n return null;\n }\n}\n\n// ── DLQ ─────────────────────────────────────────────────────────────\n\nexport interface DlqMetadata {\n error: Error;\n attempt: number;\n /** Original Kafka message headers — forwarded to DLQ to preserve correlationId, traceparent, etc. */\n originalHeaders?: MessageHeaders;\n}\n\nexport async function sendToDlq(\n topic: string,\n rawMessage: string,\n deps: { logger: KafkaLogger; producer: Producer },\n meta?: DlqMetadata,\n): Promise<void> {\n const dlqTopic = `${topic}.dlq`;\n const headers: MessageHeaders = {\n ...(meta?.originalHeaders ?? {}),\n \"x-dlq-original-topic\": topic,\n \"x-dlq-failed-at\": new Date().toISOString(),\n \"x-dlq-error-message\": meta?.error.message ?? \"unknown\",\n \"x-dlq-error-stack\": meta?.error.stack?.slice(0, 2000) ?? \"\",\n \"x-dlq-attempt-count\": String(meta?.attempt ?? 0),\n };\n try {\n await deps.producer.send({\n topic: dlqTopic,\n messages: [{ value: rawMessage, headers }],\n });\n deps.logger.warn(`Message sent to DLQ: ${dlqTopic}`);\n } catch (error) {\n deps.logger.error(\n `Failed to send message to DLQ ${dlqTopic}:`,\n toError(error).stack,\n );\n }\n}\n\n// ── Retry topic routing ─────────────────────────────────────────────\n\n/** Headers stamped on messages sent to a `<topic>.retry` topic. */\nexport const RETRY_HEADER_ATTEMPT = \"x-retry-attempt\";\nexport const RETRY_HEADER_AFTER = \"x-retry-after\";\nexport const RETRY_HEADER_MAX_RETRIES = \"x-retry-max-retries\";\nexport const RETRY_HEADER_ORIGINAL_TOPIC = \"x-retry-original-topic\";\n\n/**\n * Send raw messages to the retry topic `<originalTopic>.retry`.\n * Stamps scheduling headers so the retry consumer knows when and how many times to retry.\n */\nexport async function sendToRetryTopic(\n originalTopic: string,\n rawMessages: string[],\n attempt: number,\n maxRetries: number,\n delayMs: number,\n originalHeaders: MessageHeaders,\n deps: { logger: KafkaLogger; producer: Producer },\n): Promise<void> {\n const retryTopic = `${originalTopic}.retry.${attempt}`;\n // Strip any stale retry headers from a previous hop so they don't leak through.\n const {\n [RETRY_HEADER_ATTEMPT]: _a,\n [RETRY_HEADER_AFTER]: _b,\n [RETRY_HEADER_MAX_RETRIES]: _c,\n [RETRY_HEADER_ORIGINAL_TOPIC]: _d,\n ...userHeaders\n } = originalHeaders;\n const headers: MessageHeaders = {\n ...userHeaders,\n [RETRY_HEADER_ATTEMPT]: String(attempt),\n [RETRY_HEADER_AFTER]: String(Date.now() + delayMs),\n [RETRY_HEADER_MAX_RETRIES]: String(maxRetries),\n [RETRY_HEADER_ORIGINAL_TOPIC]: originalTopic,\n };\n try {\n for (const raw of rawMessages) {\n await deps.producer.send({\n topic: retryTopic,\n messages: [{ value: raw, headers }],\n });\n }\n deps.logger.warn(\n `Message queued in retry topic ${retryTopic} (attempt ${attempt}/${maxRetries})`,\n );\n } catch (error) {\n deps.logger.error(\n `Failed to send message to retry topic ${retryTopic}:`,\n toError(error).stack,\n );\n }\n}\n\n// ── Pipeline helpers ─────────────────────────────────────────────────\n\nasync function broadcastToInterceptors<T extends TopicMapConstraint<T>>(\n envelopes: EventEnvelope<any>[],\n interceptors: ConsumerInterceptor<T>[],\n cb: (\n interceptor: ConsumerInterceptor<T>,\n env: EventEnvelope<any>,\n ) => Promise<void> | void | undefined,\n): Promise<void> {\n for (const env of envelopes) {\n for (const interceptor of interceptors) {\n await cb(interceptor, env);\n }\n }\n}\n\n/**\n * Run `fn` through the full instrumentation and interceptor lifecycle:\n * beforeConsume → interceptor.before → fn → interceptor.after → cleanup\n *\n * On error: fires `onConsumeError` and cleanup, then returns the error.\n * The caller is responsible for calling `notifyInterceptorsOnError` (with\n * a possibly-wrapped error) and deciding what happens next.\n *\n * Returns `null` on success, the caught `Error` on failure.\n */\nexport async function runHandlerWithPipeline<T extends TopicMapConstraint<T>>(\n fn: () => Promise<void>,\n envelopes: EventEnvelope<any>[],\n interceptors: ConsumerInterceptor<T>[],\n instrumentation: KafkaInstrumentation[],\n): Promise<Error | null> {\n const cleanups: (() => void)[] = [];\n\n try {\n for (const env of envelopes) {\n for (const inst of instrumentation) {\n const cleanup = inst.beforeConsume?.(env);\n if (typeof cleanup === \"function\") cleanups.push(cleanup);\n }\n }\n for (const env of envelopes) {\n for (const interceptor of interceptors) {\n await interceptor.before?.(env);\n }\n }\n\n await fn();\n\n for (const env of envelopes) {\n for (const interceptor of interceptors) {\n await interceptor.after?.(env);\n }\n }\n for (const cleanup of cleanups) cleanup();\n\n return null;\n } catch (error) {\n const err = toError(error);\n for (const env of envelopes) {\n for (const inst of instrumentation) {\n inst.onConsumeError?.(env, err);\n }\n }\n for (const cleanup of cleanups) cleanup();\n return err;\n }\n}\n\n/**\n * Call `interceptor.onError` for every envelope with the given error.\n * Separated from `runHandlerWithPipeline` so callers can wrap the raw error\n * (e.g. in `KafkaRetryExhaustedError`) before notifying interceptors.\n */\nexport async function notifyInterceptorsOnError<\n T extends TopicMapConstraint<T>,\n>(\n envelopes: EventEnvelope<any>[],\n interceptors: ConsumerInterceptor<T>[],\n error: Error,\n): Promise<void> {\n await broadcastToInterceptors(envelopes, interceptors, (i, env) =>\n i.onError?.(env, error),\n );\n}\n\n// ── Retry pipeline ──────────────────────────────────────────────────\n\nexport interface ExecuteWithRetryContext<T extends TopicMapConstraint<T>> {\n envelope: EventEnvelope<any> | EventEnvelope<any>[];\n rawMessages: string[];\n interceptors: ConsumerInterceptor<T>[];\n dlq: boolean;\n retry?: RetryOptions;\n isBatch?: boolean;\n /**\n * When `true`, failed messages are routed to `<topic>.retry` instead of being\n * retried in-process. All backoff and subsequent attempts are handled by the\n * companion retry consumer started by `startRetryTopicConsumers`.\n */\n retryTopics?: boolean;\n}\n\n/**\n * Execute a handler with retry, interceptors, instrumentation, and DLQ support.\n * Used by both single-message and batch consumers.\n */\nexport async function executeWithRetry<T extends TopicMapConstraint<T>>(\n fn: () => Promise<void>,\n ctx: ExecuteWithRetryContext<T>,\n deps: {\n logger: KafkaLogger;\n producer: Producer;\n instrumentation: KafkaInstrumentation[];\n onMessageLost?: (ctx: MessageLostContext) => void | Promise<void>;\n },\n): Promise<void> {\n const {\n envelope,\n rawMessages,\n interceptors,\n dlq,\n retry,\n isBatch,\n retryTopics,\n } = ctx;\n // With retryTopics mode the main consumer tries exactly once — retry consumer takes over.\n const maxAttempts = retryTopics ? 1 : retry ? retry.maxRetries + 1 : 1;\n const backoffMs = retry?.backoffMs ?? 1000;\n const maxBackoffMs = retry?.maxBackoffMs ?? 30_000;\n const envelopes = Array.isArray(envelope) ? envelope : [envelope];\n const topic = envelopes[0]?.topic ?? \"unknown\";\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const error = await runHandlerWithPipeline(\n fn,\n envelopes,\n interceptors,\n deps.instrumentation,\n );\n if (!error) return;\n\n const isLastAttempt = attempt === maxAttempts;\n const reportedError =\n isLastAttempt && maxAttempts > 1\n ? new KafkaRetryExhaustedError(\n topic,\n envelopes.map((e) => e.payload),\n maxAttempts,\n { cause: error },\n )\n : error;\n\n await notifyInterceptorsOnError(envelopes, interceptors, reportedError);\n\n deps.logger.error(\n `Error processing ${isBatch ? \"batch\" : \"message\"} from topic ${topic} (attempt ${attempt}/${maxAttempts}):`,\n error.stack,\n );\n\n if (retryTopics && retry) {\n // Route to retry topic — retry consumer handles backoff and further attempts.\n // Always use attempt 1 here (main consumer never retries in-process).\n const cap = Math.min(backoffMs, maxBackoffMs);\n const delay = Math.floor(Math.random() * cap);\n await sendToRetryTopic(\n topic,\n rawMessages,\n 1,\n retry.maxRetries,\n delay,\n envelopes[0]?.headers ?? {},\n deps,\n );\n } else if (isLastAttempt) {\n if (dlq) {\n const dlqMeta: DlqMetadata = {\n error,\n attempt,\n originalHeaders: envelopes[0]?.headers,\n };\n for (const raw of rawMessages) {\n await sendToDlq(topic, raw, deps, dlqMeta);\n }\n } else {\n await deps.onMessageLost?.({\n topic,\n error,\n attempt,\n headers: envelopes[0]?.headers ?? {},\n });\n }\n } else {\n // Exponential backoff with full jitter to avoid thundering herd\n const cap = Math.min(backoffMs * 2 ** (attempt - 1), maxBackoffMs);\n await sleep(Math.random() * cap);\n }\n }\n}\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Producer = KafkaJS.Producer;\nimport {\n decodeHeaders,\n extractEnvelope,\n runWithEnvelopeContext,\n} from \"../message/envelope\";\nimport type { EventEnvelope } from \"../message/envelope\";\nimport {\n parseJsonMessage,\n validateWithSchema,\n executeWithRetry,\n} from \"../consumer/pipeline\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n BatchMeta,\n ConsumerInterceptor,\n KafkaClientOptions,\n KafkaInstrumentation,\n KafkaLogger,\n RetryOptions,\n} from \"../types\";\n\nexport type MessageHandlerDeps = {\n logger: KafkaLogger;\n producer: Producer;\n instrumentation: KafkaInstrumentation[];\n onMessageLost: KafkaClientOptions[\"onMessageLost\"];\n};\n\nexport type EachMessageOpts = {\n schemaMap: Map<string, SchemaLike>;\n handleMessage: (envelope: EventEnvelope<any>) => Promise<void>;\n interceptors: ConsumerInterceptor<any>[];\n dlq: boolean;\n retry: RetryOptions | undefined;\n retryTopics: boolean | undefined;\n timeoutMs: number | undefined;\n wrapWithTimeout: <R>(\n fn: () => Promise<R>,\n ms: number,\n topic: string,\n ) => Promise<R>;\n};\n\n/** Parse, validate and extract an envelope from a single raw Kafka message. Returns null to skip. */\nasync function parseSingleMessage(\n message: {\n value: Buffer | null;\n headers?: Record<string, any>;\n offset: string;\n },\n topic: string,\n partition: number,\n schemaMap: Map<string, SchemaLike>,\n interceptors: ConsumerInterceptor<any>[],\n dlq: boolean,\n deps: MessageHandlerDeps,\n): Promise<EventEnvelope<any> | null> {\n if (!message.value) {\n deps.logger.warn(`Received empty message from topic ${topic}`);\n return null;\n }\n\n const raw = message.value.toString();\n const parsed = parseJsonMessage(raw, topic, deps.logger);\n if (parsed === null) return null;\n\n const headers = decodeHeaders(message.headers);\n const validated = await validateWithSchema(\n parsed,\n raw,\n topic,\n schemaMap,\n interceptors,\n dlq,\n { ...deps, originalHeaders: headers },\n );\n if (validated === null) return null;\n\n return extractEnvelope(validated, headers, topic, partition, message.offset);\n}\n\nexport async function handleEachMessage(\n payload: {\n topic: string;\n partition: number;\n message: {\n value: Buffer | null;\n headers?: Record<string, any>;\n offset: string;\n };\n },\n opts: EachMessageOpts,\n deps: MessageHandlerDeps,\n): Promise<void> {\n const { topic, partition, message } = payload;\n const {\n schemaMap,\n handleMessage,\n interceptors,\n dlq,\n retry,\n retryTopics,\n timeoutMs,\n wrapWithTimeout,\n } = opts;\n\n const envelope = await parseSingleMessage(\n message,\n topic,\n partition,\n schemaMap,\n interceptors,\n dlq,\n deps,\n );\n if (envelope === null) return;\n\n await executeWithRetry(\n () => {\n const fn = () =>\n runWithEnvelopeContext(\n {\n correlationId: envelope.correlationId,\n traceparent: envelope.traceparent,\n },\n () => handleMessage(envelope),\n );\n return timeoutMs ? wrapWithTimeout(fn, timeoutMs, topic) : fn();\n },\n {\n envelope,\n rawMessages: [message.value!.toString()],\n interceptors,\n dlq,\n retry,\n retryTopics,\n },\n deps,\n );\n}\n\nexport type EachBatchOpts = {\n schemaMap: Map<string, SchemaLike>;\n handleBatch: (\n envelopes: EventEnvelope<any>[],\n meta: BatchMeta,\n ) => Promise<void>;\n interceptors: ConsumerInterceptor<any>[];\n dlq: boolean;\n retry: RetryOptions | undefined;\n timeoutMs: number | undefined;\n wrapWithTimeout: <R>(\n fn: () => Promise<R>,\n ms: number,\n topic: string,\n ) => Promise<R>;\n};\n\nexport async function handleEachBatch(\n payload: {\n batch: {\n topic: string;\n partition: number;\n highWatermark: string;\n messages: Array<{\n value: Buffer | null;\n headers?: Record<string, any>;\n offset: string;\n }>;\n };\n heartbeat(): Promise<void>;\n resolveOffset(offset: string): void;\n commitOffsetsIfNecessary(): Promise<void>;\n },\n opts: EachBatchOpts,\n deps: MessageHandlerDeps,\n): Promise<void> {\n const { batch, heartbeat, resolveOffset, commitOffsetsIfNecessary } = payload;\n const {\n schemaMap,\n handleBatch,\n interceptors,\n dlq,\n retry,\n timeoutMs,\n wrapWithTimeout,\n } = opts;\n\n const envelopes: EventEnvelope<any>[] = [];\n const rawMessages: string[] = [];\n\n for (const message of batch.messages) {\n const envelope = await parseSingleMessage(\n message,\n batch.topic,\n batch.partition,\n schemaMap,\n interceptors,\n dlq,\n deps,\n );\n if (envelope === null) continue;\n envelopes.push(envelope);\n rawMessages.push(message.value!.toString());\n }\n\n if (envelopes.length === 0) return;\n\n const meta: BatchMeta = {\n partition: batch.partition,\n highWatermark: batch.highWatermark,\n heartbeat,\n resolveOffset,\n commitOffsetsIfNecessary,\n };\n\n await executeWithRetry(\n () => {\n const fn = () => handleBatch(envelopes, meta);\n return timeoutMs ? wrapWithTimeout(fn, timeoutMs, batch.topic) : fn();\n },\n {\n envelope: envelopes,\n rawMessages: batch.messages\n .filter((m) => m.value)\n .map((m) => m.value!.toString()),\n interceptors,\n dlq,\n retry,\n isBatch: true,\n },\n deps,\n );\n}\n","import type { KafkaJS } from \"@confluentinc/kafka-javascript\";\nimport type { KafkaLogger, SubscribeRetryOptions } from \"../types\";\nimport { toError, sleep } from \"./pipeline\";\n\nexport async function subscribeWithRetry(\n consumer: KafkaJS.Consumer,\n topics: string[],\n logger: KafkaLogger,\n retryOpts?: SubscribeRetryOptions,\n): Promise<void> {\n const maxAttempts = retryOpts?.retries ?? 5;\n const backoffMs = retryOpts?.backoffMs ?? 5000;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n await consumer.subscribe({ topics });\n return;\n } catch (error) {\n if (attempt === maxAttempts) throw error;\n const msg = toError(error).message;\n logger.warn(\n `Failed to subscribe to [${topics.join(\", \")}] (attempt ${attempt}/${maxAttempts}): ${msg}. Retrying in ${backoffMs}ms...`,\n );\n await sleep(backoffMs);\n }\n }\n}\n","import { KafkaJS } from \"@confluentinc/kafka-javascript\";\ntype Consumer = KafkaJS.Consumer;\ntype Producer = KafkaJS.Producer;\nimport {\n decodeHeaders,\n extractEnvelope,\n runWithEnvelopeContext,\n} from \"../message/envelope\";\nimport type { EventEnvelope } from \"../message/envelope\";\nimport {\n parseJsonMessage,\n validateWithSchema,\n runHandlerWithPipeline,\n notifyInterceptorsOnError,\n sendToDlq,\n sendToRetryTopic,\n sleep,\n RETRY_HEADER_AFTER,\n RETRY_HEADER_MAX_RETRIES,\n RETRY_HEADER_ORIGINAL_TOPIC,\n} from \"../consumer/pipeline\";\nimport { KafkaRetryExhaustedError } from \"../errors\";\nimport { subscribeWithRetry } from \"../consumer/subscribe-retry\";\nimport type { SchemaLike } from \"../message/topic\";\nimport type {\n ConsumerInterceptor,\n KafkaClientOptions,\n KafkaInstrumentation,\n KafkaLogger,\n} from \"../types\";\n\nexport type RetryTopicDeps = {\n logger: KafkaLogger;\n producer: Producer;\n instrumentation: KafkaInstrumentation[];\n onMessageLost: KafkaClientOptions[\"onMessageLost\"];\n ensureTopic: (topic: string) => Promise<void>;\n getOrCreateConsumer: (\n groupId: string,\n fromBeginning: boolean,\n autoCommit: boolean,\n ) => Consumer;\n runningConsumers: Map<string, \"eachMessage\" | \"eachBatch\">;\n};\n\n/**\n * Poll `consumer.assignment()` until the consumer has received at least one\n * partition for the given topics, then return. Logs a warning and returns\n * (rather than throwing) on timeout so that a slow broker does not break\n * the caller.\n */\nexport async function waitForPartitionAssignment(\n consumer: Consumer,\n topics: string[],\n logger: KafkaLogger,\n timeoutMs = 10_000,\n): Promise<void> {\n const topicSet = new Set(topics);\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n const assigned: { topic: string; partition: number }[] =\n consumer.assignment();\n if (assigned.some((a) => topicSet.has(a.topic))) return;\n } catch {\n // consumer.assignment() throws if not yet in CONNECTED state — keep polling\n }\n await sleep(200);\n }\n logger.warn(\n `Retry consumer did not receive partition assignments for [${topics.join(\", \")}] within ${timeoutMs}ms`,\n );\n}\n\n/**\n * Start a single retry level consumer on `<topic>.retry.<level>`.\n *\n * At-least-once guarantee:\n * - The partition is paused while waiting for the scheduled delay window.\n * The offset is NOT committed during this window, so a process crash\n * causes the message to be redelivered on restart.\n * - The offset is committed only after the handler succeeds OR after the\n * message has been safely routed to the next level / DLQ.\n *\n * Flow per message:\n * 1. If `x-retry-after` is in the future: pause partition → sleep → resume.\n * 2. Validate and call the original handler.\n * 3. On success: commit offset.\n * 4. On failure:\n * - Not exhausted → route to `<topic>.retry.<level+1>`\n * - Exhausted + dlq → send to `<topic>.dlq`\n * - Exhausted, no dlq → call `onMessageLost`\n * 5. Commit offset after routing (message safely in next destination).\n */\nasync function startLevelConsumer(\n level: number,\n levelTopics: string[],\n levelGroupId: string,\n originalTopics: string[],\n handleMessage: (envelope: EventEnvelope<any>) => Promise<void>,\n retry: { maxRetries: number; backoffMs?: number; maxBackoffMs?: number },\n dlq: boolean,\n interceptors: ConsumerInterceptor<any>[],\n schemaMap: Map<string, SchemaLike>,\n deps: RetryTopicDeps,\n assignmentTimeoutMs?: number,\n): Promise<void> {\n const {\n logger,\n producer,\n instrumentation,\n onMessageLost,\n ensureTopic,\n getOrCreateConsumer,\n runningConsumers,\n } = deps;\n\n const backoffMs = retry.backoffMs ?? 1_000;\n const maxBackoffMs = retry.maxBackoffMs ?? 30_000;\n const pipelineDeps = { logger, producer, instrumentation, onMessageLost };\n\n for (const lt of levelTopics) {\n await ensureTopic(lt);\n }\n\n // autoCommit: false — offsets are committed manually after processing.\n const consumer = getOrCreateConsumer(levelGroupId, false, false);\n await consumer.connect();\n await subscribeWithRetry(consumer, levelTopics, logger);\n\n await consumer.run({\n eachMessage: async ({ topic: levelTopic, partition, message }) => {\n const nextOffset = {\n topic: levelTopic,\n partition,\n offset: (parseInt(message.offset, 10) + 1).toString(),\n };\n\n if (!message.value) {\n await consumer.commitOffsets([nextOffset]);\n return;\n }\n\n const headers = decodeHeaders(message.headers);\n const retryAfter = parseInt(\n (headers[RETRY_HEADER_AFTER] as string | undefined) ?? \"0\",\n 10,\n );\n const remaining = retryAfter - Date.now();\n\n // Pause this partition for the scheduled delay.\n // The offset is not committed yet — a crash here causes redelivery (at-least-once).\n if (remaining > 0) {\n consumer.pause([{ topic: levelTopic, partitions: [partition] }]);\n await sleep(remaining);\n consumer.resume([{ topic: levelTopic, partitions: [partition] }]);\n }\n\n const raw = message.value.toString();\n const parsed = parseJsonMessage(raw, levelTopic, logger);\n if (parsed === null) {\n await consumer.commitOffsets([nextOffset]);\n return;\n }\n\n const currentMaxRetries = parseInt(\n (headers[RETRY_HEADER_MAX_RETRIES] as string | undefined) ??\n String(retry.maxRetries),\n 10,\n );\n const originalTopic =\n (headers[RETRY_HEADER_ORIGINAL_TOPIC] as string | undefined) ??\n levelTopic.replace(/\\.retry\\.\\d+$/, \"\");\n\n const validated = await validateWithSchema(\n parsed,\n raw,\n originalTopic,\n schemaMap,\n interceptors,\n dlq,\n { ...pipelineDeps, originalHeaders: headers },\n );\n if (validated === null) {\n await consumer.commitOffsets([nextOffset]);\n return;\n }\n\n const envelope = extractEnvelope(\n validated,\n headers,\n originalTopic,\n partition,\n message.offset,\n );\n\n const error = await runHandlerWithPipeline(\n () =>\n runWithEnvelopeContext(\n {\n correlationId: envelope.correlationId,\n traceparent: envelope.traceparent,\n },\n () => handleMessage(envelope),\n ),\n [envelope],\n interceptors,\n instrumentation,\n );\n\n if (!error) {\n await consumer.commitOffsets([nextOffset]);\n return;\n }\n\n const exhausted = level >= currentMaxRetries;\n const reportedError =\n exhausted && currentMaxRetries > 1\n ? new KafkaRetryExhaustedError(\n originalTopic,\n [envelope.payload],\n currentMaxRetries,\n { cause: error },\n )\n : error;\n\n await notifyInterceptorsOnError([envelope], interceptors, reportedError);\n\n logger.error(\n `Retry consumer error for ${originalTopic} (level ${level}/${currentMaxRetries}):`,\n error.stack,\n );\n\n if (!exhausted) {\n const nextLevel = level + 1;\n // Exponent = current level: level 1 → delay cap = backoffMs * 2^1, etc.\n const cap = Math.min(backoffMs * 2 ** level, maxBackoffMs);\n const delay = Math.floor(Math.random() * cap);\n await sendToRetryTopic(\n originalTopic,\n [raw],\n nextLevel,\n currentMaxRetries,\n delay,\n headers,\n pipelineDeps,\n );\n } else if (dlq) {\n await sendToDlq(originalTopic, raw, pipelineDeps, {\n error,\n // +1 to account for the main consumer's initial attempt before routing.\n attempt: level + 1,\n originalHeaders: headers,\n });\n } else {\n await onMessageLost?.({\n topic: originalTopic,\n error,\n attempt: level,\n headers,\n });\n }\n\n // Commit after routing — the message is safely in the next destination.\n // If we crash between routing and this commit, the message is redelivered\n // and routed again (duplicate in the next level), which is acceptable for\n // at-least-once semantics.\n await consumer.commitOffsets([nextOffset]);\n },\n });\n\n runningConsumers.set(levelGroupId, \"eachMessage\");\n\n await waitForPartitionAssignment(consumer, levelTopics, logger, assignmentTimeoutMs);\n\n logger.log(\n `Retry level ${level}/${retry.maxRetries} consumer started for: ${originalTopics.join(\", \")} (group: ${levelGroupId})`,\n );\n}\n\n/**\n * Start one consumer per retry level on `<topic>.retry.<level>` topics.\n *\n * With `maxRetries: N`, creates N consumers:\n * - `${groupId}-retry.1` → `<topic>.retry.1`\n * - `${groupId}-retry.2` → `<topic>.retry.2`\n * - …\n * - `${groupId}-retry.N` → `<topic>.retry.N`\n *\n * Each level consumer uses pause/sleep/resume to honour the scheduled delay\n * without committing the offset early, guaranteeing at-least-once delivery\n * of retry messages even across process restarts.\n *\n * Returns the list of started consumer group IDs so the caller can stop\n * them selectively via `stopConsumer`.\n */\nexport async function startRetryTopicConsumers(\n originalTopics: string[],\n originalGroupId: string,\n handleMessage: (envelope: EventEnvelope<any>) => Promise<void>,\n retry: { maxRetries: number; backoffMs?: number; maxBackoffMs?: number },\n dlq: boolean,\n interceptors: ConsumerInterceptor<any>[],\n schemaMap: Map<string, SchemaLike>,\n deps: RetryTopicDeps,\n assignmentTimeoutMs?: number,\n): Promise<string[]> {\n const levelGroupIds: string[] = [];\n\n for (let level = 1; level <= retry.maxRetries; level++) {\n const levelTopics = originalTopics.map((t) => `${t}.retry.${level}`);\n const levelGroupId = `${originalGroupId}-retry.${level}`;\n\n await startLevelConsumer(\n level,\n levelTopics,\n levelGroupId,\n originalTopics,\n handleMessage,\n retry,\n dlq,\n interceptors,\n schemaMap,\n deps,\n assignmentTimeoutMs,\n );\n\n levelGroupIds.push(levelGroupId);\n }\n\n return levelGroupIds;\n}\n","/**\n * Any validation library with a `.parse()` method.\n * Works with Zod, Valibot, ArkType, or any custom validator.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n * const schema: SchemaLike<{ id: string }> = z.object({ id: z.string() });\n * ```\n */\nexport interface SchemaLike<T = any> {\n parse(data: unknown): T | Promise<T>;\n}\n\n/** Infer the output type from a SchemaLike. */\nexport type InferSchema<S extends SchemaLike> =\n S extends SchemaLike<infer T> ? T : never;\n\n/**\n * A typed topic descriptor that pairs a topic name with its message type.\n * Created via the `topic()` factory function.\n *\n * @typeParam N - The literal topic name string.\n * @typeParam M - The message payload type for this topic.\n */\nexport interface TopicDescriptor<\n N extends string = string,\n M extends Record<string, any> = Record<string, any>,\n> {\n readonly __topic: N;\n /** @internal Phantom type — never has a real value at runtime. */\n readonly __type: M;\n /** Runtime schema validator. Present only when created via `topic().schema()`. */\n readonly __schema?: SchemaLike<M>;\n}\n\n/**\n * Define a typed topic descriptor.\n *\n * @example\n * ```ts\n * // Without schema — explicit type via .type<T>():\n * const OrderCreated = topic('order.created').type<{ orderId: string; amount: number }>();\n *\n * // With schema — type inferred from schema:\n * const OrderCreated = topic('order.created').schema(z.object({\n * orderId: z.string(),\n * amount: z.number(),\n * }));\n *\n * // Use with KafkaClient:\n * await kafka.sendMessage(OrderCreated, { orderId: '123', amount: 100 });\n *\n * // Use with @SubscribeTo:\n * @SubscribeTo(OrderCreated)\n * async handleOrder(msg) { ... }\n * ```\n */\nexport function topic<N extends string>(name: N) {\n return {\n /** Provide an explicit message type without a runtime schema. */\n type: <M extends Record<string, any>>(): TopicDescriptor<N, M> => ({\n __topic: name,\n __type: undefined as unknown as M,\n }),\n\n schema: <S extends SchemaLike<Record<string, any>>>(\n schema: S,\n ): TopicDescriptor<N, InferSchema<S>> => ({\n __topic: name,\n __type: undefined as unknown as InferSchema<S>,\n __schema: schema as unknown as SchemaLike<InferSchema<S>>,\n }),\n };\n}\n\n/**\n * Build a topic-message map type from a union of TopicDescriptors.\n *\n * @example\n * ```ts\n * const OrderCreated = topic('order.created').type<{ orderId: string }>();\n * const OrderCompleted = topic('order.completed').type<{ completedAt: string }>();\n *\n * type MyTopics = TopicsFrom<typeof OrderCreated | typeof OrderCompleted>;\n * // { 'order.created': { orderId: string }; 'order.completed': { completedAt: string } }\n * ```\n */\nexport type TopicsFrom<D extends TopicDescriptor<any, any>> = {\n [K in D as K[\"__topic\"]]: K[\"__type\"];\n};\n"],"mappings":"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","names":["topic","topic","topic","topic","topic","getOrCreateConsumer","topic"]}
|
package/dist/core.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { KafkaClient } from './core.mjs';
|
|
2
2
|
export { KafkaProcessingError, KafkaRetryExhaustedError, KafkaValidationError } from './core.mjs';
|
|
3
|
-
import { T as TopicMapConstraint, C as ClientId, G as GroupId, K as KafkaInstrumentation, a as KafkaClientOptions, S as SchemaLike, b as ConsumerOptions, c as TopicDescriptor } from './
|
|
4
|
-
export { B as BatchMessageItem,
|
|
3
|
+
import { T as TopicMapConstraint, C as ClientId, G as GroupId, K as KafkaInstrumentation, a as KafkaClientOptions, S as SchemaLike, b as ConsumerOptions, c as TopicDescriptor, d as KafkaHealthResult } from './types-DwERZ6ql.mjs';
|
|
4
|
+
export { B as BatchMessageItem, e as BatchMeta, f as ConsumerHandle, g as ConsumerInterceptor, E as EnvelopeHeaderOptions, h as EventEnvelope, H as HEADER_CORRELATION_ID, i as HEADER_EVENT_ID, j as HEADER_SCHEMA_VERSION, k as HEADER_TIMESTAMP, l as HEADER_TRACEPARENT, I as IKafkaClient, m as InferSchema, n as KafkaLogger, M as MessageHeaders, o as MessageLostContext, R as RetryOptions, p as SendOptions, q as SubscribeRetryOptions, r as TTopicMessageMap, s as TopicsFrom, t as TransactionContext, u as buildEnvelopeHeaders, v as decodeHeaders, w as extractEnvelope, x as getEnvelopeContext, y as runWithEnvelopeContext, z as topic } from './types-DwERZ6ql.mjs';
|
|
5
5
|
import { DynamicModule, OnModuleInit } from '@nestjs/common';
|
|
6
6
|
import { DiscoveryService, ModuleRef } from '@nestjs/core';
|
|
7
7
|
|
|
@@ -86,19 +86,9 @@ declare class KafkaExplorer implements OnModuleInit {
|
|
|
86
86
|
onModuleInit(): Promise<void>;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/** Result returned by `KafkaHealthIndicator.check()`. */
|
|
90
|
-
type KafkaHealthResult = {
|
|
91
|
-
status: "up";
|
|
92
|
-
clientId: string;
|
|
93
|
-
topics: string[];
|
|
94
|
-
} | {
|
|
95
|
-
status: "down";
|
|
96
|
-
clientId: string;
|
|
97
|
-
error: string;
|
|
98
|
-
};
|
|
99
89
|
/** Health check service. Call `check(client)` to verify broker connectivity. */
|
|
100
90
|
declare class KafkaHealthIndicator {
|
|
101
91
|
check<T extends TopicMapConstraint<T>>(client: KafkaClient<T>): Promise<KafkaHealthResult>;
|
|
102
92
|
}
|
|
103
93
|
|
|
104
|
-
export { ClientId, ConsumerOptions, GroupId, InjectKafkaClient, KAFKA_CLIENT, KAFKA_SUBSCRIBER_METADATA, KafkaClient, KafkaClientOptions, KafkaExplorer, KafkaHealthIndicator,
|
|
94
|
+
export { ClientId, ConsumerOptions, GroupId, InjectKafkaClient, KAFKA_CLIENT, KAFKA_SUBSCRIBER_METADATA, KafkaClient, KafkaClientOptions, KafkaExplorer, KafkaHealthIndicator, KafkaHealthResult, KafkaInstrumentation, KafkaModule, type KafkaModuleAsyncOptions, type KafkaModuleOptions, type KafkaSubscriberMetadata, SchemaLike, SubscribeTo, TopicDescriptor, TopicMapConstraint, getKafkaClientToken };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { KafkaClient } from './core.js';
|
|
2
2
|
export { KafkaProcessingError, KafkaRetryExhaustedError, KafkaValidationError } from './core.js';
|
|
3
|
-
import { T as TopicMapConstraint, C as ClientId, G as GroupId, K as KafkaInstrumentation, a as KafkaClientOptions, S as SchemaLike, b as ConsumerOptions, c as TopicDescriptor } from './
|
|
4
|
-
export { B as BatchMessageItem,
|
|
3
|
+
import { T as TopicMapConstraint, C as ClientId, G as GroupId, K as KafkaInstrumentation, a as KafkaClientOptions, S as SchemaLike, b as ConsumerOptions, c as TopicDescriptor, d as KafkaHealthResult } from './types-DwERZ6ql.js';
|
|
4
|
+
export { B as BatchMessageItem, e as BatchMeta, f as ConsumerHandle, g as ConsumerInterceptor, E as EnvelopeHeaderOptions, h as EventEnvelope, H as HEADER_CORRELATION_ID, i as HEADER_EVENT_ID, j as HEADER_SCHEMA_VERSION, k as HEADER_TIMESTAMP, l as HEADER_TRACEPARENT, I as IKafkaClient, m as InferSchema, n as KafkaLogger, M as MessageHeaders, o as MessageLostContext, R as RetryOptions, p as SendOptions, q as SubscribeRetryOptions, r as TTopicMessageMap, s as TopicsFrom, t as TransactionContext, u as buildEnvelopeHeaders, v as decodeHeaders, w as extractEnvelope, x as getEnvelopeContext, y as runWithEnvelopeContext, z as topic } from './types-DwERZ6ql.js';
|
|
5
5
|
import { DynamicModule, OnModuleInit } from '@nestjs/common';
|
|
6
6
|
import { DiscoveryService, ModuleRef } from '@nestjs/core';
|
|
7
7
|
|
|
@@ -86,19 +86,9 @@ declare class KafkaExplorer implements OnModuleInit {
|
|
|
86
86
|
onModuleInit(): Promise<void>;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/** Result returned by `KafkaHealthIndicator.check()`. */
|
|
90
|
-
type KafkaHealthResult = {
|
|
91
|
-
status: "up";
|
|
92
|
-
clientId: string;
|
|
93
|
-
topics: string[];
|
|
94
|
-
} | {
|
|
95
|
-
status: "down";
|
|
96
|
-
clientId: string;
|
|
97
|
-
error: string;
|
|
98
|
-
};
|
|
99
89
|
/** Health check service. Call `check(client)` to verify broker connectivity. */
|
|
100
90
|
declare class KafkaHealthIndicator {
|
|
101
91
|
check<T extends TopicMapConstraint<T>>(client: KafkaClient<T>): Promise<KafkaHealthResult>;
|
|
102
92
|
}
|
|
103
93
|
|
|
104
|
-
export { ClientId, ConsumerOptions, GroupId, InjectKafkaClient, KAFKA_CLIENT, KAFKA_SUBSCRIBER_METADATA, KafkaClient, KafkaClientOptions, KafkaExplorer, KafkaHealthIndicator,
|
|
94
|
+
export { ClientId, ConsumerOptions, GroupId, InjectKafkaClient, KAFKA_CLIENT, KAFKA_SUBSCRIBER_METADATA, KafkaClient, KafkaClientOptions, KafkaExplorer, KafkaHealthIndicator, KafkaHealthResult, KafkaInstrumentation, KafkaModule, type KafkaModuleAsyncOptions, type KafkaModuleOptions, type KafkaSubscriberMetadata, SchemaLike, SubscribeTo, TopicDescriptor, TopicMapConstraint, getKafkaClientToken };
|