@stonyx/sockets 0.1.1-beta.72 → 0.1.1-beta.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -15,6 +15,19 @@ WebSocket server and client module for the [Stonyx framework](https://github.com
|
|
|
15
15
|
* **Encryption by default:** AES-256-GCM with per-session keys, zero external dependencies.
|
|
16
16
|
* **Singleton pattern:** Matches the conventions of `@stonyx/rest-server` and `stonyx-orm`.
|
|
17
17
|
|
|
18
|
+
## Samples
|
|
19
|
+
|
|
20
|
+
The handlers in [`test/sample/`](https://github.com/abofs/stonyx-sockets/tree/dev/test/sample) are the canonical usage reference for this module; the integration tests run against them. They are not included in the npm package. They are TypeScript and type-check against the published `Handler` type, which declares `server` and `client` as function-valued properties, so the TypeScript samples assign the hooks as `function` properties rather than methods. The JavaScript examples below use methods, which work the same at runtime.
|
|
21
|
+
|
|
22
|
+
Before deploying, read the [security notes](https://github.com/abofs/stonyx-sockets/blob/dev/docs/encryption.md#security-notes): `authKey` falls back to the literal `'AUTH_KEY'` if unset, any `encryption` value other than `'true'`/`true` runs in plaintext, and the module provides no transport security unless you use `wss://`.
|
|
23
|
+
|
|
24
|
+
## Exports
|
|
25
|
+
|
|
26
|
+
* `@stonyx/sockets`: named `SocketServer`, `SocketClient` and `Handler`; the default export is the `Sockets` class Stonyx uses for auto-init
|
|
27
|
+
* `@stonyx/sockets/server`: `SocketServer`
|
|
28
|
+
* `@stonyx/sockets/client`: `SocketClient`
|
|
29
|
+
* `@stonyx/sockets/handler`: `Handler`
|
|
30
|
+
|
|
18
31
|
## Installation
|
|
19
32
|
|
|
20
33
|
```bash
|
|
@@ -38,21 +51,31 @@ Each handler extends `Handler` and defines a `server()` method, a `client()` met
|
|
|
38
51
|
|
|
39
52
|
```javascript
|
|
40
53
|
// socket-handlers/auth.js
|
|
54
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
41
55
|
import { Handler } from '@stonyx/sockets';
|
|
42
56
|
import config from 'stonyx/config';
|
|
43
57
|
|
|
58
|
+
// Constant-time compare; timingSafeEqual throws on unequal lengths, so check length first.
|
|
59
|
+
function authKeyMatches(given) {
|
|
60
|
+
const { authKey } = config.sockets;
|
|
61
|
+
if (typeof authKey !== 'string' || authKey === '' || typeof given !== 'string') return false;
|
|
62
|
+
|
|
63
|
+
const a = Buffer.from(given), b = Buffer.from(authKey);
|
|
64
|
+
return a.length === b.length && timingSafeEqual(a, b);
|
|
65
|
+
}
|
|
66
|
+
|
|
44
67
|
export default class AuthHandler extends Handler {
|
|
45
68
|
static skipAuth = true; // auth handler must work before authentication
|
|
46
69
|
|
|
47
70
|
server(data, client) {
|
|
48
|
-
if (data
|
|
71
|
+
if (!authKeyMatches(data?.authKey)) return client.close();
|
|
49
72
|
|
|
50
73
|
this._serverRef.clientMap.set(client.id, client);
|
|
51
74
|
return 'success';
|
|
52
75
|
}
|
|
53
76
|
|
|
54
77
|
client(response) {
|
|
55
|
-
if (response !== 'success') this.client.promise.reject(response);
|
|
78
|
+
if (response !== 'success') return this.client.promise.reject(response);
|
|
56
79
|
this.client.promise.resolve();
|
|
57
80
|
}
|
|
58
81
|
}
|
|
@@ -206,10 +229,14 @@ Configuration is read from `stonyx/config` under `sockets`:
|
|
|
206
229
|
|--------|---------|---------|-------------|
|
|
207
230
|
| `port` | `SOCKET_PORT` | `2667` | WebSocket server port |
|
|
208
231
|
| `address` | `SOCKET_ADDRESS` | `ws://localhost:2667` | Client connection address |
|
|
209
|
-
| `authKey` | `SOCKET_AUTH_KEY` | `'AUTH_KEY'` | Shared authentication key |
|
|
232
|
+
| `authKey` | `SOCKET_AUTH_KEY` | `'AUTH_KEY'` | Shared authentication key; set it in production (see the [security notes](https://github.com/abofs/stonyx-sockets/blob/dev/docs/encryption.md#security-notes)) |
|
|
210
233
|
| `heartBeatInterval` | `SOCKET_HEARTBEAT_INTERVAL` | `30000` | Heartbeat interval in ms |
|
|
211
234
|
| `handlerDir` | `SOCKET_HANDLER_DIR` | `'./socket-handlers'` | Handler directory path |
|
|
212
235
|
| `encryption` | `SOCKET_ENCRYPTION` | `'true'` | Enable AES-256-GCM encryption |
|
|
236
|
+
| `authData` | — | `{}` | Extra fields sent with `authKey` in the auth request |
|
|
237
|
+
| `reconnectBaseDelay` | `SOCKET_RECONNECT_BASE_DELAY` | `1000` | First reconnect delay in ms (doubles per attempt) |
|
|
238
|
+
| `reconnectMaxDelay` | `SOCKET_RECONNECT_MAX_DELAY` | `60000` | Reconnect delay cap in ms |
|
|
239
|
+
| `maxReconnectAttempts` | `SOCKET_MAX_RECONNECT_ATTEMPTS` | `Infinity` | Attempts before `onReconnectFailed` |
|
|
213
240
|
|
|
214
241
|
## API Reference
|
|
215
242
|
|
|
@@ -220,7 +247,9 @@ Configuration is read from `stonyx/config` under `sockets`:
|
|
|
220
247
|
| `new SocketServer()` | Singleton constructor |
|
|
221
248
|
| `async init()` | Discover handlers, validate auth, start WebSocket server |
|
|
222
249
|
| `sendTo(clientId, request, data)` | Send to one client by ID |
|
|
250
|
+
| `sendToByMeta(key, value, request, data)` | Send to the first authenticated client whose `meta[key] === value`; returns `true`/`false` |
|
|
223
251
|
| `broadcast(request, data)` | Send to all authenticated clients |
|
|
252
|
+
| `onClientDisconnect` | Optional `(client, code, reason)` callback |
|
|
224
253
|
| `clientMap` | `Map<id, client>` of connected clients |
|
|
225
254
|
| `close()` | Terminate all connections and stop the server |
|
|
226
255
|
| `reset()` | Close + clear all state (for testing) |
|
|
@@ -233,7 +262,8 @@ Configuration is read from `stonyx/config` under `sockets`:
|
|
|
233
262
|
| `async init()` | Discover handlers, connect, authenticate |
|
|
234
263
|
| `send(payload)` | Send a message to the server |
|
|
235
264
|
| `close()` | Forcefully tear down the socket (remove listeners, terminate, null) |
|
|
236
|
-
| `reconnect()` | Reconnect (
|
|
265
|
+
| `reconnect()` | Reconnect with exponential backoff, up to `maxReconnectAttempts` (unlimited by default) |
|
|
266
|
+
| `onDisconnect`, `onReconnecting`, `onReconnected`, `onReconnectFailed` | Optional lifecycle callbacks |
|
|
237
267
|
| `reset()` | Close + clear all state (for testing) |
|
|
238
268
|
|
|
239
269
|
### Handler
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"stonyx-async",
|
|
5
5
|
"stonyx-module"
|
|
6
6
|
],
|
|
7
|
-
"version": "0.1.1-beta.
|
|
7
|
+
"version": "0.1.1-beta.74",
|
|
8
8
|
"description": "WebSocket server and client module for the Stonyx framework",
|
|
9
9
|
"main": "dist/main.js",
|
|
10
10
|
"types": "dist/main.d.ts",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"homepage": "https://github.com/abofs/stonyx-sockets#readme",
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"stonyx": "0.2.3-beta.
|
|
54
|
+
"stonyx": "0.2.3-beta.103",
|
|
55
55
|
"ws": "^8.18.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|