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

wscall-client

v0.4.0

Published

High-performance JavaScript client SDK for the WSCALL WebSocket RPC framework

Readme

wscall-client

High-performance JavaScript client SDK for the WSCALL WebSocket RPC framework.

Works in both Node.js (≥18) and modern browsers (native WebSocket + Web Crypto).

Features

  • Protocol v3 binary codec — compact 5-byte frame header, single-letter JSON keys, raw binary attachments (zero Base64 overhead).
  • Encryption — ChaCha20-Poly1305 and AES-256-GCM at frame level; no TLS required.
  • ECDH key agreement — X25519 dynamic per-connection session key (forward secrecy), no pre-shared key needed.
  • Connection authentication — submit a credential (e.g. token) during the handshake; rejected connections fail fast at connect time (requires server ≥ 0.6.0).
  • Bidirectional messaging — request/response RPC + server-pushed events with ACK correlation.
  • Automatic reconnect — exponential backoff with jitter; sticky failover across multiple server URLs.
  • Zero-copy attachments — send and receive binary files inline with RPC params or event data.

Installation

npm install wscall-client

For Node.js environments you also need a WebSocket implementation:

npm install ws

Browsers provide WebSocket natively — no extra dependency.

Quick Start

ECDH mode (recommended — no pre-shared key)

import { WscallClient, WscallClientConfig } from 'wscall-client';

const client = await WscallClient.connect(
  'ws://127.0.0.1:9001/socket',
  WscallClientConfig.ecdh()
);

// RPC call (resolves directly with the response data)
const res = await client.call('system.echo', { message: 'hello' });
console.log(res); // { message: 'hello' }

// Subscribe to server events
client.onEvent('chat.message', (event) => {
  console.log('New message:', event.data);
  return { received: true }; // sent back as ACK receipt
});

// Emit an event (resolves with the ACK receipt)
const receipt = await client.sendEvent('chat.message', { text: 'hi!' });
console.log('Server acknowledged:', receipt);

client.close();

PSK mode (pre-shared key)

import { WscallClient, WscallClientConfig } from 'wscall-client';

const key = new Uint8Array(32).fill(0x42); // 32-byte shared key

const config = WscallClientConfig.pskChaCha20(key);
const client = await WscallClient.connect('ws://127.0.0.1:9001/socket', config);

Failover across multiple servers

const config = WscallClientConfig.ecdh()
  .withFailoverUrl('ws://backup1:9001/socket')
  .withFailoverUrl('ws://backup2:9001/socket');

const client = await WscallClient.connect('ws://primary:9001/socket', config);

On disconnect the client iterates through [primary, ...failover] starting from the last successfully connected URL (sticky failover).

Authenticated connection (server ≥ 0.6.0)

When the server registers an auth_handler, submit your credential at connect time. The credential is sent as an encrypted frame right after key agreement — no tokens in URLs or HTTP headers.

const client = await WscallClient.connect(
  'ws://127.0.0.1:9001/socket',
  WscallClientConfig.ecdh().withCredential('my-token')
);

If the server rejects the credential, connect rejects with a ClientError whose code is the server error code (e.g. unauthorized) and whose details carries the full error payload.

File attachments

import { createTextAttachment, attachmentRef } from 'wscall-client';

const att = createTextAttachment('f1', 'hello.txt', 'text/plain', 'Hello, world!');

const res = await client.call(
  'files.inspect',
  { file: attachmentRef('f1') },
  [att]
);

API Overview

WscallClient.connect(url, config?) → Promise<WscallClient>

Static factory. Connects to a WSCALL server and returns a ready client.

WscallClientConfig

| Factory / Builder | Description | |-------------------|-------------| | WscallClientConfig.ecdh() | ECDH + ChaCha20 + auto-reconnect (default) | | WscallClientConfig.plaintext() | No encryption | | WscallClientConfig.pskChaCha20(key) | PSK with ChaCha20-Poly1305 | | WscallClientConfig.pskAes256(key) | PSK with AES-256-GCM | | .withAutoReconnect(bool) | Enable/disable auto-reconnect | | .withTimeout(ms) | Default request timeout (default 10s). Raise it for long-running workloads, or pass a per-call options.timeout | | .withHeartbeatInterval(ms) | Keep-alive ping interval (default 15s) | | .withIdleTimeout(ms) | Inbound idle timeout (default 45s) | | .withReconnectBaseDelay(ms) | Reconnect backoff base delay (default 3s) | | .withReconnectMaxDelay(ms) | Reconnect backoff upper bound (default 30s) | | .withAuthTimeout(ms) | Auth handshake timeout (default 10s) | | .withMetadata(obj) | Default metadata sent with requests | | .withFailoverUrl(url) | Append a failover URL | | .withFailoverUrls(urls) | Set all failover URLs | | .withCredential(credential) | Credential (token) for the auth handshake |

client

| Method | Description | |--------|-------------| | call(route, params?, attachments?, opts?) | RPC call → Promise<data> (response data directly) | | sendEvent(name, data?, attachments?, opts?) | Emit event → Promise<receipt> (ACK receipt) | | onEvent(name, handler) | Subscribe to server events | | offEvent(name, handler?) | Unsubscribe | | onConnected(handler) | Connection established hook | | onDisconnected(handler) | Disconnection hook | | close() | Graceful shutdown (stops reconnect) |

Reconnect behavior

  1. Unexpected disconnects trigger automatic reconnect (default: enabled).
  2. First retry after 3 s (reconnectBaseDelayMs), then exponential backoff (×2), capped at 30 s (reconnectMaxDelayMs).
  3. Random sub-second jitter prevents thundering-herd storms.
  4. With failoverUrls, each cycle tries all URLs before applying backoff.
  5. close() stops all reconnect attempts.

Protocol Compatibility

This SDK implements WSCALL Protocol v3 (5-byte frame header, connection-level encryption). It requires a server running wscall ≥ 0.5.1; the credential handshake (withCredential) requires server ≥ 0.6.0.

| SDK version | Protocol | Server compatibility | |-------------|----------|---------------------| | 0.4.x | v3 | wscall ≥ 0.5.1 (auth: ≥ 0.6.0; timing knobs pair best with server ≥ 0.7.0) | | 0.3.x | v3 | wscall ≥ 0.5.1 (auth: ≥ 0.6.0) | | 0.2.x | v2 | wscall 0.4.x – 0.5.0 |

Browser Usage

<script type="module">
  import { WscallClient, WscallClientConfig } from './node_modules/wscall-client/src/index.js';

  const client = await WscallClient.connect('ws://localhost:9001/socket', WscallClientConfig.ecdh());
  const res = await client.call('system.echo', { msg: 'from browser' });
  console.log(res);
</script>

In browsers the ws package is not needed — the native WebSocket global is used automatically.

Dependencies

| Package | Purpose | |---------|---------| | @noble/ciphers | ChaCha20-Poly1305 AEAD (pure JS, audited) | | @noble/curves | X25519 ECDH key agreement (pure JS, audited) | | ws (optional peer) | WebSocket implementation for Node.js |

License

MIT