@drarzter/kafka-client 0.1.8 → 0.1.9

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/dist/index.d.mts CHANGED
@@ -136,6 +136,7 @@ interface IKafkaClient<T extends TopicMapConstraint<T>> {
136
136
  topics: string[];
137
137
  }>;
138
138
  startConsumer<K extends Array<keyof T>>(topics: K, handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
139
+ startConsumer<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(topics: D[], handleMessage: (message: D["__type"], topic: D["__topic"]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
139
140
  stopConsumer(): Promise<void>;
140
141
  sendMessage<K extends keyof T>(topic: K, message: T[K], options?: SendOptions): Promise<void>;
141
142
  sendBatch<K extends keyof T>(topic: K, messages: Array<{
@@ -149,7 +150,7 @@ interface IKafkaClient<T extends TopicMapConstraint<T>> {
149
150
  }
150
151
  /** Options for `KafkaClient` constructor. */
151
152
  interface KafkaClientOptions {
152
- /** Auto-create topics via admin on first use (send/consume). Useful for development. */
153
+ /** Auto-create topics via admin before the first `sendMessage`, `sendBatch`, `transaction`, or `startConsumer` for each topic. Useful for development — not recommended in production. */
153
154
  autoCreateTopics?: boolean;
154
155
  }
155
156
 
@@ -192,7 +193,8 @@ declare class KafkaClient<T extends TopicMapConstraint<T>> implements IKafkaClie
192
193
  connectProducer(): Promise<void>;
193
194
  disconnectProducer(): Promise<void>;
194
195
  /** Subscribe to topics and start consuming messages with the given handler. */
195
- startConsumer<K extends Array<keyof T>>(topics: K | TopicDescriptor[], handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
196
+ startConsumer<K extends Array<keyof T>>(topics: K, handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
197
+ startConsumer<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(topics: D[], handleMessage: (message: D["__type"], topic: D["__topic"]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
196
198
  stopConsumer(): Promise<void>;
197
199
  /** Check broker connectivity and return available topics. */
198
200
  checkStatus(): Promise<{
@@ -247,6 +249,7 @@ declare class KafkaModule {
247
249
  declare class KafkaProcessingError extends Error {
248
250
  readonly topic: string;
249
251
  readonly originalMessage: unknown;
252
+ readonly cause?: Error;
250
253
  constructor(message: string, topic: string, originalMessage: unknown, options?: {
251
254
  cause?: Error;
252
255
  });
package/dist/index.d.ts CHANGED
@@ -136,6 +136,7 @@ interface IKafkaClient<T extends TopicMapConstraint<T>> {
136
136
  topics: string[];
137
137
  }>;
138
138
  startConsumer<K extends Array<keyof T>>(topics: K, handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
139
+ startConsumer<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(topics: D[], handleMessage: (message: D["__type"], topic: D["__topic"]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
139
140
  stopConsumer(): Promise<void>;
140
141
  sendMessage<K extends keyof T>(topic: K, message: T[K], options?: SendOptions): Promise<void>;
141
142
  sendBatch<K extends keyof T>(topic: K, messages: Array<{
@@ -149,7 +150,7 @@ interface IKafkaClient<T extends TopicMapConstraint<T>> {
149
150
  }
150
151
  /** Options for `KafkaClient` constructor. */
151
152
  interface KafkaClientOptions {
152
- /** Auto-create topics via admin on first use (send/consume). Useful for development. */
153
+ /** Auto-create topics via admin before the first `sendMessage`, `sendBatch`, `transaction`, or `startConsumer` for each topic. Useful for development — not recommended in production. */
153
154
  autoCreateTopics?: boolean;
154
155
  }
155
156
 
@@ -192,7 +193,8 @@ declare class KafkaClient<T extends TopicMapConstraint<T>> implements IKafkaClie
192
193
  connectProducer(): Promise<void>;
193
194
  disconnectProducer(): Promise<void>;
194
195
  /** Subscribe to topics and start consuming messages with the given handler. */
195
- startConsumer<K extends Array<keyof T>>(topics: K | TopicDescriptor[], handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
196
+ startConsumer<K extends Array<keyof T>>(topics: K, handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
197
+ startConsumer<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(topics: D[], handleMessage: (message: D["__type"], topic: D["__topic"]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
196
198
  stopConsumer(): Promise<void>;
197
199
  /** Check broker connectivity and return available topics. */
198
200
  checkStatus(): Promise<{
@@ -247,6 +249,7 @@ declare class KafkaModule {
247
249
  declare class KafkaProcessingError extends Error {
248
250
  readonly topic: string;
249
251
  readonly originalMessage: unknown;
252
+ readonly cause?: Error;
250
253
  constructor(message: string, topic: string, originalMessage: unknown, options?: {
251
254
  cause?: Error;
252
255
  });
package/dist/index.js CHANGED
@@ -59,6 +59,7 @@ var KafkaProcessingError = class extends Error {
59
59
  this.topic = topic2;
60
60
  this.originalMessage = originalMessage;
61
61
  this.name = "KafkaProcessingError";
62
+ if (options?.cause) this.cause = options.cause;
62
63
  }
63
64
  };
64
65
  var KafkaRetryExhaustedError = class extends KafkaProcessingError {
@@ -198,7 +199,6 @@ var KafkaClient = class {
198
199
  await this.producer.disconnect();
199
200
  this.logger.log("Producer disconnected");
200
201
  }
201
- /** Subscribe to topics and start consuming messages with the given handler. */
202
202
  async startConsumer(topics, handleMessage, options = {}) {
203
203
  const {
204
204
  fromBeginning = false,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/module/kafka.module.ts","../src/client/kafka.client.ts","../src/client/errors.ts","../src/module/kafka.constants.ts","../src/module/kafka.explorer.ts","../src/decorators/kafka.decorator.ts","../src/client/topic.ts","../src/health/kafka.health.ts"],"sourcesContent":["export * from \"./module/kafka.module\";\nexport * from \"./client/kafka.client\";\nexport * from \"./client/topic\";\nexport * from \"./client/errors\";\nexport * from \"./module/kafka.constants\";\nexport * from \"./decorators/kafka.decorator\";\nexport * from \"./module/kafka.explorer\";\nexport * from \"./health/kafka.health\";\n","import { Module, DynamicModule, Provider } from \"@nestjs/common\";\nimport { DiscoveryModule } from \"@nestjs/core\";\nimport {\n KafkaClient,\n ClientId,\n GroupId,\n TopicMapConstraint,\n} from \"../client/kafka.client\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\nimport { KafkaExplorer } from \"./kafka.explorer\";\n\n/** Synchronous configuration for `KafkaModule.register()`. */\nexport interface KafkaModuleOptions {\n /** Optional name for multi-client setups. Must match `@InjectKafkaClient(name)`. */\n name?: string;\n /** Unique Kafka client identifier. */\n clientId: ClientId;\n /** Consumer group identifier. */\n groupId: GroupId;\n /** List of Kafka broker addresses. */\n brokers: string[];\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n}\n\n/** Async configuration for `KafkaModule.registerAsync()` with dependency injection. */\nexport interface KafkaModuleAsyncOptions {\n name?: string;\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n imports?: any[];\n useFactory: (\n ...args: any[]\n ) => KafkaModuleOptions | Promise<KafkaModuleOptions>;\n inject?: any[];\n}\n\n/**\n * NestJS dynamic module for registering type-safe Kafka clients.\n * Use `register()` for static config or `registerAsync()` for DI-based config.\n */\n@Module({})\nexport class KafkaModule {\n /** Register a Kafka client with static options. */\n static register<T extends TopicMapConstraint<T>>(\n options: KafkaModuleOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(options.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (): Promise<KafkaClient<T>> => {\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: options.isGlobal ?? false,\n module: KafkaModule,\n imports: [DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n\n /** Register a Kafka client with async/factory-based options. */\n static registerAsync<T extends TopicMapConstraint<T>>(\n asyncOptions: KafkaModuleAsyncOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(asyncOptions.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (...args: any[]): Promise<KafkaClient<T>> => {\n const options = await asyncOptions.useFactory(...args);\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n inject: asyncOptions.inject || [],\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: asyncOptions.isGlobal ?? false,\n module: KafkaModule,\n imports: [...(asyncOptions.imports || []), DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n}\n","import { Consumer, Kafka, Partitioners, Producer, Admin } from \"kafkajs\";\nimport { Logger } from \"@nestjs/common\";\nimport { TopicDescriptor } from \"./topic\";\nimport { KafkaRetryExhaustedError } from \"./errors\";\nimport type {\n ClientId,\n GroupId,\n SendOptions,\n MessageHeaders,\n ConsumerOptions,\n TransactionContext,\n TopicMapConstraint,\n IKafkaClient,\n KafkaClientOptions,\n} from \"./types\";\n\n// Re-export all types so existing `import { ... } from './kafka.client'` keeps working\nexport * from \"./types\";\n\n/**\n * Type-safe Kafka client for NestJS.\n * Wraps kafkajs with JSON serialization, retries, DLQ, transactions, and interceptors.\n *\n * @typeParam T - Topic-to-message type mapping for compile-time safety.\n */\nexport class KafkaClient<T extends TopicMapConstraint<T>>\n implements IKafkaClient<T>\n{\n private readonly kafka: Kafka;\n private readonly producer: Producer;\n private readonly consumer: Consumer;\n private readonly admin: Admin;\n private readonly logger: Logger;\n private readonly autoCreateTopicsEnabled: boolean;\n private readonly ensuredTopics = new Set<string>();\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.logger = new Logger(`KafkaClient:${clientId}`);\n this.autoCreateTopicsEnabled = options?.autoCreateTopics ?? false;\n\n this.kafka = new Kafka({\n clientId: this.clientId,\n brokers,\n });\n this.producer = this.kafka.producer({\n createPartitioner: Partitioners.DefaultPartitioner,\n idempotent: true,\n transactionalId: `${clientId}-tx`,\n maxInFlightRequests: 1,\n });\n this.consumer = this.kafka.consumer({ groupId });\n this.admin = this.kafka.admin();\n }\n\n private 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 TopicDescriptor).__topic;\n }\n return String(topicOrDescriptor);\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: 1 }],\n });\n this.ensuredTopics.add(topic);\n }\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 topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\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<{\n value: D[\"__type\"];\n key?: string;\n headers?: MessageHeaders;\n }>,\n ): Promise<void>;\n public async sendBatch<K extends keyof T>(\n topic: K,\n messages: Array<{ value: T[K]; key?: string; headers?: MessageHeaders }>,\n ): Promise<void>;\n public async sendBatch(\n topicOrDesc: any,\n messages: Array<{ value: any; key?: string; headers?: MessageHeaders }>,\n ): Promise<void> {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: messages.map((m) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\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 const tx = await this.producer.transaction();\n try {\n const ctx: TransactionContext<T> = {\n send: async (\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\n },\n sendBatch: async (topicOrDesc: any, messages: any[]) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: messages.map((m: any) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\n },\n };\n await fn(ctx);\n await tx.commit();\n } catch (error) {\n await tx.abort();\n throw error;\n }\n }\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 /** Subscribe to topics and start consuming messages with the given handler. */\n public async startConsumer<K extends Array<keyof T>>(\n topics: K | TopicDescriptor[],\n handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<void> {\n const {\n fromBeginning = false,\n autoCommit = true,\n retry,\n dlq = false,\n interceptors = [],\n } = options;\n\n const topicNames = (topics as any[]).map((t: any) =>\n this.resolveTopicName(t),\n );\n\n await this.consumer.connect();\n\n for (const t of topicNames) {\n await this.ensureTopic(t);\n }\n\n await this.consumer.subscribe({ topics: topicNames, fromBeginning });\n\n this.logger.log(`Consumer subscribed to topics: ${topicNames.join(\", \")}`);\n\n await this.consumer.run({\n autoCommit,\n eachMessage: async ({ topic, message }) => {\n if (!message.value) {\n this.logger.warn(`Received empty message from topic ${topic}`);\n return;\n }\n\n const raw = message.value.toString();\n let parsedMessage: T[K[number]];\n\n try {\n parsedMessage = JSON.parse(raw) as T[K[number]];\n } catch (error) {\n this.logger.error(\n `Failed to parse message from topic ${topic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n return;\n }\n\n await this.processMessage(parsedMessage, raw, topic, handleMessage, {\n retry,\n dlq,\n interceptors,\n });\n },\n });\n }\n\n public async stopConsumer(): Promise<void> {\n\n await this.consumer.disconnect();\n this.logger.log(\"Consumer disconnected\");\n }\n\n /** Check broker connectivity and return available topics. */\n public async checkStatus(): Promise<{ topics: string[] }> {\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n const topics = await this.admin.listTopics();\n return { topics };\n }\n\n public getClientId(): ClientId {\n return this.clientId;\n }\n\n /** Gracefully disconnect producer, consumer, and admin. */\n public async disconnect(): Promise<void> {\n\n const tasks = [this.producer.disconnect(), this.consumer.disconnect()];\n if (this.isAdminConnected) {\n tasks.push(this.admin.disconnect());\n this.isAdminConnected = false;\n }\n await Promise.allSettled(tasks);\n this.logger.log(\"All connections closed\");\n }\n\n // --- Private helpers ---\n\n private async processMessage<K extends Array<keyof T>>(\n parsedMessage: T[K[number]],\n raw: string,\n topic: string,\n handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>,\n opts: Pick<ConsumerOptions<T>, \"retry\" | \"dlq\" | \"interceptors\">,\n ): Promise<void> {\n const { retry, dlq = false, interceptors = [] } = opts;\n const maxAttempts = retry ? retry.maxRetries + 1 : 1;\n const backoffMs = retry?.backoffMs ?? 1000;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n for (const interceptor of interceptors) {\n await interceptor.before?.(parsedMessage, topic);\n }\n\n await handleMessage(parsedMessage, topic as K[number]);\n\n for (const interceptor of interceptors) {\n await interceptor.after?.(parsedMessage, topic);\n }\n return;\n } catch (error) {\n const err =\n error instanceof Error ? error : new Error(String(error));\n const isLastAttempt = attempt === maxAttempts;\n\n if (isLastAttempt && maxAttempts > 1) {\n const exhaustedError = new KafkaRetryExhaustedError(\n topic,\n parsedMessage,\n maxAttempts,\n { cause: err },\n );\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, exhaustedError);\n }\n } else {\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, err);\n }\n }\n\n this.logger.error(\n `Error processing message from topic ${topic} (attempt ${attempt}/${maxAttempts}):`,\n err.stack,\n );\n\n if (isLastAttempt) {\n if (dlq) await this.sendToDlq(topic, raw);\n } else {\n await this.sleep(backoffMs * attempt);\n }\n }\n }\n }\n\n private async sendToDlq(topic: string, rawMessage: string): Promise<void> {\n const dlqTopic = `${topic}.dlq`;\n try {\n await this.producer.send({\n topic: dlqTopic,\n messages: [{ value: rawMessage }],\n acks: -1,\n });\n this.logger.warn(`Message sent to DLQ: ${dlqTopic}`);\n } catch (error) {\n this.logger.error(\n `Failed to send message to DLQ ${dlqTopic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/** Error thrown when a consumer message handler fails. */\nexport class KafkaProcessingError extends Error {\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 }\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","/** Default DI token for the Kafka client. */\nexport const KAFKA_CLIENT = \"KAFKA_CLIENT\";\n\n/** Returns the DI token for a named (or default) Kafka client instance. */\nexport const getKafkaClientToken = (name?: string): string =>\n name ? `KAFKA_CLIENT_${name}` : KAFKA_CLIENT;\n","import { Inject, Injectable, OnModuleInit, Logger } from \"@nestjs/common\";\nimport { DiscoveryService, ModuleRef } from \"@nestjs/core\";\nimport { KafkaClient } from \"../client/kafka.client\";\nimport {\n KAFKA_SUBSCRIBER_METADATA,\n KafkaSubscriberMetadata,\n} from \"../decorators/kafka.decorator\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\n\ninterface SubscriberEntry extends KafkaSubscriberMetadata {\n methodName: string | symbol;\n}\n\n/** Discovers `@SubscribeTo()` decorators and wires them to their Kafka clients on startup. */\n@Injectable()\nexport class KafkaExplorer implements OnModuleInit {\n private readonly logger = new Logger(KafkaExplorer.name);\n\n constructor(\n @Inject(DiscoveryService)\n private readonly discoveryService: DiscoveryService,\n @Inject(ModuleRef)\n private readonly moduleRef: ModuleRef,\n ) {}\n\n async onModuleInit() {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n const { instance } = wrapper;\n if (!instance || typeof instance !== \"object\") continue;\n\n const metadata: SubscriberEntry[] | undefined = Reflect.getMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n instance.constructor,\n );\n\n if (!metadata || metadata.length === 0) continue;\n\n for (const entry of metadata) {\n const token = getKafkaClientToken(entry.clientName);\n let client: KafkaClient<any>;\n\n try {\n client = this.moduleRef.get(token, { strict: false });\n } catch {\n this.logger.error(\n `KafkaClient \"${entry.clientName || \"default\"}\" not found for @SubscribeTo on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n continue;\n }\n\n const handler = (instance as any)[entry.methodName].bind(instance);\n\n await client.startConsumer(\n entry.topics as any,\n async (message: any, topic: any) => {\n await handler(message, topic);\n },\n entry.options,\n );\n\n this.logger.log(\n `Registered @SubscribeTo(${entry.topics.join(\", \")}) on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n }\n }\n }\n}\n","import { Inject } from \"@nestjs/common\";\nimport { getKafkaClientToken } from \"../module/kafka.constants\";\nimport { ConsumerOptions } from \"../client/kafka.client\";\nimport { TopicDescriptor } from \"../client/topic\";\n\nexport const KAFKA_SUBSCRIBER_METADATA = \"KAFKA_SUBSCRIBER_METADATA\";\n\nexport interface KafkaSubscriberMetadata {\n topics: string[];\n options?: ConsumerOptions;\n clientName?: string;\n}\n\n/** Inject a `KafkaClient` instance. Pass a name to target a specific named client. */\nexport const InjectKafkaClient = (name?: string): ParameterDecorator =>\n Inject(getKafkaClientToken(name));\n\n/**\n * Decorator that auto-subscribes a method to Kafka topics on module init.\n * The decorated method receives `(message, topic)` for each consumed message.\n */\nexport const SubscribeTo = (\n topics:\n | string\n | string[]\n | TopicDescriptor\n | TopicDescriptor[]\n | (string | TopicDescriptor)[],\n options?: ConsumerOptions & { clientName?: string },\n): MethodDecorator => {\n const arr = Array.isArray(topics) ? topics : [topics];\n const topicsArray = arr.map((t) =>\n typeof t === \"string\" ? t : t.__topic,\n );\n const { clientName, ...consumerOptions } = options || {};\n\n return (target, propertyKey, _descriptor) => {\n const existing: KafkaSubscriberMetadata[] =\n Reflect.getMetadata(KAFKA_SUBSCRIBER_METADATA, target.constructor) || [];\n\n Reflect.defineMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n [\n ...existing,\n {\n topics: topicsArray,\n options: Object.keys(consumerOptions).length\n ? consumerOptions\n : undefined,\n clientName,\n methodName: propertyKey,\n },\n ],\n target.constructor,\n );\n };\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}\n\n/**\n * Define a typed topic descriptor.\n *\n * @example\n * ```ts\n * const OrderCreated = topic('order.created')<{ orderId: string; amount: number }>();\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 <M extends Record<string, any>>(): TopicDescriptor<N, M> => ({\n __topic: name,\n __type: undefined as unknown as M,\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')<{ 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","import { Injectable } from \"@nestjs/common\";\nimport { KafkaClient, TopicMapConstraint } from \"../client/kafka.client\";\n\n/** Result returned by `KafkaHealthIndicator.check()`. */\nexport interface KafkaHealthResult {\n status: \"up\" | \"down\";\n clientId: string;\n topics?: string[];\n error?: string;\n}\n\n/** Health check service. Call `check(client)` to verify broker connectivity. */\n@Injectable()\nexport class KafkaHealthIndicator {\n async check<T extends TopicMapConstraint<T>>(\n client: KafkaClient<T>,\n ): Promise<KafkaHealthResult> {\n try {\n const { topics } = await client.checkStatus();\n return {\n status: \"up\",\n clientId: client.clientId,\n topics,\n };\n } catch (error) {\n return {\n status: \"down\",\n clientId: client.clientId,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n"],"mappings":"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","names":["import_common","import_core","topic","topic","import_common","import_common","topic","import_common"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/module/kafka.module.ts","../src/client/kafka.client.ts","../src/client/errors.ts","../src/module/kafka.constants.ts","../src/module/kafka.explorer.ts","../src/decorators/kafka.decorator.ts","../src/client/topic.ts","../src/health/kafka.health.ts"],"sourcesContent":["export * from \"./module/kafka.module\";\nexport * from \"./client/kafka.client\";\nexport * from \"./client/topic\";\nexport * from \"./client/errors\";\nexport * from \"./module/kafka.constants\";\nexport * from \"./decorators/kafka.decorator\";\nexport * from \"./module/kafka.explorer\";\nexport * from \"./health/kafka.health\";\n","import { Module, DynamicModule, Provider } from \"@nestjs/common\";\nimport { DiscoveryModule } from \"@nestjs/core\";\nimport {\n KafkaClient,\n ClientId,\n GroupId,\n TopicMapConstraint,\n} from \"../client/kafka.client\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\nimport { KafkaExplorer } from \"./kafka.explorer\";\n\n/** Synchronous configuration for `KafkaModule.register()`. */\nexport interface KafkaModuleOptions {\n /** Optional name for multi-client setups. Must match `@InjectKafkaClient(name)`. */\n name?: string;\n /** Unique Kafka client identifier. */\n clientId: ClientId;\n /** Consumer group identifier. */\n groupId: GroupId;\n /** List of Kafka broker addresses. */\n brokers: string[];\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n}\n\n/** Async configuration for `KafkaModule.registerAsync()` with dependency injection. */\nexport interface KafkaModuleAsyncOptions {\n name?: string;\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n imports?: any[];\n useFactory: (\n ...args: any[]\n ) => KafkaModuleOptions | Promise<KafkaModuleOptions>;\n inject?: any[];\n}\n\n/**\n * NestJS dynamic module for registering type-safe Kafka clients.\n * Use `register()` for static config or `registerAsync()` for DI-based config.\n */\n@Module({})\nexport class KafkaModule {\n /** Register a Kafka client with static options. */\n static register<T extends TopicMapConstraint<T>>(\n options: KafkaModuleOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(options.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (): Promise<KafkaClient<T>> => {\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: options.isGlobal ?? false,\n module: KafkaModule,\n imports: [DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n\n /** Register a Kafka client with async/factory-based options. */\n static registerAsync<T extends TopicMapConstraint<T>>(\n asyncOptions: KafkaModuleAsyncOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(asyncOptions.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (...args: any[]): Promise<KafkaClient<T>> => {\n const options = await asyncOptions.useFactory(...args);\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n inject: asyncOptions.inject || [],\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: asyncOptions.isGlobal ?? false,\n module: KafkaModule,\n imports: [...(asyncOptions.imports || []), DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n}\n","import { Consumer, Kafka, Partitioners, Producer, Admin } from \"kafkajs\";\nimport { Logger } from \"@nestjs/common\";\nimport { TopicDescriptor } from \"./topic\";\nimport { KafkaRetryExhaustedError } from \"./errors\";\nimport type {\n ClientId,\n GroupId,\n SendOptions,\n MessageHeaders,\n ConsumerOptions,\n TransactionContext,\n TopicMapConstraint,\n IKafkaClient,\n KafkaClientOptions,\n} from \"./types\";\n\n// Re-export all types so existing `import { ... } from './kafka.client'` keeps working\nexport * from \"./types\";\n\n/**\n * Type-safe Kafka client for NestJS.\n * Wraps kafkajs with JSON serialization, retries, DLQ, transactions, and interceptors.\n *\n * @typeParam T - Topic-to-message type mapping for compile-time safety.\n */\nexport class KafkaClient<T extends TopicMapConstraint<T>>\n implements IKafkaClient<T>\n{\n private readonly kafka: Kafka;\n private readonly producer: Producer;\n private readonly consumer: Consumer;\n private readonly admin: Admin;\n private readonly logger: Logger;\n private readonly autoCreateTopicsEnabled: boolean;\n private readonly ensuredTopics = new Set<string>();\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.logger = new Logger(`KafkaClient:${clientId}`);\n this.autoCreateTopicsEnabled = options?.autoCreateTopics ?? false;\n\n this.kafka = new Kafka({\n clientId: this.clientId,\n brokers,\n });\n this.producer = this.kafka.producer({\n createPartitioner: Partitioners.DefaultPartitioner,\n idempotent: true,\n transactionalId: `${clientId}-tx`,\n maxInFlightRequests: 1,\n });\n this.consumer = this.kafka.consumer({ groupId });\n this.admin = this.kafka.admin();\n }\n\n private 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 TopicDescriptor).__topic;\n }\n return String(topicOrDescriptor);\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: 1 }],\n });\n this.ensuredTopics.add(topic);\n }\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 topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\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<{\n value: D[\"__type\"];\n key?: string;\n headers?: MessageHeaders;\n }>,\n ): Promise<void>;\n public async sendBatch<K extends keyof T>(\n topic: K,\n messages: Array<{ value: T[K]; key?: string; headers?: MessageHeaders }>,\n ): Promise<void>;\n public async sendBatch(\n topicOrDesc: any,\n messages: Array<{ value: any; key?: string; headers?: MessageHeaders }>,\n ): Promise<void> {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: messages.map((m) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\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 const tx = await this.producer.transaction();\n try {\n const ctx: TransactionContext<T> = {\n send: async (\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\n },\n sendBatch: async (topicOrDesc: any, messages: any[]) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: messages.map((m: any) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\n },\n };\n await fn(ctx);\n await tx.commit();\n } catch (error) {\n await tx.abort();\n throw error;\n }\n }\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 /** 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: (message: T[K[number]], topic: K[number]) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<void>;\n public async startConsumer<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n topics: D[],\n handleMessage: (message: D[\"__type\"], topic: D[\"__topic\"]) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<void>;\n public async startConsumer(\n topics: any[],\n handleMessage: (message: any, topic: any) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<void> {\n const {\n fromBeginning = false,\n autoCommit = true,\n retry,\n dlq = false,\n interceptors = [],\n } = options;\n\n const topicNames = (topics as any[]).map((t: any) =>\n this.resolveTopicName(t),\n );\n\n await this.consumer.connect();\n\n for (const t of topicNames) {\n await this.ensureTopic(t);\n }\n\n await this.consumer.subscribe({ topics: topicNames, fromBeginning });\n\n this.logger.log(`Consumer subscribed to topics: ${topicNames.join(\", \")}`);\n\n await this.consumer.run({\n autoCommit,\n eachMessage: async ({ topic, message }) => {\n if (!message.value) {\n this.logger.warn(`Received empty message from topic ${topic}`);\n return;\n }\n\n const raw = message.value.toString();\n let parsedMessage: any;\n\n try {\n parsedMessage = JSON.parse(raw);\n } catch (error) {\n this.logger.error(\n `Failed to parse message from topic ${topic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n return;\n }\n\n await this.processMessage(parsedMessage, raw, topic, handleMessage, {\n retry,\n dlq,\n interceptors,\n });\n },\n });\n }\n\n public async stopConsumer(): Promise<void> {\n\n await this.consumer.disconnect();\n this.logger.log(\"Consumer disconnected\");\n }\n\n /** Check broker connectivity and return available topics. */\n public async checkStatus(): Promise<{ topics: string[] }> {\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n const topics = await this.admin.listTopics();\n return { topics };\n }\n\n public getClientId(): ClientId {\n return this.clientId;\n }\n\n /** Gracefully disconnect producer, consumer, and admin. */\n public async disconnect(): Promise<void> {\n\n const tasks = [this.producer.disconnect(), this.consumer.disconnect()];\n if (this.isAdminConnected) {\n tasks.push(this.admin.disconnect());\n this.isAdminConnected = false;\n }\n await Promise.allSettled(tasks);\n this.logger.log(\"All connections closed\");\n }\n\n // --- Private helpers ---\n\n private async processMessage<K extends Array<keyof T>>(\n parsedMessage: T[K[number]],\n raw: string,\n topic: string,\n handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>,\n opts: Pick<ConsumerOptions<T>, \"retry\" | \"dlq\" | \"interceptors\">,\n ): Promise<void> {\n const { retry, dlq = false, interceptors = [] } = opts;\n const maxAttempts = retry ? retry.maxRetries + 1 : 1;\n const backoffMs = retry?.backoffMs ?? 1000;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n for (const interceptor of interceptors) {\n await interceptor.before?.(parsedMessage, topic);\n }\n\n await handleMessage(parsedMessage, topic as K[number]);\n\n for (const interceptor of interceptors) {\n await interceptor.after?.(parsedMessage, topic);\n }\n return;\n } catch (error) {\n const err =\n error instanceof Error ? error : new Error(String(error));\n const isLastAttempt = attempt === maxAttempts;\n\n if (isLastAttempt && maxAttempts > 1) {\n const exhaustedError = new KafkaRetryExhaustedError(\n topic,\n parsedMessage,\n maxAttempts,\n { cause: err },\n );\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, exhaustedError);\n }\n } else {\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, err);\n }\n }\n\n this.logger.error(\n `Error processing message from topic ${topic} (attempt ${attempt}/${maxAttempts}):`,\n err.stack,\n );\n\n if (isLastAttempt) {\n if (dlq) await this.sendToDlq(topic, raw);\n } else {\n await this.sleep(backoffMs * attempt);\n }\n }\n }\n }\n\n private async sendToDlq(topic: string, rawMessage: string): Promise<void> {\n const dlqTopic = `${topic}.dlq`;\n try {\n await this.producer.send({\n topic: dlqTopic,\n messages: [{ value: rawMessage }],\n acks: -1,\n });\n this.logger.warn(`Message sent to DLQ: ${dlqTopic}`);\n } catch (error) {\n this.logger.error(\n `Failed to send message to DLQ ${dlqTopic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\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 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","/** Default DI token for the Kafka client. */\nexport const KAFKA_CLIENT = \"KAFKA_CLIENT\";\n\n/** Returns the DI token for a named (or default) Kafka client instance. */\nexport const getKafkaClientToken = (name?: string): string =>\n name ? `KAFKA_CLIENT_${name}` : KAFKA_CLIENT;\n","import { Inject, Injectable, OnModuleInit, Logger } from \"@nestjs/common\";\nimport { DiscoveryService, ModuleRef } from \"@nestjs/core\";\nimport { KafkaClient } from \"../client/kafka.client\";\nimport {\n KAFKA_SUBSCRIBER_METADATA,\n KafkaSubscriberMetadata,\n} from \"../decorators/kafka.decorator\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\n\ninterface SubscriberEntry extends KafkaSubscriberMetadata {\n methodName: string | symbol;\n}\n\n/** Discovers `@SubscribeTo()` decorators and wires them to their Kafka clients on startup. */\n@Injectable()\nexport class KafkaExplorer implements OnModuleInit {\n private readonly logger = new Logger(KafkaExplorer.name);\n\n constructor(\n @Inject(DiscoveryService)\n private readonly discoveryService: DiscoveryService,\n @Inject(ModuleRef)\n private readonly moduleRef: ModuleRef,\n ) {}\n\n async onModuleInit() {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n const { instance } = wrapper;\n if (!instance || typeof instance !== \"object\") continue;\n\n const metadata: SubscriberEntry[] | undefined = Reflect.getMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n instance.constructor,\n );\n\n if (!metadata || metadata.length === 0) continue;\n\n for (const entry of metadata) {\n const token = getKafkaClientToken(entry.clientName);\n let client: KafkaClient<any>;\n\n try {\n client = this.moduleRef.get(token, { strict: false });\n } catch {\n this.logger.error(\n `KafkaClient \"${entry.clientName || \"default\"}\" not found for @SubscribeTo on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n continue;\n }\n\n const handler = (instance as any)[entry.methodName].bind(instance);\n\n await client.startConsumer(\n entry.topics as any,\n async (message: any, topic: any) => {\n await handler(message, topic);\n },\n entry.options,\n );\n\n this.logger.log(\n `Registered @SubscribeTo(${entry.topics.join(\", \")}) on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n }\n }\n }\n}\n","import { Inject } from \"@nestjs/common\";\nimport { getKafkaClientToken } from \"../module/kafka.constants\";\nimport { ConsumerOptions } from \"../client/kafka.client\";\nimport { TopicDescriptor } from \"../client/topic\";\n\nexport const KAFKA_SUBSCRIBER_METADATA = \"KAFKA_SUBSCRIBER_METADATA\";\n\nexport interface KafkaSubscriberMetadata {\n topics: string[];\n options?: ConsumerOptions;\n clientName?: string;\n}\n\n/** Inject a `KafkaClient` instance. Pass a name to target a specific named client. */\nexport const InjectKafkaClient = (name?: string): ParameterDecorator =>\n Inject(getKafkaClientToken(name));\n\n/**\n * Decorator that auto-subscribes a method to Kafka topics on module init.\n * The decorated method receives `(message, topic)` for each consumed message.\n */\nexport const SubscribeTo = (\n topics:\n | string\n | string[]\n | TopicDescriptor\n | TopicDescriptor[]\n | (string | TopicDescriptor)[],\n options?: ConsumerOptions & { clientName?: string },\n): MethodDecorator => {\n const arr = Array.isArray(topics) ? topics : [topics];\n const topicsArray = arr.map((t) =>\n typeof t === \"string\" ? t : t.__topic,\n );\n const { clientName, ...consumerOptions } = options || {};\n\n return (target, propertyKey, _descriptor) => {\n const existing: KafkaSubscriberMetadata[] =\n Reflect.getMetadata(KAFKA_SUBSCRIBER_METADATA, target.constructor) || [];\n\n Reflect.defineMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n [\n ...existing,\n {\n topics: topicsArray,\n options: Object.keys(consumerOptions).length\n ? consumerOptions\n : undefined,\n clientName,\n methodName: propertyKey,\n },\n ],\n target.constructor,\n );\n };\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}\n\n/**\n * Define a typed topic descriptor.\n *\n * @example\n * ```ts\n * const OrderCreated = topic('order.created')<{ orderId: string; amount: number }>();\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 <M extends Record<string, any>>(): TopicDescriptor<N, M> => ({\n __topic: name,\n __type: undefined as unknown as M,\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')<{ 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","import { Injectable } from \"@nestjs/common\";\nimport { KafkaClient, TopicMapConstraint } from \"../client/kafka.client\";\n\n/** Result returned by `KafkaHealthIndicator.check()`. */\nexport interface KafkaHealthResult {\n status: \"up\" | \"down\";\n clientId: string;\n topics?: string[];\n error?: string;\n}\n\n/** Health check service. Call `check(client)` to verify broker connectivity. */\n@Injectable()\nexport class KafkaHealthIndicator {\n async check<T extends TopicMapConstraint<T>>(\n client: KafkaClient<T>,\n ): Promise<KafkaHealthResult> {\n try {\n const { topics } = await client.checkStatus();\n return {\n status: \"up\",\n clientId: client.clientId,\n topics,\n };\n } catch (error) {\n return {\n status: \"down\",\n clientId: client.clientId,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n"],"mappings":"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","names":["import_common","import_core","topic","topic","import_common","import_common","topic","import_common"]}
package/dist/index.mjs CHANGED
@@ -25,6 +25,7 @@ var KafkaProcessingError = class extends Error {
25
25
  this.topic = topic2;
26
26
  this.originalMessage = originalMessage;
27
27
  this.name = "KafkaProcessingError";
28
+ if (options?.cause) this.cause = options.cause;
28
29
  }
29
30
  };
30
31
  var KafkaRetryExhaustedError = class extends KafkaProcessingError {
@@ -164,7 +165,6 @@ var KafkaClient = class {
164
165
  await this.producer.disconnect();
165
166
  this.logger.log("Producer disconnected");
166
167
  }
167
- /** Subscribe to topics and start consuming messages with the given handler. */
168
168
  async startConsumer(topics, handleMessage, options = {}) {
169
169
  const {
170
170
  fromBeginning = false,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/module/kafka.module.ts","../src/client/kafka.client.ts","../src/client/errors.ts","../src/module/kafka.constants.ts","../src/module/kafka.explorer.ts","../src/decorators/kafka.decorator.ts","../src/client/topic.ts","../src/health/kafka.health.ts"],"sourcesContent":["import { Module, DynamicModule, Provider } from \"@nestjs/common\";\nimport { DiscoveryModule } from \"@nestjs/core\";\nimport {\n KafkaClient,\n ClientId,\n GroupId,\n TopicMapConstraint,\n} from \"../client/kafka.client\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\nimport { KafkaExplorer } from \"./kafka.explorer\";\n\n/** Synchronous configuration for `KafkaModule.register()`. */\nexport interface KafkaModuleOptions {\n /** Optional name for multi-client setups. Must match `@InjectKafkaClient(name)`. */\n name?: string;\n /** Unique Kafka client identifier. */\n clientId: ClientId;\n /** Consumer group identifier. */\n groupId: GroupId;\n /** List of Kafka broker addresses. */\n brokers: string[];\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n}\n\n/** Async configuration for `KafkaModule.registerAsync()` with dependency injection. */\nexport interface KafkaModuleAsyncOptions {\n name?: string;\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n imports?: any[];\n useFactory: (\n ...args: any[]\n ) => KafkaModuleOptions | Promise<KafkaModuleOptions>;\n inject?: any[];\n}\n\n/**\n * NestJS dynamic module for registering type-safe Kafka clients.\n * Use `register()` for static config or `registerAsync()` for DI-based config.\n */\n@Module({})\nexport class KafkaModule {\n /** Register a Kafka client with static options. */\n static register<T extends TopicMapConstraint<T>>(\n options: KafkaModuleOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(options.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (): Promise<KafkaClient<T>> => {\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: options.isGlobal ?? false,\n module: KafkaModule,\n imports: [DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n\n /** Register a Kafka client with async/factory-based options. */\n static registerAsync<T extends TopicMapConstraint<T>>(\n asyncOptions: KafkaModuleAsyncOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(asyncOptions.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (...args: any[]): Promise<KafkaClient<T>> => {\n const options = await asyncOptions.useFactory(...args);\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n inject: asyncOptions.inject || [],\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: asyncOptions.isGlobal ?? false,\n module: KafkaModule,\n imports: [...(asyncOptions.imports || []), DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n}\n","import { Consumer, Kafka, Partitioners, Producer, Admin } from \"kafkajs\";\nimport { Logger } from \"@nestjs/common\";\nimport { TopicDescriptor } from \"./topic\";\nimport { KafkaRetryExhaustedError } from \"./errors\";\nimport type {\n ClientId,\n GroupId,\n SendOptions,\n MessageHeaders,\n ConsumerOptions,\n TransactionContext,\n TopicMapConstraint,\n IKafkaClient,\n KafkaClientOptions,\n} from \"./types\";\n\n// Re-export all types so existing `import { ... } from './kafka.client'` keeps working\nexport * from \"./types\";\n\n/**\n * Type-safe Kafka client for NestJS.\n * Wraps kafkajs with JSON serialization, retries, DLQ, transactions, and interceptors.\n *\n * @typeParam T - Topic-to-message type mapping for compile-time safety.\n */\nexport class KafkaClient<T extends TopicMapConstraint<T>>\n implements IKafkaClient<T>\n{\n private readonly kafka: Kafka;\n private readonly producer: Producer;\n private readonly consumer: Consumer;\n private readonly admin: Admin;\n private readonly logger: Logger;\n private readonly autoCreateTopicsEnabled: boolean;\n private readonly ensuredTopics = new Set<string>();\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.logger = new Logger(`KafkaClient:${clientId}`);\n this.autoCreateTopicsEnabled = options?.autoCreateTopics ?? false;\n\n this.kafka = new Kafka({\n clientId: this.clientId,\n brokers,\n });\n this.producer = this.kafka.producer({\n createPartitioner: Partitioners.DefaultPartitioner,\n idempotent: true,\n transactionalId: `${clientId}-tx`,\n maxInFlightRequests: 1,\n });\n this.consumer = this.kafka.consumer({ groupId });\n this.admin = this.kafka.admin();\n }\n\n private 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 TopicDescriptor).__topic;\n }\n return String(topicOrDescriptor);\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: 1 }],\n });\n this.ensuredTopics.add(topic);\n }\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 topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\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<{\n value: D[\"__type\"];\n key?: string;\n headers?: MessageHeaders;\n }>,\n ): Promise<void>;\n public async sendBatch<K extends keyof T>(\n topic: K,\n messages: Array<{ value: T[K]; key?: string; headers?: MessageHeaders }>,\n ): Promise<void>;\n public async sendBatch(\n topicOrDesc: any,\n messages: Array<{ value: any; key?: string; headers?: MessageHeaders }>,\n ): Promise<void> {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: messages.map((m) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\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 const tx = await this.producer.transaction();\n try {\n const ctx: TransactionContext<T> = {\n send: async (\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\n },\n sendBatch: async (topicOrDesc: any, messages: any[]) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: messages.map((m: any) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\n },\n };\n await fn(ctx);\n await tx.commit();\n } catch (error) {\n await tx.abort();\n throw error;\n }\n }\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 /** Subscribe to topics and start consuming messages with the given handler. */\n public async startConsumer<K extends Array<keyof T>>(\n topics: K | TopicDescriptor[],\n handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<void> {\n const {\n fromBeginning = false,\n autoCommit = true,\n retry,\n dlq = false,\n interceptors = [],\n } = options;\n\n const topicNames = (topics as any[]).map((t: any) =>\n this.resolveTopicName(t),\n );\n\n await this.consumer.connect();\n\n for (const t of topicNames) {\n await this.ensureTopic(t);\n }\n\n await this.consumer.subscribe({ topics: topicNames, fromBeginning });\n\n this.logger.log(`Consumer subscribed to topics: ${topicNames.join(\", \")}`);\n\n await this.consumer.run({\n autoCommit,\n eachMessage: async ({ topic, message }) => {\n if (!message.value) {\n this.logger.warn(`Received empty message from topic ${topic}`);\n return;\n }\n\n const raw = message.value.toString();\n let parsedMessage: T[K[number]];\n\n try {\n parsedMessage = JSON.parse(raw) as T[K[number]];\n } catch (error) {\n this.logger.error(\n `Failed to parse message from topic ${topic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n return;\n }\n\n await this.processMessage(parsedMessage, raw, topic, handleMessage, {\n retry,\n dlq,\n interceptors,\n });\n },\n });\n }\n\n public async stopConsumer(): Promise<void> {\n\n await this.consumer.disconnect();\n this.logger.log(\"Consumer disconnected\");\n }\n\n /** Check broker connectivity and return available topics. */\n public async checkStatus(): Promise<{ topics: string[] }> {\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n const topics = await this.admin.listTopics();\n return { topics };\n }\n\n public getClientId(): ClientId {\n return this.clientId;\n }\n\n /** Gracefully disconnect producer, consumer, and admin. */\n public async disconnect(): Promise<void> {\n\n const tasks = [this.producer.disconnect(), this.consumer.disconnect()];\n if (this.isAdminConnected) {\n tasks.push(this.admin.disconnect());\n this.isAdminConnected = false;\n }\n await Promise.allSettled(tasks);\n this.logger.log(\"All connections closed\");\n }\n\n // --- Private helpers ---\n\n private async processMessage<K extends Array<keyof T>>(\n parsedMessage: T[K[number]],\n raw: string,\n topic: string,\n handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>,\n opts: Pick<ConsumerOptions<T>, \"retry\" | \"dlq\" | \"interceptors\">,\n ): Promise<void> {\n const { retry, dlq = false, interceptors = [] } = opts;\n const maxAttempts = retry ? retry.maxRetries + 1 : 1;\n const backoffMs = retry?.backoffMs ?? 1000;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n for (const interceptor of interceptors) {\n await interceptor.before?.(parsedMessage, topic);\n }\n\n await handleMessage(parsedMessage, topic as K[number]);\n\n for (const interceptor of interceptors) {\n await interceptor.after?.(parsedMessage, topic);\n }\n return;\n } catch (error) {\n const err =\n error instanceof Error ? error : new Error(String(error));\n const isLastAttempt = attempt === maxAttempts;\n\n if (isLastAttempt && maxAttempts > 1) {\n const exhaustedError = new KafkaRetryExhaustedError(\n topic,\n parsedMessage,\n maxAttempts,\n { cause: err },\n );\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, exhaustedError);\n }\n } else {\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, err);\n }\n }\n\n this.logger.error(\n `Error processing message from topic ${topic} (attempt ${attempt}/${maxAttempts}):`,\n err.stack,\n );\n\n if (isLastAttempt) {\n if (dlq) await this.sendToDlq(topic, raw);\n } else {\n await this.sleep(backoffMs * attempt);\n }\n }\n }\n }\n\n private async sendToDlq(topic: string, rawMessage: string): Promise<void> {\n const dlqTopic = `${topic}.dlq`;\n try {\n await this.producer.send({\n topic: dlqTopic,\n messages: [{ value: rawMessage }],\n acks: -1,\n });\n this.logger.warn(`Message sent to DLQ: ${dlqTopic}`);\n } catch (error) {\n this.logger.error(\n `Failed to send message to DLQ ${dlqTopic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/** Error thrown when a consumer message handler fails. */\nexport class KafkaProcessingError extends Error {\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 }\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","/** Default DI token for the Kafka client. */\nexport const KAFKA_CLIENT = \"KAFKA_CLIENT\";\n\n/** Returns the DI token for a named (or default) Kafka client instance. */\nexport const getKafkaClientToken = (name?: string): string =>\n name ? `KAFKA_CLIENT_${name}` : KAFKA_CLIENT;\n","import { Inject, Injectable, OnModuleInit, Logger } from \"@nestjs/common\";\nimport { DiscoveryService, ModuleRef } from \"@nestjs/core\";\nimport { KafkaClient } from \"../client/kafka.client\";\nimport {\n KAFKA_SUBSCRIBER_METADATA,\n KafkaSubscriberMetadata,\n} from \"../decorators/kafka.decorator\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\n\ninterface SubscriberEntry extends KafkaSubscriberMetadata {\n methodName: string | symbol;\n}\n\n/** Discovers `@SubscribeTo()` decorators and wires them to their Kafka clients on startup. */\n@Injectable()\nexport class KafkaExplorer implements OnModuleInit {\n private readonly logger = new Logger(KafkaExplorer.name);\n\n constructor(\n @Inject(DiscoveryService)\n private readonly discoveryService: DiscoveryService,\n @Inject(ModuleRef)\n private readonly moduleRef: ModuleRef,\n ) {}\n\n async onModuleInit() {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n const { instance } = wrapper;\n if (!instance || typeof instance !== \"object\") continue;\n\n const metadata: SubscriberEntry[] | undefined = Reflect.getMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n instance.constructor,\n );\n\n if (!metadata || metadata.length === 0) continue;\n\n for (const entry of metadata) {\n const token = getKafkaClientToken(entry.clientName);\n let client: KafkaClient<any>;\n\n try {\n client = this.moduleRef.get(token, { strict: false });\n } catch {\n this.logger.error(\n `KafkaClient \"${entry.clientName || \"default\"}\" not found for @SubscribeTo on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n continue;\n }\n\n const handler = (instance as any)[entry.methodName].bind(instance);\n\n await client.startConsumer(\n entry.topics as any,\n async (message: any, topic: any) => {\n await handler(message, topic);\n },\n entry.options,\n );\n\n this.logger.log(\n `Registered @SubscribeTo(${entry.topics.join(\", \")}) on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n }\n }\n }\n}\n","import { Inject } from \"@nestjs/common\";\nimport { getKafkaClientToken } from \"../module/kafka.constants\";\nimport { ConsumerOptions } from \"../client/kafka.client\";\nimport { TopicDescriptor } from \"../client/topic\";\n\nexport const KAFKA_SUBSCRIBER_METADATA = \"KAFKA_SUBSCRIBER_METADATA\";\n\nexport interface KafkaSubscriberMetadata {\n topics: string[];\n options?: ConsumerOptions;\n clientName?: string;\n}\n\n/** Inject a `KafkaClient` instance. Pass a name to target a specific named client. */\nexport const InjectKafkaClient = (name?: string): ParameterDecorator =>\n Inject(getKafkaClientToken(name));\n\n/**\n * Decorator that auto-subscribes a method to Kafka topics on module init.\n * The decorated method receives `(message, topic)` for each consumed message.\n */\nexport const SubscribeTo = (\n topics:\n | string\n | string[]\n | TopicDescriptor\n | TopicDescriptor[]\n | (string | TopicDescriptor)[],\n options?: ConsumerOptions & { clientName?: string },\n): MethodDecorator => {\n const arr = Array.isArray(topics) ? topics : [topics];\n const topicsArray = arr.map((t) =>\n typeof t === \"string\" ? t : t.__topic,\n );\n const { clientName, ...consumerOptions } = options || {};\n\n return (target, propertyKey, _descriptor) => {\n const existing: KafkaSubscriberMetadata[] =\n Reflect.getMetadata(KAFKA_SUBSCRIBER_METADATA, target.constructor) || [];\n\n Reflect.defineMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n [\n ...existing,\n {\n topics: topicsArray,\n options: Object.keys(consumerOptions).length\n ? consumerOptions\n : undefined,\n clientName,\n methodName: propertyKey,\n },\n ],\n target.constructor,\n );\n };\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}\n\n/**\n * Define a typed topic descriptor.\n *\n * @example\n * ```ts\n * const OrderCreated = topic('order.created')<{ orderId: string; amount: number }>();\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 <M extends Record<string, any>>(): TopicDescriptor<N, M> => ({\n __topic: name,\n __type: undefined as unknown as M,\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')<{ 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","import { Injectable } from \"@nestjs/common\";\nimport { KafkaClient, TopicMapConstraint } from \"../client/kafka.client\";\n\n/** Result returned by `KafkaHealthIndicator.check()`. */\nexport interface KafkaHealthResult {\n status: \"up\" | \"down\";\n clientId: string;\n topics?: string[];\n error?: string;\n}\n\n/** Health check service. Call `check(client)` to verify broker connectivity. */\n@Injectable()\nexport class KafkaHealthIndicator {\n async check<T extends TopicMapConstraint<T>>(\n client: KafkaClient<T>,\n ): Promise<KafkaHealthResult> {\n try {\n const { topics } = await client.checkStatus();\n return {\n status: \"up\",\n clientId: client.clientId,\n topics,\n };\n } catch (error) {\n return {\n status: \"down\",\n clientId: client.clientId,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n"],"mappings":"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","names":["topic","topic","Inject","Logger","Logger","topic","Inject","Injectable","Injectable"]}
1
+ {"version":3,"sources":["../src/module/kafka.module.ts","../src/client/kafka.client.ts","../src/client/errors.ts","../src/module/kafka.constants.ts","../src/module/kafka.explorer.ts","../src/decorators/kafka.decorator.ts","../src/client/topic.ts","../src/health/kafka.health.ts"],"sourcesContent":["import { Module, DynamicModule, Provider } from \"@nestjs/common\";\nimport { DiscoveryModule } from \"@nestjs/core\";\nimport {\n KafkaClient,\n ClientId,\n GroupId,\n TopicMapConstraint,\n} from \"../client/kafka.client\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\nimport { KafkaExplorer } from \"./kafka.explorer\";\n\n/** Synchronous configuration for `KafkaModule.register()`. */\nexport interface KafkaModuleOptions {\n /** Optional name for multi-client setups. Must match `@InjectKafkaClient(name)`. */\n name?: string;\n /** Unique Kafka client identifier. */\n clientId: ClientId;\n /** Consumer group identifier. */\n groupId: GroupId;\n /** List of Kafka broker addresses. */\n brokers: string[];\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n}\n\n/** Async configuration for `KafkaModule.registerAsync()` with dependency injection. */\nexport interface KafkaModuleAsyncOptions {\n name?: string;\n /** If true, makes KAFKA_CLIENT available globally without importing KafkaModule in every feature module. */\n isGlobal?: boolean;\n /** Auto-create topics via admin on first use (send/consume). Useful for development. */\n autoCreateTopics?: boolean;\n imports?: any[];\n useFactory: (\n ...args: any[]\n ) => KafkaModuleOptions | Promise<KafkaModuleOptions>;\n inject?: any[];\n}\n\n/**\n * NestJS dynamic module for registering type-safe Kafka clients.\n * Use `register()` for static config or `registerAsync()` for DI-based config.\n */\n@Module({})\nexport class KafkaModule {\n /** Register a Kafka client with static options. */\n static register<T extends TopicMapConstraint<T>>(\n options: KafkaModuleOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(options.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (): Promise<KafkaClient<T>> => {\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: options.isGlobal ?? false,\n module: KafkaModule,\n imports: [DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n\n /** Register a Kafka client with async/factory-based options. */\n static registerAsync<T extends TopicMapConstraint<T>>(\n asyncOptions: KafkaModuleAsyncOptions,\n ): DynamicModule {\n const token = getKafkaClientToken(asyncOptions.name);\n\n const kafkaClientProvider: Provider = {\n provide: token,\n useFactory: async (...args: any[]): Promise<KafkaClient<T>> => {\n const options = await asyncOptions.useFactory(...args);\n const client = new KafkaClient<T>(\n options.clientId,\n options.groupId,\n options.brokers,\n { autoCreateTopics: options.autoCreateTopics },\n );\n await client.connectProducer();\n return client;\n },\n inject: asyncOptions.inject || [],\n };\n\n const destroyProvider: Provider = {\n provide: `${token}_DESTROY`,\n useFactory: (client: KafkaClient<T>) => ({\n onModuleDestroy: () => client.disconnect(),\n }),\n inject: [token],\n };\n\n return {\n global: asyncOptions.isGlobal ?? false,\n module: KafkaModule,\n imports: [...(asyncOptions.imports || []), DiscoveryModule],\n providers: [kafkaClientProvider, destroyProvider, KafkaExplorer],\n exports: [kafkaClientProvider],\n };\n }\n}\n","import { Consumer, Kafka, Partitioners, Producer, Admin } from \"kafkajs\";\nimport { Logger } from \"@nestjs/common\";\nimport { TopicDescriptor } from \"./topic\";\nimport { KafkaRetryExhaustedError } from \"./errors\";\nimport type {\n ClientId,\n GroupId,\n SendOptions,\n MessageHeaders,\n ConsumerOptions,\n TransactionContext,\n TopicMapConstraint,\n IKafkaClient,\n KafkaClientOptions,\n} from \"./types\";\n\n// Re-export all types so existing `import { ... } from './kafka.client'` keeps working\nexport * from \"./types\";\n\n/**\n * Type-safe Kafka client for NestJS.\n * Wraps kafkajs with JSON serialization, retries, DLQ, transactions, and interceptors.\n *\n * @typeParam T - Topic-to-message type mapping for compile-time safety.\n */\nexport class KafkaClient<T extends TopicMapConstraint<T>>\n implements IKafkaClient<T>\n{\n private readonly kafka: Kafka;\n private readonly producer: Producer;\n private readonly consumer: Consumer;\n private readonly admin: Admin;\n private readonly logger: Logger;\n private readonly autoCreateTopicsEnabled: boolean;\n private readonly ensuredTopics = new Set<string>();\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.logger = new Logger(`KafkaClient:${clientId}`);\n this.autoCreateTopicsEnabled = options?.autoCreateTopics ?? false;\n\n this.kafka = new Kafka({\n clientId: this.clientId,\n brokers,\n });\n this.producer = this.kafka.producer({\n createPartitioner: Partitioners.DefaultPartitioner,\n idempotent: true,\n transactionalId: `${clientId}-tx`,\n maxInFlightRequests: 1,\n });\n this.consumer = this.kafka.consumer({ groupId });\n this.admin = this.kafka.admin();\n }\n\n private 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 TopicDescriptor).__topic;\n }\n return String(topicOrDescriptor);\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: 1 }],\n });\n this.ensuredTopics.add(topic);\n }\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 topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\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<{\n value: D[\"__type\"];\n key?: string;\n headers?: MessageHeaders;\n }>,\n ): Promise<void>;\n public async sendBatch<K extends keyof T>(\n topic: K,\n messages: Array<{ value: T[K]; key?: string; headers?: MessageHeaders }>,\n ): Promise<void>;\n public async sendBatch(\n topicOrDesc: any,\n messages: Array<{ value: any; key?: string; headers?: MessageHeaders }>,\n ): Promise<void> {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await this.producer.send({\n topic,\n messages: messages.map((m) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\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 const tx = await this.producer.transaction();\n try {\n const ctx: TransactionContext<T> = {\n send: async (\n topicOrDesc: any,\n message: any,\n options: SendOptions = {},\n ) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: [\n {\n value: JSON.stringify(message),\n key: options.key ?? null,\n headers: options.headers,\n },\n ],\n acks: -1,\n });\n },\n sendBatch: async (topicOrDesc: any, messages: any[]) => {\n const topic = this.resolveTopicName(topicOrDesc);\n await this.ensureTopic(topic);\n await tx.send({\n topic,\n messages: messages.map((m: any) => ({\n value: JSON.stringify(m.value),\n key: m.key ?? null,\n headers: m.headers,\n })),\n acks: -1,\n });\n },\n };\n await fn(ctx);\n await tx.commit();\n } catch (error) {\n await tx.abort();\n throw error;\n }\n }\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 /** 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: (message: T[K[number]], topic: K[number]) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<void>;\n public async startConsumer<\n D extends TopicDescriptor<string & keyof T, T[string & keyof T]>,\n >(\n topics: D[],\n handleMessage: (message: D[\"__type\"], topic: D[\"__topic\"]) => Promise<void>,\n options?: ConsumerOptions<T>,\n ): Promise<void>;\n public async startConsumer(\n topics: any[],\n handleMessage: (message: any, topic: any) => Promise<void>,\n options: ConsumerOptions<T> = {},\n ): Promise<void> {\n const {\n fromBeginning = false,\n autoCommit = true,\n retry,\n dlq = false,\n interceptors = [],\n } = options;\n\n const topicNames = (topics as any[]).map((t: any) =>\n this.resolveTopicName(t),\n );\n\n await this.consumer.connect();\n\n for (const t of topicNames) {\n await this.ensureTopic(t);\n }\n\n await this.consumer.subscribe({ topics: topicNames, fromBeginning });\n\n this.logger.log(`Consumer subscribed to topics: ${topicNames.join(\", \")}`);\n\n await this.consumer.run({\n autoCommit,\n eachMessage: async ({ topic, message }) => {\n if (!message.value) {\n this.logger.warn(`Received empty message from topic ${topic}`);\n return;\n }\n\n const raw = message.value.toString();\n let parsedMessage: any;\n\n try {\n parsedMessage = JSON.parse(raw);\n } catch (error) {\n this.logger.error(\n `Failed to parse message from topic ${topic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n return;\n }\n\n await this.processMessage(parsedMessage, raw, topic, handleMessage, {\n retry,\n dlq,\n interceptors,\n });\n },\n });\n }\n\n public async stopConsumer(): Promise<void> {\n\n await this.consumer.disconnect();\n this.logger.log(\"Consumer disconnected\");\n }\n\n /** Check broker connectivity and return available topics. */\n public async checkStatus(): Promise<{ topics: string[] }> {\n if (!this.isAdminConnected) {\n await this.admin.connect();\n this.isAdminConnected = true;\n }\n const topics = await this.admin.listTopics();\n return { topics };\n }\n\n public getClientId(): ClientId {\n return this.clientId;\n }\n\n /** Gracefully disconnect producer, consumer, and admin. */\n public async disconnect(): Promise<void> {\n\n const tasks = [this.producer.disconnect(), this.consumer.disconnect()];\n if (this.isAdminConnected) {\n tasks.push(this.admin.disconnect());\n this.isAdminConnected = false;\n }\n await Promise.allSettled(tasks);\n this.logger.log(\"All connections closed\");\n }\n\n // --- Private helpers ---\n\n private async processMessage<K extends Array<keyof T>>(\n parsedMessage: T[K[number]],\n raw: string,\n topic: string,\n handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>,\n opts: Pick<ConsumerOptions<T>, \"retry\" | \"dlq\" | \"interceptors\">,\n ): Promise<void> {\n const { retry, dlq = false, interceptors = [] } = opts;\n const maxAttempts = retry ? retry.maxRetries + 1 : 1;\n const backoffMs = retry?.backoffMs ?? 1000;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n for (const interceptor of interceptors) {\n await interceptor.before?.(parsedMessage, topic);\n }\n\n await handleMessage(parsedMessage, topic as K[number]);\n\n for (const interceptor of interceptors) {\n await interceptor.after?.(parsedMessage, topic);\n }\n return;\n } catch (error) {\n const err =\n error instanceof Error ? error : new Error(String(error));\n const isLastAttempt = attempt === maxAttempts;\n\n if (isLastAttempt && maxAttempts > 1) {\n const exhaustedError = new KafkaRetryExhaustedError(\n topic,\n parsedMessage,\n maxAttempts,\n { cause: err },\n );\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, exhaustedError);\n }\n } else {\n for (const interceptor of interceptors) {\n await interceptor.onError?.(parsedMessage, topic, err);\n }\n }\n\n this.logger.error(\n `Error processing message from topic ${topic} (attempt ${attempt}/${maxAttempts}):`,\n err.stack,\n );\n\n if (isLastAttempt) {\n if (dlq) await this.sendToDlq(topic, raw);\n } else {\n await this.sleep(backoffMs * attempt);\n }\n }\n }\n }\n\n private async sendToDlq(topic: string, rawMessage: string): Promise<void> {\n const dlqTopic = `${topic}.dlq`;\n try {\n await this.producer.send({\n topic: dlqTopic,\n messages: [{ value: rawMessage }],\n acks: -1,\n });\n this.logger.warn(`Message sent to DLQ: ${dlqTopic}`);\n } catch (error) {\n this.logger.error(\n `Failed to send message to DLQ ${dlqTopic}:`,\n error instanceof Error ? error.stack : String(error),\n );\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\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 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","/** Default DI token for the Kafka client. */\nexport const KAFKA_CLIENT = \"KAFKA_CLIENT\";\n\n/** Returns the DI token for a named (or default) Kafka client instance. */\nexport const getKafkaClientToken = (name?: string): string =>\n name ? `KAFKA_CLIENT_${name}` : KAFKA_CLIENT;\n","import { Inject, Injectable, OnModuleInit, Logger } from \"@nestjs/common\";\nimport { DiscoveryService, ModuleRef } from \"@nestjs/core\";\nimport { KafkaClient } from \"../client/kafka.client\";\nimport {\n KAFKA_SUBSCRIBER_METADATA,\n KafkaSubscriberMetadata,\n} from \"../decorators/kafka.decorator\";\nimport { getKafkaClientToken } from \"./kafka.constants\";\n\ninterface SubscriberEntry extends KafkaSubscriberMetadata {\n methodName: string | symbol;\n}\n\n/** Discovers `@SubscribeTo()` decorators and wires them to their Kafka clients on startup. */\n@Injectable()\nexport class KafkaExplorer implements OnModuleInit {\n private readonly logger = new Logger(KafkaExplorer.name);\n\n constructor(\n @Inject(DiscoveryService)\n private readonly discoveryService: DiscoveryService,\n @Inject(ModuleRef)\n private readonly moduleRef: ModuleRef,\n ) {}\n\n async onModuleInit() {\n const providers = this.discoveryService.getProviders();\n\n for (const wrapper of providers) {\n const { instance } = wrapper;\n if (!instance || typeof instance !== \"object\") continue;\n\n const metadata: SubscriberEntry[] | undefined = Reflect.getMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n instance.constructor,\n );\n\n if (!metadata || metadata.length === 0) continue;\n\n for (const entry of metadata) {\n const token = getKafkaClientToken(entry.clientName);\n let client: KafkaClient<any>;\n\n try {\n client = this.moduleRef.get(token, { strict: false });\n } catch {\n this.logger.error(\n `KafkaClient \"${entry.clientName || \"default\"}\" not found for @SubscribeTo on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n continue;\n }\n\n const handler = (instance as any)[entry.methodName].bind(instance);\n\n await client.startConsumer(\n entry.topics as any,\n async (message: any, topic: any) => {\n await handler(message, topic);\n },\n entry.options,\n );\n\n this.logger.log(\n `Registered @SubscribeTo(${entry.topics.join(\", \")}) on ${instance.constructor.name}.${String(entry.methodName)}`,\n );\n }\n }\n }\n}\n","import { Inject } from \"@nestjs/common\";\nimport { getKafkaClientToken } from \"../module/kafka.constants\";\nimport { ConsumerOptions } from \"../client/kafka.client\";\nimport { TopicDescriptor } from \"../client/topic\";\n\nexport const KAFKA_SUBSCRIBER_METADATA = \"KAFKA_SUBSCRIBER_METADATA\";\n\nexport interface KafkaSubscriberMetadata {\n topics: string[];\n options?: ConsumerOptions;\n clientName?: string;\n}\n\n/** Inject a `KafkaClient` instance. Pass a name to target a specific named client. */\nexport const InjectKafkaClient = (name?: string): ParameterDecorator =>\n Inject(getKafkaClientToken(name));\n\n/**\n * Decorator that auto-subscribes a method to Kafka topics on module init.\n * The decorated method receives `(message, topic)` for each consumed message.\n */\nexport const SubscribeTo = (\n topics:\n | string\n | string[]\n | TopicDescriptor\n | TopicDescriptor[]\n | (string | TopicDescriptor)[],\n options?: ConsumerOptions & { clientName?: string },\n): MethodDecorator => {\n const arr = Array.isArray(topics) ? topics : [topics];\n const topicsArray = arr.map((t) =>\n typeof t === \"string\" ? t : t.__topic,\n );\n const { clientName, ...consumerOptions } = options || {};\n\n return (target, propertyKey, _descriptor) => {\n const existing: KafkaSubscriberMetadata[] =\n Reflect.getMetadata(KAFKA_SUBSCRIBER_METADATA, target.constructor) || [];\n\n Reflect.defineMetadata(\n KAFKA_SUBSCRIBER_METADATA,\n [\n ...existing,\n {\n topics: topicsArray,\n options: Object.keys(consumerOptions).length\n ? consumerOptions\n : undefined,\n clientName,\n methodName: propertyKey,\n },\n ],\n target.constructor,\n );\n };\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}\n\n/**\n * Define a typed topic descriptor.\n *\n * @example\n * ```ts\n * const OrderCreated = topic('order.created')<{ orderId: string; amount: number }>();\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 <M extends Record<string, any>>(): TopicDescriptor<N, M> => ({\n __topic: name,\n __type: undefined as unknown as M,\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')<{ 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","import { Injectable } from \"@nestjs/common\";\nimport { KafkaClient, TopicMapConstraint } from \"../client/kafka.client\";\n\n/** Result returned by `KafkaHealthIndicator.check()`. */\nexport interface KafkaHealthResult {\n status: \"up\" | \"down\";\n clientId: string;\n topics?: string[];\n error?: string;\n}\n\n/** Health check service. Call `check(client)` to verify broker connectivity. */\n@Injectable()\nexport class KafkaHealthIndicator {\n async check<T extends TopicMapConstraint<T>>(\n client: KafkaClient<T>,\n ): Promise<KafkaHealthResult> {\n try {\n const { topics } = await client.checkStatus();\n return {\n status: \"up\",\n clientId: client.clientId,\n topics,\n };\n } catch (error) {\n return {\n status: \"down\",\n clientId: client.clientId,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n"],"mappings":"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","names":["topic","topic","Inject","Logger","Logger","topic","Inject","Injectable","Injectable"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drarzter/kafka-client",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Type-safe Kafka client wrapper for NestJS with typed topic-message maps",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",