npm package: @jnode/websocket
Description: Simple WebSocket package for Node.js.
Author: JustApple
Latest version: 1.0.1

# `@jnode/websocket`

Simple WebSocket package for Node.js.

## Installation

```bash
npm i @jnode/websocket
```

## Quick start

### Import

```js
const { WSConnection, calculateWSKey } = require('@jnode/websocket');
```

### Usage with `@jnode/server`

You can perform a WebSocket handshake within a custom handler:

```js
const { WSConnection, calculateWSKey } = require('@jnode/websocket');

const wsHandler = (ctx) => {
  const key = ctx.headers['sec-websocket-key'];
  if (!key) throw 400;

  // Handshake
  ctx.res.writeHead(101, {
    'Upgrade': 'websocket',
    'Connection': 'Upgrade',
    'Sec-WebSocket-Accept': calculateWSKey(key)
  });
  ctx.res.detachSocket(); // Take control of the socket

  const ws = new WSConnection(ctx.req.socket, ctx.req.socket, {
      useMask: false // Servers should not mask frames sent to clients
  });

  ws.on('message', (msg) => {
    console.log('Received:', msg.payload);
    ws.send(0x1, 'Hello from server!'); // 0x1 is Text frame
  });

  ws.on('close', (code, reason) => {
    console.log(`Closed: ${code} ${reason}`);
  });
};
```

---

# Reference

## Class: `WSConnection`

- Extends: [\<EventEmitter\>](https://nodejs.org/docs/latest/api/events.html#class-eventemitter)

The core class for managing a WebSocket connection over any duplex stream.

### `new WSConnection(readable, writable, options)`

- `readable` [\<stream.Readable\>](https://nodejs.org/docs/latest/api/stream.html#class-streamreadable) The input stream (e.g., a TCP socket).
- `writable` [\<stream.Writable\>](https://nodejs.org/docs/latest/api/stream.html#class-streamwritable) The output stream.
- `options` [\<Object\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
  - `maxMessageSize` [\<number\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type) The maximum allowed size for a single message. **Default:** `1048576` (1MB).
  - `useMask` [\<boolean\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#boolean_type) Whether to mask outgoing frames. **Note:** Servers MUST NOT mask frames sent to clients, while clients MUST mask frames sent to servers. **Default:** `undefined` (treated as `false`).
  - `autoPing` [\<boolean\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#boolean_type) Whether to automatically reply with a Pong frame when a Ping is received. **Default:** `undefined`.

### `ws.send(opcode, payload)`

- `opcode` [\<number\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type) The WebSocket opcode (e.g., `0x1` for text, `0x2` for binary).
- `payload` [\<string\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#string_type) | [\<Buffer\>](https://nodejs.org/docs/latest/api/buffer.html#class-buffer) The data to send.
- Returns: [\<boolean\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#boolean_type) Same as `writable.write()`.

Sends a single WebSocket frame with `fin` bit set to 1.

### `ws.sendFrame(fin, opcode, payload)`

- `fin` [\<number\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type) The FIN bit (0 or 1).
- `opcode` [\<number\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type) The opcode.
- `payload` [\<Buffer\>](https://nodejs.org/docs/latest/api/buffer.html#class-buffer) The frame payload.

Low-level method to send a raw WebSocket frame. Useful for manual fragmentation.

### `ws.close([code[, reason]])`

- `code` [\<number\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type) Status code for closure. **Default:** `1000`.
- `reason` [\<string\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#string_type) Human-readable reason for closure.

Sends a Close frame and destroys the underlying writable stream.

### Event: `'message'`

- `message` [\<Object\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
  - `opcode` [\<number\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type) `0x1` (text) or `0x2` (binary).
  - `payload` [\<string\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#string_type) | [\<Buffer\>](https://nodejs.org/docs/latest/api/buffer.html#class-buffer) The message content. If opcode is `0x1`, it is automatically converted to a string.

Emitted when a full message (including fragmented ones) is received.

### Event: `'close'`

- `code` [\<number\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type) Closure status code.
- `reason` [\<string\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#string_type) Closure reason.

Emitted when the connection is closed.

### Event: `'ping'` / `'pong'`

- `frame` [\<Object\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) The raw frame object.

Emitted when a Ping or Pong frame is received.

---

## `calculateWSKey(key)`

- `key` [\<string\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#string_type) The `Sec-WebSocket-Key` header from the client request.
- Returns: [\<string\>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#string_type) The base64 encoded SHA-1 hash required for the `Sec-WebSocket-Accept` header.

A helper function to facilitate the WebSocket handshake process.