@drarzter/kafka-client 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -12
- package/dist/chunk-A56D7HXR.mjs +545 -0
- package/dist/chunk-A56D7HXR.mjs.map +1 -0
- package/dist/chunk-EQQGB2QZ.mjs +17 -0
- package/dist/chunk-EQQGB2QZ.mjs.map +1 -0
- package/dist/core.d.mts +118 -0
- package/dist/core.d.ts +118 -0
- package/dist/core.js +575 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +16 -0
- package/dist/core.mjs.map +1 -0
- package/dist/index.d.mts +5 -324
- package/dist/index.d.ts +5 -324
- package/dist/index.js +73 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +29 -534
- package/dist/index.mjs.map +1 -1
- package/dist/testing.d.mts +104 -0
- package/dist/testing.d.ts +104 -0
- package/dist/testing.js +151 -0
- package/dist/testing.js.map +1 -0
- package/dist/testing.mjs +127 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/types-CtwJihJ3.d.mts +224 -0
- package/dist/types-CtwJihJ3.d.ts +224 -0
- package/package.json +23 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,303 +1,10 @@
|
|
|
1
|
+
import { KafkaClient } from './core.js';
|
|
2
|
+
export { KafkaProcessingError, KafkaRetryExhaustedError, KafkaValidationError } from './core.js';
|
|
3
|
+
import { T as TopicMapConstraint, C as ClientId, G as GroupId, S as SchemaLike, a as ConsumerOptions, b as TopicDescriptor } from './types-CtwJihJ3.js';
|
|
4
|
+
export { B as BatchMeta, c as ConsumerInterceptor, I as IKafkaClient, d as InferSchema, K as KafkaClientOptions, e as KafkaLogger, M as MessageHeaders, R as RetryOptions, f as SendOptions, g as SubscribeRetryOptions, h as TTopicMessageMap, i as TopicsFrom, j as TransactionContext, t as topic } from './types-CtwJihJ3.js';
|
|
1
5
|
import { DynamicModule, OnModuleInit } from '@nestjs/common';
|
|
2
6
|
import { DiscoveryService, ModuleRef } from '@nestjs/core';
|
|
3
7
|
|
|
4
|
-
/**
|
|
5
|
-
* Any validation library with a `.parse()` method.
|
|
6
|
-
* Works with Zod, Valibot, ArkType, or any custom validator.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* import { z } from 'zod';
|
|
11
|
-
* const schema: SchemaLike<{ id: string }> = z.object({ id: z.string() });
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
interface SchemaLike<T = any> {
|
|
15
|
-
parse(data: unknown): T;
|
|
16
|
-
}
|
|
17
|
-
/** Infer the output type from a SchemaLike. */
|
|
18
|
-
type InferSchema<S extends SchemaLike> = S extends SchemaLike<infer T> ? T : never;
|
|
19
|
-
/**
|
|
20
|
-
* A typed topic descriptor that pairs a topic name with its message type.
|
|
21
|
-
* Created via the `topic()` factory function.
|
|
22
|
-
*
|
|
23
|
-
* @typeParam N - The literal topic name string.
|
|
24
|
-
* @typeParam M - The message payload type for this topic.
|
|
25
|
-
*/
|
|
26
|
-
interface TopicDescriptor<N extends string = string, M extends Record<string, any> = Record<string, any>> {
|
|
27
|
-
readonly __topic: N;
|
|
28
|
-
/** @internal Phantom type — never has a real value at runtime. */
|
|
29
|
-
readonly __type: M;
|
|
30
|
-
/** Runtime schema validator. Present only when created via `topic().schema()`. */
|
|
31
|
-
readonly __schema?: SchemaLike<M>;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Define a typed topic descriptor.
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```ts
|
|
38
|
-
* // Without schema — type provided explicitly:
|
|
39
|
-
* const OrderCreated = topic('order.created')<{ orderId: string; amount: number }>();
|
|
40
|
-
*
|
|
41
|
-
* // With schema — type inferred from schema:
|
|
42
|
-
* const OrderCreated = topic('order.created').schema(z.object({
|
|
43
|
-
* orderId: z.string(),
|
|
44
|
-
* amount: z.number(),
|
|
45
|
-
* }));
|
|
46
|
-
*
|
|
47
|
-
* // Use with KafkaClient:
|
|
48
|
-
* await kafka.sendMessage(OrderCreated, { orderId: '123', amount: 100 });
|
|
49
|
-
*
|
|
50
|
-
* // Use with @SubscribeTo:
|
|
51
|
-
* @SubscribeTo(OrderCreated)
|
|
52
|
-
* async handleOrder(msg) { ... }
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
declare function topic<N extends string>(name: N): {
|
|
56
|
-
<M extends Record<string, any>>(): TopicDescriptor<N, M>;
|
|
57
|
-
schema<S extends SchemaLike<Record<string, any>>>(schema: S): TopicDescriptor<N, InferSchema<S>>;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Build a topic-message map type from a union of TopicDescriptors.
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```ts
|
|
64
|
-
* const OrderCreated = topic('order.created')<{ orderId: string }>();
|
|
65
|
-
* const OrderCompleted = topic('order.completed')<{ completedAt: string }>();
|
|
66
|
-
*
|
|
67
|
-
* type MyTopics = TopicsFrom<typeof OrderCreated | typeof OrderCompleted>;
|
|
68
|
-
* // { 'order.created': { orderId: string }; 'order.completed': { completedAt: string } }
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
type TopicsFrom<D extends TopicDescriptor<any, any>> = {
|
|
72
|
-
[K in D as K["__topic"]]: K["__type"];
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Mapping of topic names to their message types.
|
|
77
|
-
* Define this interface to get type-safe publish/subscribe across your app.
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```ts
|
|
81
|
-
* // with explicit extends (IDE hints for values)
|
|
82
|
-
* interface MyTopics extends TTopicMessageMap {
|
|
83
|
-
* "orders.created": { orderId: string; amount: number };
|
|
84
|
-
* "users.updated": { userId: string; name: string };
|
|
85
|
-
* }
|
|
86
|
-
*
|
|
87
|
-
* // or plain interface / type — works the same
|
|
88
|
-
* interface MyTopics {
|
|
89
|
-
* "orders.created": { orderId: string; amount: number };
|
|
90
|
-
* }
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
93
|
-
type TTopicMessageMap = {
|
|
94
|
-
[topic: string]: Record<string, any>;
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* Generic constraint for topic-message maps.
|
|
98
|
-
* Works with both `type` aliases and `interface` declarations.
|
|
99
|
-
*/
|
|
100
|
-
type TopicMapConstraint<T> = {
|
|
101
|
-
[K in keyof T]: Record<string, any>;
|
|
102
|
-
};
|
|
103
|
-
type ClientId = string;
|
|
104
|
-
type GroupId = string;
|
|
105
|
-
type MessageHeaders = Record<string, string>;
|
|
106
|
-
/** Options for sending a single message. */
|
|
107
|
-
interface SendOptions {
|
|
108
|
-
/** Partition key for message routing. */
|
|
109
|
-
key?: string;
|
|
110
|
-
/** Custom headers attached to the message. */
|
|
111
|
-
headers?: MessageHeaders;
|
|
112
|
-
}
|
|
113
|
-
/** Metadata exposed to batch consumer handlers. */
|
|
114
|
-
interface BatchMeta {
|
|
115
|
-
/** Partition number for this batch. */
|
|
116
|
-
partition: number;
|
|
117
|
-
/** Highest offset available on the broker for this partition. */
|
|
118
|
-
highWatermark: string;
|
|
119
|
-
/** Send a heartbeat to the broker to prevent session timeout. */
|
|
120
|
-
heartbeat(): Promise<void>;
|
|
121
|
-
/** Mark an offset as processed (for manual offset management). */
|
|
122
|
-
resolveOffset(offset: string): void;
|
|
123
|
-
/** Commit offsets if the auto-commit threshold has been reached. */
|
|
124
|
-
commitOffsetsIfNecessary(): Promise<void>;
|
|
125
|
-
}
|
|
126
|
-
/** Options for configuring a Kafka consumer. */
|
|
127
|
-
interface ConsumerOptions<T extends TopicMapConstraint<T> = TTopicMessageMap> {
|
|
128
|
-
/** Override the default consumer group ID from the constructor. */
|
|
129
|
-
groupId?: string;
|
|
130
|
-
/** Start reading from earliest offset. Default: `false`. */
|
|
131
|
-
fromBeginning?: boolean;
|
|
132
|
-
/** Automatically commit offsets. Default: `true`. */
|
|
133
|
-
autoCommit?: boolean;
|
|
134
|
-
/** Retry policy for failed message processing. */
|
|
135
|
-
retry?: RetryOptions;
|
|
136
|
-
/** Send failed messages to a Dead Letter Queue (`<topic>.dlq`). */
|
|
137
|
-
dlq?: boolean;
|
|
138
|
-
/** Interceptors called before/after each message. */
|
|
139
|
-
interceptors?: ConsumerInterceptor<T>[];
|
|
140
|
-
/** @internal Schema map populated by @SubscribeTo when descriptors have schemas. */
|
|
141
|
-
schemas?: Map<string, SchemaLike>;
|
|
142
|
-
/** Retry config for `consumer.subscribe()` when the topic doesn't exist yet. */
|
|
143
|
-
subscribeRetry?: SubscribeRetryOptions;
|
|
144
|
-
}
|
|
145
|
-
/** Configuration for consumer retry behavior. */
|
|
146
|
-
interface RetryOptions {
|
|
147
|
-
/** Maximum number of retry attempts before giving up. */
|
|
148
|
-
maxRetries: number;
|
|
149
|
-
/** Base delay between retries in ms (multiplied by attempt number). Default: `1000`. */
|
|
150
|
-
backoffMs?: number;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Interceptor hooks for consumer message processing.
|
|
154
|
-
* All methods are optional — implement only what you need.
|
|
155
|
-
*/
|
|
156
|
-
interface ConsumerInterceptor<T extends TopicMapConstraint<T> = TTopicMessageMap> {
|
|
157
|
-
/** Called before the message handler. */
|
|
158
|
-
before?(message: T[keyof T], topic: string): Promise<void> | void;
|
|
159
|
-
/** Called after the message handler succeeds. */
|
|
160
|
-
after?(message: T[keyof T], topic: string): Promise<void> | void;
|
|
161
|
-
/** Called when the message handler throws. */
|
|
162
|
-
onError?(message: T[keyof T], topic: string, error: Error): Promise<void> | void;
|
|
163
|
-
}
|
|
164
|
-
/** Context passed to the `transaction()` callback with type-safe send methods. */
|
|
165
|
-
interface TransactionContext<T extends TopicMapConstraint<T>> {
|
|
166
|
-
send<K extends keyof T>(topic: K, message: T[K], options?: SendOptions): Promise<void>;
|
|
167
|
-
send<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(descriptor: D, message: D["__type"], options?: SendOptions): Promise<void>;
|
|
168
|
-
sendBatch<K extends keyof T>(topic: K, messages: Array<{
|
|
169
|
-
value: T[K];
|
|
170
|
-
key?: string;
|
|
171
|
-
headers?: MessageHeaders;
|
|
172
|
-
}>): Promise<void>;
|
|
173
|
-
sendBatch<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(descriptor: D, messages: Array<{
|
|
174
|
-
value: D["__type"];
|
|
175
|
-
key?: string;
|
|
176
|
-
headers?: MessageHeaders;
|
|
177
|
-
}>): Promise<void>;
|
|
178
|
-
}
|
|
179
|
-
/** Interface describing all public methods of the Kafka client. */
|
|
180
|
-
interface IKafkaClient<T extends TopicMapConstraint<T>> {
|
|
181
|
-
checkStatus(): Promise<{
|
|
182
|
-
topics: string[];
|
|
183
|
-
}>;
|
|
184
|
-
startConsumer<K extends Array<keyof T>>(topics: K, handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
|
|
185
|
-
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>;
|
|
186
|
-
startBatchConsumer<K extends Array<keyof T>>(topics: K, handleBatch: (messages: T[K[number]][], topic: K[number], meta: BatchMeta) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
|
|
187
|
-
startBatchConsumer<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(topics: D[], handleBatch: (messages: D["__type"][], topic: D["__topic"], meta: BatchMeta) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
|
|
188
|
-
stopConsumer(): Promise<void>;
|
|
189
|
-
sendMessage<K extends keyof T>(topic: K, message: T[K], options?: SendOptions): Promise<void>;
|
|
190
|
-
sendBatch<K extends keyof T>(topic: K, messages: Array<{
|
|
191
|
-
value: T[K];
|
|
192
|
-
key?: string;
|
|
193
|
-
headers?: MessageHeaders;
|
|
194
|
-
}>): Promise<void>;
|
|
195
|
-
transaction(fn: (ctx: TransactionContext<T>) => Promise<void>): Promise<void>;
|
|
196
|
-
getClientId: () => ClientId;
|
|
197
|
-
disconnect(): Promise<void>;
|
|
198
|
-
}
|
|
199
|
-
/** Options for `KafkaClient` constructor. */
|
|
200
|
-
interface KafkaClientOptions {
|
|
201
|
-
/** Auto-create topics via admin before the first `sendMessage`, `sendBatch`, or `transaction` for each topic. Useful for development — not recommended in production. */
|
|
202
|
-
autoCreateTopics?: boolean;
|
|
203
|
-
/** When `true`, string topic keys are validated against any schema previously registered via a TopicDescriptor. Default: `true`. */
|
|
204
|
-
strictSchemas?: boolean;
|
|
205
|
-
}
|
|
206
|
-
/** Options for consumer subscribe retry when topic doesn't exist yet. */
|
|
207
|
-
interface SubscribeRetryOptions {
|
|
208
|
-
/** Maximum number of subscribe attempts. Default: `5`. */
|
|
209
|
-
retries?: number;
|
|
210
|
-
/** Delay between retries in ms. Default: `5000`. */
|
|
211
|
-
backoffMs?: number;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Type-safe Kafka client for NestJS.
|
|
216
|
-
* Wraps kafkajs with JSON serialization, retries, DLQ, transactions, and interceptors.
|
|
217
|
-
*
|
|
218
|
-
* @typeParam T - Topic-to-message type mapping for compile-time safety.
|
|
219
|
-
*/
|
|
220
|
-
declare class KafkaClient<T extends TopicMapConstraint<T>> implements IKafkaClient<T> {
|
|
221
|
-
private readonly kafka;
|
|
222
|
-
private readonly producer;
|
|
223
|
-
private readonly consumers;
|
|
224
|
-
private readonly admin;
|
|
225
|
-
private readonly logger;
|
|
226
|
-
private readonly autoCreateTopicsEnabled;
|
|
227
|
-
private readonly strictSchemasEnabled;
|
|
228
|
-
private readonly ensuredTopics;
|
|
229
|
-
private readonly defaultGroupId;
|
|
230
|
-
private readonly schemaRegistry;
|
|
231
|
-
private readonly runningConsumers;
|
|
232
|
-
private isAdminConnected;
|
|
233
|
-
readonly clientId: ClientId;
|
|
234
|
-
constructor(clientId: ClientId, groupId: GroupId, brokers: string[], options?: KafkaClientOptions);
|
|
235
|
-
/** Send a single typed message. Accepts a topic key or a TopicDescriptor. */
|
|
236
|
-
sendMessage<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(descriptor: D, message: D["__type"], options?: SendOptions): Promise<void>;
|
|
237
|
-
sendMessage<K extends keyof T>(topic: K, message: T[K], options?: SendOptions): Promise<void>;
|
|
238
|
-
/** Send multiple typed messages in one call. Accepts a topic key or a TopicDescriptor. */
|
|
239
|
-
sendBatch<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(descriptor: D, messages: Array<{
|
|
240
|
-
value: D["__type"];
|
|
241
|
-
key?: string;
|
|
242
|
-
headers?: MessageHeaders;
|
|
243
|
-
}>): Promise<void>;
|
|
244
|
-
sendBatch<K extends keyof T>(topic: K, messages: Array<{
|
|
245
|
-
value: T[K];
|
|
246
|
-
key?: string;
|
|
247
|
-
headers?: MessageHeaders;
|
|
248
|
-
}>): Promise<void>;
|
|
249
|
-
/** Execute multiple sends atomically. Commits on success, aborts on error. */
|
|
250
|
-
transaction(fn: (ctx: TransactionContext<T>) => Promise<void>): Promise<void>;
|
|
251
|
-
/** Connect the idempotent producer. Called automatically by `KafkaModule.register()`. */
|
|
252
|
-
connectProducer(): Promise<void>;
|
|
253
|
-
disconnectProducer(): Promise<void>;
|
|
254
|
-
/** Subscribe to topics and start consuming messages with the given handler. */
|
|
255
|
-
startConsumer<K extends Array<keyof T>>(topics: K, handleMessage: (message: T[K[number]], topic: K[number]) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
|
|
256
|
-
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>;
|
|
257
|
-
/** Subscribe to topics and consume messages in batches. */
|
|
258
|
-
startBatchConsumer<K extends Array<keyof T>>(topics: K, handleBatch: (messages: T[K[number]][], topic: K[number], meta: BatchMeta) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
|
|
259
|
-
startBatchConsumer<D extends TopicDescriptor<string & keyof T, T[string & keyof T]>>(topics: D[], handleBatch: (messages: D["__type"][], topic: D["__topic"], meta: BatchMeta) => Promise<void>, options?: ConsumerOptions<T>): Promise<void>;
|
|
260
|
-
stopConsumer(): Promise<void>;
|
|
261
|
-
/** Check broker connectivity and return available topics. */
|
|
262
|
-
checkStatus(): Promise<{
|
|
263
|
-
topics: string[];
|
|
264
|
-
}>;
|
|
265
|
-
getClientId(): ClientId;
|
|
266
|
-
/** Gracefully disconnect producer, all consumers, and admin. */
|
|
267
|
-
disconnect(): Promise<void>;
|
|
268
|
-
private getOrCreateConsumer;
|
|
269
|
-
private resolveTopicName;
|
|
270
|
-
private ensureTopic;
|
|
271
|
-
/** Register schema from descriptor into global registry (side-effect). */
|
|
272
|
-
private registerSchema;
|
|
273
|
-
/** Validate message against schema. Pure — no side-effects on registry. */
|
|
274
|
-
private validateMessage;
|
|
275
|
-
/**
|
|
276
|
-
* Build a kafkajs-ready send payload.
|
|
277
|
-
* Handles: topic resolution, schema registration, validation, JSON serialization.
|
|
278
|
-
*/
|
|
279
|
-
private buildSendPayload;
|
|
280
|
-
/** Shared consumer setup: groupId check, schema map, connect, subscribe. */
|
|
281
|
-
private setupConsumer;
|
|
282
|
-
private buildSchemaMap;
|
|
283
|
-
/** Parse raw message as JSON. Returns null on failure (logs error). */
|
|
284
|
-
private parseJsonMessage;
|
|
285
|
-
/**
|
|
286
|
-
* Validate a parsed message against the schema map.
|
|
287
|
-
* On failure: logs error, sends to DLQ if enabled, calls interceptor.onError.
|
|
288
|
-
* Returns validated message or null.
|
|
289
|
-
*/
|
|
290
|
-
private validateWithSchema;
|
|
291
|
-
/**
|
|
292
|
-
* Execute a handler with retry, interceptors, and DLQ support.
|
|
293
|
-
* Used by both single-message and batch consumers.
|
|
294
|
-
*/
|
|
295
|
-
private executeWithRetry;
|
|
296
|
-
private sendToDlq;
|
|
297
|
-
private subscribeWithRetry;
|
|
298
|
-
private sleep;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
8
|
/** Synchronous configuration for `KafkaModule.register()`. */
|
|
302
9
|
interface KafkaModuleOptions {
|
|
303
10
|
/** Optional name for multi-client setups. Must match `@InjectKafkaClient(name)`. */
|
|
@@ -335,32 +42,6 @@ declare class KafkaModule {
|
|
|
335
42
|
static registerAsync<T extends TopicMapConstraint<T>>(asyncOptions: KafkaModuleAsyncOptions): DynamicModule;
|
|
336
43
|
}
|
|
337
44
|
|
|
338
|
-
/** Error thrown when a consumer message handler fails. */
|
|
339
|
-
declare class KafkaProcessingError extends Error {
|
|
340
|
-
readonly topic: string;
|
|
341
|
-
readonly originalMessage: unknown;
|
|
342
|
-
readonly cause?: Error;
|
|
343
|
-
constructor(message: string, topic: string, originalMessage: unknown, options?: {
|
|
344
|
-
cause?: Error;
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
/** Error thrown when schema validation fails on send or consume. */
|
|
348
|
-
declare class KafkaValidationError extends Error {
|
|
349
|
-
readonly topic: string;
|
|
350
|
-
readonly originalMessage: unknown;
|
|
351
|
-
readonly cause?: Error;
|
|
352
|
-
constructor(topic: string, originalMessage: unknown, options?: {
|
|
353
|
-
cause?: Error;
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
/** Error thrown when all retry attempts are exhausted for a message. */
|
|
357
|
-
declare class KafkaRetryExhaustedError extends KafkaProcessingError {
|
|
358
|
-
readonly attempts: number;
|
|
359
|
-
constructor(topic: string, originalMessage: unknown, attempts: number, options?: {
|
|
360
|
-
cause?: Error;
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
45
|
/** Default DI token for the Kafka client. */
|
|
365
46
|
declare const KAFKA_CLIENT = "KAFKA_CLIENT";
|
|
366
47
|
/** Returns the DI token for a named (or default) Kafka client instance. */
|
|
@@ -407,4 +88,4 @@ declare class KafkaHealthIndicator {
|
|
|
407
88
|
check<T extends TopicMapConstraint<T>>(client: KafkaClient<T>): Promise<KafkaHealthResult>;
|
|
408
89
|
}
|
|
409
90
|
|
|
410
|
-
export {
|
|
91
|
+
export { ClientId, ConsumerOptions, GroupId, InjectKafkaClient, KAFKA_CLIENT, KAFKA_SUBSCRIBER_METADATA, KafkaClient, KafkaExplorer, KafkaHealthIndicator, type KafkaHealthResult, KafkaModule, type KafkaModuleAsyncOptions, type KafkaModuleOptions, type KafkaSubscriberMetadata, SchemaLike, SubscribeTo, TopicDescriptor, TopicMapConstraint, getKafkaClientToken };
|
package/dist/index.js
CHANGED
|
@@ -45,13 +45,8 @@ __export(index_exports, {
|
|
|
45
45
|
});
|
|
46
46
|
module.exports = __toCommonJS(index_exports);
|
|
47
47
|
|
|
48
|
-
// src/module/kafka.module.ts
|
|
49
|
-
var import_common4 = require("@nestjs/common");
|
|
50
|
-
var import_core2 = require("@nestjs/core");
|
|
51
|
-
|
|
52
48
|
// src/client/kafka.client.ts
|
|
53
49
|
var import_kafkajs = require("kafkajs");
|
|
54
|
-
var import_common = require("@nestjs/common");
|
|
55
50
|
|
|
56
51
|
// src/client/errors.ts
|
|
57
52
|
var KafkaProcessingError = class extends Error {
|
|
@@ -98,6 +93,7 @@ var KafkaClient = class {
|
|
|
98
93
|
logger;
|
|
99
94
|
autoCreateTopicsEnabled;
|
|
100
95
|
strictSchemasEnabled;
|
|
96
|
+
numPartitions;
|
|
101
97
|
ensuredTopics = /* @__PURE__ */ new Set();
|
|
102
98
|
defaultGroupId;
|
|
103
99
|
schemaRegistry = /* @__PURE__ */ new Map();
|
|
@@ -107,12 +103,31 @@ var KafkaClient = class {
|
|
|
107
103
|
constructor(clientId, groupId, brokers, options) {
|
|
108
104
|
this.clientId = clientId;
|
|
109
105
|
this.defaultGroupId = groupId;
|
|
110
|
-
this.logger =
|
|
106
|
+
this.logger = options?.logger ?? {
|
|
107
|
+
log: (msg) => console.log(`[KafkaClient:${clientId}] ${msg}`),
|
|
108
|
+
warn: (msg, ...args) => console.warn(`[KafkaClient:${clientId}] ${msg}`, ...args),
|
|
109
|
+
error: (msg, ...args) => console.error(`[KafkaClient:${clientId}] ${msg}`, ...args)
|
|
110
|
+
};
|
|
111
111
|
this.autoCreateTopicsEnabled = options?.autoCreateTopics ?? false;
|
|
112
112
|
this.strictSchemasEnabled = options?.strictSchemas ?? true;
|
|
113
|
+
this.numPartitions = options?.numPartitions ?? 1;
|
|
113
114
|
this.kafka = new import_kafkajs.Kafka({
|
|
114
115
|
clientId: this.clientId,
|
|
115
|
-
brokers
|
|
116
|
+
brokers,
|
|
117
|
+
logLevel: import_kafkajs.logLevel.WARN,
|
|
118
|
+
logCreator: () => ({ level, log }) => {
|
|
119
|
+
const msg = `[kafkajs] ${log.message}`;
|
|
120
|
+
if (level === import_kafkajs.logLevel.ERROR) {
|
|
121
|
+
const text = log.message ?? "";
|
|
122
|
+
const isRetriable = text.includes("TOPIC_ALREADY_EXISTS") || text.includes("GROUP_COORDINATOR_NOT_AVAILABLE") || text.includes("NOT_COORDINATOR") || text.includes("Response GroupCoordinator") || text.includes("Response CreateTopics");
|
|
123
|
+
if (isRetriable) this.logger.warn(msg);
|
|
124
|
+
else this.logger.error(msg);
|
|
125
|
+
} else if (level === import_kafkajs.logLevel.WARN) {
|
|
126
|
+
this.logger.warn(msg);
|
|
127
|
+
} else {
|
|
128
|
+
this.logger.log(msg);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
116
131
|
});
|
|
117
132
|
this.producer = this.kafka.producer({
|
|
118
133
|
createPartitioner: import_kafkajs.Partitioners.DefaultPartitioner,
|
|
@@ -155,7 +170,14 @@ var KafkaClient = class {
|
|
|
155
170
|
await fn(ctx);
|
|
156
171
|
await tx.commit();
|
|
157
172
|
} catch (error) {
|
|
158
|
-
|
|
173
|
+
try {
|
|
174
|
+
await tx.abort();
|
|
175
|
+
} catch (abortError) {
|
|
176
|
+
this.logger.error(
|
|
177
|
+
"Failed to abort transaction:",
|
|
178
|
+
toError(abortError).message
|
|
179
|
+
);
|
|
180
|
+
}
|
|
159
181
|
throw error;
|
|
160
182
|
}
|
|
161
183
|
}
|
|
@@ -316,7 +338,7 @@ var KafkaClient = class {
|
|
|
316
338
|
this.isAdminConnected = true;
|
|
317
339
|
}
|
|
318
340
|
await this.admin.createTopics({
|
|
319
|
-
topics: [{ topic: topic2, numPartitions:
|
|
341
|
+
topics: [{ topic: topic2, numPartitions: this.numPartitions }]
|
|
320
342
|
});
|
|
321
343
|
this.ensuredTopics.add(topic2);
|
|
322
344
|
}
|
|
@@ -546,18 +568,36 @@ var KafkaClient = class {
|
|
|
546
568
|
}
|
|
547
569
|
};
|
|
548
570
|
|
|
549
|
-
// src/
|
|
571
|
+
// src/client/topic.ts
|
|
572
|
+
function topic(name) {
|
|
573
|
+
const fn = () => ({
|
|
574
|
+
__topic: name,
|
|
575
|
+
__type: void 0
|
|
576
|
+
});
|
|
577
|
+
fn.schema = (schema) => ({
|
|
578
|
+
__topic: name,
|
|
579
|
+
__type: void 0,
|
|
580
|
+
__schema: schema
|
|
581
|
+
});
|
|
582
|
+
return fn;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/nest/kafka.module.ts
|
|
586
|
+
var import_common3 = require("@nestjs/common");
|
|
587
|
+
var import_core2 = require("@nestjs/core");
|
|
588
|
+
|
|
589
|
+
// src/nest/kafka.constants.ts
|
|
550
590
|
var KAFKA_CLIENT = "KAFKA_CLIENT";
|
|
551
591
|
var getKafkaClientToken = (name) => name ? `KAFKA_CLIENT_${name}` : KAFKA_CLIENT;
|
|
552
592
|
|
|
553
|
-
// src/
|
|
554
|
-
var
|
|
593
|
+
// src/nest/kafka.explorer.ts
|
|
594
|
+
var import_common2 = require("@nestjs/common");
|
|
555
595
|
var import_core = require("@nestjs/core");
|
|
556
596
|
|
|
557
|
-
// src/
|
|
558
|
-
var
|
|
597
|
+
// src/nest/kafka.decorator.ts
|
|
598
|
+
var import_common = require("@nestjs/common");
|
|
559
599
|
var KAFKA_SUBSCRIBER_METADATA = "KAFKA_SUBSCRIBER_METADATA";
|
|
560
|
-
var InjectKafkaClient = (name) => (0,
|
|
600
|
+
var InjectKafkaClient = (name) => (0, import_common.Inject)(getKafkaClientToken(name));
|
|
561
601
|
var SubscribeTo = (topics, options) => {
|
|
562
602
|
const arr = Array.isArray(topics) ? topics : [topics];
|
|
563
603
|
const topicsArray = arr.map((t) => typeof t === "string" ? t : t.__topic);
|
|
@@ -588,13 +628,13 @@ var SubscribeTo = (topics, options) => {
|
|
|
588
628
|
};
|
|
589
629
|
};
|
|
590
630
|
|
|
591
|
-
// src/
|
|
631
|
+
// src/nest/kafka.explorer.ts
|
|
592
632
|
var KafkaExplorer = class {
|
|
593
633
|
constructor(discoveryService, moduleRef) {
|
|
594
634
|
this.discoveryService = discoveryService;
|
|
595
635
|
this.moduleRef = moduleRef;
|
|
596
636
|
}
|
|
597
|
-
logger = new
|
|
637
|
+
logger = new import_common2.Logger(KafkaExplorer.name);
|
|
598
638
|
async onModuleInit() {
|
|
599
639
|
const providers = this.discoveryService.getProviders();
|
|
600
640
|
for (const wrapper of providers) {
|
|
@@ -646,12 +686,12 @@ var KafkaExplorer = class {
|
|
|
646
686
|
}
|
|
647
687
|
};
|
|
648
688
|
KafkaExplorer = __decorateClass([
|
|
649
|
-
(0,
|
|
650
|
-
__decorateParam(0, (0,
|
|
651
|
-
__decorateParam(1, (0,
|
|
689
|
+
(0, import_common2.Injectable)(),
|
|
690
|
+
__decorateParam(0, (0, import_common2.Inject)(import_core.DiscoveryService)),
|
|
691
|
+
__decorateParam(1, (0, import_common2.Inject)(import_core.ModuleRef))
|
|
652
692
|
], KafkaExplorer);
|
|
653
693
|
|
|
654
|
-
// src/
|
|
694
|
+
// src/nest/kafka.module.ts
|
|
655
695
|
var KafkaModule = class {
|
|
656
696
|
/** Register a Kafka client with static options. */
|
|
657
697
|
static register(options) {
|
|
@@ -663,7 +703,10 @@ var KafkaModule = class {
|
|
|
663
703
|
options.clientId,
|
|
664
704
|
options.groupId,
|
|
665
705
|
options.brokers,
|
|
666
|
-
{
|
|
706
|
+
{
|
|
707
|
+
autoCreateTopics: options.autoCreateTopics,
|
|
708
|
+
logger: new import_common3.Logger(`KafkaClient:${options.clientId}`)
|
|
709
|
+
}
|
|
667
710
|
);
|
|
668
711
|
await client.connectProducer();
|
|
669
712
|
return client;
|
|
@@ -695,7 +738,10 @@ var KafkaModule = class {
|
|
|
695
738
|
options.clientId,
|
|
696
739
|
options.groupId,
|
|
697
740
|
options.brokers,
|
|
698
|
-
{
|
|
741
|
+
{
|
|
742
|
+
autoCreateTopics: options.autoCreateTopics,
|
|
743
|
+
logger: new import_common3.Logger(`KafkaClient:${options.clientId}`)
|
|
744
|
+
}
|
|
699
745
|
);
|
|
700
746
|
await client.connectProducer();
|
|
701
747
|
return client;
|
|
@@ -719,25 +765,11 @@ var KafkaModule = class {
|
|
|
719
765
|
}
|
|
720
766
|
};
|
|
721
767
|
KafkaModule = __decorateClass([
|
|
722
|
-
(0,
|
|
768
|
+
(0, import_common3.Module)({})
|
|
723
769
|
], KafkaModule);
|
|
724
770
|
|
|
725
|
-
// src/
|
|
726
|
-
|
|
727
|
-
const fn = () => ({
|
|
728
|
-
__topic: name,
|
|
729
|
-
__type: void 0
|
|
730
|
-
});
|
|
731
|
-
fn.schema = (schema) => ({
|
|
732
|
-
__topic: name,
|
|
733
|
-
__type: void 0,
|
|
734
|
-
__schema: schema
|
|
735
|
-
});
|
|
736
|
-
return fn;
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// src/health/kafka.health.ts
|
|
740
|
-
var import_common5 = require("@nestjs/common");
|
|
771
|
+
// src/nest/kafka.health.ts
|
|
772
|
+
var import_common4 = require("@nestjs/common");
|
|
741
773
|
var KafkaHealthIndicator = class {
|
|
742
774
|
async check(client) {
|
|
743
775
|
try {
|
|
@@ -757,7 +789,7 @@ var KafkaHealthIndicator = class {
|
|
|
757
789
|
}
|
|
758
790
|
};
|
|
759
791
|
KafkaHealthIndicator = __decorateClass([
|
|
760
|
-
(0,
|
|
792
|
+
(0, import_common4.Injectable)()
|
|
761
793
|
], KafkaHealthIndicator);
|
|
762
794
|
// Annotate the CommonJS export names for ESM import in node:
|
|
763
795
|
0 && (module.exports = {
|