@woovi/kafka 1.0.4 → 1.0.8

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 CHANGED
@@ -184,6 +184,61 @@ await consumer.pause(['events']); // Pause specific topics
184
184
  await consumer.resume(); // Resume all topics
185
185
  ```
186
186
 
187
+ ## Event Envelope
188
+
189
+ Wrap event data with standardized metadata using the event envelope pattern:
190
+
191
+ ```typescript
192
+ import { createEventEnvelope } from '@woovi/kafka';
193
+
194
+ const envelope = createEventEnvelope({
195
+ eventType: 'pix-out.compliance.approved',
196
+ operationType: 'update',
197
+ source: 'woovi-compliance',
198
+ data: { movementId: '123', pixOutId: '456' },
199
+ extraMetadata: { correlationId: 'abc-123', traceId: 'xyz-789' },
200
+ });
201
+
202
+ await producer.publish({ data: envelope });
203
+ ```
204
+
205
+ The envelope has the shape:
206
+
207
+ ```typescript
208
+ {
209
+ metadata: {
210
+ eventId: string; // auto-generated UUID
211
+ eventType: string; // e.g. "pix-out.compliance.approved"
212
+ eventTime: string; // auto-generated ISO 8601 timestamp
213
+ operationType?: string; // e.g. "insert", "update", "delete"
214
+ source: string; // e.g. "woovi-compliance"
215
+ // ...any extra metadata fields
216
+ },
217
+ data: T;
218
+ }
219
+ ```
220
+
221
+ ### Parsing Event Envelopes (Consumer Side)
222
+
223
+ Use `parseEventEnvelope` to validate and unwrap envelope-wrapped messages in your consumer handlers:
224
+
225
+ ```typescript
226
+ import type { ConsumerMessage, EventEnvelope } from '@woovi/kafka';
227
+ import { parseEventEnvelope } from '@woovi/kafka';
228
+
229
+ const handler = async (message: ConsumerMessage<EventEnvelope<MyEvent>>) => {
230
+ const { metadata, data } = parseEventEnvelope(message);
231
+
232
+ console.log(metadata.eventId); // UUID
233
+ console.log(metadata.eventType); // e.g. "pix-out.compliance.approved"
234
+ console.log(metadata.eventTime); // ISO 8601 timestamp
235
+ console.log(metadata.source); // e.g. "woovi-compliance"
236
+ console.log(data); // typed as MyEvent
237
+ };
238
+ ```
239
+
240
+ Throws with a descriptive error if the message does not follow the envelope pattern (missing metadata, missing data, or malformed metadata fields).
241
+
187
242
  ## Health Check
188
243
 
189
244
  ```typescript
@@ -266,6 +321,29 @@ it('publishes a user event', async () => {
266
321
  });
