@relab/nestjs-kafka 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 re:lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # @relab/nestjs-kafka
2
+
3
+ ## Purpose
4
+
5
+ This package provides helpers for integrating Kafka with [NestJS](https://nestjs.com/) microservices. It simplifies Kafka client/consumer/producer configuration, resilient consumer restart strategy, and subscription behavior, so you can focus on your business logic.
6
+
7
+ ### Key Features
8
+
9
+ - **Simple setup**: One call to configure a Kafka microservice transport in your NestJS app.
10
+ - **Resilient consumption**: Automatic consumer restart with backoff after failures.
11
+ - **Configurable logging**: Uses `kafkajs` log levels and a structured log creator.
12
+ - **Producer defaults**: Sensible producer defaults (default partitioner, no auto topic creation).
13
+
14
+ ---
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pnpm add @relab/nestjs-kafka
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Usage
25
+
26
+ ### Consumer
27
+
28
+ **main.ts**
29
+ ```typescript
30
+ import { NestFactory } from '@nestjs/core'
31
+ import { AppModule } from './app.module'
32
+ import { configureKafkaMicroservice } from '@relab/nestjs-kafka'
33
+
34
+ async function bootstrap() {
35
+ const app = await NestFactory.create(AppModule)
36
+
37
+ await configureKafkaMicroservice(app, {
38
+ clientId: 'my-service',
39
+ brokers: ['localhost:9092'],
40
+ consumerGroup: 'my-service-consumers',
41
+ restartTimeout: 60_000, // ms
42
+ fromBeginning: true, // optional
43
+ })
44
+
45
+ await app.startAllMicroservices()
46
+ await app.listen(3000)
47
+ }
48
+
49
+ bootstrap()
50
+ ```
51
+
52
+ ### Producer
53
+
54
+ Use NestJS `ClientKafka` or your own `kafkajs` producer as needed. This package focuses on configuring the microservice transport for consumers; it does not provide a custom producer factory.
55
+
56
+ ---
57
+
58
+ ## API
59
+
60
+ ### `configureKafkaMicroservice(app, options)`
61
+
62
+ Configures your NestJS app to use Kafka as a microservice transport and applies resilient consumer restart behavior and sensible defaults.
63
+
64
+ #### Parameters
65
+
66
+ - **app**: `INestApplication` — Your NestJS application instance.
67
+ - **options**: `object`
68
+ - `clientId` (`string`, optional): Kafka client ID (defaults to host name).
69
+ - `brokers` (`string[]`, required): Kafka broker addresses, e.g. `['localhost:9092']`.
70
+ - `consumerGroup` (`string`, required): Kafka consumer group ID.
71
+ - `logLevel` (`KafkaLogLevel`, optional): `kafkajs` log level (default: `INFO`).
72
+ - `restartTimeout` (`number`, required): Pause (ms) before restarting the consumer after a failure.
73
+ - `fromBeginning` (`boolean`, optional, default: `true`): Subscribe from the beginning on first subscription.
74
+
75
+ ---
76
+
77
+ ## How it works
78
+
79
+ - **Kafka client setup**: Configures client ID, brokers, structured logging, and log level.
80
+ - **Consumer config**: Sets group, session/heartbeat timeouts, disables auto topic creation, and enables a retry strategy with automatic restart after failures (waiting `restartTimeout`).
81
+ - **Producer config**: Uses the default partitioner and disables auto topic creation.
82
+ - **Subscription**: Subscribes with `fromBeginning` on first subscription by default.
83
+
84
+ ---
85
+
86
+ ## Advanced
87
+
88
+ You can import the following for custom setups:
89
+
90
+ - `configureKafkaMicroservice`: Helper to attach a Kafka microservice transport to your NestJS app with resilient defaults.
91
+
92
+ ---
93
+
94
+ ## License
95
+
96
+ MIT
97
+
98
+
@@ -0,0 +1,15 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+ import { logLevel } from 'kafkajs';
3
+
4
+ type KafkaServiceOptions = {
5
+ clientId?: string;
6
+ brokers: string[];
7
+ consumerGroup: string;
8
+ logLevel?: logLevel;
9
+ restartTimeout: number;
10
+ fromBeginning?: boolean;
11
+ };
12
+
13
+ declare const configureKafkaMicroservice: <T extends INestApplication = INestApplication>(app: T, options: KafkaServiceOptions) => Promise<void>;
14
+
15
+ export { configureKafkaMicroservice };
@@ -0,0 +1,15 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+ import { logLevel } from 'kafkajs';
3
+
4
+ type KafkaServiceOptions = {
5
+ clientId?: string;
6
+ brokers: string[];
7
+ consumerGroup: string;
8
+ logLevel?: logLevel;
9
+ restartTimeout: number;
10
+ fromBeginning?: boolean;
11
+ };
12
+
13
+ declare const configureKafkaMicroservice: <T extends INestApplication = INestApplication>(app: T, options: KafkaServiceOptions) => Promise<void>;
14
+
15
+ export { configureKafkaMicroservice };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ var T=Object.create;var n=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var d=Object.getPrototypeOf,v=Object.prototype.hasOwnProperty;var s=(r,e)=>n(r,"name",{value:e,configurable:!0});var I=(r,e)=>{for(var o in e)n(r,o,{get:e[o],enumerable:!0})},l=(r,e,o,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of K(e))!v.call(r,t)&&t!==o&&n(r,t,{get:()=>e[t],enumerable:!(a=w(e,t))||a.enumerable});return r};var b=(r,e,o)=>(o=r!=null?T(d(r)):{},l(e||!r||!r.__esModule?n(o,"default",{value:r,enumerable:!0}):o,r)),A=r=>l(n({},"__esModule",{value:!0}),r);var R={};I(R,{configureKafkaMicroservice:()=>L});module.exports=A(R);var u=require("@nestjs/common"),p=require("@nestjs/microservices"),k=b(require("os")),m=require("kafkajs");var c=require("@nestjs/common"),g=require("kafkajs");var i=new c.Logger("Kafka"),f=s(()=>({level:r,log:{timestamp:e,logger:o,message:a,...t}})=>{(r===g.logLevel.DEBUG?i.debug:r===g.logLevel.INFO?i.log:r===g.logLevel.WARN?i.warn:r===g.logLevel.ERROR?i.error:i.log).call(i,a,t)},"kafkaLogger");var L=s(async(r,e)=>{let o=new u.Logger("Kafka");await r.connectMicroservice({transport:p.Transport.KAFKA,options:{postfixId:"",client:{clientId:e.clientId||k.default.hostname(),brokers:e.brokers,logCreator:f,logLevel:e.logLevel??m.logLevel.INFO},consumer:{groupId:e.consumerGroup,sessionTimeout:3e4,heartbeatInterval:3e3,allowAutoTopicCreation:!1,retry:{initialRetryTime:500,maxRetryTime:1e3,multiplier:2,factor:0,retries:5,restartOnFailure:s(async()=>(o.fatal(`Consumer failed to process messages. Sleeping for ${e.restartTimeout/6e4} minutes(s).`),await new Promise(a=>setTimeout(a,e.restartTimeout)),!0),"restartOnFailure")}},producer:{createPartitioner:m.Partitioners.DefaultPartitioner,allowAutoTopicCreation:!1},subscribe:{fromBeginning:e.fromBeginning??!0}}},{inheritAppConfig:!0})},"configureKafkaMicroservice");0&&(module.exports={configureKafkaMicroservice});
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ var m=Object.defineProperty;var t=(e,r)=>m(e,"name",{value:r,configurable:!0});import{Logger as c}from"@nestjs/common";import{Transport as f}from"@nestjs/microservices";import u from"os";import{logLevel as p,Partitioners as k}from"kafkajs";import{Logger as l}from"@nestjs/common";import{logLevel as a}from"kafkajs";var o=new l("Kafka"),s=t(()=>({level:e,log:{timestamp:r,logger:n,message:i,...g}})=>{(e===a.DEBUG?o.debug:e===a.INFO?o.log:e===a.WARN?o.warn:e===a.ERROR?o.error:o.log).call(o,i,g)},"kafkaLogger");var L=t(async(e,r)=>{let n=new c("Kafka");await e.connectMicroservice({transport:f.KAFKA,options:{postfixId:"",client:{clientId:r.clientId||u.hostname(),brokers:r.brokers,logCreator:s,logLevel:r.logLevel??p.INFO},consumer:{groupId:r.consumerGroup,sessionTimeout:3e4,heartbeatInterval:3e3,allowAutoTopicCreation:!1,retry:{initialRetryTime:500,maxRetryTime:1e3,multiplier:2,factor:0,retries:5,restartOnFailure:t(async()=>(n.fatal(`Consumer failed to process messages. Sleeping for ${r.restartTimeout/6e4} minutes(s).`),await new Promise(i=>setTimeout(i,r.restartTimeout)),!0),"restartOnFailure")}},producer:{createPartitioner:k.DefaultPartitioner,allowAutoTopicCreation:!1},subscribe:{fromBeginning:r.fromBeginning??!0}}},{inheritAppConfig:!0})},"configureKafkaMicroservice");export{L as configureKafkaMicroservice};
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@relab/nestjs-kafka",
3
+ "version": "1.0.0",
4
+ "description": "Kafka helpers for Nest.js",
5
+ "main": "dist/index.js",
6
+ "keywords": [
7
+ "nest.js"
8
+ ],
9
+ "author": "Sergey Zwezdin <sergey@zwezdin.com>",
10
+ "license": "MIT",
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "peerDependencies": {
15
+ "@nestjs/common": "^11.1.5",
16
+ "@nestjs/microservices": "^11.1.5",
17
+ "kafkajs": "^2.2.4",
18
+ "rxjs": "^7.8.2",
19
+ "@relab/nestjs-trace-context": "^3.7.0"
20
+ },
21
+ "devDependencies": {
22
+ "@nestjs/common": "^11.1.5",
23
+ "@nestjs/microservices": "^11.1.5",
24
+ "kafkajs": "^2.2.4",
25
+ "rxjs": "^7.8.2",
26
+ "tsup": "^8.5.0",
27
+ "@relab/nestjs-trace-context": "^3.7.0"
28
+ },
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ "import": "./dist/index.mjs",
32
+ "require": "./dist/index.js"
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsup src/index.ts --dts --format esm,cjs --out-dir dist",
39
+ "dev": "tsup src/index.ts --dts --format esm,cjs --out-dir dist --watch"
40
+ }
41
+ }