npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@innobridge/qatar

v1.1.0

Published

A TypeScript library for Queue management, qatar is Sanskrit for queue

Downloads

5

Readme

rabbitmq

npm install amqplib dotenv
npm i --save-dev @types/amqplib

RabbitMQ message has 2 parts

  • payload
  • label

label only describes the message with a label (an exchange name and optionally a topic tag)

Consumers attach to a broker server and subscribe to a queue, the consumer only receives the payload, the label doesn't get pass to the consumer so unless specified the consumer does not have information about producer.

Producer and consumer communicates to rabbitmq through channels. First the application opens a tcp connection with rabbitmq broker, once connection is established your app creates an AMQP channel. Your app can publish message or subscribe to queue through a channel.

The reason for a channel is because setting up and tearing down tcp connection is expensive, channels is less resource intensive in the situation where your application is subscribed to multiple queues it can be done through different channels.

There are 3 parts to rabbitmq

  • exchange: is where producers publish their message to
  • binding: routes messages from an exchange to particular queue/s
  • queues: where consumers receives messages from

There are ways consumers receive message from queue

  • basic.consume: This will place a channel in receive mode until it unsubscribes, the consumer will auto receive message from queue as soon it arrives to the queue.

  • basic.get: This will only receive one message from queue, unless the channel is set basic.get again. It basically subscribe and unsubscribe everytime you receive a message. Resource intensive.

  • routing key: A queue is bounded to an exchange by a routing key. There is a routing key in the message and one in binding.

If you publish a message to an exchange, it will have a routing key (it will be an empty key if you don't specify), RabbitMQ will try to match the routing key in its bindings. If they match the message will be delivered to the queue. If the message binding key don't match any bind patterns it will be "black holed".

Exchanges

There are 4 types of exchanges in RabbitMQ

  • Direct Exchange
  • Topic Exchange
  • Fanout Exchange
  • Header Exchange

Direct Exchange

await channel.assertExchange('direct-exchange', 'direct');
await channel.bindQueue('user-queue', 'direct-exchange', 'user.123');

// Message with routing key 'user.123' goes to user-queue
channel.publish('direct-exchange', 'user.123', Buffer.from('message'));
  • Exact match of routing keys
  • One-to-one routing

Default exchange is direct, it is specify with empty string

// These are equivalent:
channel.sendToQueue('jobs', Buffer.from('message'));

// Is the same as:
channel.publish('', 'jobs', Buffer.from('message'));
//               ↑    ↑
//        default exchange  routing key = queue name

Topic Exchange

await channel.assertExchange('topic-exchange', 'topic');
await channel.bindQueue('email-queue', 'topic-exchange', 'user.email.*');
await channel.bindQueue('all-queue', 'topic-exchange', 'user.#');

// Matches 'user.email.*' pattern
channel.publish('topic-exchange', 'user.email.welcome', Buffer.from('message'));

Pattern matching with wild cards:

  • *: one word
  • #: zero or more words

Fanout Exchange

await channel.assertExchange('fanout-exchange', 'fanout');
await channel.bindQueue('queue1', 'fanout-exchange', ''); // routing key ignored
await channel.bindQueue('queue2', 'fanout-exchange', '');

// Goes to ALL bound queues regardless of routing key
channel.publish('fanout-exchange', 'any-key', Buffer.from('message'));
  • Broadcasts to all bound queues
  • ignore routing keys

Header Exchange

await channel.assertExchange('headers-exchange', 'headers');
await channel.bindQueue('priority-queue', 'headers-exchange', '', {
    'x-match': 'all',
    'priority': 'high',
    'type': 'urgent'
});

// Matches based on message headers, not routing key
channel.publish('headers-exchange', '', Buffer.from('message'), {
    headers: { priority: 'high', type: 'urgent' }
});

Header-based routing instad of routing keys

  • x-match: 'all': all headers must match
  • x-match: 'any': any headers can match