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 🙏

© 2024 – Pkg Stats / Ryan Hefner

mercure

v0.1.0

Published

Mercure Hub implementation in Node.js.

Downloads

52

Readme

mercure

Mercure Hub & Publisher implemented in Node.js.

stability-beta

npm version Known Vulnerabilities dependency status devdependency status downloads Code Climate

NPM

Note : this npm package has been transfered for a new project by the initial owner, which serves a totally different purpose. This new version is an implementation of the Mercure protocol. The previous mercure package had 1 release (0.0.1) and served as a file downloader. You can still access it : https://www.npmjs.com/package/mercure/v/0.0.1. Please make sure to lock this version in your package.json file, as the new versions will begin at 0.0.2 and will keep following the semver versioning.

TODOs

  • CORS
  • Hearthbeat mechanism (https://github.com/dunglas/mercure/pull/53)
  • Docker image (iso with official image)
  • Prometheus metrics exporter
  • Events database
  • Export authorization.js mechanism
  • Discovery helpers
  • Increase code quality score
  • JSDoc
  • Logging
  • Unit tests
  • Find a way to clear Redis if the process gets interrupted
  • Benchmarks

State

This is a beta version. This has not fully been tested in production yet.

Requirements

  • node.js >= 11.7.0
  • Redis (optional)

Features

  • 100% implementation of the protocol
  • Events asymmetric encryption
  • Easy integration to any existing app using http.Server or express
  • Redis-based clustering support
  • Inventory of all open connections stored in Redis, per node process
  • Kill switch

Future improvements

  • Implement as a lambda function ?

Installation

npm install mercure --save

Usage

This library provides 3 components : a Hub, a Server and a Publisher :

Classes preview

Simple hub

-> Documentation

The Hub class is the core component that uses a simple http.Server instance. An existing instance can be provided to the Hub, thus the Hub will use it instead of creating a new one.

Use case : implanting the hub on an existing http.Server app, without the need to handle external publishers (only the app does the publishing).

It handles :

  • the SSE connections
  • the events database
  • the authorization mechanism
  • events related to the Hub activity
const http = require('http');
const { Hub } = require('mercure');

const server = http.createHttpServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('200');
});

const hub = new Hub(server, {
  jwtKey: '!UnsecureChangeMe!',
  path: '/hub',
});

hub.listen();

Hub server

-> Documentation

The Server is built upon the Hub component. It creates a new Express instance and allows external publishers to POST an event to the hub.

Use case : implanting he hub on an new application that is meant to accept external publishers, with no other HTTP server ... or one listening on a different port.

It handles everything the Hub does, plus :

  • a freshly created Express instance, built upon the Hub's http.Server (middlewares can be applied to enhance security)
  • external publishers (POST requests)
const { Server } = require('mercure');

const server = new Server({
  jwtKey: '!UnsecureChangeMe!',
  path: '/hub',
});

server.listen(3000);

Because the Server is leverages Express, it is possible to add middlewares in front of the internal Hub middleware :

const compression = require('compression');

class SecuredHubServer extends Server {
  configure() {
    this.app.use(compression());
  }
}

const server = new SecuredHubServer(...);

Publisher

-> Documentation

It can be created in different ways :

  • using an existing Hub instance (when the app is meant to be THE ONLY publisher)
  • using an existing Server instance (when the app is meant to be a publisher)
  • using configuration : host, port... (when the publisher and the hub are distant)

It handles :

  • Message publication to the Hub
  • Message encryption (optional)
const { Publisher } = require('mercure');

const publisher = new Publisher({
  protocol: 'https', // or 'http', but please don't.
  host: 'example.com',
  port: 3000,
  path: '/hub',
  jwt: 'PUBLISHER_JWT',
});

// Payload to send to the subscribers.
const data = {
  '@id': 'http://localhost:3000/books/666.jsonld',
  hello: 'world',
};

await publisher.publish(
  ['https://example.com:3000/books/666.jsonld'], // Topics.
  JSON.stringify(data),
);

API

API docs can be found in the docs/API.md file.

Encrypting the datas

In certain cases, the Mercure hub can be hosted by a third-party host. You don't really want them to "sniff" all your cleartext messages. To make the Publisher => Hub => Subscriber flow fully encrypted, it is required that the Publisher sends encrypted data.

To achieve this, the Publisher#useEncryption() method will activate messages encryption. Thus, the Hub will not be able to access your private datas :

const crypto = require('crypto');
const util = require('util');

const publisher = new Publisher({
  // ...
});

const data = { message: 'TOP SECRET DATAS' };
const { privateKey } = await util.promisify(crypto.generateKeyPair)('rsa', {
  modulusLength: 4096,
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
  },
});

// Start encrypting the events.
await publisher.useEncryption({
  rsaPrivateKey: privateKey,
});

// Will send encrypted datas.
await publisher.publish(
  [...], // Topics.
  JSON.stringify(data),
);

Decrypting :

const jose = require('node-jose');

const encryptedData = 'ENCRYPTED DATA';
const decrypted = await jose.JWE.createDecrypt(publisher.keystore).decrypt(encryptedData);

console.log(decrypted.plaintext.toString());

Kill switch

In case the hub must urgently close all connections (e.g.: in case of compromission of the JWT key), a kill switch is available :

await hub.killSwitch();

The new JWT Key will be output to stdout.

License

GNU GENERAL PUBLIC LICENSE v3.