267
322
  ```
268
323
 
324
+ ### Asserting Event Envelopes
325
+
326
+ Use `kafkaAssertEventEnvelope` to assert messages published with the event envelope pattern:
327
+
328
+ ```typescript
329
+ import { kafkaAssertEventEnvelope, clearAllMocks } from '@woovi/kafka/test-utils';
330
+
331
+ beforeEach(() => clearAllMocks());
332
+
333
+ it('publishes a compliance event', async () => {
334
+ await myService.approveCompliance({ movementId: '123' });
335
+
336
+ kafkaAssertEventEnvelope({
337
+ topic: 'pix-out.compliance.approved',
338
+ eventType: 'pix-out.compliance.approved',
339
+ source: 'woovi-compliance',
340
+ data: { movementId: '123', pixOutId: '456' },
341
+ });
342
+ });
343
+ ```
344
+
345
+ This validates the full envelope structure (metadata with `eventId`, `eventType`, `eventTime`, `source`) and checks that the data is a subset match.
346
+
269
347
  ## License
270
348
 
271
349
  ISC
package/dist/index.cjs CHANGED
@@ -38,11 +38,13 @@ __webpack_require__.d(__webpack_exports__, {
38
38
  produceLatency: ()=>produceLatency,
39
39
  createConsumer: ()=>createConsumer,
40
40
  getKafka: ()=>getKafka,
41
+ parseEventEnvelope: ()=>parseEventEnvelope,
41
42
  resetMetrics: ()=>resetMetrics,
42
- disableTracing: ()=>disableTracing,
43
43
  getMetricsContentType: ()=>getMetricsContentType,
44
+ disableTracing: ()=>disableTracing,
44
45
  WooviProducer: ()=>WooviProducer,
45
46
  enableDefaultMetrics: ()=>enableDefaultMetrics,
47
+ createEventEnvelope: ()=>createEventEnvelope,
46
48
  messagesProducedTotal: ()=>messagesProducedTotal,
47
49
  messageProcessingDuration: ()=>messageProcessingDuration,
48
50
  createProducer: ()=>createProducer,
@@ -1085,6 +1087,33 @@ class WooviConsumer {
1085
1087
  function createConsumer(config) {
1086
1088
  return new WooviConsumer(config);
1087
1089
  }
1090
+ const external_node_crypto_namespaceObject = require("node:crypto");
1091
+ const createEventEnvelope = (args)=>({
1092
+ metadata: {
1093
+ eventId: (0, external_node_crypto_namespaceObject.randomUUID)(),
1094
+ eventType: args.eventType,
1095
+ eventTime: new Date().toISOString(),
1096
+ operationType: args.operationType,
1097
+ source: args.source,
1098
+ ...args.extraMetadata
1099
+ },
1100
+ data: args.data
1101
+ });
1102
+ const isValidMetadata = (metadata)=>{
1103
+ if ('object' != typeof metadata || null === metadata) return false;
1104
+ const m = metadata;
1105
+ return 'string' == typeof m.eventId && 'string' == typeof m.eventType && 'string' == typeof m.eventTime && 'string' == typeof m.source;
1106
+ };
1107
+ const parseEventEnvelope = (message)=>{
1108
+ const envelope = message.data;
1109
+ if (!envelope || 'object' != typeof envelope) throw new Error(`Invalid event envelope: message data is not an object. Topic: ${message.topic}, offset: ${message.offset}`);
1110
+ if (!isValidMetadata(envelope.metadata)) throw new Error(`Invalid event envelope: missing or malformed metadata. Expected eventId, eventType, eventTime, and source. Topic: ${message.topic}, offset: ${message.offset}`);
1111
+ if (!('data' in envelope) || void 0 === envelope.data) throw new Error(`Invalid event envelope: missing data field. Topic: ${message.topic}, offset: ${message.offset}`);
1112
+ return {
1113
+ metadata: envelope.metadata,
1114
+ data: envelope.data
1115
+ };
1116
+ };
1088
1117
  exports.Kafka = __webpack_exports__.Kafka;
1089
1118
  exports.WooviConsumer = __webpack_exports__.WooviConsumer;
1090
1119
  exports.WooviProducer = __webpack_exports__.WooviProducer;
@@ -1092,6 +1121,7 @@ exports.batchProcessingDuration = __webpack_exports__.batchProcessingDuration;
1092
1121
  exports.batchSize = __webpack_exports__.batchSize;
1093
1122
  exports.consumerLag = __webpack_exports__.consumerLag;
1094
1123
  exports.createConsumer = __webpack_exports__.createConsumer;
1124
+ exports.createEventEnvelope = __webpack_exports__.createEventEnvelope;
1095
1125
  exports.createKafka = __webpack_exports__.createKafka;
1096
1126
  exports.createKafkaFromEnv = __webpack_exports__.createKafkaFromEnv;
1097
1127
  exports.createProducer = __webpack_exports__.createProducer;
@@ -1115,6 +1145,7 @@ exports.messagesFailedTotal = __webpack_exports__.messagesFailedTotal;
1115
1145
  exports.messagesProcessedTotal = __webpack_exports__.messagesProcessedTotal;
1116
1146
  exports.messagesProducedTotal = __webpack_exports__.messagesProducedTotal;
1117
1147
  exports.onShutdown = __webpack_exports__.onShutdown;
1148
+ exports.parseEventEnvelope = __webpack_exports__.parseEventEnvelope;
1118
1149
  exports.produceLatency = __webpack_exports__.produceLatency;
1119
1150
  exports.resetMetrics = __webpack_exports__.resetMetrics;
1120
1151
  exports.setMockKafkaForTestMode = __webpack_exports__.setMockKafkaForTestMode;
@@ -1126,6 +1157,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
1126
1157
  "batchSize",
1127
1158
  "consumerLag",
1128
1159
  "createConsumer",
1160
+ "createEventEnvelope",
1129
1161
  "createKafka",
1130
1162
  "createKafkaFromEnv",
1131
1163
  "createProducer",
@@ -1149,6 +1181,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
1149
1181
  "messagesProcessedTotal",
1150
1182
  "messagesProducedTotal",
1151
1183
  "onShutdown",
1184
+ "parseEventEnvelope",
1152
1185
  "produceLatency",
1153
1186
  "resetMetrics",
1154
1187
  "setMockKafkaForTestMode"
package/dist/index.d.ts CHANGED
@@ -85,6 +85,36 @@ declare interface Context {
85
85
  */
86
86
  export declare function createConsumer(config: WooviConsumerConfig): WooviConsumer;
87
87
 
88
+ /**
89
+ * Creates an event envelope wrapping data with standardized metadata.
90
+ * Extra metadata fields can be passed to extend the envelope dynamically.
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const envelope = createEventEnvelope({
95
+ * eventType: 'pix-out.compliance.approved',
96
+ * operationType: 'update',
97
+ * source: 'woovi-compliance',
98
+ * data: { movementId: '123', pixOutId: '456' },
99
+ * extraMetadata: { correlationId: 'abc-123', traceId: 'xyz-789' },
100
+ * });
101
+ * ```
102
+ */
103
+ export declare const createEventEnvelope: <T>(args: CreateEventEnvelopeArgs<T>) => EventEnvelope<T>;
104
+
105
+ declare interface CreateEventEnvelopeArgs<T> {
106
+ /** Type/name of the event (e.g. "pix-out.compliance.approved") */
107
+ eventType: string;
108
+ /** Type of operation that triggered the event (e.g. "insert", "update", "delete") */
109
+ operationType?: string;
110
+ /** Source system that produced the event (e.g. "woovi-compliance") */
111
+ source: string;
112
+ /** The event payload data */
113
+ data: T;
114
+ /** Additional custom metadata fields to include in the envelope */
115
+ extraMetadata?: Record<string, unknown>;
116
+ }
117
+
88
118
  export declare function createKafka(config: KafkaConfig): Kafka;
