# @nktkas/rews

> Drop-in WebSocket replacement with automatic reconnection.

Latest version **5.0.0** (published 2026-08-31) · MIT license · 0 weekly downloads

## Install

```sh
npm install @nktkas/rews
pnpm add @nktkas/rews
yarn add @nktkas/rews
bun add @nktkas/rews
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 5.0.0 |
| Published | 2026-08-31 |
| First published | 2025-11-03 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=22.12.0 |
| Dependencies | 0 |
| Unpacked size | 105.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 1 |
| Author | nktkas |
| Maintainers | nktkas |
| Keywords | websocket, ws, reconnect, retry |

## Links

- npm: https://www.npmjs.com/package/@nktkas/rews
- Repository: https://github.com/nktkas/rews
- Issues: https://github.com/nktkas/rews/issues
- npm.io page: https://npm.io/package/@nktkas/rews

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 5.0.0 (latest) — 2026-08-31
- 4.1.0 — 2026-07-06
- 4.0.1 — 2026-06-10
- 4.0.0 — 2026-06-10
- 3.0.0 — 2026-06-06
- 2.1.2 — 2026-06-04
- 2.1.1 — 2026-04-10
- 2.1.0 — 2026-04-04
- 2.0.2 — 2026-02-28
- 2.0.1 — 2026-02-24
- 2.0.0 — 2026-02-22
- 1.2.3 — 2025-12-25
- 1.2.2 — 2025-11-30
- 1.2.1 — 2025-11-26
- 1.2.0 — 2025-11-15
- … 4 more at https://npm.io/package/@nktkas/rews/versions

## README

# @nktkas/rews

[![npm](https://img.shields.io/npm/v/@nktkas/rews)](https://www.npmjs.com/package/@nktkas/rews)
[![JSR](https://jsr.io/badges/@nktkas/rews)](https://jsr.io/@nktkas/rews)
[![bundlejs](https://img.shields.io/bundlejs/size/@nktkas/rews)](https://bundlejs.com/?q=@nktkas/rews)

Drop-in [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) replacement with automatic
reconnection.

---

**Without rews** — manual reconnection, listener re-attachment, message queuing:

```ts
let ws: WebSocket;
let attempts = 0;
const queue: string[] = [];
const onMessage = (e: MessageEvent) => console.log(e.data);

function connect() {
  ws = new WebSocket("wss://example.com");
  ws.addEventListener("message", onMessage);
  ws.onopen = () => {
    attempts = 0;
    while (queue.length) ws.send(queue.shift()!);
  };
  ws.onclose = () => {
    if (attempts++ < 3) setTimeout(connect, 1000);
  };
}

function send(data: string) {
  ws.readyState === WebSocket.OPEN ? ws.send(data) : queue.push(data);
}

connect();
send("hello");
```

**With rews** — standard `WebSocket` API, no changes needed:

```ts
import { ReconnectingWebSocket } from "@nktkas/rews";

const ws = new ReconnectingWebSocket("wss://example.com");
ws.addEventListener("message", (e) => console.log(e.data));
ws.send("hello");
```

## Features

- **Drop-in replacement** — standard `WebSocket` API, swap one line
- **Auto-reconnection** — configurable retries and delay strategy
- **Message buffering** — `send()` queues data while offline, flushes on reconnect
- **Persistent listeners** — `addEventListener` and `on*` handlers survive reconnections
- **Dynamic URL & protocols** — resolve fresh values on each reconnection
- **Zero dependencies** — works in Node.js, Deno, Bun, and browsers

## Installation

```sh
# Node.js 22.12+ / React Native 0.86+
npm i @nktkas/rews

# Deno 2+
deno add jsr:@nktkas/rews

