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

@eric8810/catcher-napi-ws

v0.3.8

Published

catcher WebSocket native addon for Node.js via napi-rs

Readme

@eric8810/catcher-napi-ws

npm version License: MIT

Rust-powered WebSocket client for Node.js via napi-rs. Part of the catcher toolkit.

Wraps catcher-ws's WsTransport — tokio-tungstenite + auto-reconnect + heartbeat, compiled to a native addon. Includes typed TypeScript wrappers with auto-generated .d.ts.

⚠️ Breaking Changes (0.3.0+)

Migrate from 0.2.x → 0.3.x — see napi API docs for full details.

v0.3.2: wss:// connections now work correctly (TLS via rustls enabled by default).

| Change | Before | After | |--------|--------|-------| | Entry point | client.js / client.d.ts | dist/client.js / dist/client.d.ts | | Config format | JSON.stringify(config) only | Typed object or JSON string | | Class name | JsWsClient | WsClient | | Callback events | Raw JSON strings, need JSON.parse() | Typed objects, auto-parsed | | Message event data | event.data (raw) | event.data_base64 (base64 encoded) | | Default handshake_timeout_ms | 10000 | 15000 | | Default per_message_deflate | true | false | | Default initial_delay_ms | 1000 | 500 | | camelCase fields | Not supported | #[serde(alias)] — both snake_case and camelCase accepted |

- const ws = new WsClient(JSON.stringify(config), (eventJson) => {
-   const event = JSON.parse(eventJson)
-   console.log(event.data)
+ import { WsClient } from '@eric8810/catcher-napi-ws'
+ const ws = new WsClient(config, (event) => {
+   if (event.type === 'Message') {
+     console.log(Buffer.from(event.data_base64, 'base64').toString())
+   }
})

Install

npm install @eric8810/catcher-napi-ws

Pre-built binaries available for Linux (x64/arm64 gnu/musl), macOS (x64/arm64), and Windows (x64/arm64). Installed automatically via platform-specific optionalDependencies.

TLS: wss:// connections supported out of the box via rustls (bundled, no system TLS dependency).

Usage

import { WsClient } from '@eric8810/catcher-napi-ws'
import type { WsEvent } from '@eric8810/catcher-napi-ws'

// Config as typed object (recommended) or JSON string
const ws = new WsClient(
  {
    urls: ['wss://echo.example.com'],
    reconnect: { initial_delay_ms: 500, max_delay_ms: 30000 },
    heartbeat: { interval_ms: 30000, adaptive: true },
  },
  (event: WsEvent) => {
    switch (event.type) {
      case 'Connected':
        console.log(`Connected to ${event.url} (${event.latency_ms}ms)`)
        break
      case 'Message':
        console.log('Received:', event.is_binary ? '(binary)' : Buffer.from(event.data_base64, 'base64').toString())
        break
      case 'Disconnected':
        console.log(`Disconnected: ${event.code} ${event.reason}`)
        break
      case 'Reconnecting':
        console.log(`Reconnecting attempt ${event.attempt} in ${event.delay_ms}ms`)
        break
      case 'HeartbeatRtt':
        console.log(`RTT: ${event.rtt_ms}ms`)
        break
      case 'Error':
        console.error('Error:', event.message)
        break
    }
  },
)

ws.send('hello')
// later:
ws.close()

Note: Do not call send() synchronously inside event callbacks — this can deadlock due to napi's single-threaded nature. Use setImmediate or process.nextTick to defer.

API

new WsClient(config: WsClientConfig | string, onEvent?: (event: WsEvent) => void)

Create a WebSocket client and connect. Config is a typed object or JSON string. Events are delivered as parsed objects (not JSON strings). Supports both snake_case and camelCase field names.

interface WsClientConfig {
  urls: string[]                              // required
  protocols?: string[]
  headers?: Record<string, string>
  per_message_deflate?: boolean               // default: false
  deflate_threshold_bytes?: number            // default: 1024
  handshake_timeout_ms?: number               // default: 15000
  max_payload_bytes?: number                  // default: 67108864 (64MB)
  reconnect?: ReconnectConfig
  heartbeat?: HeartbeatConfig
  race_count?: number                         // default: 1
}

Methods

| Method | Signature | |--------|-----------| | send(data) | (data: string) => void | | sendBinary(data) | (data: Buffer \| ArrayBuffer \| Uint8Array) => void | | close(code?, reason?) | (code?: number, reason?: string) => void |

Event Types

Events are delivered as typed objects (auto-parsed from JSON):

| Event | Shape | |-------|-------| | Connected | { type: 'Connected', url: string, latency_ms: number } | | Disconnected | { type: 'Disconnected', code: number, reason: string } | | Message | { type: 'Message', data_base64: string, is_binary: boolean } | | Error | { type: 'Error', message: string } | | Reconnecting | { type: 'Reconnecting', attempt: number, delay_ms: number } | | HeartbeatRtt | { type: 'HeartbeatRtt', rtt_ms: number } |

data_base64 is the base64-encoded payload. Decode with Buffer.from(event.data_base64, 'base64').

Build from Source

Requires Rust toolchain.

npm run build       # napi build + tsup compile
npm run build:ts    # tsup only (no Rust rebuild)

License

MIT