fastify-rabbitmq 3.4.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 +22 -2
- package/README.md +23 -10
- package/dist/decorate.d.ts +0 -1
- package/dist/errors.d.ts +0 -1
- package/dist/index.cjs +41 -5
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +40 -4
- package/dist/types.d.ts +0 -1
- package/dist/validation.d.ts +0 -1
- package/package.json +2 -1
- package/dist/decorate.d.ts.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/validation.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Fastify RabbitMQ
|
|
2
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
|
+
|
|
3
25
|
## v3.4.0 - 2026-06-09
|
|
4
26
|
|
|
5
27
|
### What Changed 👀
|
|
@@ -60,8 +82,6 @@
|
|
|
60
82
|
|
|
61
83
|
#### What Changed 👀
|
|
62
84
|
|
|
63
|
-
- ci: update workflows @Bugs5382 (#103)
|
|
64
|
-
|
|
65
85
|
#### 🧩 Dependency Updates
|
|
66
86
|
|
|
67
87
|
- feat: updated packages @Bugs5382 (#105)
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Fastify RabbitMQ 🐰
|
|
2
|
+
|
|
3
|
+
> 📨 A Fastify RabbitMQ plugin developed in pure TypeScript.
|
|
2
4
|
|
|
3
|
-
A Fastify RabbitMQ plugin developed in pure TypeScript.
|
|
4
5
|
It wraps the [`rabbitmq-client`](https://www.npmjs.com/package/rabbitmq-client) package so a Fastify
|
|
5
6
|
app can publish, consume, and RPC over RabbitMQ (AMQP 0-9-1).
|
|
6
7
|
|
|
@@ -15,7 +16,7 @@ contribution from the outside.
|
|
|
15
16
|
|
|
16
17
|
> 🟢 **Requires Node.js ≥ 20.15.**
|
|
17
18
|
|
|
18
|
-
## Table of Contents
|
|
19
|
+
## 📑 Table of Contents
|
|
19
20
|
|
|
20
21
|
1. [Install](#-install)
|
|
21
22
|
2. [Basic Usage](#-basic-usage)
|
|
@@ -58,6 +59,16 @@ await app.register(fastifyRabbitMQ, {
|
|
|
58
59
|
Registering decorates the Fastify instance with `app.rabbitmq` — a live `rabbitmq-client`
|
|
59
60
|
`Connection`. Use it to create publishers, consumers, and RPC clients, or to declare topology.
|
|
60
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
|
+
|
|
61
72
|
## 🧩 Recipes
|
|
62
73
|
|
|
63
74
|
### 1. Publish a message
|
|
@@ -195,8 +206,9 @@ export default fp(
|
|
|
195
206
|
},
|
|
196
207
|
);
|
|
197
208
|
|
|
198
|
-
// 5.
|
|
199
|
-
//
|
|
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.
|
|
200
212
|
app.addHook("onClose", async () => {
|
|
201
213
|
await consumer.close();
|
|
202
214
|
await publisher.close();
|
|
@@ -228,9 +240,9 @@ Why this shape works well:
|
|
|
228
240
|
shutdown live together; the rest of the app depends only on `app.events`.
|
|
229
241
|
- **Startup declares, routes send.** Topology is declared once at boot, so the first
|
|
230
242
|
request never races a missing exchange.
|
|
231
|
-
- **Lifecycle is handled.** The `onClose` hook closes the consumer and publisher
|
|
232
|
-
the
|
|
233
|
-
repeatedly.
|
|
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.
|
|
234
246
|
- **Swappable.** Because routes only know `app.events`, you can change brokers, add a
|
|
235
247
|
[namespace](#5-multiple-connections-with-namespaces), or stub the decorator in a test
|
|
236
248
|
without touching route code.
|
|
@@ -253,8 +265,9 @@ methods you will use most:
|
|
|
253
265
|
| `queueDeclare(params)` | Declare a queue. |
|
|
254
266
|
| `queueBind(params)` | Bind a queue to an exchange. |
|
|
255
267
|
| `acquire()` | Acquire a raw channel. |
|
|
256
|
-
| `
|
|
257
|
-
| `
|
|
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. |
|
|
258
271
|
|
|
259
272
|
The full option shapes for each come from `rabbitmq-client` — see [External Libraries](#-external-libraries).
|
|
260
273
|
|
package/dist/decorate.d.ts
CHANGED
package/dist/errors.d.ts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -19,7 +19,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
19
19
|
}
|
|
20
20
|
return to;
|
|
21
21
|
};
|
|
22
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
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
23
|
value: mod,
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
@@ -105,9 +105,47 @@ const decorateFastifyInstance = (fastify, options, connection) => {
|
|
|
105
105
|
*/
|
|
106
106
|
const fastifyRabbit = (0, fastify_plugin.default)(async (fastify, opts) => {
|
|
107
107
|
await validateOpts(opts);
|
|
108
|
-
const { connection } = opts;
|
|
109
|
-
|
|
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
|
+
});
|
|
110
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
|
+
};
|
|
111
149
|
//#endregion
|
|
112
150
|
Object.defineProperty(exports, "AMQPChannelError", {
|
|
113
151
|
enumerable: true,
|
|
@@ -135,5 +173,3 @@ Object.defineProperty(exports, "ConsumerStatus", {
|
|
|
135
173
|
});
|
|
136
174
|
exports.decorateFastifyInstance = decorateFastifyInstance;
|
|
137
175
|
exports.default = fastifyRabbit;
|
|
138
|
-
|
|
139
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -33,4 +33,3 @@ export { decorateFastifyInstance };
|
|
|
33
33
|
export * from "./types";
|
|
34
34
|
export type { AsyncMessage, Channel, Connection, ConnectionOptions, Consumer, ConsumerHandler, ConsumerProps, Envelope, HeaderFields, MessageBody, Publisher, PublisherProps, ReturnedMessage, RPCClient, RPCProps, SyncMessage, } from "rabbitmq-client";
|
|
35
35
|
export { AMQPChannelError, AMQPConnectionError, AMQPError, ConsumerStatus, } from "rabbitmq-client";
|
|
36
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.mjs
CHANGED
|
@@ -77,10 +77,46 @@ const decorateFastifyInstance = (fastify, options, connection) => {
|
|
|
77
77
|
*/
|
|
78
78
|
const fastifyRabbit = fp(async (fastify, opts) => {
|
|
79
79
|
await validateOpts(opts);
|
|
80
|
-
const { connection } = opts;
|
|
81
|
-
|
|
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
|
+
});
|
|
82
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
|
+
};
|
|
83
121
|
//#endregion
|
|
84
122
|
export { AMQPChannelError, AMQPConnectionError, AMQPError, ConsumerStatus, decorateFastifyInstance, fastifyRabbit as default };
|
|
85
|
-
|
|
86
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/types.d.ts
CHANGED
package/dist/validation.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify-rabbitmq",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "A Fastify RabbitMQ Plugin Developed in Pure TypeScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rabbitmq-client",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
],
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsdown && tsc --emitDeclarationOnly",
|
|
45
|
+
"check:pack": "node scripts/checkPack.mjs",
|
|
45
46
|
"clean": "rm -rf coverage docs dist temp",
|
|
46
47
|
"lint": "eslint .",
|
|
47
48
|
"lint:fix": "eslint . --fix",
|
package/dist/decorate.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"decorate.d.ts","sourceRoot":"","sources":["../src/decorate.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,UAAU,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
package/dist/errors.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,MAAM;IACjB,oEAAoE;;;;IAKpE,6DAA6D;;;;IAK7D,mEAAmE;;;;CAKpE,CAAC"}
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["RabbitMQConnection"],"sources":["../src/errors.ts","../src/validation.ts","../src/index.ts"],"sourcesContent":["/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport createError from \"@fastify/error\";\n\nexport const errors = {\n /** Error if there is an invalid option used during registration. */\n FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: createError(\n \"FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS\",\n \"Invalid options: %s\",\n ),\n /** Error if there is an setup error of the plugin itself. */\n FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: createError(\n \"FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS\",\n \"Setup error: %s\",\n ),\n /** If an invalid usage error was done, this error would pop up. */\n FASTIFY_RABBIT_MQ_ERR_USAGE: createError(\n \"FASTIFY_RABBIT_MQ_ERR_USAGE\",\n \"Usage error: %s\",\n ),\n};\n","/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport { FastifyRabbitMQOptions } from \"./decorate\";\nimport { errors } from \"./errors\";\n\n/**\n * Validate Options\n *\n * The plugin validates only the *shape* of `connection` -- that it is a\n * non-empty connection string or a `ConnectionOptions` object. Parsing the URL\n * and validating the broker options (hosts, TLS, reconnect, etc.) is delegated\n * to `rabbitmq-client`. The shape guard exists because `new Connection(...)`\n * accepts garbage (a number, an array, `null`, `{}`) without throwing and then\n * silently fails to connect at runtime; rejecting it here surfaces a clear\n * registration-time error instead.\n * @since 1.0.0\n * @param options\n */\nexport const validateOpts = async (\n options: FastifyRabbitMQOptions,\n): Promise<void> => {\n const { connection } = options;\n\n // Mandatory\n if (connection === undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection must be defined.\",\n );\n }\n\n if (typeof connection === \"string\") {\n if (connection.length === 0) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection string must not be empty.\",\n );\n }\n return;\n }\n\n const isConnectionOptions =\n typeof connection === \"object\" &&\n connection !== null &&\n !Array.isArray(connection);\n\n if (!isConnectionOptions) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection must be a connection string or a ConnectionOptions object.\",\n );\n }\n};\n","/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport { FastifyInstance } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { Connection as RabbitMQConnection } from \"rabbitmq-client\";\n\nimport { FastifyRabbitMQOptions } from \"./decorate\";\nimport { errors } from \"./errors\";\nimport { validateOpts } from \"./validation\";\nexport { type FastifyRabbitMQOptions } from \"./decorate\";\n\n/**\n * How we talk with Fastify\n * @since 1.0.0\n * @param fastify\n * @param options\n * @param connection\n */\nconst decorateFastifyInstance = (\n fastify: FastifyInstance,\n options: FastifyRabbitMQOptions,\n connection: any,\n): void => {\n const { namespace = \"\" } = options;\n\n if (namespace !== undefined && namespace !== \"\") {\n fastify.log.debug(\"[fastify-rabbitmq] Namespace Attempt: %s\", namespace);\n }\n if (namespace !== undefined && namespace !== \"\") {\n if (fastify.rabbitmq === undefined) {\n fastify.decorate(\"rabbitmq\", Object.create(null));\n }\n\n if (fastify.rabbitmq[namespace] !== undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(\n `Already registered with namespace: ${namespace}`,\n );\n }\n\n fastify.log.trace(\n `[fastify-rabbitmq] Decorate Fastify with Namespace: ${namespace}`,\n );\n fastify.rabbitmq[namespace] = connection;\n } else {\n if (fastify.rabbitmq !== undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(\n \"Already registered.\",\n );\n }\n }\n\n if (fastify.rabbitmq === undefined) {\n fastify.log.trace(\"[fastify-rabbitmq] Decorate Fastify\");\n fastify.decorate(\"rabbitmq\", connection);\n }\n};\n\n/**\n * Main Function\n * @since 1.0.0\n * @example\n * This is the basics on how to use this plugin:\n * ```js\n * app.register(fastifyRabbit, {\n * connection: 'amqp://guest:guest@localhost'\n * })\n * ```\n * This will allow you to read from your Fastify \"object\" and\n * use this plugin at the \"rabbitmq\" level. From there you can execute and maintain\n * the RabbitMQ Connection using the 'rabbitmq-client' package, which is wrapping around\n * this plugin to execute functions it provides.\n *\n * @see [https://cody-greene.github.io/node-rabbitmq-client/latest/index.html](https://cody-greene.github.io/node-rabbitmq-client/latest/index.html)\n *\n */\nconst fastifyRabbit = fp<FastifyRabbitMQOptions>(async (fastify, opts) => {\n await validateOpts(opts);\n\n const { connection } = opts;\n\n const c = new RabbitMQConnection(connection);\n\n decorateFastifyInstance(fastify, opts, c);\n});\n\nexport default fastifyRabbit;\n\nexport { decorateFastifyInstance };\n\nexport * from \"./types\";\n\n// Re-export the rabbitmq-client surface so consumers import from this package\n// instead of reaching for the wrapped client. These are the exact types the\n// app.rabbitmq decorator hands back, so they stay correct without owning a\n// parallel definition.\nexport type {\n AsyncMessage,\n Channel,\n Connection,\n ConnectionOptions,\n Consumer,\n ConsumerHandler,\n ConsumerProps,\n Envelope,\n HeaderFields,\n MessageBody,\n Publisher,\n PublisherProps,\n ReturnedMessage,\n RPCClient,\n RPCProps,\n SyncMessage,\n} from \"rabbitmq-client\";\nexport {\n AMQPChannelError,\n AMQPConnectionError,\n AMQPError,\n ConsumerStatus,\n} from \"rabbitmq-client\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,SAAS;;CAEpB,qCAAA,GAAA,eAAA,QAAA,CACE,sCACA,qBACF;;CAEA,qCAAA,GAAA,eAAA,QAAA,CACE,sCACA,iBACF;;CAEA,8BAAA,GAAA,eAAA,QAAA,CACE,+BACA,iBACF;AACF;;;;;;;;;;;;;;;;ACFA,MAAa,eAAe,OAC1B,YACkB;CAClB,MAAM,EAAE,eAAe;CAGvB,IAAI,eAAe,KAAA,GACjB,MAAM,IAAI,OAAO,mCACf,6BACF;CAGF,IAAI,OAAO,eAAe,UAAU;EAClC,IAAI,WAAW,WAAW,GACxB,MAAM,IAAI,OAAO,mCACf,sCACF;EAEF;CACF;CAOA,IAAI,EAJF,OAAO,eAAe,YACtB,eAAe,QACf,CAAC,MAAM,QAAQ,UAAU,IAGzB,MAAM,IAAI,OAAO,mCACf,uEACF;AAEJ;;;;;;;;;;AC/BA,MAAM,2BACJ,SACA,SACA,eACS;CACT,MAAM,EAAE,YAAY,OAAO;CAE3B,IAAI,cAAc,KAAA,KAAa,cAAc,IAC3C,QAAQ,IAAI,MAAM,4CAA4C,SAAS;CAEzE,IAAI,cAAc,KAAA,KAAa,cAAc,IAAI;EAC/C,IAAI,QAAQ,aAAa,KAAA,GACvB,QAAQ,SAAS,YAAY,OAAO,OAAO,IAAI,CAAC;EAGlD,IAAI,QAAQ,SAAS,eAAe,KAAA,GAClC,MAAM,IAAI,OAAO,mCACf,sCAAsC,WACxC;EAGF,QAAQ,IAAI,MACV,uDAAuD,WACzD;EACA,QAAQ,SAAS,aAAa;CAChC,OACE,IAAI,QAAQ,aAAa,KAAA,GACvB,MAAM,IAAI,OAAO,mCACf,qBACF;CAIJ,IAAI,QAAQ,aAAa,KAAA,GAAW;EAClC,QAAQ,IAAI,MAAM,qCAAqC;EACvD,QAAQ,SAAS,YAAY,UAAU;CACzC;AACF;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,iBAAA,GAAA,eAAA,QAAA,CAA2C,OAAO,SAAS,SAAS;CACxE,MAAM,aAAa,IAAI;CAEvB,MAAM,EAAE,eAAe;CAIvB,wBAAwB,SAAS,MAAM,IAFzBA,gBAAAA,WAAmB,UAEM,CAAC;AAC1C,CAAC"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;;GAMG;AACH,QAAA,MAAM,uBAAuB,GAC3B,SAAS,eAAe,EACxB,SAAS,sBAAsB,EAC/B,YAAY,GAAG,KACd,IAiCF,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,aAAa,wLAQjB,CAAC;AAEH,eAAe,aAAa,CAAC;AAE7B,OAAO,EAAE,uBAAuB,EAAE,CAAC;AAEnC,cAAc,SAAS,CAAC;AAMxB,YAAY,EACV,YAAY,EACZ,OAAO,EACP,UAAU,EACV,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,eAAe,EACf,SAAS,EACT,QAAQ,EACR,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,cAAc,GACf,MAAM,iBAAiB,CAAC"}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["RabbitMQConnection"],"sources":["../src/errors.ts","../src/validation.ts","../src/index.ts"],"sourcesContent":["/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport createError from \"@fastify/error\";\n\nexport const errors = {\n /** Error if there is an invalid option used during registration. */\n FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: createError(\n \"FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS\",\n \"Invalid options: %s\",\n ),\n /** Error if there is an setup error of the plugin itself. */\n FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: createError(\n \"FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS\",\n \"Setup error: %s\",\n ),\n /** If an invalid usage error was done, this error would pop up. */\n FASTIFY_RABBIT_MQ_ERR_USAGE: createError(\n \"FASTIFY_RABBIT_MQ_ERR_USAGE\",\n \"Usage error: %s\",\n ),\n};\n","/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport { FastifyRabbitMQOptions } from \"./decorate\";\nimport { errors } from \"./errors\";\n\n/**\n * Validate Options\n *\n * The plugin validates only the *shape* of `connection` -- that it is a\n * non-empty connection string or a `ConnectionOptions` object. Parsing the URL\n * and validating the broker options (hosts, TLS, reconnect, etc.) is delegated\n * to `rabbitmq-client`. The shape guard exists because `new Connection(...)`\n * accepts garbage (a number, an array, `null`, `{}`) without throwing and then\n * silently fails to connect at runtime; rejecting it here surfaces a clear\n * registration-time error instead.\n * @since 1.0.0\n * @param options\n */\nexport const validateOpts = async (\n options: FastifyRabbitMQOptions,\n): Promise<void> => {\n const { connection } = options;\n\n // Mandatory\n if (connection === undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection must be defined.\",\n );\n }\n\n if (typeof connection === \"string\") {\n if (connection.length === 0) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection string must not be empty.\",\n );\n }\n return;\n }\n\n const isConnectionOptions =\n typeof connection === \"object\" &&\n connection !== null &&\n !Array.isArray(connection);\n\n if (!isConnectionOptions) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection must be a connection string or a ConnectionOptions object.\",\n );\n }\n};\n","/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport { FastifyInstance } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { Connection as RabbitMQConnection } from \"rabbitmq-client\";\n\nimport { FastifyRabbitMQOptions } from \"./decorate\";\nimport { errors } from \"./errors\";\nimport { validateOpts } from \"./validation\";\nexport { type FastifyRabbitMQOptions } from \"./decorate\";\n\n/**\n * How we talk with Fastify\n * @since 1.0.0\n * @param fastify\n * @param options\n * @param connection\n */\nconst decorateFastifyInstance = (\n fastify: FastifyInstance,\n options: FastifyRabbitMQOptions,\n connection: any,\n): void => {\n const { namespace = \"\" } = options;\n\n if (namespace !== undefined && namespace !== \"\") {\n fastify.log.debug(\"[fastify-rabbitmq] Namespace Attempt: %s\", namespace);\n }\n if (namespace !== undefined && namespace !== \"\") {\n if (fastify.rabbitmq === undefined) {\n fastify.decorate(\"rabbitmq\", Object.create(null));\n }\n\n if (fastify.rabbitmq[namespace] !== undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(\n `Already registered with namespace: ${namespace}`,\n );\n }\n\n fastify.log.trace(\n `[fastify-rabbitmq] Decorate Fastify with Namespace: ${namespace}`,\n );\n fastify.rabbitmq[namespace] = connection;\n } else {\n if (fastify.rabbitmq !== undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(\n \"Already registered.\",\n );\n }\n }\n\n if (fastify.rabbitmq === undefined) {\n fastify.log.trace(\"[fastify-rabbitmq] Decorate Fastify\");\n fastify.decorate(\"rabbitmq\", connection);\n }\n};\n\n/**\n * Main Function\n * @since 1.0.0\n * @example\n * This is the basics on how to use this plugin:\n * ```js\n * app.register(fastifyRabbit, {\n * connection: 'amqp://guest:guest@localhost'\n * })\n * ```\n * This will allow you to read from your Fastify \"object\" and\n * use this plugin at the \"rabbitmq\" level. From there you can execute and maintain\n * the RabbitMQ Connection using the 'rabbitmq-client' package, which is wrapping around\n * this plugin to execute functions it provides.\n *\n * @see [https://cody-greene.github.io/node-rabbitmq-client/latest/index.html](https://cody-greene.github.io/node-rabbitmq-client/latest/index.html)\n *\n */\nconst fastifyRabbit = fp<FastifyRabbitMQOptions>(async (fastify, opts) => {\n await validateOpts(opts);\n\n const { connection } = opts;\n\n const c = new RabbitMQConnection(connection);\n\n decorateFastifyInstance(fastify, opts, c);\n});\n\nexport default fastifyRabbit;\n\nexport { decorateFastifyInstance };\n\nexport * from \"./types\";\n\n// Re-export the rabbitmq-client surface so consumers import from this package\n// instead of reaching for the wrapped client. These are the exact types the\n// app.rabbitmq decorator hands back, so they stay correct without owning a\n// parallel definition.\nexport type {\n AsyncMessage,\n Channel,\n Connection,\n ConnectionOptions,\n Consumer,\n ConsumerHandler,\n ConsumerProps,\n Envelope,\n HeaderFields,\n MessageBody,\n Publisher,\n PublisherProps,\n ReturnedMessage,\n RPCClient,\n RPCProps,\n SyncMessage,\n} from \"rabbitmq-client\";\nexport {\n AMQPChannelError,\n AMQPConnectionError,\n AMQPError,\n ConsumerStatus,\n} from \"rabbitmq-client\";\n"],"mappings":";;;;AAwBA,MAAa,SAAS;;CAEpB,oCAAoC,YAClC,sCACA,qBACF;;CAEA,oCAAoC,YAClC,sCACA,iBACF;;CAEA,6BAA6B,YAC3B,+BACA,iBACF;AACF;;;;;;;;;;;;;;;;ACFA,MAAa,eAAe,OAC1B,YACkB;CAClB,MAAM,EAAE,eAAe;CAGvB,IAAI,eAAe,KAAA,GACjB,MAAM,IAAI,OAAO,mCACf,6BACF;CAGF,IAAI,OAAO,eAAe,UAAU;EAClC,IAAI,WAAW,WAAW,GACxB,MAAM,IAAI,OAAO,mCACf,sCACF;EAEF;CACF;CAOA,IAAI,EAJF,OAAO,eAAe,YACtB,eAAe,QACf,CAAC,MAAM,QAAQ,UAAU,IAGzB,MAAM,IAAI,OAAO,mCACf,uEACF;AAEJ;;;;;;;;;;AC/BA,MAAM,2BACJ,SACA,SACA,eACS;CACT,MAAM,EAAE,YAAY,OAAO;CAE3B,IAAI,cAAc,KAAA,KAAa,cAAc,IAC3C,QAAQ,IAAI,MAAM,4CAA4C,SAAS;CAEzE,IAAI,cAAc,KAAA,KAAa,cAAc,IAAI;EAC/C,IAAI,QAAQ,aAAa,KAAA,GACvB,QAAQ,SAAS,YAAY,OAAO,OAAO,IAAI,CAAC;EAGlD,IAAI,QAAQ,SAAS,eAAe,KAAA,GAClC,MAAM,IAAI,OAAO,mCACf,sCAAsC,WACxC;EAGF,QAAQ,IAAI,MACV,uDAAuD,WACzD;EACA,QAAQ,SAAS,aAAa;CAChC,OACE,IAAI,QAAQ,aAAa,KAAA,GACvB,MAAM,IAAI,OAAO,mCACf,qBACF;CAIJ,IAAI,QAAQ,aAAa,KAAA,GAAW;EAClC,QAAQ,IAAI,MAAM,qCAAqC;EACvD,QAAQ,SAAS,YAAY,UAAU;CACzC;AACF;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,gBAAgB,GAA2B,OAAO,SAAS,SAAS;CACxE,MAAM,aAAa,IAAI;CAEvB,MAAM,EAAE,eAAe;CAIvB,wBAAwB,SAAS,MAAM,IAFzBA,WAAmB,UAEM,CAAC;AAC1C,CAAC"}
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAiB,eAAe;QAC9B,kCAAkC;QAClC,QAAQ,EAAE,eAAe,CAAC,iBAAiB,GAAG,kBAAkB,CAAC;KAClE;CACF;AAGD,MAAM,CAAC,OAAO,WAAW,eAAe,CAAC;IACvC,UAAiB,iBAAiB;QAChC,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,CAAC;KACzC;CACF"}
|
package/dist/validation.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,GACvB,SAAS,sBAAsB,KAC9B,OAAO,CAAC,IAAI,CA6Bd,CAAC"}
|