89
119
 
90
120
  export declare function createKafkaFromEnv(clientId: string): Kafka;
@@ -130,6 +160,47 @@ export declare interface ErrorHandler<T = unknown> {
130
160
  (error: Error, message: ConsumerMessage<T>): Promise<void>;
131
161
  }
132
162
 
163
+ /**
164
+ * Generic event envelope that wraps event data with standardized metadata.
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const envelope: EventEnvelope<UserCreatedData> = {
169
+ * metadata: {
170
+ * eventId: "9e28d9f6-693e-4aff-92f5-0d85faa06442",
171
+ * eventType: "user.created",
172
+ * eventTime: "2026-02-08T12:33:02.470Z",
173
+ * operationType: "insert",
174
+ * source: "user-service",
175
+ * },
176
+ * data: { userId: "123", name: "John" },
177
+ * };
178
+ * ```
179
+ */
180
+ export declare interface EventEnvelope<T> {
181
+ metadata: EventMetadata;
182
+ data: T;
183
+ }
184
+
185
+ /**
186
+ * Standard event metadata following the event envelope pattern.
187
+ * Can be extended with additional fields via index signature.
188
+ */
189
+ export declare interface EventMetadata {
190
+ /** Unique identifier for the event (UUID) */
191
+ eventId: string;
192
+ /** Type/name of the event (e.g. "pix-out.compliance.approved") */
193
+ eventType: string;
194
+ /** ISO 8601 timestamp of when the event was created */
195
+ eventTime: string;
196
+ /** Type of operation that triggered the event (e.g. "insert", "update", "delete") */
197
+ operationType?: string;
198
+ /** Source system that produced the event (e.g. "woovi-compliance") */
199
+ source: string;
200
+ /** Additional custom metadata fields */
201
+ [key: string]: unknown;
202
+ }
203
+
133
204
  /**
134
205
  * Extract trace context from Kafka message headers.
135
206
  * Returns a Context that can be used to create child spans.
@@ -216,6 +287,26 @@ export declare const messagesProducedTotal: Counter<"topic" | "status">;
216
287
 
217
288
  export declare function onShutdown(callback: () => Promise<void>): void;
218
289
 
290
+ declare interface ParsedEventEnvelope<T> {
291
+ metadata: EventMetadata;
292
+ data: T;
293
+ }
294
+
295
+ /**
296
+ * Validates and unwraps an event envelope from a consumed message.
297
+ * Throws if the message does not follow the event envelope pattern.
298
+ *
299
+ * @example
300
+ * ```typescript
301
+ * const handler = async (message: ConsumerMessage<EventEnvelope<MyEvent>>) => {
302
+ * const { metadata, data } = parseEventEnvelope<MyEvent>(message);
303
+ * console.log(metadata.eventType, metadata.source);
304
+ * console.log(data); // typed as MyEvent
305
+ * };
306
+ * ```
307
+ */
308
+ export declare const parseEventEnvelope: <T>(message: ConsumerMessage<EventEnvelope<T>>) => ParsedEventEnvelope<T>;
309
+
219
310
  export declare const produceLatency: Histogram<"topic">;
