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 🙏

© 2025 – Pkg Stats / Ryan Hefner

typed-websocket-client

v1.0.0

Published

[![npm version](https://img.shields.io/npm/v/typed-websocket-client)](https://npm.im/typed-websocket-client) [![npm downloads](https://img.shields.io/npm/dm/typed-websocket-client)](https://npm.im/typed-websocket-client) [![License](https://img.shields.io

Readme

typed-websocket-client

npm version npm downloads License

A robust, type-safe WebSocket client for browsers and Node.js with automatic reconnection, heartbeat, and a message buffer.

typed-websocket-client is designed to handle the complexities of real-world WebSocket connections, so you can focus on your application logic. It provides a simple, event-driven API while managing connection stability under the hood.

This package is heavily inspired by the Socket part of the Phoenix Framework.

Features

  • Type-Safe: Use generics for SendType and ReceiveType to get full type-safety and autocompletion for your messages.
  • 🔄 Automatic Reconnection: Automatically reconnects with an exponential backoff strategy when the connection is unexpectedly lost.
  • ❤️ Heartbeat / Keep-alive: Prevents idle connections from being dropped by firewalls or load balancers by periodically sending heartbeat messages.
  • 📬 Send Buffer: Messages sent while the connection is down are queued and sent automatically upon reconnection.
  • 🔧 Highly Customizable:
    • Custom encoding/decoding (defaults to JSON).
    • Custom heartbeat payload and reply detection.
    • Custom reconnection timing.
    • Pluggable logger for easy debugging.
  • 🌐 Isomorphic: Works seamlessly in both browsers and Node.js environments (by providing a ws constructor).
  • modern Modern API:
  • Familiar on/off event listener interface.
  • Supports AbortSignal for automatic listener cleanup.

Installation

npm install typed-websocket-client

Usage

Basic Usage

Here's a simple example of connecting to a WebSocket echo server.

import { WebSocketClient } from 'typed-websocket-client';

// Create a new client instance
const client = new WebSocketClient('wss://echo.websocket.org/');

// Listen for the 'open' event
client.on('open', () => {
	console.log('Connection established!');
	client.push('Hello, WebSocket!');
});

// Listen for incoming messages
client.on('message', (data) => {
	console.log('Received:', data); // Received: Hello, WebSocket!
});

// Listen for the 'close' event
client.on('close', (event) => {
	console.log(`Connection closed: ${event.reason} (Code: ${event.code})`);
});

// Listen for errors
client.on('error', (error) => {
	console.error('WebSocket Error:', error);
});

// Start the connection
client.connect();

Type-Safe Usage

The real power comes from defining types for your messages.

import { WebSocketClient } from 'typed-websocket-client';

// 1. Define your message types
interface UserMessage {
	type: 'message';
	payload: {
		text: string;
		timestamp: number;
	};
}

interface ServerEvent {
	type: 'event';
	payload: {
		name: 'user_joined' | 'user_left';
		userId: string;
	};
}

type SendType = UserMessage;
type ReceiveType = UserMessage | ServerEvent;

// 2. Create a typed client instance
const client = new WebSocketClient<SendType, ReceiveType>('ws://localhost:8080/socket');

client.on('open', () => {
	// `push` is now strongly typed. This is valid:
	client.push({
		type: 'message',
		payload: { text: 'Hello from a typed client!', timestamp: Date.now() },
	});

	// This would cause a TypeScript error:
	// client.push({ type: 'invalid_type' });
});

// 3. The `data` in the message handler is also strongly typed
client.on('message', (data) => {
	// `data` is of type `UserMessage | ServerEvent`
	switch (data.type) {
		case 'message':
			console.log(`Received message: "${data.payload.text}"`);
			break;
		case 'event':
			console.log(`Server event: ${data.payload.name}`);
			break;
	}
});

client.connect();

Advanced Configuration

You can customize almost every aspect of the client's behavior.

import { WebSocketClient } from 'typed-websocket-client';
// For Node.js, you need to install and provide a WebSocket implementation
import WebSocket from 'ws';

const controller = new AbortController();

const client = new WebSocketClient('ws://localhost:8080/socket', {
	// Use the 'ws' library in Node.js
	WebSocketCtor: WebSocket,

	// Custom reconnection strategy (e.g., every 3 seconds)
	reconnectAfterMs: (tries) => 3000,

	// Custom heartbeat interval and timeout
	heartbeatIntervalMs: 25000,
	timeout: 5000,

	// Add dynamic query parameters for authentication
	params: () => ({
		token: getAuthToken(), // Your function to get a fresh token
	}),

	// Enable logging for debugging
	logger: (kind, msg, data) => {
		console.log(`[${new Date().toISOString()}] ${kind.toUpperCase()}: ${msg}`, data || '');
	},
});

// Add a listener that can be removed via an AbortSignal
client.on(
	'message',
	(data) => {
		console.log('This listener will only fire once.', data);
		controller.abort(); // Abort the signal to remove the listener
	},
	{ signal: controller.signal },
);

client.connect();

function getAuthToken() {
	return 'some-secret-jwt-token';
}

API

new WebSocketClient(endPoint, options?)

Creates a new client instance.

  • endPoint (string): The WebSocket URL.
  • options (WebSocketClientOptions): Configuration options.

Options

| Option | Type | Default | Description | | --------------------- | --------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------- | | WebSocketCtor | new (...) => WebSocket | window.WebSocket | A WebSocket constructor, required for Node.js environments. | | timeout | number | 10000 | Timeout in ms for connection and heartbeat events. | | heartbeatIntervalMs | number | 30000 | Interval in ms for sending heartbeat messages. | | reconnectAfterMs | (tries: number) => number | Exponential backoff | A function returning the reconnection delay in ms. | | logger | (kind, msg, data?) => void | undefined | A function for logging internal events. | | params | Record<string, any> \| (() => Record) | {} | Query parameters to append to the URL. Can be a function for dynamic values. | | protocols | string \| string[] | undefined | WebSocket sub-protocols. | | binaryType | BinaryType | 'arraybuffer' | The binary data type to use. | | encode | (data, callback) => void | JSON.stringify | Custom function to encode outgoing messages. | | decode | (data, callback) => void | JSON.parse | Custom function to decode incoming messages. | | heartbeatPayload | () => SendType | { event: 'heartbeat', ref: ... } | A function that returns the payload for a heartbeat message. | | isHeartbeatReply | (data: ReceiveType) => boolean | Checks for matching ref | A function to identify if an incoming message is a reply to a heartbeat. |

Methods

  • connect(): Establishes the connection.
  • disconnect(callback?, code?, reason?): Closes the connection cleanly.
  • push(data: SendType): Sends a message. Buffers if offline.
  • on(event, callback, options?): Adds an event listener.
  • off(event, callback): Removes an event listener.
  • connectionState(): Returns 'connecting' | 'open' | 'closing' | 'closed'.
  • isConnected(): Returns true if the connection is open.

License

MIT License