fastify-rabbitmq 3.3.0 → 3.4.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/CHANGELOG.md ADDED
@@ -0,0 +1,91 @@
1
+ # Fastify RabbitMQ
2
+
3
+ ## v3.4.1 - 2026-09-26
4
+
5
+ ### What Changed 👀
6
+
7
+ #### 🐛 Bug Fixes
8
+
9
+ - fix: close the RabbitMQ connection when the Fastify app closes @Bugs5382 (#166)
10
+ - fix(test): stop declaring transient non-exclusive queues so tests pass on RabbitMQ 4 @Bugs5382 (#165)
11
+ - fix(build): keep source maps out of the npm package @Bugs5382 (#163)
12
+
13
+ #### 📄 Documentation
14
+
15
+ - docs(readme): apply the lite emoji treatment @Bugs5382 (#158)
16
+
17
+ #### 🧩 Dependency Updates
18
+
19
+ - build(deps): bump the github-actions group with 9 updates @[dependabot[bot]](https://github.com/apps/dependabot) (#143)
20
+
21
+ ### Extra
22
+
23
+ **Full Changelog**: https://github.com/Bugs5382/fastify-rabbitmq/compare/v3.4.0...v3.4.1
24
+
25
+ ## v3.4.0 - 2026-06-09
26
+
27
+ ### What Changed 👀
28
+
29
+ #### 🚀 Features
30
+
31
+ - feat: re-export the rabbitmq-client types from fastify-rabbitmq @Bugs5382 (#135)
32
+ - build: migrate to tsdown and the shared eslint-config @Bugs5382 (#119)
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - fix: validate connection shape and reject invalid registration options @Bugs5382 (#125)
37
+
38
+ #### 📄 Documentation
39
+
40
+ - docs: point consumers at the re-exported client types @Bugs5382 (#137)
41
+ - docs: show how to encapsulate messaging in a Fastify plugin @Bugs5382 (#131)
42
+ - docs: rewrite README to standard, add AGENTS.md, fix typedoc parent-export @Bugs5382 (#124)
43
+
44
+ #### 🧩 Dependency Updates
45
+
46
+ - build(deps): bump the production-dependencies group across 1 directory with 3 updates @[dependabot[bot]](https://github.com/apps/dependabot) (#121)
47
+ - build: migrate to tsdown and the shared eslint-config @Bugs5382 (#119)
48
+
49
+ ### Extra
50
+
51
+ **Full Changelog**: https://github.com/Bugs5382/fastify-rabbitmq/compare/v3.3.0...v3.4.0
52
+
53
+ ## v3.3.0 - 2025-05-31
54
+
55
+ #### What Changed 👀
56
+
57
+ #### 🚀 Features
58
+
59
+ - feat: remove old build method @Bugs5382 (#108)
60
+
61
+ #### 🧩 Dependency Updates
62
+
63
+ - feat: remove old build method @Bugs5382 (#108)
64
+
65
+ ### Extra
66
+
67
+ **Full Changelog**: https://github.com/Bugs5382/fastify-rabbitmq/compare/v3.2.0...v3.3.0
68
+
69
+ ## v3.2.0 - 2025-03-25
70
+
71
+ #### What Changed 👀
72
+
73
+ #### 🧩 Dependency Updates
74
+
75
+ - feat: updated dependencies @Bugs5382 (#106)
76
+
77
+ ### Extra
78
+
79
+ **Full Changelog**: https://github.com/Bugs5382/fastify-rabbitmq/compare/v3.1.0...v3.2.0
80
+
81
+ ## v3.1.0 - 2024-11-17
82
+
83
+ #### What Changed 👀
84
+
85
+ #### 🧩 Dependency Updates
86
+
87
+ - feat: updated packages @Bugs5382 (#105)
88
+
89
+ ### Extra
90
+
91
+ **Full Changelog**: https://github.com/Bugs5382/fastify-rabbitmq/compare/v3.0.0...v3.1.0
package/README.md CHANGED
@@ -1,104 +1,304 @@
1
- # Fastify RabbitMQ
1
+ # Fastify RabbitMQ 🐰
2
2
 
3
- A Fastify RabbitMQ Plugin Developed in Pure TypeScript.
4
- It uses the [node-rabbitmq-client](https://github.com/cody-greene/node-rabbitmq-client/) plugin as a wrapper.
3
+ > 📨 A Fastify RabbitMQ plugin developed in pure TypeScript.
5
4
 
6
- The build exports this to valid ESM and CJS for ease of cross-compatibility.
5
+ It wraps the [`rabbitmq-client`](https://www.npmjs.com/package/rabbitmq-client) package so a Fastify
6
+ app can publish, consume, and RPC over RabbitMQ (AMQP 0-9-1).
7
7
 
8
- If you are using this NPM package, please consider giving it a :star: star.
9
- This will increase its visibility and solicit more contribution from the outside.
8
+ The build exports valid ESM and CJS for cross-compatibility.
10
9
 
11
- ## Table of Contents
10
+ If you use this package, please consider giving it a ⭐ — it raises visibility and brings in more
11
+ contribution from the outside.
12
12
 
13
- 1. [Install](#install)
14
- 2. [Basic Usage](#basic-usage)
15
- 3. [Full Documentation](#full-documentation)
16
- 1. [Options](#options)
17
- 4. [Acknowledgements](#acknowledgements)
18
- 5. [License](#license)
13
+ > This documentation covers **how to use the plugin**. The decorator `app.rabbitmq` is a live
14
+ > `rabbitmq-client` `Connection`, so its full API is available — for publisher/consumer/RPC option
15
+ > details, see [External Libraries](#-external-libraries).
19
16
 
20
- ## Install
17
+ > 🟢 **Requires Node.js ≥ 20.15.**
21
18
 
22
- ```
19
+ ## 📑 Table of Contents
20
+
21
+ 1. [Install](#-install)
22
+ 2. [Basic Usage](#-basic-usage)
23
+ 3. [Recipes](#-recipes)
24
+ 1. [Publish a message](#1-publish-a-message)
25
+ 2. [Consume a queue](#2-consume-a-queue)
26
+ 3. [RPC (request/response)](#3-rpc-requestresponse)
27
+ 4. [Declare exchanges, queues, and bindings](#4-declare-exchanges-queues-and-bindings)
28
+ 5. [Multiple connections with namespaces](#5-multiple-connections-with-namespaces)
29
+ 6. [Encapsulate messaging in your own plugin](#6-encapsulate-messaging-in-your-own-plugin)
30
+ 4. [API Reference](#-api-reference-fastifyrabbitmq)
31
+ 5. [Plugin Options](#-plugin-options)
32
+ 6. [External Libraries](#-external-libraries)
33
+ 7. [Acknowledgements](#-acknowledgements)
34
+ 8. [License](#-license)
35
+
36
+ ## 📦 Install
37
+
38
+ ```shell
23
39
  npm install fastify-rabbitmq
24
40
  ```
25
41
 
26
- ## Basic Usage
42
+ Requires Node.js ≥ 20.15.
43
+
44
+ ## 🚀 Basic Usage
45
+
46
+ Register the plugin (before any routes that use it):
47
+
48
+ ```ts
49
+ import fastify from "fastify";
50
+ import fastifyRabbitMQ from "fastify-rabbitmq";
51
+
52
+ const app = fastify();
53
+
54
+ await app.register(fastifyRabbitMQ, {
55
+ connection: "amqp://guest:guest@localhost",
56
+ });
57
+ ```
58
+
59
+ Registering decorates the Fastify instance with `app.rabbitmq` — a live `rabbitmq-client`
60
+ `Connection`. Use it to create publishers, consumers, and RPC clients, or to declare topology.
61
+
62
+ The plugin owns the connection's lifecycle:
63
+
64
+ - **`app.close()` closes the connection** (each one, with namespaces), so the process can exit.
65
+ Close your own consumers and publishers in an `onClose` hook, as in
66
+ [recipe 6](#6-encapsulate-messaging-in-your-own-plugin).
67
+ - **Connection errors are logged, not thrown.** If the broker is down or drops the connection,
68
+ the error goes to `app.log.error` and `rabbitmq-client` keeps reconnecting in the background.
69
+ The app does not crash. Add your own `app.rabbitmq.on("error", ...)` listener if you need to
70
+ react to it.
71
+
72
+ ## 🧩 Recipes
73
+
74
+ ### 1. Publish a message
75
+
76
+ ```ts
77
+ const publisher = app.rabbitmq.createPublisher({
78
+ confirm: true,
79
+ maxAttempts: 1,
80
+ });
81
+
82
+ await publisher.send("foo", "bar"); // routing key "foo", body "bar"
83
+ ```
84
+
85
+ In a route, reach the instance via `request.server`:
27
86
 
28
- Register this as a plugin.
29
- Make sure it is loaded before any **_routes_** are loaded.
87
+ ```ts
88
+ app.get("/publish", async (request, reply) => {
89
+ const publisher = request.server.rabbitmq.createPublisher({ confirm: true });
90
+ await publisher.send("foo", "bar");
91
+ return { sent: true };
92
+ });
93
+ ```
30
94
 
31
- ### Quick Setup on the Server Side
95
+ ### 2. Consume a queue
32
96
 
33
- ```typescript
34
- export default fp<FastifyRabbitMQOptions>((fastify, options, done) => {
35
- void fastify.register(fastifyRabbit, {
36
- connection: `amqp://guest:guest@localhost`,
37
- });
97
+ ```ts
98
+ const consumer = app.rabbitmq.createConsumer(
99
+ {
100
+ queue: "foo",
101
+ queueOptions: { durable: true },
102
+ },
103
+ async (msg) => {
104
+ app.log.info({ body: msg.body }, "received");
105
+ // ...handle the message...
106
+ },
107
+ );
108
+ ```
109
+
110
+ ### 3. RPC (request/response)
111
+
112
+ ```ts
113
+ const rpc = app.rabbitmq.createRPCClient({ confirm: true });
114
+ const response = await rpc.send("my-rpc-queue", "ping");
115
+ app.log.info({ response: response.body }, "rpc reply");
116
+ ```
38
117
 
39
- void fastify.ready().then(async () => {
40
- const consumer = fastify.rabbitmq.createConsumer(
118
+ ### 4. Declare exchanges, queues, and bindings
119
+
120
+ ```ts
121
+ await app.rabbitmq.queueDeclare({ queue: "foo", durable: true });
122
+ await app.rabbitmq.exchangeDeclare({ exchange: "my-exchange", type: "topic" });
123
+ await app.rabbitmq.queueBind({
124
+ queue: "foo",
125
+ exchange: "my-exchange",
126
+ routingKey: "foo.#",
127
+ });
128
+ ```
129
+
130
+ ### 5. Multiple connections with namespaces
131
+
132
+ To talk to more than one broker (or keep separate connections), register the plugin once per
133
+ `namespace`; each is reachable at `app.rabbitmq.<namespace>`:
134
+
135
+ ```ts
136
+ await app.register(fastifyRabbitMQ, {
137
+ connection: "amqp://guest:guest@broker-a",
138
+ namespace: "a",
139
+ });
140
+ await app.register(fastifyRabbitMQ, {
141
+ connection: "amqp://guest:guest@broker-b",
142
+ namespace: "b",
143
+ });
144
+
145
+ const pubA = app.rabbitmq.a.createPublisher();
146
+ const pubB = app.rabbitmq.b.createPublisher();
147
+ ```
148
+
149
+ Registering the same namespace twice throws `FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS`.
150
+
151
+ ### 6. Encapsulate messaging in your own plugin
152
+
153
+ This is the pattern the plugin is built for, and the reason it is a plugin at all.
154
+ Fastify's encapsulation lets you keep every messaging concern — the connection, the
155
+ topology, the publishers, the consumers, and their shutdown — in **one plugin**, and
156
+ expose just a small, intent-named surface (a decorator like `app.events`) to the rest
157
+ of the app. Your routes publish business events; they never see exchanges, routing
158
+ keys, or the AMQP client.
159
+
160
+ Wrap it with [`fastify-plugin`](https://github.com/fastify/fastify-plugin) so the
161
+ decorator is visible to sibling plugins and routes (without `fp`, the decorator would
162
+ be trapped inside this plugin's encapsulation context):
163
+
164
+ ```ts
165
+ // plugins/messaging.ts
166
+ import fp from "fastify-plugin";
167
+ import fastifyRabbitMQ, { type Publisher } from "fastify-rabbitmq";
168
+
169
+ declare module "fastify" {
170
+ interface FastifyInstance {
171
+ events: Publisher;
172
+ }
173
+ }
174
+
175
+ export default fp(
176
+ async (app) => {
177
+ // 1. Open the connection.
178
+ await app.register(fastifyRabbitMQ, {
179
+ connection: process.env.RABBITMQ_URL ?? "amqp://guest:guest@localhost",
180
+ });
181
+
182
+ // 2. Declare the topology and a publisher once, at startup. The publisher
183
+ // re-declares these on every reconnect, so the exchange always exists
184
+ // before the first send.
185
+ const publisher = app.rabbitmq.createPublisher({
186
+ confirm: true,
187
+ maxAttempts: 2,
188
+ exchanges: [{ exchange: "events", type: "topic" }],
189
+ });
190
+
191
+ // 3. Expose one intent-named sender. Routes call app.events.send(...) and
192
+ // stay ignorant of AMQP.
193
+ app.decorate("events", publisher);
194
+
195
+ // 4. Run consumers as part of the app lifecycle. The consumer manages its
196
+ // own channel and re-subscribes across reconnects.
197
+ const consumer = app.rabbitmq.createConsumer(
41
198
  {
42
- queue: "foo",
199
+ queue: "user-events",
43
200
  queueOptions: { durable: true },
201
+ queueBindings: [{ exchange: "events", routingKey: "user.#" }],
44
202
  },
45
- async (msg: any) => {
46
- console.log(msg); // ==> bar
203
+ async (msg) => {
204
+ app.log.info({ body: msg.body }, "user event");
205
+ // ...handle the message; throw to nack/retry...
47
206
  },
48
207
  );
49
- });
50
- });
208
+
209
+ // 5. Close the consumer and publisher with the app. The plugin then
210
+ // closes the connection itself, after this hook has released the
211
+ // channels, so app.close() resolves and the process can exit.
212
+ app.addHook("onClose", async () => {
213
+ await consumer.close();
214
+ await publisher.close();
215
+ });
216
+ },
217
+ { name: "messaging" },
218
+ );
51
219
  ```
52
220
 
53
- ### Quick Setup on the Client Side
221
+ Register it once, then publish from anywhere:
54
222
 
55
- Within any "endpoint" function, or if you have access to `fastify.rabbitmq` you can then call:
223
+ ```ts
224
+ import messaging from "./plugins/messaging";
56
225
 
57
- ```js
58
- fastify.get("/rabbitmq", async (request, reply) => {
59
- let pub = request.rabbitmq.createPublisher({
60
- confirm: true,
61
- maxAttempts: 1,
62
- });
226
+ await app.register(messaging);
63
227
 
64
- await pub.send("foo", "bar"); // ==> sent to foo queue
228
+ app.post("/signup", async (request, reply) => {
229
+ await app.events.send(
230
+ { exchange: "events", routingKey: "user.created" },
231
+ request.body,
232
+ );
233
+ return { accepted: true };
65
234
  });
66
235
  ```
67
236
 
68
- Sending the string `bar` to the queue called `foo`.
237
+ Why this shape works well:
69
238
 
70
- ## Full Documentation
239
+ - **One place owns messaging.** Connection, topology, publishers, consumers, and
240
+ shutdown live together; the rest of the app depends only on `app.events`.
241
+ - **Startup declares, routes send.** Topology is declared once at boot, so the first
242
+ request never races a missing exchange.
243
+ - **Lifecycle is handled.** The `onClose` hook closes the consumer and publisher, and
244
+ the plugin closes the connection, all with `app.close()` — important for graceful
245
+ shutdown and for tests that start and stop Fastify repeatedly.
246
+ - **Swappable.** Because routes only know `app.events`, you can change brokers, add a
247
+ [namespace](#5-multiple-connections-with-namespaces), or stub the decorator in a test
248
+ without touching route code.
71
249
 
72
- ### Options
250
+ > The types you need — `Publisher`, `Consumer`, `RPCClient`, `Connection`, `ConnectionOptions`,
251
+ > `Envelope`, the message types, and the AMQP error classes — are re-exported from
252
+ > `fastify-rabbitmq`. Import them from here, not from `rabbitmq-client`.
73
253
 
74
- ```typescript
75
- export interface FastifyRabbitMQOptions {
76
- /** Connection String or object pointing to the RabbitMQ Broker Services */
77
- connection: string | ConnectionOptions;
78
- /** To set the custom nNamespace within this plugin instance. Used to register this plugin more than one time. */
79
- namespace?: string;
80
- }
81
- ```
254
+ ## 📖 API Reference (`fastify.rabbitmq`)
255
+
256
+ `app.rabbitmq` is a `rabbitmq-client` `Connection` (and, with namespaces, an index of them). The
257
+ methods you will use most:
258
+
259
+ | Method | Description |
260
+ |---|---|
261
+ | `createPublisher(options?)` | Create a `Publisher` (`.send(routingKey, body)`). |
262
+ | `createConsumer(options, handler)` | Create a `Consumer` bound to a queue; `handler(msg)` runs per message. |
263
+ | `createRPCClient(options?)` | Create an RPC client (`.send(queue, body)` returns the reply). |
264
+ | `exchangeDeclare(params)` | Declare an exchange. |
265
+ | `queueDeclare(params)` | Declare a queue. |
266
+ | `queueBind(params)` | Bind a queue to an exchange. |
267
+ | `acquire()` | Acquire a raw channel. |
268
+ | `onConnect(timeout?)` | Resolve once the connection is established. |
269
+ | `ready` | `true` while the connection is established and unblocked. |
270
+ | `close()` | Close the connection. `app.close()` already does this for you. |
271
+
272
+ The full option shapes for each come from `rabbitmq-client` — see [External Libraries](#-external-libraries).
273
+
274
+ ## ⚙️ Plugin Options
275
+
276
+ Pass these to `app.register(fastifyRabbitMQ, options)`:
277
+
278
+ ### `connection`
279
+
280
+ A connection string (e.g. `"amqp://guest:guest@localhost"`) or a `ConnectionOptions` object from
281
+ `rabbitmq-client` pointing at the broker. **Required.**
82
282
 
83
- #### FastifyRabbitMQOptions
283
+ ### `namespace`
84
284
 
85
- ##### `connection`
285
+ `string` — register the plugin more than once by giving each instance a unique namespace; the
286
+ connection is then exposed at `app.rabbitmq.<namespace>`. Re-using a namespace fails to load.
86
287
 
87
- Connection String or object pointing to the RabbitMQ Broker Services.
88
- This can be an object of `ConnectionOptions` from the `node-rabbitmq-client` plugin options.
288
+ ## 🔌 External Libraries
89
289
 
90
- ##### `namespace`
290
+ This plugin documents only its own surface. For publisher/consumer/RPC options, connection options
291
+ (`ConnectionOptions`), TLS, and reconnect behavior, see the package it wraps:
91
292
 
92
- If you need more than one "connection" to a different set and/or array of RabbitMQ servers,
93
- either on network or cloud, each registration of the plugin needs it to be in its own namespace.
94
- If the name space is duplicated, it will fail to load.
293
+ - [`rabbitmq-client`](https://www.npmjs.com/package/rabbitmq-client) — the underlying AMQP client
294
+ (repo: [cody-greene/node-rabbitmq-client](https://github.com/cody-greene/node-rabbitmq-client)).
95
295
 
96
- ## Acknowledgements
296
+ ## 🙏 Acknowledgements
97
297
 
98
- - [node-rabbitmq-client](https://www.npmjs.com/package/rabbitmq-client)
99
- - [fastify](https://fastify.dev/)
100
- - ... and my Wife and Baby Girl.
298
+ - [`rabbitmq-client`](https://www.npmjs.com/package/rabbitmq-client)
299
+ - [Fastify](https://fastify.dev/)
300
+ - ...and my Wife and Baby Girl.
101
301
 
102
- ## License
302
+ ## 📄 License
103
303
 
104
304
  Licensed under [MIT](./LICENSE).
@@ -0,0 +1,13 @@
1
+ import { ConnectionOptions } from "rabbitmq-client";
2
+ export interface FastifyRabbitMQOptions {
3
+ /**
4
+ * @since 1.0.0
5
+ * @remarks Connection String or object pointing to the RabbitMQ Broker Services
6
+ */
7
+ connection: ConnectionOptions | string;
8
+ /**
9
+ * @since 1.0.0
10
+ * @remarks To set the custom nNamespace within this plugin instance. Used to register this plugin more than one time.
11
+ */
12
+ namespace?: string;
13
+ }
@@ -0,0 +1,14 @@
1
+ export declare const errors: {
2
+ /** Error if there is an invalid option used during registration. */
3
+ FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: import("@fastify/error").FastifyErrorConstructor<{
4
+ code: "FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS";
5
+ }, [any?, any?, any?]>;
6
+ /** Error if there is an setup error of the plugin itself. */
7
+ FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: import("@fastify/error").FastifyErrorConstructor<{
8
+ code: "FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS";
9
+ }, [any?, any?, any?]>;
10
+ /** If an invalid usage error was done, this error would pop up. */
11
+ FASTIFY_RABBIT_MQ_ERR_USAGE: import("@fastify/error").FastifyErrorConstructor<{
12
+ code: "FASTIFY_RABBIT_MQ_ERR_USAGE";
13
+ }, [any?, any?, any?]>;
14
+ };
package/dist/index.cjs ADDED
@@ -0,0 +1,175 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
+ key = keys[i];
15
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ //#endregion
27
+ let fastify_plugin = require("fastify-plugin");
28
+ fastify_plugin = __toESM(fastify_plugin);
29
+ let rabbitmq_client = require("rabbitmq-client");
30
+ let _fastify_error = require("@fastify/error");
31
+ _fastify_error = __toESM(_fastify_error);
32
+ //#region src/errors.ts
33
+ const errors = {
34
+ /** Error if there is an invalid option used during registration. */
35
+ FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: (0, _fastify_error.default)("FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS", "Invalid options: %s"),
36
+ /** Error if there is an setup error of the plugin itself. */
37
+ FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: (0, _fastify_error.default)("FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS", "Setup error: %s"),
38
+ /** If an invalid usage error was done, this error would pop up. */
39
+ FASTIFY_RABBIT_MQ_ERR_USAGE: (0, _fastify_error.default)("FASTIFY_RABBIT_MQ_ERR_USAGE", "Usage error: %s")
40
+ };
41
+ //#endregion
42
+ //#region src/validation.ts
43
+ /**
44
+ * Validate Options
45
+ *
46
+ * The plugin validates only the *shape* of `connection` -- that it is a
47
+ * non-empty connection string or a `ConnectionOptions` object. Parsing the URL
48
+ * and validating the broker options (hosts, TLS, reconnect, etc.) is delegated
49
+ * to `rabbitmq-client`. The shape guard exists because `new Connection(...)`
50
+ * accepts garbage (a number, an array, `null`, `{}`) without throwing and then
51
+ * silently fails to connect at runtime; rejecting it here surfaces a clear
52
+ * registration-time error instead.
53
+ * @since 1.0.0
54
+ * @param options
55
+ */
56
+ const validateOpts = async (options) => {
57
+ const { connection } = options;
58
+ if (connection === void 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS("connection must be defined.");
59
+ if (typeof connection === "string") {
60
+ if (connection.length === 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS("connection string must not be empty.");
61
+ return;
62
+ }
63
+ if (!(typeof connection === "object" && connection !== null && !Array.isArray(connection))) throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS("connection must be a connection string or a ConnectionOptions object.");
64
+ };
65
+ //#endregion
66
+ //#region src/index.ts
67
+ /**
68
+ * How we talk with Fastify
69
+ * @since 1.0.0
70
+ * @param fastify
71
+ * @param options
72
+ * @param connection
73
+ */
74
+ const decorateFastifyInstance = (fastify, options, connection) => {
75
+ const { namespace = "" } = options;
76
+ if (namespace !== void 0 && namespace !== "") fastify.log.debug("[fastify-rabbitmq] Namespace Attempt: %s", namespace);
77
+ if (namespace !== void 0 && namespace !== "") {
78
+ if (fastify.rabbitmq === void 0) fastify.decorate("rabbitmq", Object.create(null));
79
+ if (fastify.rabbitmq[namespace] !== void 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(`Already registered with namespace: ${namespace}`);
80
+ fastify.log.trace(`[fastify-rabbitmq] Decorate Fastify with Namespace: ${namespace}`);
81
+ fastify.rabbitmq[namespace] = connection;
82
+ } else if (fastify.rabbitmq !== void 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS("Already registered.");
83
+ if (fastify.rabbitmq === void 0) {
84
+ fastify.log.trace("[fastify-rabbitmq] Decorate Fastify");
85
+ fastify.decorate("rabbitmq", connection);
86
+ }
87
+ };
88
+ /**
89
+ * Main Function
90
+ * @since 1.0.0
91
+ * @example
92
+ * This is the basics on how to use this plugin:
93
+ * ```js
94
+ * app.register(fastifyRabbit, {
95
+ * connection: 'amqp://guest:guest@localhost'
96
+ * })
97
+ * ```
98
+ * This will allow you to read from your Fastify "object" and
99
+ * use this plugin at the "rabbitmq" level. From there you can execute and maintain
100
+ * the RabbitMQ Connection using the 'rabbitmq-client' package, which is wrapping around
101
+ * this plugin to execute functions it provides.
102
+ *
103
+ * @see [https://cody-greene.github.io/node-rabbitmq-client/latest/index.html](https://cody-greene.github.io/node-rabbitmq-client/latest/index.html)
104
+ *
105
+ */
106
+ const fastifyRabbit = (0, fastify_plugin.default)(async (fastify, opts) => {
107
+ await validateOpts(opts);
108
+ const { connection, namespace = "" } = opts;
109
+ const label = namespace === "" ? "(default)" : namespace;
110
+ fastify.log.debug("[fastify-rabbitmq] Creating connection for namespace %s", label);
111
+ const c = new rabbitmq_client.Connection(connection);
112
+ watchConnection(fastify, c, label);
113
+ decorateFastifyInstance(fastify, opts, c);
114
+ fastify.addHook("onClose", async () => {
115
+ const started = Date.now();
116
+ fastify.log.debug("[fastify-rabbitmq] Closing connection for namespace %s", label);
117
+ try {
118
+ await c.close();
119
+ fastify.log.info("[fastify-rabbitmq] Connection for namespace %s closed in %dms", label, Date.now() - started);
120
+ } catch (error) {
121
+ fastify.log.error({ err: error }, "[fastify-rabbitmq] Failed to close connection for namespace %s", label);
122
+ }
123
+ });
124
+ });
125
+ /**
126
+ * Log the connection's lifecycle events. The 'error' listener also keeps a
127
+ * refused or dropped connection from becoming an unhandled 'error' event,
128
+ * which would crash the process (#164). rabbitmq-client keeps retrying in the
129
+ * background, so an error here is reported, not fatal.
130
+ * @since 3.4.1
131
+ * @param fastify
132
+ * @param c
133
+ * @param label
134
+ */
135
+ const watchConnection = (fastify, c, label) => {
136
+ c.on("error", (err) => {
137
+ fastify.log.error({ err }, "[fastify-rabbitmq] RabbitMQ connection error for namespace %s", label);
138
+ });
139
+ c.on("connection", () => {
140
+ fastify.log.info("[fastify-rabbitmq] RabbitMQ connection established for namespace %s", label);
141
+ });
142
+ c.on("connection.blocked", (reason) => {
143
+ fastify.log.warn("[fastify-rabbitmq] RabbitMQ connection blocked for namespace %s: %s", label, reason);
144
+ });
145
+ c.on("connection.unblocked", () => {
146
+ fastify.log.info("[fastify-rabbitmq] RabbitMQ connection unblocked for namespace %s", label);
147
+ });
148
+ };
149
+ //#endregion
150
+ Object.defineProperty(exports, "AMQPChannelError", {
151
+ enumerable: true,
152
+ get: function() {
153
+ return rabbitmq_client.AMQPChannelError;
154
+ }
155
+ });
156
+ Object.defineProperty(exports, "AMQPConnectionError", {
157
+ enumerable: true,
158
+ get: function() {
159
+ return rabbitmq_client.AMQPConnectionError;
160
+ }
161
+ });
162
+ Object.defineProperty(exports, "AMQPError", {
163
+ enumerable: true,
164
+ get: function() {
165
+ return rabbitmq_client.AMQPError;
166
+ }
167
+ });
168
+ Object.defineProperty(exports, "ConsumerStatus", {
169
+ enumerable: true,
170
+ get: function() {
171
+ return rabbitmq_client.ConsumerStatus;
172
+ }
173
+ });
174
+ exports.decorateFastifyInstance = decorateFastifyInstance;
175
+ exports.default = fastifyRabbit;
@@ -0,0 +1,35 @@
1
+ import { FastifyInstance } from "fastify";
2
+ import { FastifyRabbitMQOptions } from "./decorate";
3
+ export { type FastifyRabbitMQOptions } from "./decorate";
4
+ /**
5
+ * How we talk with Fastify
6
+ * @since 1.0.0
7
+ * @param fastify
8
+ * @param options
9
+ * @param connection
10
+ */
11
+ declare const decorateFastifyInstance: (fastify: FastifyInstance, options: FastifyRabbitMQOptions, connection: any) => void;
12
+ /**
13
+ * Main Function
14
+ * @since 1.0.0
15
+ * @example
16
+ * This is the basics on how to use this plugin:
17
+ * ```js
18
+ * app.register(fastifyRabbit, {
19
+ * connection: 'amqp://guest:guest@localhost'
20
+ * })
21
+ * ```
22
+ * This will allow you to read from your Fastify "object" and
23
+ * use this plugin at the "rabbitmq" level. From there you can execute and maintain
24
+ * the RabbitMQ Connection using the 'rabbitmq-client' package, which is wrapping around
25
+ * this plugin to execute functions it provides.
26
+ *
27
+ * @see [https://cody-greene.github.io/node-rabbitmq-client/latest/index.html](https://cody-greene.github.io/node-rabbitmq-client/latest/index.html)
28
+ *
29
+ */
30
+ declare const fastifyRabbit: import("fastify").FastifyPluginCallback<FastifyRabbitMQOptions, import("fastify").RawServerDefault, import("fastify").FastifyTypeProviderDefault, import("fastify").FastifyBaseLogger>;
31
+ export default fastifyRabbit;
32
+ export { decorateFastifyInstance };
33
+ export * from "./types";
34
+ export type { AsyncMessage, Channel, Connection, ConnectionOptions, Consumer, ConsumerHandler, ConsumerProps, Envelope, HeaderFields, MessageBody, Publisher, PublisherProps, ReturnedMessage, RPCClient, RPCProps, SyncMessage, } from "rabbitmq-client";
35
+ export { AMQPChannelError, AMQPConnectionError, AMQPError, ConsumerStatus, } from "rabbitmq-client";
package/dist/index.mjs ADDED
@@ -0,0 +1,122 @@
1
+ import fp from "fastify-plugin";
2
+ import { AMQPChannelError, AMQPConnectionError, AMQPError, Connection, ConsumerStatus } from "rabbitmq-client";
3
+ import createError from "@fastify/error";
4
+ //#region src/errors.ts
5
+ const errors = {
6
+ /** Error if there is an invalid option used during registration. */
7
+ FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: createError("FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS", "Invalid options: %s"),
8
+ /** Error if there is an setup error of the plugin itself. */
9
+ FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: createError("FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS", "Setup error: %s"),
10
+ /** If an invalid usage error was done, this error would pop up. */
11
+ FASTIFY_RABBIT_MQ_ERR_USAGE: createError("FASTIFY_RABBIT_MQ_ERR_USAGE", "Usage error: %s")
12
+ };
13
+ //#endregion
14
+ //#region src/validation.ts
15
+ /**
16
+ * Validate Options
17
+ *
18
+ * The plugin validates only the *shape* of `connection` -- that it is a
19
+ * non-empty connection string or a `ConnectionOptions` object. Parsing the URL
20
+ * and validating the broker options (hosts, TLS, reconnect, etc.) is delegated
21
+ * to `rabbitmq-client`. The shape guard exists because `new Connection(...)`
22
+ * accepts garbage (a number, an array, `null`, `{}`) without throwing and then
23
+ * silently fails to connect at runtime; rejecting it here surfaces a clear
24
+ * registration-time error instead.
25
+ * @since 1.0.0
26
+ * @param options
27
+ */
28
+ const validateOpts = async (options) => {
29
+ const { connection } = options;
30
+ if (connection === void 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS("connection must be defined.");
31
+ if (typeof connection === "string") {
32
+ if (connection.length === 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS("connection string must not be empty.");
33
+ return;
34
+ }
35
+ if (!(typeof connection === "object" && connection !== null && !Array.isArray(connection))) throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS("connection must be a connection string or a ConnectionOptions object.");
36
+ };
37
+ //#endregion
38
+ //#region src/index.ts
39
+ /**
40
+ * How we talk with Fastify
41
+ * @since 1.0.0
42
+ * @param fastify
43
+ * @param options
44
+ * @param connection
45
+ */
46
+ const decorateFastifyInstance = (fastify, options, connection) => {
47
+ const { namespace = "" } = options;
48
+ if (namespace !== void 0 && namespace !== "") fastify.log.debug("[fastify-rabbitmq] Namespace Attempt: %s", namespace);
49
+ if (namespace !== void 0 && namespace !== "") {
50
+ if (fastify.rabbitmq === void 0) fastify.decorate("rabbitmq", Object.create(null));
51
+ if (fastify.rabbitmq[namespace] !== void 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(`Already registered with namespace: ${namespace}`);
52
+ fastify.log.trace(`[fastify-rabbitmq] Decorate Fastify with Namespace: ${namespace}`);
53
+ fastify.rabbitmq[namespace] = connection;
54
+ } else if (fastify.rabbitmq !== void 0) throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS("Already registered.");
55
+ if (fastify.rabbitmq === void 0) {
56
+ fastify.log.trace("[fastify-rabbitmq] Decorate Fastify");
57
+ fastify.decorate("rabbitmq", connection);
58
+ }
59
+ };
60
+ /**
61
+ * Main Function
62
+ * @since 1.0.0
63
+ * @example
64
+ * This is the basics on how to use this plugin:
65
+ * ```js
66
+ * app.register(fastifyRabbit, {
67
+ * connection: 'amqp://guest:guest@localhost'
68
+ * })
69
+ * ```
70
+ * This will allow you to read from your Fastify "object" and
71
+ * use this plugin at the "rabbitmq" level. From there you can execute and maintain
72
+ * the RabbitMQ Connection using the 'rabbitmq-client' package, which is wrapping around
73
+ * this plugin to execute functions it provides.
74
+ *
75
+ * @see [https://cody-greene.github.io/node-rabbitmq-client/latest/index.html](https://cody-greene.github.io/node-rabbitmq-client/latest/index.html)
76
+ *
77
+ */
78
+ const fastifyRabbit = fp(async (fastify, opts) => {
79
+ await validateOpts(opts);
80
+ const { connection, namespace = "" } = opts;
81
+ const label = namespace === "" ? "(default)" : namespace;
82
+ fastify.log.debug("[fastify-rabbitmq] Creating connection for namespace %s", label);
83
+ const c = new Connection(connection);
84
+ watchConnection(fastify, c, label);
85
+ decorateFastifyInstance(fastify, opts, c);
86
+ fastify.addHook("onClose", async () => {
87
+ const started = Date.now();
88
+ fastify.log.debug("[fastify-rabbitmq] Closing connection for namespace %s", label);
89
+ try {
90
+ await c.close();
91
+ fastify.log.info("[fastify-rabbitmq] Connection for namespace %s closed in %dms", label, Date.now() - started);
92
+ } catch (error) {
93
+ fastify.log.error({ err: error }, "[fastify-rabbitmq] Failed to close connection for namespace %s", label);
94
+ }
95
+ });
96
+ });
97
+ /**
98
+ * Log the connection's lifecycle events. The 'error' listener also keeps a
99
+ * refused or dropped connection from becoming an unhandled 'error' event,
100
+ * which would crash the process (#164). rabbitmq-client keeps retrying in the
101
+ * background, so an error here is reported, not fatal.
102
+ * @since 3.4.1
103
+ * @param fastify
104
+ * @param c
105
+ * @param label
106
+ */
107
+ const watchConnection = (fastify, c, label) => {
108
+ c.on("error", (err) => {
109
+ fastify.log.error({ err }, "[fastify-rabbitmq] RabbitMQ connection error for namespace %s", label);
110
+ });
111
+ c.on("connection", () => {
112
+ fastify.log.info("[fastify-rabbitmq] RabbitMQ connection established for namespace %s", label);
113
+ });
114
+ c.on("connection.blocked", (reason) => {
115
+ fastify.log.warn("[fastify-rabbitmq] RabbitMQ connection blocked for namespace %s: %s", label, reason);
116
+ });
117
+ c.on("connection.unblocked", () => {
118
+ fastify.log.info("[fastify-rabbitmq] RabbitMQ connection unblocked for namespace %s", label);
119
+ });
120
+ };
121
+ //#endregion
122
+ export { AMQPChannelError, AMQPConnectionError, AMQPError, ConsumerStatus, decorateFastifyInstance, fastifyRabbit as default };
@@ -0,0 +1,12 @@
1
+ import { Connection as RabbitMQConnection } from "rabbitmq-client";
2
+ declare module "fastify" {
3
+ interface FastifyInstance {
4
+ /** Main Decorator for Fastify **/
5
+ rabbitmq: fastifyRabbitMQ.FastifyRabbitMQNO & RabbitMQConnection;
6
+ }
7
+ }
8
+ export declare namespace fastifyRabbitMQ {
9
+ interface FastifyRabbitMQNO {
10
+ [namespace: string]: RabbitMQConnection;
11
+ }
12
+ }
@@ -0,0 +1,15 @@
1
+ import { FastifyRabbitMQOptions } from "./decorate";
2
+ /**
3
+ * Validate Options
4
+ *
5
+ * The plugin validates only the *shape* of `connection` -- that it is a
6
+ * non-empty connection string or a `ConnectionOptions` object. Parsing the URL
7
+ * and validating the broker options (hosts, TLS, reconnect, etc.) is delegated
8
+ * to `rabbitmq-client`. The shape guard exists because `new Connection(...)`
9
+ * accepts garbage (a number, an array, `null`, `{}`) without throwing and then
10
+ * silently fails to connect at runtime; rejecting it here surfaces a clear
11
+ * registration-time error instead.
12
+ * @since 1.0.0
13
+ * @param options
14
+ */
15
+ export declare const validateOpts: (options: FastifyRabbitMQOptions) => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify-rabbitmq",
3
- "version": "3.3.0",
3
+ "version": "3.4.1",
4
4
  "description": "A Fastify RabbitMQ Plugin Developed in Pure TypeScript.",
5
5
  "keywords": [
6
6
  "rabbitmq-client",
@@ -21,32 +21,35 @@
21
21
  "author": "Shane Froebel",
22
22
  "exports": {
23
23
  ".": {
24
- "types": "./lib/types/index.d.ts",
25
- "import": "./lib/esm/index.mjs",
26
- "require": "./lib/cjs/index.js",
27
- "default": "./lib/cjs/index.js"
24
+ "import": {
25
+ "types": "./dist/index.d.ts",
26
+ "default": "./dist/index.mjs"
27
+ },
28
+ "require": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.cjs"
31
+ }
28
32
  }
29
33
  },
30
- "main": "./lib/cjs/index.js",
31
- "module": "./lib/esm/index.mjs",
32
- "types": "./lib/types/index.d.ts",
34
+ "main": "./dist/index.cjs",
35
+ "module": "./dist/index.mjs",
36
+ "types": "./dist/index.d.ts",
33
37
  "files": [
34
- "lib/",
38
+ "dist",
35
39
  "README.md",
36
- "LICENSE"
40
+ "LICENSE",
41
+ "CHANGELOG.md"
37
42
  ],
38
43
  "scripts": {
39
- "build": "tsup",
40
- "build:dev": "NODE_ENV=development tsup",
41
- "clean": "rm -rf coverage docs lib temp",
42
- "format:check": "prettier --check '**/*.{md,ts,json,mts}'",
43
- "format:write": "prettier --write '**/*.{md,ts,json,mts}'",
44
- "lint": "npm run lint:npm && eslint | snazzy && npm run format:check",
45
- "lint:fix": "npm run lint:npm && eslint --fix | snazzy && npm run format:write",
44
+ "build": "tsdown && tsc --emitDeclarationOnly",
45
+ "check:pack": "node scripts/checkPack.mjs",
46
+ "clean": "rm -rf coverage docs dist temp",
47
+ "lint": "eslint .",
48
+ "lint:fix": "eslint . --fix",
46
49
  "lint:npm": "npmPkgJsonLint .",
47
50
  "lint:package": "npx sort-package-json",
48
51
  "pack": "npm pack",
49
- "prepublishOnly": "npm run clean && npm run build && npm run pack",
52
+ "prepublishOnly": "npm run clean && npm run build",
50
53
  "test": "vitest run",
51
54
  "test:coverage": "vitest --coverage",
52
55
  "test:verbose": "vitest run --reporter verbose",
@@ -54,16 +57,17 @@
54
57
  "typedoc": "typedoc",
55
58
  "typedoc:watch": "typedoc -watch",
56
59
  "update": "npx npm-check-updates -u --enginesNode && npm run update:post-update",
57
- "update:post-update": "npm install && npm run test"
60
+ "update:post-update": "npm install && npm run test",
61
+ "build:watch": "tsdown --watch",
62
+ "typecheck": "tsc --noEmit"
58
63
  },
59
64
  "dependencies": {
60
- "@fastify/error": "^4.1.0",
61
- "fastify-plugin": "^5.0.1",
62
- "rabbitmq-client": "^5.0.4"
65
+ "@fastify/error": "^4.2.0",
66
+ "fastify-plugin": "^5.1.0",
67
+ "rabbitmq-client": "^5.0.8"
63
68
  },
64
69
  "devDependencies": {
65
70
  "@eslint/js": "^9.28.0",
66
- "@ianvs/prettier-plugin-sort-imports": "^4.4.2",
67
71
  "@shipgirl/typedoc-plugin-versions": "^0.3.1",
68
72
  "@types/node": "^22.15.29",
69
73
  "@typescript-eslint/eslint-plugin": "^8.33.0",
@@ -71,27 +75,25 @@
71
75
  "@vitest/coverage-v8": "^3.1.4",
72
76
  "@vitest/ui": "^3.1.4",
73
77
  "eslint": "^9.28.0",
74
- "eslint-config-prettier": "^10.1.5",
75
- "eslint-plugin-prettier": "^5.4.1",
76
78
  "eslint-plugin-sort-class-members": "^1.21.0",
77
79
  "fastify": "^5.3.3",
78
80
  "npm-check-updates": "^18.0.1",
79
81
  "npm-package-json-lint": "^8.0.0",
80
82
  "npm-package-json-lint-config-default": "^7.0.1",
81
83
  "pre-commit": "^1.2.2",
82
- "prettier-plugin-organize-imports": "^4.1.0",
83
84
  "snazzy": "^9.0.0",
84
85
  "sort-package-json": "^3.2.1",
85
86
  "ts-node": "^10.9.2",
86
87
  "tsd": "^0.32.0",
87
- "tsup": "^8.5.0",
88
88
  "typedoc": "^0.28.5",
89
89
  "typescript": "^5.8.3",
90
90
  "typescript-eslint": "^8.33.0",
91
- "vitest": "^3.1.4"
91
+ "vitest": "^3.1.4",
92
+ "@the-rabbit-hole/eslint-config": "^0.4.0",
93
+ "tsdown": "^0.22.2"
92
94
  },
93
95
  "engines": {
94
- "node": ">=20.11.0"
96
+ "node": ">=20.15.0"
95
97
  },
96
98
  "precommit": [
97
99
  "test",
package/lib/cjs/index.js DELETED
@@ -1,115 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- decorateFastifyInstance: () => decorateFastifyInstance,
34
- default: () => index_default
35
- });
36
- module.exports = __toCommonJS(index_exports);
37
- var import_fastify_plugin = __toESM(require("fastify-plugin"));
38
- var import_rabbitmq_client = require("rabbitmq-client");
39
-
40
- // src/errors.ts
41
- var import_error = __toESM(require("@fastify/error"));
42
- var errors = {
43
- /** Error if there is an invalid option used during registration. */
44
- FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: (0, import_error.default)(
45
- "FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS",
46
- "Invalid options: %s"
47
- ),
48
- /** Error if there is an setup error of the plugin itself. */
49
- FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: (0, import_error.default)(
50
- "FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS",
51
- "Setup error: %s"
52
- ),
53
- /** If an invalid usage error was done, this error would pop up. */
54
- FASTIFY_RABBIT_MQ_ERR_USAGE: (0, import_error.default)(
55
- "FASTIFY_RABBIT_MQ_ERR_USAGE",
56
- "Usage error: %s"
57
- )
58
- };
59
-
60
- // src/validation.ts
61
- var validateOpts = async (options) => {
62
- if (typeof options.connection === "undefined") {
63
- throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(
64
- "connection or findServers must be defined."
65
- );
66
- }
67
- if (typeof options.connection !== "undefined") {
68
- if (typeof options.connection !== "object") {
69
- }
70
- }
71
- };
72
-
73
- // src/index.ts
74
- var decorateFastifyInstance = (fastify, options, connection) => {
75
- const { namespace = "" } = options;
76
- if (typeof namespace !== "undefined" && namespace !== "") {
77
- fastify.log.debug("[fastify-rabbitmq] Namespace Attempt: %s", namespace);
78
- }
79
- if (typeof namespace !== "undefined" && namespace !== "") {
80
- if (typeof fastify.rabbitmq === "undefined") {
81
- fastify.decorate("rabbitmq", /* @__PURE__ */ Object.create(null));
82
- }
83
- if (typeof fastify.rabbitmq[namespace] !== "undefined") {
84
- throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(
85
- `Already registered with namespace: ${namespace}`
86
- );
87
- }
88
- fastify.log.trace(
89
- "[fastify-rabbitmq] Decorate Fastify with Namespace: %",
90
- namespace
91
- );
92
- fastify.rabbitmq[namespace] = connection;
93
- } else {
94
- if (typeof fastify.rabbitmq !== "undefined") {
95
- throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(
96
- "Already registered."
97
- );
98
- }
99
- }
100
- if (typeof fastify.rabbitmq === "undefined") {
101
- fastify.log.trace("[fastify-rabbitmq] Decorate Fastify");
102
- fastify.decorate("rabbitmq", connection);
103
- }
104
- };
105
- var fastifyRabbit = (0, import_fastify_plugin.default)(async (fastify, opts) => {
106
- await validateOpts(opts);
107
- const { connection } = opts;
108
- const c = new import_rabbitmq_client.Connection(connection);
109
- decorateFastifyInstance(fastify, opts, c);
110
- });
111
- var index_default = fastifyRabbit;
112
- // Annotate the CommonJS export names for ESM import in node:
113
- 0 && (module.exports = {
114
- decorateFastifyInstance
115
- });
package/lib/esm/index.mjs DELETED
@@ -1,82 +0,0 @@
1
- // src/index.ts
2
- import fp from "fastify-plugin";
3
- import {
4
- Connection as RabbitMQConnection
5
- } from "rabbitmq-client";
6
-
7
- // src/errors.ts
8
- import createError from "@fastify/error";
9
- var errors = {
10
- /** Error if there is an invalid option used during registration. */
11
- FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: createError(
12
- "FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS",
13
- "Invalid options: %s"
14
- ),
15
- /** Error if there is an setup error of the plugin itself. */
16
- FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: createError(
17
- "FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS",
18
- "Setup error: %s"
19
- ),
20
- /** If an invalid usage error was done, this error would pop up. */
21
- FASTIFY_RABBIT_MQ_ERR_USAGE: createError(
22
- "FASTIFY_RABBIT_MQ_ERR_USAGE",
23
- "Usage error: %s"
24
- )
25
- };
26
-
27
- // src/validation.ts
28
- var validateOpts = async (options) => {
29
- if (typeof options.connection === "undefined") {
30
- throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(
31
- "connection or findServers must be defined."
32
- );
33
- }
34
- if (typeof options.connection !== "undefined") {
35
- if (typeof options.connection !== "object") {
36
- }
37
- }
38
- };
39
-
40
- // src/index.ts
41
- var decorateFastifyInstance = (fastify, options, connection) => {
42
- const { namespace = "" } = options;
43
- if (typeof namespace !== "undefined" && namespace !== "") {
44
- fastify.log.debug("[fastify-rabbitmq] Namespace Attempt: %s", namespace);
45
- }
46
- if (typeof namespace !== "undefined" && namespace !== "") {
47
- if (typeof fastify.rabbitmq === "undefined") {
48
- fastify.decorate("rabbitmq", /* @__PURE__ */ Object.create(null));
49
- }
50
- if (typeof fastify.rabbitmq[namespace] !== "undefined") {
51
- throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(
52
- `Already registered with namespace: ${namespace}`
53
- );
54
- }
55
- fastify.log.trace(
56
- "[fastify-rabbitmq] Decorate Fastify with Namespace: %",
57
- namespace
58
- );
59
- fastify.rabbitmq[namespace] = connection;
60
- } else {
61
- if (typeof fastify.rabbitmq !== "undefined") {
62
- throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(
63
- "Already registered."
64
- );
65
- }
66
- }
67
- if (typeof fastify.rabbitmq === "undefined") {
68
- fastify.log.trace("[fastify-rabbitmq] Decorate Fastify");
69
- fastify.decorate("rabbitmq", connection);
70
- }
71
- };
72
- var fastifyRabbit = fp(async (fastify, opts) => {
73
- await validateOpts(opts);
74
- const { connection } = opts;
75
- const c = new RabbitMQConnection(connection);
76
- decorateFastifyInstance(fastify, opts, c);
77
- });
78
- var index_default = fastifyRabbit;
79
- export {
80
- decorateFastifyInstance,
81
- index_default as default
82
- };
@@ -1,59 +0,0 @@
1
- import * as fastify from 'fastify';
2
- import { FastifyInstance } from 'fastify';
3
- import { ConnectionOptions, Connection } from 'rabbitmq-client';
4
- export { ConnectionOptions } from 'rabbitmq-client';
5
-
6
- interface FastifyRabbitMQOptions {
7
- /**
8
- * @since 1.0.0
9
- * @remarks Connection String or object pointing to the RabbitMQ Broker Services
10
- */
11
- connection: string | ConnectionOptions;
12
- /**
13
- * @since 1.0.0
14
- * @remarks To set the custom nNamespace within this plugin instance. Used to register this plugin more than one time.
15
- */
16
- namespace?: string;
17
- }
18
-
19
- declare module "fastify" {
20
- interface FastifyInstance {
21
- /** Main Decorator for Fastify **/
22
- rabbitmq: Connection & fastifyRabbitMQ.FastifyRabbitMQNO;
23
- }
24
- }
25
- declare namespace fastifyRabbitMQ {
26
- interface FastifyRabbitMQNO {
27
- [namespace: string]: Connection;
28
- }
29
- }
30
-
31
- /**
32
- * How we talk with Fastify
33
- * @since 1.0.0
34
- * @param fastify
35
- * @param options
36
- * @param connection
37
- */
38
- declare const decorateFastifyInstance: (fastify: FastifyInstance, options: FastifyRabbitMQOptions, connection: any) => void;
39
- /**
40
- * Main Function
41
- * @since 1.0.0
42
- * @example
43
- * This is the basics on how to use this plugin:
44
- * ```js
45
- * app.register(fastifyRabbit, {
46
- * connection: 'amqp://guest:guest@localhost'
47
- * })
48
- * ```
49
- * This will allow you to read from your Fastify "object" and
50
- * use this plugin at the "rabbitmq" level. From there you can execute and maintain
51
- * the RabbitMQ Connection using the 'rabbitmq-client' package, which is wrapping around
52
- * this plugin to execute functions it provides.
53
- *
54
- * @see [https://cody-greene.github.io/node-rabbitmq-client/latest/index.html](https://cody-greene.github.io/node-rabbitmq-client/latest/index.html)
55
- *
56
- */
57
- declare const fastifyRabbit: fastify.FastifyPluginCallback<FastifyRabbitMQOptions, fastify.RawServerDefault, fastify.FastifyTypeProviderDefault, fastify.FastifyBaseLogger>;
58
-
59
- export { type FastifyRabbitMQOptions, decorateFastifyInstance, fastifyRabbit as default, fastifyRabbitMQ };