220
311
 
221
312
  export declare interface PublishArgs<T = unknown> {
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Kafka, logLevel } from "kafkajs";
2
2
  import { logger } from "@woovi/logger";
3
3
  import { Counter, Gauge, Histogram, Registry, collectDefaultMetrics } from "prom-client";
4
+ import { randomUUID } from "node:crypto";
4
5
  let kafkaInstance = null;
5
6
  let testMode = false;
6
7
  const shutdownCallbacks = [];
@@ -1025,4 +1026,30 @@ class WooviConsumer {
1025
1026
  function createConsumer(config) {
1026
1027
  return new WooviConsumer(config);
1027
1028
  }
1028
- export { Kafka, WooviConsumer, WooviProducer, batchProcessingDuration, batchSize, consumerLag, createConsumer, createKafka, createKafkaFromEnv, createProducer, disableTestMode, disableTracing, enableDefaultMetrics, enableTestMode, extractContextFromHeaders, getKafka, getMetrics, getMetricsContentType, healthCheck, initializeTracing, injectContextIntoHeaders, isTestMode, kafkaRegistry, lastMessageTimestamp, logLevel, messageProcessingDuration, messagesFailedTotal, messagesProcessedTotal, messagesProducedTotal, onShutdown, produceLatency, resetMetrics, setMockKafkaForTestMode };
1029
+ const createEventEnvelope = (args)=>({
1030
+ metadata: {
1031
+ eventId: randomUUID(),
1032
+ eventType: args.eventType,
1033
+ eventTime: new Date().toISOString(),
1034
+ operationType: args.operationType,
1035
+ source: args.source,
1036
+ ...args.extraMetadata
1037
+ },
1038
+ data: args.data
1039
+ });
1040
+ const isValidMetadata = (metadata)=>{
1041
+ if ('object' != typeof metadata || null === metadata) return false;
1042
+ const m = metadata;
1043
+ return 'string' == typeof m.eventId && 'string' == typeof m.eventType && 'string' == typeof m.eventTime && 'string' == typeof m.source;
1044
+ };
1045
+ const parseEventEnvelope = (message)=>{
1046
+ const envelope = message.data;
1047
+ if (!envelope || 'object' != typeof envelope) throw new Error(`Invalid event envelope: message data is not an object. Topic: ${message.topic}, offset: ${message.offset}`);
1048
+ if (!isValidMetadata(envelope.metadata)) throw new Error(`Invalid event envelope: missing or malformed metadata. Expected eventId, eventType, eventTime, and source. Topic: ${message.topic}, offset: ${message.offset}`);
1049
+ if (!('data' in envelope) || void 0 === envelope.data) throw new Error(`Invalid event envelope: missing data field. Topic: ${message.topic}, offset: ${message.offset}`);
1050
+ return {
1051
+ metadata: envelope.metadata,
1052
+ data: envelope.data
1053
+ };
1054
+ };
1055
+ export { Kafka, WooviConsumer, WooviProducer, batchProcessingDuration, batchSize, consumerLag, createConsumer, createEventEnvelope, createKafka, createKafkaFromEnv, createProducer, disableTestMode, disableTracing, enableDefaultMetrics, enableTestMode, extractContextFromHeaders, getKafka, getMetrics, getMetricsContentType, healthCheck, initializeTracing, injectContextIntoHeaders, isTestMode, kafkaRegistry, lastMessageTimestamp, logLevel, messageProcessingDuration, messagesFailedTotal, messagesProcessedTotal, messagesProducedTotal, onShutdown, parseEventEnvelope, produceLatency, resetMetrics, setMockKafkaForTestMode };
@@ -33,14 +33,15 @@ __webpack_require__.d(__webpack_exports__, {
33
33
  mockConsumer: ()=>mockConsumer,
34
34
  kafkaAssert: ()=>kafkaAssert,
35
35
  Kafka: ()=>Kafka,
36
+ kafkaAssertEventEnvelope: ()=>kafkaAssertEventEnvelope,
36
37
  kafkaAssertLength: ()=>kafkaAssertLength,
37
38
  mockProducerSend: ()=>mockProducerSend,
38
- mockTransaction: ()=>mockTransaction,
39
39
  mockProducerSendBatch: ()=>mockProducerSendBatch,
40
- mockTransactionSend: ()=>mockTransactionSend,
40
+ mockTransaction: ()=>mockTransaction,
41
41
  KafkaJSNonRetriableError: ()=>KafkaJSNonRetriableError,
42
- setupKafkaTest: ()=>setupKafkaTest,
42
+ mockTransactionSend: ()=>mockTransactionSend,
43
43
  CompressionTypes: ()=>CompressionTypes,
44
+ setupKafkaTest: ()=>setupKafkaTest,
44
45
  mockProducer: ()=>mockProducer
45
46
  });
46
47
  const getMockFn = ()=>{
@@ -221,6 +222,39 @@ const kafkaAssert = (args)=>{
221
222
  throw error;
222
223
  }
223
224
  };
225
+ const kafkaAssertEventEnvelope_isSubset = (subset, superset)=>{
226
+ for (const key of Object.keys(subset)){
227
+ const subValue = subset[key];
228
+ const superValue = superset[key];
229
+ if ('object' == typeof subValue && null !== subValue && 'object' == typeof superValue && null !== superValue) {
230
+ if (!kafkaAssertEventEnvelope_isSubset(subValue, superValue)) return false;
231
+ } else if (subValue !== superValue) return false;
232
+ }
233
+ return true;
234
+ };
235
+ const kafkaAssertEventEnvelope = (args)=>{
236
+ const { topic, eventType, source, data } = args;
237
+ const kafkaMessages = getKafkaMessages();
238
+ const topicMessages = kafkaMessages.filter((m)=>m.topic === topic);
239
+ if (0 === topicMessages.length) {
240
+ const error = new Error(`No messages found for topic: ${topic}`);
241
+ Error.captureStackTrace(error, kafkaAssertEventEnvelope);
242
+ throw error;
243
+ }
244
+ const parsedMessages = topicMessages.flatMap((m)=>m.messages.map((msg)=>JSON.parse(msg.value)));
245
+ const found = parsedMessages.some((envelope)=>{
246
+ if (!envelope.metadata || !envelope.data) return false;
247
+ if (envelope.metadata.eventType !== eventType) return false;
248
+ if (envelope.metadata.source !== source) return false;
249
+ if (!envelope.metadata.eventId || !envelope.metadata.eventTime) return false;
250
+ return kafkaAssertEventEnvelope_isSubset(data, envelope.data);
251
+ });
252
+ if (!found) {
253
+ const error = new Error(`Event envelope not found in topic "${topic}".\nExpected eventType: ${eventType}\nExpected source: ${source}\nExpected data: ${JSON.stringify(data, null, 2)}\nReceived: ${JSON.stringify(parsedMessages, null, 2)}`);
254
+ Error.captureStackTrace(error, kafkaAssertEventEnvelope);
255
+ throw error;
256
+ }
257
+ };
224
258
  const kafkaAssertLength = (args)=>{
225
259
  const { topic, length } = args;
226
260
  const kafkaMessages = getKafkaMessages();
@@ -256,6 +290,7 @@ exports.clearAllMocks = __webpack_exports__.clearAllMocks;
256
290
  exports.createMockKafka = __webpack_exports__.createMockKafka;
257
291
  exports.getKafkaMessages = __webpack_exports__.getKafkaMessages;
258
292
  exports.kafkaAssert = __webpack_exports__.kafkaAssert;
293
+ exports.kafkaAssertEventEnvelope = __webpack_exports__.kafkaAssertEventEnvelope;
259
294
  exports.kafkaAssertLength = __webpack_exports__.kafkaAssertLength;
260
295
  exports.logLevel = __webpack_exports__.logLevel;
261
296
  exports.mockAdmin = __webpack_exports__.mockAdmin;
@@ -275,6 +310,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
275
310
  "createMockKafka",
276
311
  "getKafkaMessages",
277
312
  "kafkaAssert",
313
+ "kafkaAssertEventEnvelope",
278
314
  "kafkaAssertLength",
279
315
  "logLevel",
280
316
  "mockAdmin",
@@ -33,6 +33,29 @@ declare type KafkaAssertArgs = {
33
33
  message: Record<string, unknown>;
34
34
  };
35
35
 
36
+ /**
37
+ * Asserts that a message with the event envelope pattern was published to a topic.
38
+ * Validates the envelope structure (metadata + data) and checks the data content.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * kafkaAssertEventEnvelope({
43
+ * topic: 'pix-out.compliance.approved',
44
+ * eventType: 'pix-out.compliance.approved',
45
+ * source: 'woovi-compliance',
46
+ * data: { movementId: '123', pixOutId: '456' },
47
+ * });
48
+ * ```
49
+ */
50
+ export declare const kafkaAssertEventEnvelope: (args: KafkaAssertEventEnvelopeArgs) => void;
51
+
52
+ declare type KafkaAssertEventEnvelopeArgs = {
53
+ topic: string;
54
+ eventType: string;
55
+ source: string;
56
+ data: Record<string, unknown>;
57
+ };
58
+
36
59
  export declare const kafkaAssertLength: (args: KafkaAssertLengthArgs) => void;
37
60
 
38
61
  declare type KafkaAssertLengthArgs = {
@@ -176,6 +176,39 @@ const kafkaAssert = (args)=>{
176
176
  throw error;
177
177
  }
178
178
  };
179
+ const kafkaAssertEventEnvelope_isSubset = (subset, superset)=>{
180
+ for (const key of Object.keys(subset)){
181
+ const subValue = subset[key];
182
+ const superValue = superset[key];
183
+ if ('object' == typeof subValue && null !== subValue && 'object' == typeof superValue && null !== superValue) {
184
+ if (!kafkaAssertEventEnvelope_isSubset(subValue, superValue)) return false;
185
+ } else if (subValue !== superValue) return false;
186
+ }
187
+ return true;
188
+ };
189
+ const kafkaAssertEventEnvelope = (args)=>{
190
+ const { topic, eventType, source, data } = args;
191
+ const kafkaMessages = getKafkaMessages();
192
+ const topicMessages = kafkaMessages.filter((m)=>m.topic === topic);
193
+ if (0 === topicMessages.length) {
194
+ const error = new Error(`No messages found for topic: ${topic}`);
195
+ Error.captureStackTrace(error, kafkaAssertEventEnvelope);
196
+ throw error;
197
+ }
198
+ const parsedMessages = topicMessages.flatMap((m)=>m.messages.map((msg)=>JSON.parse(msg.value)));
199
+ const found = parsedMessages.some((envelope)=>{
200
+ if (!envelope.metadata || !envelope.data) return false;
201
+ if (envelope.metadata.eventType !== eventType) return false;
202
+ if (envelope.metadata.source !== source) return false;
203
+ if (!envelope.metadata.eventId || !envelope.metadata.eventTime) return false;
204
+ return kafkaAssertEventEnvelope_isSubset(data, envelope.data);
205
+ });
206
+ if (!found) {
207
+ const error = new Error(`Event envelope not found in topic "${topic}".\nExpected eventType: ${eventType}\nExpected source: ${source}\nExpected data: ${JSON.stringify(data, null, 2)}\nReceived: ${JSON.stringify(parsedMessages, null, 2)}`);
208
+ Error.captureStackTrace(error, kafkaAssertEventEnvelope);
209
+ throw error;
210
+ }
211
+ };
179
212
  const kafkaAssertLength = (args)=>{
180
213
  const { topic, length } = args;
181
214
  const kafkaMessages = getKafkaMessages();
@@ -203,4 +236,4 @@ function setupKafkaTest() {
203
236
  testMode: true
204
237
  };
205
238
  }
206
- export { CompressionTypes, Kafka, KafkaJSNonRetriableError, KafkaJSProtocolError, clearAllMocks, createMockKafka, getKafkaMessages, kafkaAssert, kafkaAssertLength, logLevel, mockAdmin, mockConsumer, mockProducer, mockProducerSend, mockProducerSendBatch, mockTransaction, mockTransactionSend, setupKafkaTest };
239
+ export { CompressionTypes, Kafka, KafkaJSNonRetriableError, KafkaJSProtocolError, clearAllMocks, createMockKafka, getKafkaMessages, kafkaAssert, kafkaAssertEventEnvelope, kafkaAssertLength, logLevel, mockAdmin, mockConsumer, mockProducer, mockProducerSend, mockProducerSendBatch, mockTransaction, mockTransactionSend, setupKafkaTest };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@woovi/kafka",
3
3
  "description": "Kafka setup and utilities for Woovi microservices",
4
- "version": "1.0.4",
4
+ "version": "1.0.8",
5
5
  "author": "",
6
6
  "type": "module",
7
7
  "dependencies": {
@@ -47,10 +47,10 @@
47
47
  ],
48
48
  "license": "ISC",
49
49
  "main": "./dist/index.cjs",
50
+ "packageManager": "pnpm@10.14.0",
50
51
  "publishConfig": {
51
52
  "access": "public"
52
53
  },
53
- "types": "./dist/index.d.ts",
54
54
  "scripts": {
55
55
  "build": "rslib build",
56
56
  "test": "vitest",
@@ -63,5 +63,6 @@
63
63
  "release:major": "npm version major && git push --follow-tags",
64
64
  "release:minor": "npm version minor && git push --follow-tags",
65
65
  "release:patch": "npm version patch && git push --follow-tags"
66
- }
67
- }
66
+ },
67
+ "types": "./dist/index.d.ts"
68
+ }