# Bun 1+
bun add @nktkas/rews
```

> React Native below 0.86 requires `Event` / `EventTarget` polyfills. On all versions, React Native's built-in
> `AbortController` polyfill drops `terminationSignal.reason`.

## Options

```ts
interface ReconnectingWebSocketOptions {
  /** Maximum number of consecutive failed reconnection attempts. @default Infinity */
  maxRetries?: number;
  /** Maximum number of messages buffered while disconnected. @default Infinity */
  maxEnqueuedMessages?: number;
  /** Connection timeout in ms (null to disable). @default 10_000 */
  connectionTimeout?: number | null;
  /** Time in ms a connection must stay open before the retry counter resets. @default 3_000 */
  stableTimeout?: number;
  /** Delay before reconnection in ms, or a function of attempt number. @default exponential backoff with jitter, max 10s */
  reconnectionDelay?: number | ((attempt: number) => number);
  /** Decide whether to reconnect after a non-user closure. @default () => true */
  shouldReconnect?: (event: CloseEvent, attempt: number) => boolean;
}
```

## Beyond Standard WebSocket

### Dynamic URL & Protocols

`url` and `protocols` accept functions (sync or async), invoked on each reconnection:

```ts
const ws = new ReconnectingWebSocket(
  () => `wss://example.com?token=${getToken()}`,
  () => ["v2"],
);
```

Errors thrown by these functions count as failed connection attempts and follow the normal retry flow. The same applies
to a permanently invalid URL: with the default `maxRetries: Infinity` it is retried forever, each close event carrying
the error in its `reason`.

### Event Lifecycle

Standard `open`, `close`, `error`, and `message` events fire on **every** connection cycle — not just the first one. A
single `ReconnectingWebSocket` instance may emit multiple `open`/`close` pairs over its lifetime as it reconnects.

```ts
ws.addEventListener("open", () => console.log("connected")); // fires on each (re)connection
ws.addEventListener("close", () => console.log("disconnected")); // fires on each disconnection

// use { once: true } if you only need the first occurrence
ws.addEventListener("open", () => init(), { once: true });
```

### readyState

`CLOSED` means permanently terminated. While reconnecting — a retry pause, a connection attempt, a url/protocols factory
await — `readyState` is `CONNECTING`; `CLOSING` is never reported.

### retryCount

Number of consecutive failed reconnection attempts; resets after a connection stays open for `stableTimeout`.

### Termination

`terminationSignal` is an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that aborts when
the connection is permanently closed. The abort reason is always a `ReconnectingWebSocketError`:

| Code                    | Description                                              |
| ----------------------- | -------------------------------------------------------- |
| `RECONNECTION_LIMIT`    | Max retries exceeded                                     |
| `RECONNECTION_DECLINED` | `shouldReconnect` returned `false`                       |
| `TERMINATED_BY_USER`    | `close()` called                                         |
| `UNKNOWN_ERROR`         | Unhandled error in `reconnectionDelay`/`shouldReconnect` |

```ts
ws.terminationSignal.aborted; // boolean
ws.terminationSignal.reason; // ReconnectingWebSocketError, once aborted

ws.terminationSignal.addEventListener("abort", () => {
  ws.terminationSignal.reason.code; // ReconnectingWebSocketErrorCode
  ws.terminationSignal.reason.cause; // original error, if any
});
```

Being a standard `AbortSignal`, it composes with `AbortSignal.any()`, `fetch()`, `addEventListener(..., { signal })`,
and other platform APIs.

### Closing Behavior

```ts
ws.close(code?, reason?); // permanently close — the standard WebSocket method
ws.reconnect(code?, reason?); // drop the current connection and reconnect immediately
```

`reconnect()` skips the current retry delay, is not counted towards `maxRetries`, and does nothing once the instance is
permanently terminated.

## License

**@nktkas/rews** is licensed under the [MIT License](LICENSE).

Copyright © 2025-present [nktkas](https://github.com/nktkas) and
[contributors](https://github.com/nktkas/rews/graphs/contributors).

---
_Source: https://npm.io/package/@nktkas/rews · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
