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

r2-notify-client

v1.2.1

Published

Framework-agnostic WebSocket notification client for r2-notify-server. Consumes real-time events and emits notification actions.

Readme

r2-notify-client

Framework-agnostic TypeScript client for r2-notify-server. Connects over WebSocket and lets you receive real-time notifications and send actions back to the server.

Works with React, Vue, Svelte, vanilla JS — or any environment that supports WebSocket and fetch.


Features

  • 🔌 Real-time notifications over WebSocket
  • 🔐 Secure auth — two-step token exchange keeps your API key out of URLs
  • 🔄 Automatic reconnection with configurable delay
  • 🎯 Fully typed — written in TypeScript with exported types for everything
  • 🪶 Lightweight — only one dependency (eventemitter3)
  • 🎭 Event-driven — subscribe to server events and lifecycle changes with .on()

Installation

npm install r2-notify-client

Quick Start

import { R2NotifyClient } from 'r2-notify-client';

const client = new R2NotifyClient({
  serverUrl: 'https://your-r2-notify-server.com',
  apiKey: 'your-api-key',
});

client.on('connected', () => console.log('Connected'));
client.on('disconnected', () => console.log('Disconnected'));
client.on('error', (err) => console.error('Error:', err));

client.on('listNotifications', (notifications) => {
  console.log('All notifications:', notifications);
});

client.on('newNotification', (notification) => {
  console.log('New notification arrived:', notification);
});

await client.connect();

You can also pass event handlers directly into connect():

await client.connect({
  listNotifications: (notifications) => { ... },
  newNotification: (notification) => { ... },
  listConfigurations: (config) => { ... },
});

Note: handlers passed to connect() only cover notification events (listNotifications, newNotification, listConfigurations). For lifecycle events (connected, disconnected, error) always use .on().


How It Works

The client performs a two-step connection automatically — you never need to manage this yourself:

  1. POSTs your API key to {serverUrl}/ws-token via HTTPS → receives a short-lived token
  2. Opens a WebSocket to {serverUrl}/ws?token=<token>

The serverUrl protocol determines both connections:

| serverUrl | Token endpoint | WebSocket | |---|---|---| | http://localhost:8081 | http://localhost:8081/ws-token | ws://localhost:8081/ws | | https://your-server.com | https://your-server.com/ws-token | wss://your-server.com/ws |

Your API key only ever travels in an HTTPS Authorization header — it never appears in a WebSocket URL.

On every reconnect a fresh token is fetched automatically, so page refreshes, network drops, and tab restores all work without any extra handling on your end.


Configuration

new R2NotifyClient({
  serverUrl: 'https://your-server.com', // required
  apiKey: 'your-api-key',               // required
  reconnect: true,                       // default true
  reconnectDelayMs: 1500,               // default 1500
  debug: false,                          // default false
});

| Option | Type | Default | Description | |---|---|---|---| | serverUrl | string | required | Base URL of your r2-notify-server instance | | apiKey | string | required | Your API key | | reconnect | boolean | true | Automatically reconnect when the connection drops | | reconnectDelayMs | number | 1500 | How long to wait before reconnecting (ms) | | debug | boolean | false | Print WebSocket activity to the console |


API Reference

connect(handlers?)

Fetches a token and opens the WebSocket. Returns this for chaining. async — await it if you need to act after the token exchange completes.

await client.connect();

close()

Closes the connection and disables auto-reconnect.

client.close();

emitAction(action, payload?)

Sends a raw action envelope to the server. Prefer the convenience methods below.

client.emitAction('markNotificationAsRead', { id: 'abc123' });

Events

Lifecycle

Use .on() and .off() to subscribe and unsubscribe.

| Event | Payload | Description | |---|---|---| | connected | void | WebSocket connection established | | disconnected | void | WebSocket connection closed | | error | Error | Connection or token fetch error |

Notification

| Event | Payload | Description | |---|---|---| | listNotifications | NotificationMessage[] | Full notification list — sent on connect and after any action | | newNotification | NotificationMessage | A single notification pushed in real time | | listConfigurations | NotificationConfig | User notification config |


Actions

Convenience methods that send the corresponding action to the server. After each action the server responds with an updated listNotifications event.

Mark as read

client.markAsRead();
client.markAppAsRead('app-id');
client.markGroupAsRead('app-id', 'group-key');
client.markNotificationAsRead('notification-id');

Delete

client.deleteNotifications();
client.deleteAppNotifications('app-id');
client.deleteGroupNotifications('app-id', 'group-key');
client.deleteNotification('notification-id');

Other

client.reloadNotifications();          // request a fresh list from the server
client.setNotificationStatus(true);    // enable notifications
client.setNotificationStatus(false);   // disable notifications

TypeScript Types

import type {
  R2NotifyClientOptions,
  NotificationMessage,
  NotificationGroup,
  NotificationApp,
  NotificationConfig,
  NotifyEvent,
  NotifyAction,
  ActionEnvelope,
  ServerEventEnvelope,
} from 'r2-notify-client';

NotificationMessage

interface NotificationMessage {
  id: string;
  appId: string;
  userId: string;
  groupKey: string;
  message: string;
  status: 'success' | 'error' | 'warning' | 'info';
  readStatus: boolean;
  createdAt: string;
  updatedAt: string;
}

NotificationConfig

type NotificationConfig = {
  id: string;
  userId: string;
  enableNotification: boolean;
};

NotificationGroup

interface NotificationGroup {
  groupKey: string;
  latest: number;
  unread: number;
  items: NotificationMessage[];
}

NotificationApp

interface NotificationApp {
  appId: string;
  latest: number;
  unread: number;
  groups: NotificationGroup[];
  total: number;
}

Advanced Usage

Disable auto-reconnect

const client = new R2NotifyClient({
  serverUrl: 'https://your-server.com',
  apiKey: 'your-api-key',
  reconnect: false,
});

Dynamic event listeners

const handler = (notification: unknown) => {
  console.log('New notification:', notification);
};

client.on('newNotification', handler);

// Later — clean up
client.off('newNotification', handler);

Debug mode

new R2NotifyClient({
  serverUrl: 'https://your-server.com',
  apiKey: 'your-api-key',
  debug: true, // logs all WebSocket activity to the console
});

React

For React projects, r2-notify-react wraps this client with a provider and hooks (useNotifications, useNotifyActions, useNotifyEvent) so you don't need to manage the client instance yourself.


License

MIT © Sherantha Perera