@kaushverse/rabbitmq-core 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +98 -0
  2. package/dist/index.js +27 -17
  3. package/package.json +3 -2
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # @kaushverse/rabbitmq-core
2
+
3
+ Production-ready RabbitMQ SDK for Node.js microservices.
4
+
5
+ This package provides a clean and opinionated way to **connect**, **publish**, **consume**, and **monitor RabbitMQ**, while handling **TLS**, **logging**, **health checks**, and **graceful shutdown** automatically.
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ - Single RabbitMQ connection per service
12
+ - Supports `amqp://` and `amqps://`
13
+ - Message publishing and consuming helpers
14
+ - Built-in bootstrap for service lifecycle
15
+ - Structured logger (pretty logs in dev, JSON in prod)
16
+ - Health check helper for monitoring
17
+ - Graceful shutdown (SIGINT / SIGTERM)
18
+ - Framework agnostic (Express, Fastify, NestJS)
19
+
20
+ ---
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install @kaushverse/rabbitmq-core
26
+ ```
27
+
28
+ ## Full Express Service Example
29
+
30
+ Below is a complete example showing how to use `@kaushverse/rabbitmq-core`
31
+ inside an Express-based microservice with health checks and publishing routes.
32
+
33
+ ### Example: `order-service`
34
+
35
+ ```ts
36
+ import "dotenv/config";
37
+ import express from "express";
38
+ import { bootstrap, rabbitHealth } from "@kaushverse/rabbitmq-core";
39
+
40
+ const app = express();
41
+ app.use(express.json());
42
+
43
+ // Health check endpoint
44
+ app.get("/health", (_, res) => {
45
+ res.json({
46
+ status: "ok",
47
+ ...rabbitHealth(),
48
+ });
49
+ });
50
+
51
+ // Bootstrap the service
52
+ bootstrap({
53
+ serviceName: "order-service",
54
+ rabbit: {
55
+ url: process.env.RABBITMQ_URL!,
56
+ tls: {
57
+ caPath: process.env.RABBITMQ_CA_PATH,
58
+ servername: process.env.RABBITMQ_SERVERNAME,
59
+ rejectUnauthorized: false, // set true in production
60
+ },
61
+ },
62
+ start: () => {
63
+ app.listen(3000, () => {
64
+ console.log("🚀 API running on port 3000");
65
+ });
66
+ },
67
+ });
68
+ ```
69
+
70
+ ```js
71
+ RABBITMQ_URL=amqps://user:password@mq.example.com:5671/vhost
72
+ RABBITMQ_CA_PATH=./certs/ca.pem
73
+ RABBITMQ_SERVERNAME=mq.example.com
74
+ ```
75
+
76
+ ## Publishing Messages
77
+
78
+ Use `publishMessage` to publish events to RabbitMQ.
79
+ The SDK automatically handles channels, serialization, and persistence.
80
+
81
+ ### Import
82
+
83
+ ```js
84
+ import { publishMessage } from "@kaushverse/rabbitmq-core";
85
+
86
+ await publishMessage({
87
+ exchange: "order.events",
88
+ type: "topic",
89
+ routingKey: "order.created",
90
+ message: {
91
+ orderId: "ORD-123",
92
+ amount: 499,
93
+ },
94
+ headers: {
95
+ source: "order-service",
96
+ },
97
+ });
98
+ ```
package/dist/index.js CHANGED
@@ -61,39 +61,50 @@ function loadCA(caPath) {
61
61
  // src/connection.ts
62
62
  var connection = null;
63
63
  var channel = null;
64
- var connected = false;
65
64
  var rabbitEvents = new import_events.EventEmitter();
65
+ rabbitEvents.setMaxListeners(20);
66
66
  async function connectRabbitMQ(options) {
67
- if (channel && connected) return channel;
67
+ if (connection && channel) return channel;
68
68
  try {
69
- const ca = loadCA(options.tls?.caPath);
70
- connection = await import_amqplib.default.connect(options.url, {
71
- ca,
69
+ const isSecure = options.url.startsWith("amqps://");
70
+ if (!isSecure && options.tls) {
71
+ console.warn("\u26A0\uFE0F TLS options ignored for amqp:// connection");
72
+ }
73
+ const socketOptions = isSecure ? {
74
+ ca: loadCA(options.tls?.caPath),
72
75
  servername: options.tls?.servername,
73
76
  rejectUnauthorized: options.tls?.rejectUnauthorized ?? true
74
- });
77
+ } : void 0;
78
+ connection = await import_amqplib.default.connect(options.url, socketOptions);
75
79
  channel = await connection.createChannel();
76
- connected = true;
77
80
  rabbitEvents.emit("connected");
78
81
  connection.on("close", () => {
79
- connected = false;
82
+ connection = null;
80
83
  channel = null;
81
84
  rabbitEvents.emit("disconnected");
82
85
  });
83
86
  connection.on("error", (err) => {
84
- connected = false;
87
+ rabbitEvents.emit("error", err);
88
+ });
89
+ channel.on("close", () => {
90
+ channel = null;
91
+ });
92
+ channel.on("error", (err) => {
85
93
  rabbitEvents.emit("error", err);
86
94
  });
87
95
  return channel;
88
96
  } catch (err) {
89
- connected = false;
97
+ connection = null;
98
+ channel = null;
90
99
  rabbitEvents.emit("error", err);
91
100
  throw err;
92
101
  }
93
102
  }
94
103
  function getChannel() {
95
104
  if (!channel) {
96
- throw new Error("\u274C RabbitMQ not initialized. Call connectRabbitMQ()");
105
+ throw new Error(
106
+ "\u274C RabbitMQ channel not available. Call connectRabbitMQ()"
107
+ );
97
108
  }
98
109
  return channel;
99
110
  }
@@ -104,12 +115,11 @@ async function closeRabbitMQ() {
104
115
  } finally {
105
116
  channel = null;
106
117
  connection = null;
107
- connected = false;
108
118
  rabbitEvents.emit("disconnected");
109
119
  }
110
120
  }
111
121
  function isRabbitConnected() {
112
- return connected;
122
+ return Boolean(connection && channel);
113
123
  }
114
124
 
115
125
  // src/consumer.ts
@@ -219,7 +229,7 @@ async function bootstrap({
219
229
  await connectRabbitMQ(rabbit);
220
230
  logger.info("\u{1F407} RabbitMQ connected");
221
231
  await start();
222
- logger.info("\u{1F680} Service started successfully");
232
+ logger.info(`\u{1F680} ${serviceName2} started successfully`);
223
233
  const shutdown = async (signal) => {
224
234
  logger.warn("\u{1F6D1} Shutdown signal received", { signal });
225
235
  await closeRabbitMQ();
@@ -239,12 +249,12 @@ async function bootstrap({
239
249
 
240
250
  // src/health/index.ts
241
251
  function rabbitHealth() {
242
- const connected2 = isRabbitConnected();
252
+ const connected = isRabbitConnected();
243
253
  return {
244
254
  "\u{1F407}": {
245
255
  service: "rabbitmq",
246
- status: connected2 ? "\u{1F7E2} up" : "\u{1F534} down",
247
- healthy: connected2
256
+ status: connected ? "\u{1F7E2} up" : "\u{1F534} down",
257
+ healthy: connected
248
258
  }
249
259
  };
250
260
  }
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@kaushverse/rabbitmq-core",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Reusable RabbitMQ (AMQP / AMQPS) core for Node.js & microservices",
5
5
  "author": "Kaushik (KaushVerse)",
6
6
  "license": "MIT",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
9
  "files": [
10
- "dist"
10
+ "dist",
11
+ "README.md"
11
12
  ],
12
13
  "scripts": {
13
14
  "build": "tsup src/index.ts --dts",