chub-dev 0.1.0 → 0.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1193 @@
1
+ ---
2
+ name: message-queue
3
+ description: "RabbitMQ amqplib coding guidelines for JavaScript/Node.js message broker interactions"
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "0.10.9"
7
+ updated-on: "2026-03-02"
8
+ source: maintainer
9
+ tags: "rabbitmq,queue,amqp,messaging,async"
10
+ ---
11
+
12
+ # RabbitMQ amqplib Coding Guidelines (JavaScript/Node.js)
13
+
14
+ You are a RabbitMQ amqplib coding expert. Help me with writing code using RabbitMQ message broker via the official amqplib library.
15
+
16
+ ## Golden Rule: Use the Correct and Current SDK
17
+
18
+ Always use the official amqplib library for all RabbitMQ (AMQP 0-9-1) interactions in Node.js.
19
+
20
+ - **Library Name:** amqplib
21
+ - **NPM Package:** `amqplib`
22
+ - **Current Version:** 0.10.9 or higher
23
+ - **Minimum Required Version:** 0.10.7+ (for RabbitMQ 4.1.0+ compatibility)
24
+
25
+ **Installation:**
26
+
27
+ ```bash
28
+ npm install amqplib
29
+ ```
30
+
31
+ **IMPORTANT:** Do not use the deprecated `amqp` or `node-amqp` packages. Always use `amqplib`.
32
+
33
+ **Import Patterns:**
34
+
35
+ ```javascript
36
+ // Callback API
37
+ const amqp = require('amqplib/callback_api');
38
+
39
+ // Promise/async-await API (recommended)
40
+ const amqp = require('amqplib');
41
+
42
+ // ES6 import
43
+ import amqp from 'amqplib';
44
+ ```
45
+
46
+ ## Initialization and Connection
47
+
48
+ ### Environment Variables
49
+
50
+ Configure RabbitMQ connection using environment variables:
51
+
52
+ ```javascript
53
+ // .env file
54
+ RABBITMQ_URL=amqp://username:password@localhost:5672
55
+ RABBITMQ_HOST=localhost
56
+ RABBITMQ_PORT=5672
57
+ RABBITMQ_USER=guest
58
+ RABBITMQ_PASS=guest
59
+ RABBITMQ_VHOST=/
60
+ ```
61
+
62
+ ### Basic Connection (Promise API)
63
+
64
+ ```javascript
65
+ const amqp = require('amqplib');
66
+
67
+ async function connect() {
68
+ try {
69
+ // Using connection URL from environment
70
+ const connection = await amqp.connect(process.env.RABBITMQ_URL || 'amqp://localhost');
71
+
72
+ console.log('Connected to RabbitMQ');
73
+ return connection;
74
+ } catch (error) {
75
+ console.error('Connection failed:', error);
76
+ throw error;
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### Connection with Options
82
+
83
+ ```javascript
84
+ const amqp = require('amqplib');
85
+
86
+ async function connectWithOptions() {
87
+ const connection = await amqp.connect({
88
+ protocol: 'amqp',
89
+ hostname: process.env.RABBITMQ_HOST || 'localhost',
90
+ port: parseInt(process.env.RABBITMQ_PORT) || 5672,
91
+ username: process.env.RABBITMQ_USER || 'guest',
92
+ password: process.env.RABBITMQ_PASS || 'guest',
93
+ vhost: process.env.RABBITMQ_VHOST || '/',
94
+ heartbeat: 30, // Heartbeat interval in seconds (recommended: 30)
95
+ });
96
+
97
+ return connection;
98
+ }
99
+ ```
100
+
101
+ ### Connection with Socket Options
102
+
103
+ ```javascript
104
+ const amqp = require('amqplib');
105
+
106
+ async function connectWithSocketOptions() {
107
+ const connection = await amqp.connect(
108
+ process.env.RABBITMQ_URL || 'amqp://localhost',
109
+ {
110
+ timeout: 10000, // Socket timeout in milliseconds
111
+ noDelay: true, // Disable Nagle's algorithm
112
+ keepAlive: true, // Enable TCP keep-alive
113
+ keepAliveDelay: 30000 // Keep-alive delay in ms
114
+ }
115
+ );
116
+
117
+ return connection;
118
+ }
119
+ ```
120
+
121
+ ### Callback API Connection
122
+
123
+ ```javascript
124
+ const amqp = require('amqplib/callback_api');
125
+
126
+ amqp.connect('amqp://localhost', function(error, connection) {
127
+ if (error) {
128
+ throw error;
129
+ }
130
+ console.log('Connected to RabbitMQ');
131
+
132
+ // Use connection here
133
+ });
134
+ ```
135
+
136
+ ## Channel API
137
+
138
+ ### Creating a Channel
139
+
140
+ ```javascript
141
+ const amqp = require('amqplib');
142
+
143
+ async function createChannel() {
144
+ const connection = await amqp.connect('amqp://localhost');
145
+ const channel = await connection.createChannel();
146
+
147
+ return { connection, channel };
148
+ }
149
+ ```
150
+
151
+ ### Creating a Confirm Channel
152
+
153
+ ```javascript
154
+ const amqp = require('amqplib');
155
+
156
+ async function createConfirmChannel() {
157
+ const connection = await amqp.connect('amqp://localhost');
158
+ const channel = await connection.createConfirmChannel();
159
+
160
+ // Confirm channel provides publisher confirms
161
+ return { connection, channel };
162
+ }
163
+ ```
164
+
165
+ ## Core Messaging Patterns
166
+
167
+ ### 1. Simple Queue - Producer
168
+
169
+ ```javascript
170
+ const amqp = require('amqplib');
171
+
172
+ async function sendMessage(queueName, message) {
173
+ const connection = await amqp.connect('amqp://localhost');
174
+ const channel = await connection.createChannel();
175
+
176
+ // Assert queue exists (create if it doesn't)
177
+ await channel.assertQueue(queueName, {
178
+ durable: true // Queue survives broker restart
179
+ });
180
+
181
+ // Send message
182
+ channel.sendToQueue(queueName, Buffer.from(message), {
183
+ persistent: true // Message survives broker restart
184
+ });
185
+
186
+ console.log(`Sent: ${message}`);
187
+
188
+ // Close connection after a delay to ensure message is sent
189
+ setTimeout(() => {
190
+ connection.close();
191
+ }, 500);
192
+ }
193
+
194
+ // Usage
195
+ sendMessage('task_queue', 'Hello World!');
196
+ ```
197
+
198
+ ### 2. Simple Queue - Consumer
199
+
200
+ ```javascript
201
+ const amqp = require('amqplib');
202
+
203
+ async function receiveMessages(queueName) {
204
+ const connection = await amqp.connect('amqp://localhost');
205
+ const channel = await connection.createChannel();
206
+
207
+ await channel.assertQueue(queueName, {
208
+ durable: true
209
+ });
210
+
211
+ console.log(`Waiting for messages in ${queueName}`);
212
+
213
+ // Consume messages
214
+ channel.consume(queueName, (msg) => {
215
+ if (msg !== null) {
216
+ const content = msg.content.toString();
217
+ console.log(`Received: ${content}`);
218
+
219
+ // Acknowledge message
220
+ channel.ack(msg);
221
+ }
222
+ }, {
223
+ noAck: false // Manual acknowledgment
224
+ });
225
+ }
226
+
227
+ // Usage
228
+ receiveMessages('task_queue');
229
+ ```
230
+
231
+ ### 3. Work Queue with Prefetch
232
+
233
+ ```javascript
234
+ const amqp = require('amqplib');
235
+
236
+ async function worker(queueName) {
237
+ const connection = await amqp.connect('amqp://localhost');
238
+ const channel = await connection.createChannel();
239
+
240
+ await channel.assertQueue(queueName, {
241
+ durable: true
242
+ });
243
+
244
+ // Fair dispatch - only send one message at a time to each worker
245
+ channel.prefetch(1);
246
+
247
+ console.log(`Worker waiting for tasks in ${queueName}`);
248
+
249
+ channel.consume(queueName, async (msg) => {
250
+ if (msg !== null) {
251
+ const task = msg.content.toString();
252
+ console.log(`Processing: ${task}`);
253
+
254
+ // Simulate work
255
+ const workTime = (task.match(/\./g) || []).length * 1000;
256
+ await new Promise(resolve => setTimeout(resolve, workTime));
257
+
258
+ console.log(`Done: ${task}`);
259
+ channel.ack(msg);
260
+ }
261
+ }, {
262
+ noAck: false
263
+ });
264
+ }
265
+
266
+ // Usage
267
+ worker('task_queue');
268
+ ```
269
+
270
+ ### 4. Publish/Subscribe with Fanout Exchange
271
+
272
+ **Publisher:**
273
+
274
+ ```javascript
275
+ const amqp = require('amqplib');
276
+
277
+ async function publishLog(message) {
278
+ const connection = await amqp.connect('amqp://localhost');
279
+ const channel = await connection.createChannel();
280
+
281
+ const exchange = 'logs';
282
+
283
+ await channel.assertExchange(exchange, 'fanout', {
284
+ durable: false
285
+ });
286
+
287
+ channel.publish(exchange, '', Buffer.from(message));
288
+ console.log(`Sent: ${message}`);
289
+
290
+ setTimeout(() => {
291
+ connection.close();
292
+ }, 500);
293
+ }
294
+
295
+ // Usage
296
+ publishLog('Hello World!');
297
+ ```
298
+
299
+ **Subscriber:**
300
+
301
+ ```javascript
302
+ const amqp = require('amqplib');
303
+
304
+ async function subscribeLogs() {
305
+ const connection = await amqp.connect('amqp://localhost');
306
+ const channel = await connection.createChannel();
307
+
308
+ const exchange = 'logs';
309
+
310
+ await channel.assertExchange(exchange, 'fanout', {
311
+ durable: false
312
+ });
313
+
314
+ // Create exclusive queue (auto-delete when consumer disconnects)
315
+ const q = await channel.assertQueue('', {
316
+ exclusive: true
317
+ });
318
+
319
+ console.log(`Waiting for logs. Queue: ${q.queue}`);
320
+
321
+ // Bind queue to exchange
322
+ channel.bindQueue(q.queue, exchange, '');
323
+
324
+ channel.consume(q.queue, (msg) => {
325
+ if (msg !== null) {
326
+ console.log(`Received: ${msg.content.toString()}`);
327
+ }
328
+ }, {
329
+ noAck: true
330
+ });
331
+ }
332
+
333
+ // Usage
334
+ subscribeLogs();
335
+ ```
336
+
337
+ ### 5. Routing with Direct Exchange
338
+
339
+ **Emitter:**
340
+
341
+ ```javascript
342
+ const amqp = require('amqplib');
343
+
344
+ async function emitLog(severity, message) {
345
+ const connection = await amqp.connect('amqp://localhost');
346
+ const channel = await connection.createChannel();
347
+
348
+ const exchange = 'direct_logs';
349
+
350
+ await channel.assertExchange(exchange, 'direct', {
351
+ durable: false
352
+ });
353
+
354
+ channel.publish(exchange, severity, Buffer.from(message));
355
+ console.log(`Sent [${severity}]: ${message}`);
356
+
357
+ setTimeout(() => {
358
+ connection.close();
359
+ }, 500);
360
+ }
361
+
362
+ // Usage
363
+ emitLog('error', 'Critical system error!');
364
+ emitLog('info', 'System started');
365
+ emitLog('warning', 'Disk space low');
366
+ ```
367
+
368
+ **Receiver:**
369
+
370
+ ```javascript
371
+ const amqp = require('amqplib');
372
+
373
+ async function receiveLogs(severities) {
374
+ const connection = await amqp.connect('amqp://localhost');
375
+ const channel = await connection.createChannel();
376
+
377
+ const exchange = 'direct_logs';
378
+
379
+ await channel.assertExchange(exchange, 'direct', {
380
+ durable: false
381
+ });
382
+
383
+ const q = await channel.assertQueue('', {
384
+ exclusive: true
385
+ });
386
+
387
+ console.log(`Waiting for logs with severities: ${severities.join(', ')}`);
388
+
389
+ // Bind queue for each severity
390
+ for (const severity of severities) {
391
+ channel.bindQueue(q.queue, exchange, severity);
392
+ }
393
+
394
+ channel.consume(q.queue, (msg) => {
395
+ if (msg !== null) {
396
+ console.log(`[${msg.fields.routingKey}]: ${msg.content.toString()}`);
397
+ }
398
+ }, {
399
+ noAck: true
400
+ });
401
+ }
402
+
403
+ // Usage - receive only error and warning logs
404
+ receiveLogs(['error', 'warning']);
405
+ ```
406
+
407
+ ### 6. Topics with Topic Exchange
408
+
409
+ **Emit Log Topic:**
410
+
411
+ ```javascript
412
+ const amqp = require('amqplib');
413
+
414
+ async function emitLogTopic(routingKey, message) {
415
+ const connection = await amqp.connect('amqp://localhost');
416
+ const channel = await connection.createChannel();
417
+
418
+ const exchange = 'topic_logs';
419
+
420
+ await channel.assertExchange(exchange, 'topic', {
421
+ durable: false
422
+ });
423
+
424
+ channel.publish(exchange, routingKey, Buffer.from(message));
425
+ console.log(`Sent [${routingKey}]: ${message}`);
426
+
427
+ setTimeout(() => {
428
+ connection.close();
429
+ }, 500);
430
+ }
431
+
432
+ // Usage - routing keys with dot-separated words
433
+ emitLogTopic('kern.critical', 'A critical kernel error');
434
+ emitLogTopic('kern.info', 'Kernel information');
435
+ emitLogTopic('auth.warning', 'Authentication warning');
436
+ ```
437
+
438
+ **Receive Log Topic:**
439
+
440
+ ```javascript
441
+ const amqp = require('amqplib');
442
+
443
+ async function receiveLogsTopic(bindingKeys) {
444
+ const connection = await amqp.connect('amqp://localhost');
445
+ const channel = await connection.createChannel();
446
+
447
+ const exchange = 'topic_logs';
448
+
449
+ await channel.assertExchange(exchange, 'topic', {
450
+ durable: false
451
+ });
452
+
453
+ const q = await channel.assertQueue('', {
454
+ exclusive: true
455
+ });
456
+
457
+ console.log(`Waiting for logs matching: ${bindingKeys.join(', ')}`);
458
+
459
+ // Bind queue with patterns
460
+ // * (star) can substitute for exactly one word
461
+ // # (hash) can substitute for zero or more words
462
+ for (const key of bindingKeys) {
463
+ channel.bindQueue(q.queue, exchange, key);
464
+ }
465
+
466
+ channel.consume(q.queue, (msg) => {
467
+ if (msg !== null) {
468
+ console.log(`[${msg.fields.routingKey}]: ${msg.content.toString()}`);
469
+ }
470
+ }, {
471
+ noAck: true
472
+ });
473
+ }
474
+
475
+ // Usage - pattern matching
476
+ receiveLogsTopic(['kern.*']); // All kernel messages
477
+ receiveLogsTopic(['*.critical']); // All critical messages
478
+ receiveLogsTopic(['kern.#']); // All kern.* messages
479
+ receiveLogsTopic(['#']); // All messages
480
+ receiveLogsTopic(['kern.critical', 'auth.*']); // Multiple patterns
481
+ ```
482
+
483
+ ### 7. RPC (Remote Procedure Call) Pattern
484
+
485
+ **RPC Client:**
486
+
487
+ ```javascript
488
+ const amqp = require('amqplib');
489
+ const { v4: uuidv4 } = require('uuid');
490
+
491
+ class RPCClient {
492
+ constructor() {
493
+ this.connection = null;
494
+ this.channel = null;
495
+ this.replyQueue = null;
496
+ this.responseHandlers = new Map();
497
+ }
498
+
499
+ async connect() {
500
+ this.connection = await amqp.connect('amqp://localhost');
501
+ this.channel = await this.connection.createChannel();
502
+
503
+ // Create reply queue
504
+ const q = await this.channel.assertQueue('', {
505
+ exclusive: true
506
+ });
507
+
508
+ this.replyQueue = q.queue;
509
+
510
+ // Consume from reply queue
511
+ this.channel.consume(this.replyQueue, (msg) => {
512
+ const correlationId = msg.properties.correlationId;
513
+ const handler = this.responseHandlers.get(correlationId);
514
+
515
+ if (handler) {
516
+ handler(msg.content.toString());
517
+ this.responseHandlers.delete(correlationId);
518
+ }
519
+ }, {
520
+ noAck: true
521
+ });
522
+ }
523
+
524
+ async call(n) {
525
+ const correlationId = uuidv4();
526
+
527
+ return new Promise((resolve) => {
528
+ // Store response handler
529
+ this.responseHandlers.set(correlationId, resolve);
530
+
531
+ // Send RPC request
532
+ this.channel.sendToQueue('rpc_queue', Buffer.from(n.toString()), {
533
+ correlationId: correlationId,
534
+ replyTo: this.replyQueue
535
+ });
536
+ });
537
+ }
538
+
539
+ async close() {
540
+ await this.connection.close();
541
+ }
542
+ }
543
+
544
+ // Usage
545
+ async function makeRPCCall() {
546
+ const client = new RPCClient();
547
+ await client.connect();
548
+
549
+ console.log('Requesting fib(30)');
550
+ const result = await client.call(30);
551
+ console.log(`Result: ${result}`);
552
+
553
+ await client.close();
554
+ }
555
+
556
+ makeRPCCall();
557
+ ```
558
+
559
+ **RPC Server:**
560
+
561
+ ```javascript
562
+ const amqp = require('amqplib');
563
+
564
+ function fibonacci(n) {
565
+ if (n === 0 || n === 1) return n;
566
+ return fibonacci(n - 1) + fibonacci(n - 2);
567
+ }
568
+
569
+ async function startRPCServer() {
570
+ const connection = await amqp.connect('amqp://localhost');
571
+ const channel = await connection.createChannel();
572
+
573
+ const queue = 'rpc_queue';
574
+
575
+ await channel.assertQueue(queue, {
576
+ durable: false
577
+ });
578
+
579
+ channel.prefetch(1);
580
+ console.log('Awaiting RPC requests');
581
+
582
+ channel.consume(queue, (msg) => {
583
+ const n = parseInt(msg.content.toString());
584
+
585
+ console.log(`Computing fibonacci(${n})`);
586
+ const result = fibonacci(n);
587
+
588
+ // Send response
589
+ channel.sendToQueue(
590
+ msg.properties.replyTo,
591
+ Buffer.from(result.toString()),
592
+ {
593
+ correlationId: msg.properties.correlationId
594
+ }
595
+ );
596
+
597
+ channel.ack(msg);
598
+ });
599
+ }
600
+
601
+ startRPCServer();
602
+ ```
603
+
604
+ ## Advanced Configuration
605
+
606
+ ### Message Properties
607
+
608
+ ```javascript
609
+ const amqp = require('amqplib');
610
+
611
+ async function sendWithProperties(queue, message) {
612
+ const connection = await amqp.connect('amqp://localhost');
613
+ const channel = await connection.createChannel();
614
+
615
+ await channel.assertQueue(queue, { durable: true });
616
+
617
+ channel.sendToQueue(queue, Buffer.from(message), {
618
+ persistent: true, // Survive broker restart
619
+ expiration: '60000', // Message TTL in milliseconds
620
+ priority: 5, // Message priority (0-255)
621
+ contentType: 'application/json', // MIME type
622
+ contentEncoding: 'utf-8', // Encoding
623
+ timestamp: Date.now(), // Timestamp
624
+ messageId: 'msg-123', // Application message ID
625
+ userId: 'guest', // Creating user
626
+ appId: 'my-app', // Application ID
627
+ headers: { // Custom headers
628
+ 'x-custom-header': 'value'
629
+ }
630
+ });
631
+
632
+ setTimeout(() => connection.close(), 500);
633
+ }
634
+ ```
635
+
636
+ ### Queue Options
637
+
638
+ ```javascript
639
+ const amqp = require('amqplib');
640
+
641
+ async function declareQueueWithOptions() {
642
+ const connection = await amqp.connect('amqp://localhost');
643
+ const channel = await connection.createChannel();
644
+
645
+ await channel.assertQueue('advanced_queue', {
646
+ durable: true, // Queue survives broker restart
647
+ exclusive: false, // Can be accessed by other connections
648
+ autoDelete: false, // Queue won't be deleted when no consumers
649
+ messageTtl: 60000, // Message TTL in milliseconds
650
+ expires: 300000, // Queue expires after 5 minutes of non-use
651
+ maxLength: 1000, // Maximum queue length
652
+ maxPriority: 10, // Enable priority queue (0-10)
653
+ deadLetterExchange: 'dlx', // DLX for rejected messages
654
+ deadLetterRoutingKey: 'dead.letter' // Routing key for DLX
655
+ });
656
+
657
+ await connection.close();
658
+ }
659
+ ```
660
+
661
+ ### Exchange Options
662
+
663
+ ```javascript
664
+ const amqp = require('amqplib');
665
+
666
+ async function declareExchangeWithOptions() {
667
+ const connection = await amqp.connect('amqp://localhost');
668
+ const channel = await connection.createChannel();
669
+
670
+ await channel.assertExchange('advanced_exchange', 'topic', {
671
+ durable: true, // Exchange survives broker restart
672
+ autoDelete: false, // Exchange won't be deleted when no bindings
673
+ internal: false, // Can be published to by clients
674
+ alternateExchange: 'alternate_exchange' // AE for unroutable messages
675
+ });
676
+
677
+ await connection.close();
678
+ }
679
+ ```
680
+
681
+ ### Dead Letter Queue (DLQ)
682
+
683
+ ```javascript
684
+ const amqp = require('amqplib');
685
+
686
+ async function setupDeadLetterQueue() {
687
+ const connection = await amqp.connect('amqp://localhost');
688
+ const channel = await connection.createChannel();
689
+
690
+ // Declare dead letter exchange
691
+ await channel.assertExchange('dlx', 'direct', {
692
+ durable: true
693
+ });
694
+
695
+ // Declare dead letter queue
696
+ await channel.assertQueue('dead_letter_queue', {
697
+ durable: true
698
+ });
699
+
700
+ // Bind DLQ to DLX
701
+ await channel.bindQueue('dead_letter_queue', 'dlx', 'dead.letter');
702
+
703
+ // Declare main queue with DLX
704
+ await channel.assertQueue('main_queue', {
705
+ durable: true,
706
+ deadLetterExchange: 'dlx',
707
+ deadLetterRoutingKey: 'dead.letter',
708
+ messageTtl: 10000 // Messages expire after 10 seconds
709
+ });
710
+
711
+ console.log('Dead letter queue setup complete');
712
+ await connection.close();
713
+ }
714
+
715
+ setupDeadLetterQueue();
716
+ ```
717
+
718
+ ### Consuming from Dead Letter Queue
719
+
720
+ ```javascript
721
+ const amqp = require('amqplib');
722
+
723
+ async function consumeDeadLetters() {
724
+ const connection = await amqp.connect('amqp://localhost');
725
+ const channel = await connection.createChannel();
726
+
727
+ await channel.assertQueue('dead_letter_queue', {
728
+ durable: true
729
+ });
730
+
731
+ console.log('Waiting for dead letter messages');
732
+
733
+ channel.consume('dead_letter_queue', (msg) => {
734
+ if (msg !== null) {
735
+ console.log('Dead letter received:', msg.content.toString());
736
+ console.log('Original routing key:', msg.fields.routingKey);
737
+ console.log('Death reason:', msg.properties.headers['x-death']);
738
+
739
+ // Process or log dead letter
740
+ channel.ack(msg);
741
+ }
742
+ });
743
+ }
744
+
745
+ consumeDeadLetters();
746
+ ```
747
+
748
+ ### Message Rejection and Requeuing
749
+
750
+ ```javascript
751
+ const amqp = require('amqplib');
752
+
753
+ async function consumerWithRetry() {
754
+ const connection = await amqp.connect('amqp://localhost');
755
+ const channel = await connection.createChannel();
756
+
757
+ await channel.assertQueue('task_queue', {
758
+ durable: true
759
+ });
760
+
761
+ channel.consume('task_queue', async (msg) => {
762
+ if (msg !== null) {
763
+ try {
764
+ const task = msg.content.toString();
765
+ console.log('Processing:', task);
766
+
767
+ // Simulate processing
768
+ await processTask(task);
769
+
770
+ // Success - acknowledge
771
+ channel.ack(msg);
772
+ } catch (error) {
773
+ console.error('Processing failed:', error);
774
+
775
+ // Check retry count
776
+ const retryCount = (msg.properties.headers?.['x-retry-count'] || 0);
777
+
778
+ if (retryCount < 3) {
779
+ // Reject and requeue for retry
780
+ channel.nack(msg, false, true);
781
+ } else {
782
+ // Max retries reached - reject without requeue (goes to DLQ)
783
+ channel.nack(msg, false, false);
784
+ }
785
+ }
786
+ }
787
+ });
788
+ }
789
+
790
+ async function processTask(task) {
791
+ // Simulate work
792
+ if (Math.random() < 0.3) {
793
+ throw new Error('Random failure');
794
+ }
795
+ }
796
+
797
+ consumerWithRetry();
798
+ ```
799
+
800
+ ### Publisher Confirms
801
+
802
+ ```javascript
803
+ const amqp = require('amqplib');
804
+
805
+ async function publishWithConfirm() {
806
+ const connection = await amqp.connect('amqp://localhost');
807
+ const channel = await connection.createConfirmChannel();
808
+
809
+ const queue = 'confirm_queue';
810
+ await channel.assertQueue(queue, { durable: true });
811
+
812
+ const message = 'Important message';
813
+
814
+ try {
815
+ channel.sendToQueue(queue, Buffer.from(message), {
816
+ persistent: true
817
+ });
818
+
819
+ // Wait for confirmation
820
+ await channel.waitForConfirms();
821
+ console.log('Message confirmed by broker');
822
+ } catch (error) {
823
+ console.error('Message nacked by broker:', error);
824
+ }
825
+
826
+ await connection.close();
827
+ }
828
+
829
+ publishWithConfirm();
830
+ ```
831
+
832
+ ### Batch Publishing with Confirms
833
+
834
+ ```javascript
835
+ const amqp = require('amqplib');
836
+
837
+ async function batchPublishWithConfirms() {
838
+ const connection = await amqp.connect('amqp://localhost');
839
+ const channel = await connection.createConfirmChannel();
840
+
841
+ const queue = 'batch_queue';
842
+ await channel.assertQueue(queue, { durable: true });
843
+
844
+ const messages = Array.from({ length: 100 }, (_, i) => `Message ${i}`);
845
+
846
+ for (const message of messages) {
847
+ channel.sendToQueue(queue, Buffer.from(message), {
848
+ persistent: true
849
+ });
850
+ }
851
+
852
+ try {
853
+ await channel.waitForConfirms();
854
+ console.log('All messages confirmed');
855
+ } catch (error) {
856
+ console.error('Some messages were nacked:', error);
857
+ }
858
+
859
+ await connection.close();
860
+ }
861
+
862
+ batchPublishWithConfirms();
863
+ ```
864
+
865
+ ## Error Handling and Reconnection
866
+
867
+ ### Connection Error Handling
868
+
869
+ ```javascript
870
+ const amqp = require('amqplib');
871
+
872
+ async function connectWithErrorHandling() {
873
+ let connection;
874
+
875
+ try {
876
+ connection = await amqp.connect('amqp://localhost');
877
+
878
+ // Handle connection errors
879
+ connection.on('error', (err) => {
880
+ console.error('Connection error:', err);
881
+ });
882
+
883
+ // Handle connection close
884
+ connection.on('close', () => {
885
+ console.log('Connection closed');
886
+ // Implement reconnection logic here
887
+ setTimeout(() => {
888
+ console.log('Attempting to reconnect...');
889
+ connectWithErrorHandling();
890
+ }, 5000);
891
+ });
892
+
893
+ const channel = await connection.createChannel();
894
+
895
+ // Handle channel errors
896
+ channel.on('error', (err) => {
897
+ console.error('Channel error:', err);
898
+ });
899
+
900
+ // Handle channel close
901
+ channel.on('close', () => {
902
+ console.log('Channel closed');
903
+ });
904
+
905
+ return { connection, channel };
906
+ } catch (error) {
907
+ console.error('Failed to connect:', error);
908
+
909
+ // Retry connection after delay
910
+ setTimeout(() => {
911
+ console.log('Retrying connection...');
912
+ connectWithErrorHandling();
913
+ }, 5000);
914
+ }
915
+ }
916
+
917
+ connectWithErrorHandling();
918
+ ```
919
+
920
+ ### Robust Connection Manager
921
+
922
+ ```javascript
923
+ const amqp = require('amqplib');
924
+
925
+ class RabbitMQConnection {
926
+ constructor(url) {
927
+ this.url = url;
928
+ this.connection = null;
929
+ this.channel = null;
930
+ this.reconnecting = false;
931
+ }
932
+
933
+ async connect() {
934
+ try {
935
+ this.connection = await amqp.connect(this.url);
936
+ this.channel = await this.connection.createChannel();
937
+
938
+ console.log('Connected to RabbitMQ');
939
+
940
+ this.connection.on('error', (err) => {
941
+ console.error('Connection error:', err);
942
+ this.reconnect();
943
+ });
944
+
945
+ this.connection.on('close', () => {
946
+ console.log('Connection closed');
947
+ this.reconnect();
948
+ });
949
+
950
+ return this.channel;
951
+ } catch (error) {
952
+ console.error('Connection failed:', error);
953
+ this.reconnect();
954
+ }
955
+ }
956
+
957
+ async reconnect() {
958
+ if (this.reconnecting) return;
959
+
960
+ this.reconnecting = true;
961
+ console.log('Reconnecting in 5 seconds...');
962
+
963
+ setTimeout(async () => {
964
+ this.reconnecting = false;
965
+ await this.connect();
966
+ }, 5000);
967
+ }
968
+
969
+ async close() {
970
+ if (this.channel) {
971
+ await this.channel.close();
972
+ }
973
+ if (this.connection) {
974
+ await this.connection.close();
975
+ }
976
+ }
977
+ }
978
+
979
+ // Usage
980
+ const manager = new RabbitMQConnection('amqp://localhost');
981
+ const channel = await manager.connect();
982
+ ```
983
+
984
+ ### Graceful Shutdown
985
+
986
+ ```javascript
987
+ const amqp = require('amqplib');
988
+
989
+ let connection = null;
990
+ let channel = null;
991
+
992
+ async function setup() {
993
+ connection = await amqp.connect('amqp://localhost');
994
+ channel = await connection.createChannel();
995
+
996
+ await channel.assertQueue('shutdown_queue', { durable: true });
997
+
998
+ channel.consume('shutdown_queue', (msg) => {
999
+ if (msg !== null) {
1000
+ console.log('Processing:', msg.content.toString());
1001
+ channel.ack(msg);
1002
+ }
1003
+ });
1004
+ }
1005
+
1006
+ async function cleanup() {
1007
+ console.log('Shutting down gracefully...');
1008
+
1009
+ if (channel) {
1010
+ // Cancel consumers
1011
+ await channel.close();
1012
+ }
1013
+
1014
+ if (connection) {
1015
+ await connection.close();
1016
+ }
1017
+
1018
+ console.log('Cleanup complete');
1019
+ process.exit(0);
1020
+ }
1021
+
1022
+ // Handle shutdown signals
1023
+ process.on('SIGINT', cleanup);
1024
+ process.on('SIGTERM', cleanup);
1025
+
1026
+ setup();
1027
+ ```
1028
+
1029
+ ## Common Patterns
1030
+
1031
+ ### Message Retry with Delay
1032
+
1033
+ ```javascript
1034
+ const amqp = require('amqplib');
1035
+
1036
+ async function setupRetryQueue() {
1037
+ const connection = await amqp.connect('amqp://localhost');
1038
+ const channel = await connection.createChannel();
1039
+
1040
+ // Main queue
1041
+ await channel.assertQueue('main_queue', {
1042
+ durable: true,
1043
+ deadLetterExchange: 'retry',
1044
+ deadLetterRoutingKey: 'retry'
1045
+ });
1046
+
1047
+ // Retry exchange
1048
+ await channel.assertExchange('retry', 'direct', {
1049
+ durable: true
1050
+ });
1051
+
1052
+ // Retry queue with delay
1053
+ await channel.assertQueue('retry_queue', {
1054
+ durable: true,
1055
+ messageTtl: 30000, // 30 second delay
1056
+ deadLetterExchange: '',
1057
+ deadLetterRoutingKey: 'main_queue'
1058
+ });
1059
+
1060
+ await channel.bindQueue('retry_queue', 'retry', 'retry');
1061
+
1062
+ console.log('Retry queue setup complete');
1063
+ await connection.close();
1064
+ }
1065
+
1066
+ setupRetryQueue();
1067
+ ```
1068
+
1069
+ ### Priority Queue
1070
+
1071
+ ```javascript
1072
+ const amqp = require('amqplib');
1073
+
1074
+ async function setupPriorityQueue() {
1075
+ const connection = await amqp.connect('amqp://localhost');
1076
+ const channel = await connection.createChannel();
1077
+
1078
+ // Queue with priority support
1079
+ await channel.assertQueue('priority_queue', {
1080
+ durable: true,
1081
+ maxPriority: 10
1082
+ });
1083
+
1084
+ // Send messages with different priorities
1085
+ channel.sendToQueue('priority_queue', Buffer.from('Low priority'), {
1086
+ priority: 1
1087
+ });
1088
+
1089
+ channel.sendToQueue('priority_queue', Buffer.from('High priority'), {
1090
+ priority: 10
1091
+ });
1092
+
1093
+ channel.sendToQueue('priority_queue', Buffer.from('Medium priority'), {
1094
+ priority: 5
1095
+ });
1096
+
1097
+ setTimeout(() => connection.close(), 500);
1098
+ }
1099
+
1100
+ setupPriorityQueue();
1101
+ ```
1102
+
1103
+ ### Rate Limiting Consumer
1104
+
1105
+ ```javascript
1106
+ const amqp = require('amqplib');
1107
+
1108
+ async function rateLimitedConsumer() {
1109
+ const connection = await amqp.connect('amqp://localhost');
1110
+ const channel = await connection.createChannel();
1111
+
1112
+ await channel.assertQueue('rate_limited_queue', {
1113
+ durable: true
1114
+ });
1115
+
1116
+ // Process only 1 message at a time
1117
+ channel.prefetch(1);
1118
+
1119
+ let processing = false;
1120
+
1121
+ channel.consume('rate_limited_queue', async (msg) => {
1122
+ if (msg !== null && !processing) {
1123
+ processing = true;
1124
+
1125
+ console.log('Processing:', msg.content.toString());
1126
+
1127
+ // Simulate rate-limited processing
1128
+ await new Promise(resolve => setTimeout(resolve, 2000));
1129
+
1130
+ channel.ack(msg);
1131
+ processing = false;
1132
+ }
1133
+ });
1134
+ }
1135
+
1136
+ rateLimitedConsumer();
1137
+ ```
1138
+
1139
+ ### JSON Message Handling
1140
+
1141
+ ```javascript
1142
+ const amqp = require('amqplib');
1143
+
1144
+ async function sendJSON(queue, data) {
1145
+ const connection = await amqp.connect('amqp://localhost');
1146
+ const channel = await connection.createChannel();
1147
+
1148
+ await channel.assertQueue(queue, { durable: true });
1149
+
1150
+ const message = JSON.stringify(data);
1151
+
1152
+ channel.sendToQueue(queue, Buffer.from(message), {
1153
+ contentType: 'application/json',
1154
+ persistent: true
1155
+ });
1156
+
1157
+ console.log('Sent JSON:', data);
1158
+
1159
+ setTimeout(() => connection.close(), 500);
1160
+ }
1161
+
1162
+ async function receiveJSON(queue) {
1163
+ const connection = await amqp.connect('amqp://localhost');
1164
+ const channel = await connection.createChannel();
1165
+
1166
+ await channel.assertQueue(queue, { durable: true });
1167
+
1168
+ channel.consume(queue, (msg) => {
1169
+ if (msg !== null) {
1170
+ try {
1171
+ const data = JSON.parse(msg.content.toString());
1172
+ console.log('Received JSON:', data);
1173
+ channel.ack(msg);
1174
+ } catch (error) {
1175
+ console.error('Invalid JSON:', error);
1176
+ channel.nack(msg, false, false);
1177
+ }
1178
+ }
1179
+ });
1180
+ }
1181
+
1182
+ // Usage
1183
+ sendJSON('json_queue', { user: 'john', action: 'login', timestamp: Date.now() });
1184
+ receiveJSON('json_queue');
1185
+ ```
1186
+
1187
+ ## Useful Links
1188
+
1189
+ - **Official Documentation:** https://www.rabbitmq.com/docs
1190
+ - **amqplib GitHub:** https://github.com/amqp-node/amqplib
1191
+ - **amqplib API Reference:** https://amqp-node.github.io/amqplib/channel_api.html
1192
+ - **RabbitMQ Tutorials:** https://www.rabbitmq.com/tutorials
1193
+ - **AMQP 0-9-1 Reference:** https://www.rabbitmq.com/amqp-0-9-1-reference.html