insite-ws 2.3.5 → 2.4.1
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/LICENSE +1 -1
- package/README.md +255 -4
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +4 -4
- package/dist/client/node/index.js +1 -1
- package/dist/client/node/index.js.map +4 -4
- package/dist/server/WSSCWithUser.d.ts +10 -0
- package/dist/server/WSSCWithUser.d.ts.map +1 -0
- package/dist/server/WSServerClient.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -6
- package/dist/server/index.js.map +4 -4
- package/package.json +52 -39
- package/dist/server/common.d.ts +0 -2
- package/dist/server/common.d.ts.map +0 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,13 +1,264 @@
|
|
|
1
|
-
#
|
|
1
|
+
# insite-ws
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/insite-ws)
|
|
4
|
+
|
|
5
|
+
WebSocket abstraction for the inSite stack. Server and client with heartbeat, request/response protocol, and connection quality tracking.
|
|
6
|
+
|
|
7
|
+
Part of [inSite](../../README.md) — used by [insite-ws-transfers](../ws-transfers/README.md), [insite-users-server-ws](../users-server-ws/README.md), [insite-subscriptions-server](../subscriptions-server/README.md), [insite-cookie](../cookie/README.md).
|
|
2
8
|
|
|
3
9
|
## Installation
|
|
4
10
|
|
|
5
11
|
```sh
|
|
6
|
-
|
|
12
|
+
npm install insite-ws
|
|
7
13
|
```
|
|
8
14
|
|
|
9
|
-
Or
|
|
15
|
+
Or:
|
|
10
16
|
|
|
11
17
|
```sh
|
|
12
|
-
|
|
18
|
+
bun add insite-ws
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
The package provides three entry points:
|
|
24
|
+
|
|
25
|
+
| Entry | Environment | Description |
|
|
26
|
+
|-------|-------------|-------------|
|
|
27
|
+
| `insite-ws/server` | Node.js | WebSocket server with heartbeat and request handlers |
|
|
28
|
+
| `insite-ws/client` | Browser, Bun | WebSocket client with auto-reconnect and request/response |
|
|
29
|
+
| `insite-ws/client/node` | Node.js | Same client; polyfills `globalThis.WebSocket` with `ws` |
|
|
30
|
+
|
|
31
|
+
**Message format:** JSON arrays. First element is the message kind; the rest are payload. Example: `["my-event", { id: 1 }]`.
|
|
32
|
+
|
|
33
|
+
**Request/response:** Built-in RPC uses `~r-q` (request) and `~r-s` (response) as message kinds. Client sends `["~r-q", id, kind, ...args]`; server replies with `["~r-s-{id}", error, result]`.
|
|
34
|
+
|
|
35
|
+
**Heartbeat:** Empty frames sent every 5 seconds. Missing heartbeat triggers disconnect after timeout.
|
|
36
|
+
|
|
37
|
+
## Server API (`insite-ws/server`)
|
|
38
|
+
|
|
39
|
+
### Exports
|
|
40
|
+
|
|
41
|
+
| Export | Type | Description |
|
|
42
|
+
|--------|------|-------------|
|
|
43
|
+
| `WSServer` | class | WebSocket server |
|
|
44
|
+
| `WSServerClient` | class | WebSocket client (extends `ws` WebSocket) |
|
|
45
|
+
| `Options` | type | Constructor options for `WSServer` |
|
|
46
|
+
|
|
47
|
+
### WSServer
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { WSServer } from "insite-ws/server";
|
|
51
|
+
|
|
52
|
+
const wss = new WSServer({ port: 8080 });
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Constructor:** `new WSServer(options: Options<WSSC>)`
|
|
56
|
+
|
|
57
|
+
**Options:**
|
|
58
|
+
|
|
59
|
+
| Option | Type | Default | Description |
|
|
60
|
+
|--------|------|---------|-------------|
|
|
61
|
+
| `icon` | `string` | `"🔌"` | Icon for console logs |
|
|
62
|
+
| `name` | `string` | `"WS"` | Server name |
|
|
63
|
+
| `ssl` | `{ cert, key }` | — | TLS config (Buffer or string) |
|
|
64
|
+
| `port` | `number \| string` | 80/443 | Port to listen on |
|
|
65
|
+
| `server` | `http.Server \| https.Server` | — | Existing HTTP server; if omitted, one is created |
|
|
66
|
+
| `quiet` | `boolean` | `false` | Suppress console output |
|
|
67
|
+
| `WebSocket` | class | `WSServerClient` | Custom client class |
|
|
68
|
+
|
|
69
|
+
Also accepts `ws` `ServerOptions` (e.g. `path`, `verifyClient`).
|
|
70
|
+
|
|
71
|
+
**Properties:**
|
|
72
|
+
|
|
73
|
+
| Property | Type | Description |
|
|
74
|
+
|----------|------|-------------|
|
|
75
|
+
| `icon` | `string` | Icon for logs |
|
|
76
|
+
| `name` | `string` | Server name |
|
|
77
|
+
| `protocol` | `getter` | `"ws"` or `"wss"` |
|
|
78
|
+
| `server` | `http.Server \| https.Server` | Underlying HTTP server |
|
|
79
|
+
| `isS` | `getter` | `true` if HTTPS |
|
|
80
|
+
| `isWebSocketServer` | `true` | Type guard |
|
|
81
|
+
| `isWebSocketServerClient` | `false` | Type guard |
|
|
82
|
+
| `isWebSocket` | `false` | Type guard |
|
|
83
|
+
|
|
84
|
+
**Methods:**
|
|
85
|
+
|
|
86
|
+
| Method | Description |
|
|
87
|
+
|--------|--------------|
|
|
88
|
+
| `addRequestListener(kind, listener)` | Register handler for request kind. `listener(wssc, ...args)` returns result or throws. |
|
|
89
|
+
| `removeRequestListener(kind)` | Unregister handler |
|
|
90
|
+
| `onRequest` | Alias for `addRequestListener` |
|
|
91
|
+
| `offRequest` | Alias for `removeRequestListener` |
|
|
92
|
+
|
|
93
|
+
**Static:**
|
|
94
|
+
|
|
95
|
+
| Method/Property | Description |
|
|
96
|
+
|-----------------|--------------|
|
|
97
|
+
| `makeProps({ ssl })` | Returns HTTP server options from `ssl` |
|
|
98
|
+
| `CLOSE_CODES` | See close codes below |
|
|
99
|
+
|
|
100
|
+
**Events:**
|
|
101
|
+
|
|
102
|
+
| Event | Args | Description |
|
|
103
|
+
|-------|------|-------------|
|
|
104
|
+
| `connection` | `(socket, request)` | From `ws`; socket is `WSServerClient` |
|
|
105
|
+
| `client-connect` | `(wssc, request)` | Client connected |
|
|
106
|
+
| `client-error` | `(wssc, error?)` | Client error |
|
|
107
|
+
| `client-close` | `(wssc)` | Client disconnected |
|
|
108
|
+
| `client-message` | `(wssc, kind, ...rest)` | Any message |
|
|
109
|
+
| `client-message:${kind}` | `(wssc, ...rest)` | Message of specific kind |
|
|
110
|
+
|
|
111
|
+
### WSServerClient
|
|
112
|
+
|
|
113
|
+
Extends `WebSocket` from `ws`. Each connected client is an instance.
|
|
114
|
+
|
|
115
|
+
**Properties:**
|
|
116
|
+
|
|
117
|
+
| Property | Type | Description |
|
|
118
|
+
|----------|------|-------------|
|
|
119
|
+
| `wss` | `WSServer<this>` | Parent server |
|
|
120
|
+
| `userAgent` | `string` | From request headers |
|
|
121
|
+
| `remoteAddress` | `string` | Client IP |
|
|
122
|
+
| `latency` | `number` | Last heartbeat round-trip (ms) |
|
|
123
|
+
| `isConnecting` | `getter` | `readyState === CONNECTING` |
|
|
124
|
+
| `isOpen` | `getter` | `readyState === OPEN` |
|
|
125
|
+
| `isClosing` | `getter` | `readyState === CLOSING` |
|
|
126
|
+
| `isClosed` | `getter` | `readyState === CLOSED` |
|
|
127
|
+
| `isWebSocketServerClient` | `true` | Type guard |
|
|
128
|
+
| `isWebSocketServer` | `false` | Type guard |
|
|
129
|
+
| `isWebSocket` | `false` | Type guard |
|
|
130
|
+
|
|
131
|
+
**Methods:**
|
|
132
|
+
|
|
133
|
+
| Method | Description |
|
|
134
|
+
|--------|--------------|
|
|
135
|
+
| `sendMessage(...args)` | Sends `JSON.stringify(args)` |
|
|
136
|
+
| `sendRequest(...args)` | RPC. Last arg can be callback `(error, result) => void`; otherwise returns `Promise<unknown>` |
|
|
137
|
+
|
|
138
|
+
**Static:** `CLOSE_CODES` — same as `WSServer.CLOSE_CODES`
|
|
139
|
+
|
|
140
|
+
## Client API (`insite-ws/client`)
|
|
141
|
+
|
|
142
|
+
### Exports
|
|
143
|
+
|
|
144
|
+
| Export | Type | Description |
|
|
145
|
+
|--------|------|-------------|
|
|
146
|
+
| `WS` | class | WebSocket client |
|
|
147
|
+
| `Options` | type | Constructor options |
|
|
148
|
+
|
|
149
|
+
### WS
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { WS } from "insite-ws/client";
|
|
153
|
+
|
|
154
|
+
const ws = new WS({ url: "wss://example.com" });
|
|
155
|
+
ws.on("open", () => ws.sendMessage("hello", { data: 1 }));
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Constructor:** `new WS(options?: Options)`
|
|
159
|
+
|
|
160
|
+
**Options:**
|
|
161
|
+
|
|
162
|
+
| Option | Type | Default | Description |
|
|
163
|
+
|--------|------|---------|-------------|
|
|
164
|
+
| `url` | `URL \| string` | `globalThis.__insite?.wss_url \|\| "/"` | WebSocket URL |
|
|
165
|
+
| `name` | `string` | `"0"`, `"1"`, … | Client name (for logs) |
|
|
166
|
+
| `protocols` | `string[]` | — | Subprotocols |
|
|
167
|
+
| `immediately` | `boolean` | `true` | Connect on construction |
|
|
168
|
+
| `reconnectAfter` | `number \| null` | `2000` | Reconnect delay (ms); `null` disables |
|
|
169
|
+
| `on` | `Record<string, Function>` | — | Event listeners to attach |
|
|
170
|
+
| `once` | `Record<string, Function>` | — | One-time listeners |
|
|
171
|
+
| `quiet` | `boolean` | `false` | Suppress console output |
|
|
172
|
+
| `signal` | `AbortSignal` | — | Abort on signal |
|
|
173
|
+
|
|
174
|
+
**Properties:**
|
|
175
|
+
|
|
176
|
+
| Property | Type | Description |
|
|
177
|
+
|----------|------|-------------|
|
|
178
|
+
| `url` | `string \| URL` | Current URL |
|
|
179
|
+
| `name` | `string` | Client name |
|
|
180
|
+
| `protocols` | `string[] \| undefined` | Subprotocols |
|
|
181
|
+
| `reconnectAfter` | `number \| null` | Reconnect delay |
|
|
182
|
+
| `connectionQuality` | `ConnectionQuality` | 0–4; see `CONNECTION_QUALITY` |
|
|
183
|
+
| `webSocket` | `WebSocket \| null` | Underlying socket |
|
|
184
|
+
| `state` | `getter` | `"connecting" \| "open" \| "unresponsive" \| "closing" \| "closed"` |
|
|
185
|
+
| `isConnecting` | `getter` | `true` when connecting |
|
|
186
|
+
| `isOpen` | `getter` | `true` when open |
|
|
187
|
+
| `isClosing` | `getter` | `true` when closing |
|
|
188
|
+
| `isClosed` | `getter` | `true` when closed |
|
|
189
|
+
| `closedWith` | `{ code, reason, wasClean } \| null` | Last close info |
|
|
190
|
+
| `isUsed` | `boolean` | Set after first connect |
|
|
191
|
+
| `isDestroyed` | `boolean` | If `destroy()` was called |
|
|
192
|
+
| `isWebSocket` | `true` | Type guard |
|
|
193
|
+
| `isWebSocketServer` | `false` | Type guard |
|
|
194
|
+
| `isWebSocketServerClient` | `false` | Type guard |
|
|
195
|
+
|
|
196
|
+
**Methods:**
|
|
197
|
+
|
|
198
|
+
| Method | Description |
|
|
199
|
+
|--------|--------------|
|
|
200
|
+
| `open(options?)` | Connect. `options` can override `url` and `protocols`. Returns `Promise<void>`. |
|
|
201
|
+
| `connect` | Alias for `open` |
|
|
202
|
+
| `close(code?, reason?, wasClean?)` | Close connection. Defaults: `code=3500`, `reason="manual"`, `wasClean=true` |
|
|
203
|
+
| `disconnect` | Alias for `close` |
|
|
204
|
+
| `send(data)` | Send raw data (string, Blob, ArrayBuffer, etc.) |
|
|
205
|
+
| `sendMessage(...args)` | Sends `JSON.stringify(args)` |
|
|
206
|
+
| `sendRequest(...args)` | RPC. Last arg can be callback `(error, result) => void`; otherwise returns `Promise<T>`. |
|
|
207
|
+
| `addRequestListener(kind, listener)` | Register handler for request kind. `listener(...args)` returns result or throws. |
|
|
208
|
+
| `removeRequestListener(kind)` | Unregister handler |
|
|
209
|
+
| `onRequest` | Alias for `addRequestListener` |
|
|
210
|
+
| `offRequest` | Alias for `removeRequestListener` |
|
|
211
|
+
| `destroy()` | Close, remove listeners, mark destroyed |
|
|
212
|
+
|
|
213
|
+
**Static:**
|
|
214
|
+
|
|
215
|
+
| Property | Description |
|
|
216
|
+
|----------|-------------|
|
|
217
|
+
| `CONNECTION_QUALITY` | `{ CLOSED: 0, RECONNECTING: 1, UNRESPONSIVE: 2, CHECKING_RESPONSIVENESS: 3, OPEN: 4 }` |
|
|
218
|
+
|
|
219
|
+
**Events:**
|
|
220
|
+
|
|
221
|
+
| Event | Args | Description |
|
|
222
|
+
|-------|------|-------------|
|
|
223
|
+
| `connecting` | — | Connection attempt started |
|
|
224
|
+
| `open` | — | Connected |
|
|
225
|
+
| `close` | `(closeEvent)` | Disconnected |
|
|
226
|
+
| `message` | `(kind, ...rest)` | Any message |
|
|
227
|
+
| `message:${kind}` | `(...rest)` | Message of specific kind |
|
|
228
|
+
| `error` | `(error)` | Error |
|
|
229
|
+
| `responsive` | — | Was unresponsive, now responsive |
|
|
230
|
+
| `unresponsive` | — | No heartbeat response; may be offline |
|
|
231
|
+
| `connection-quality-change` | `(quality, prevQuality)` | Connection quality changed |
|
|
232
|
+
| `server-change` | `(url, prevUrl)` | URL changed before connect |
|
|
233
|
+
| `destroy` | — | `destroy()` called |
|
|
234
|
+
|
|
235
|
+
## Client (Node) (`insite-ws/client/node`)
|
|
236
|
+
|
|
237
|
+
Re-exports everything from `insite-ws/client`. Importing this module polyfills `globalThis.WebSocket` with the `ws` package, so `WS` works in Node.js without a native WebSocket.
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
import { WS } from "insite-ws/client/node";
|
|
241
|
+
// globalThis.WebSocket is now set
|
|
13
242
|
```
|
|
243
|
+
|
|
244
|
+
## Close Codes
|
|
245
|
+
|
|
246
|
+
`WSServer.CLOSE_CODES` and `WSServerClient.CLOSE_CODES`:
|
|
247
|
+
|
|
248
|
+
| Code | Value | Description |
|
|
249
|
+
|------|-------|-------------|
|
|
250
|
+
| `NORMAL` | 1000 | Normal closure |
|
|
251
|
+
| `PROTOCOL_ERROR` | 1002 | Protocol error |
|
|
252
|
+
| `ABNORMAL` | 1006 | Abnormal closure |
|
|
253
|
+
| `NO_HEARTBEAT` | 3000 | No heartbeat received |
|
|
254
|
+
| `OFFLINE` | 3001 | Client went offline |
|
|
255
|
+
| `MANUAL` | 3500 | Manual close |
|
|
256
|
+
| `REOPEN` | 4000 | Reconnecting (e.g. URL change) |
|
|
257
|
+
|
|
258
|
+
## Related
|
|
259
|
+
|
|
260
|
+
- [insite-ws-transfers](../ws-transfers/README.md), [insite-users-server-ws](../users-server-ws/README.md), [insite-subscriptions-server](../subscriptions-server/README.md), [insite-cookie](../cookie/README.md)
|
|
261
|
+
|
|
262
|
+
## License
|
|
263
|
+
|
|
264
|
+
MIT
|
package/dist/client/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var ae=Object.defineProperty;var ne=r=>{throw TypeError(r)};var he=(r,i,e)=>i in r?ae(r,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[i]=e;var c=(r,i,e)=>he(r,typeof i!="symbol"?i+"":i,e),X=(r,i,e)=>i.has(r)||ne("Cannot "+e);var n=(r,i,e)=>(X(r,i,"read from private field"),e?e.call(r):i.get(r)),f=(r,i,e)=>i.has(r)?ne("Cannot add the same private member more than once"):i instanceof WeakSet?i.add(r):i.set(r,e),l=(r,i,e,t)=>(X(r,i,"write to private field"),t?t.call(r,e):i.set(r,e),e),x=(r,i,e)=>(X(r,i,"access private method"),e);var re=(r,i,e,t)=>({set _(o){l(r,i,o,e)},get _(){return n(r,i,t)}});import xe from"eventemitter3";function g(){}var q=new WeakMap,A=class r extends Promise{constructor(e,t){let o,a;super((s,u)=>{o=s,a=u});c(this,"isPending",!0);c(this,"isFulfilled",!1);c(this,"isRejected",!1);c(this,"state","pending");c(this,"result");c(this,"resolve",e=>{if(this.isPending){this.isPending=!1,this.isFulfilled=!0,this.state="fulfilled",this.result=e;let t=q.get(this);t&&(t.resolve.call(this,e),q.delete(this))}});c(this,"reject",e=>{if(this.isPending){this.isPending=!1,this.isRejected=!0,this.state="rejected",this.result=e;let t=q.get(this);t&&(t.reject.call(this,e),q.delete(this))}});if(q.set(this,{resolve:o,reject:a}),t?.signal)if(t.signal.aborted)this.reject(new DOMException("Aborted","AbortError"));else{let s=()=>this.reject(new DOMException("Aborted","AbortError"));t.signal.addEventListener("abort",s),this.finally(()=>t.signal?.removeEventListener("abort",s))}if(typeof t?.timeout=="number"&&Number.isFinite(t.timeout)){let s=setTimeout(()=>this.reject(new DOMException("Timeout exceeded","TimeoutError")),t.timeout);this.finally(()=>clearTimeout(s))}e?.(this.resolve,this.reject)}static resolved(e){return new r(t=>t(e))}static rejected(e){return new r((t,o)=>o(e))}};function de(r,i=0,e={}){let{leading:t=!1,trailing:o=!0}=e,{maxWait:a=1/0}=e,s,u,d,E,k,S,h,J,te=async()=>{let b=Date.now();b>=d?(s=void 0,d=void 0,clearTimeout(u),u=void 0,typeof h=="function"&&await h(),w.resolve(J),S=t):(clearTimeout(s),s=setTimeout(te,d-b))},z=Number.isFinite(a)?()=>{h===L&&(h=!1),L(),u=setTimeout(z,a)}:null;async function L(){try{return J=await r.apply(E,k),J}catch(b){throw w.reject(b),b}}t&&typeof t=="boolean"&&(t=L),S=t,o&&typeof o=="boolean"&&(o=L),h=o;let w=Object.assign(function(...b){return k=b,E=this,d=Date.now()+i,h=o,w.promise.isPending||(w.promise=new A((ue,fe)=>{w.resolve=ue,w.reject=fe,typeof S=="function"&&(S(),S=!1,h===L&&(h=!1)),s||(s=setTimeout(te,i),z&&(u=setTimeout(z,a)))})),w.promise},{callback:r,promise:A.resolved(void 0),resolve:g,reject:g,run:L,clear:async b=>{clearTimeout(s),s=void 0,clearTimeout(u),u=void 0,w.resolve(b?await L():J)}});return w}de.noop=Object.assign(()=>{},{callback:g,promise:A.resolved(void 0),resolve:g,reject:g,run:g,clear:g});function oe(r,i,e,t,o=!0){return Array.isArray(r)&&(r=r.length),typeof t!="string"&&(o=t??!0,t=e),(o?`${r}\xA0`:"")+oe.raw(r,i,e,t)}oe.raw=(r,i,e,t=e)=>{r=Math.abs(r);let o=r%10,a=r%100;return o===1&&a!==11?i:o>=2&&o<=4&&!(a>=12&&a<=15)?e:t};var ie=Number.MAX_SAFE_INTEGER/2,y={NORMAL:1e3,PROTOCOL_ERROR:1002,ABNORMAL:1006,NO_HEARTBEAT:3e3,OFFLINE:3001,MANUAL:3500,REOPEN:4e3},se=[y.PROTOCOL_ERROR,y.MANUAL,y.REOPEN],j={REQUEST:"~r-q",RESPONSE:"~r-s"};var ge=0,$,M,m,_,R,Z,T,C,O,v,p,U,F,V,D,P,ee,W,G,I,Y,B,Q,K,H,N=class N extends xe{constructor(e={}){super();f(this,m);c(this,"isWebSocket",!0);c(this,"isWebSocketServer",!1);c(this,"isWebSocketServerClient",!1);c(this,"url");c(this,"name");c(this,"protocols");c(this,"reconnectAfter");f(this,$);f(this,M);c(this,"isUsed",!1);c(this,"connectionQuality",0);c(this,"webSocket",null);f(this,R);f(this,T);f(this,C,!1);f(this,O);f(this,v,!1);c(this,"isDestroyed",!1);f(this,p);f(this,U,!1);f(this,F,()=>{l(this,U,!0),this.closedWith=null,n(this,p).resolve(),x(this,m,Z).call(this),this.emit("open")});f(this,V,({data:e})=>{if(x(this,m,Z).call(this),e){if(e!=="!")try{let[t,...o]=JSON.parse(e);switch(t){case j.REQUEST:n(this,K).call(this,...o);break;default:this.emit("message",t,...o),this.emit(`message:${t}`,...o)}}catch(t){n(this,D).call(this,t)}}else this.webSocket.send("")});f(this,D,e=>{e instanceof Event&&(e=void 0),n(this,p)?.isPending&&n(this,p).reject(e),this.emit("error",e)});f(this,P);f(this,W,e=>{let{code:t,reason:o,wasClean:a}=e;if(this.closedWith={code:t,reason:o,wasClean:a},n(this,R)&&(clearTimeout(n(this,R)),l(this,R,void 0)),n(this,T)&&(clearTimeout(n(this,T)),l(this,T,void 0)),l(this,C,!1),n(this,O)&&(clearTimeout(n(this,O)),l(this,O,void 0)),l(this,v,!1),n(this,p)?.isPending&&n(this,p).reject(new Error("Closed")),process.env.NODE_ENV==="development"&&!n(this,$)){let u=`\u{1F50C} WS ${this.name} is closed`;switch(t&&(u+=` with code ${t}`),t&&o&&(u+=" and"),o&&(u+=` reason "${o}"`),o){case"no-heartbeat":u+=". Going offline"}!a||t===y.ABNORMAL?(u+=" [UNEXPECTED]",console.warn(u)):console.info(u)}let s=this.webSocket;s.removeEventListener("open",n(this,F)),s.removeEventListener("message",n(this,V)),s.removeEventListener("error",n(this,D)),n(this,U)&&(this.emit("close",e),l(this,U,!1)),this.webSocket=null,x(this,m,ee).call(this,t),"navigator"in globalThis&&"addEventListener"in globalThis&&globalThis.removeEventListener("offline",n(this,H))});f(this,G,()=>n(this,p)?.isPending&&n(this,p).reject(new DOMException("Operation aborted","AbortError")));c(this,"connect",this.open);c(this,"closedWith",null);c(this,"disconnect",this.close);f(this,I,[]);f(this,Y,()=>{for(let e of n(this,I))this.webSocket.send(e);n(this,I).length=0});f(this,B,0);f(this,Q,new Map);c(this,"onRequest",this.addRequestListener);c(this,"offRequest",this.removeRequestListener);f(this,K,async(e,t,...o)=>{let a=n(this,Q).get(t),s,u=null;if(a)try{s=await a.apply(this,o)}catch(d){if(d instanceof Error){let{message:E,...k}=d;u={message:E,...k}}}else u={message:`Unknown request kind "${t}"`};this.sendMessage(`${j.RESPONSE}-${e}`,u,s)});f(this,H,()=>{this.isOpen&&!n(this,C)&&(l(this,C,!0),x(this,m,_).call(this,N.CONNECTION_QUALITY.CHECKING_RESPONSIVENESS),l(this,T,setTimeout(()=>{l(this,C,!1),l(this,v,!0),x(this,m,_).call(this,N.CONNECTION_QUALITY.UNRESPONSIVE),this.emit("unresponsive"),l(this,O,setTimeout(()=>{l(this,v,!1),this.close(y.OFFLINE,"offline",!1)},4e3))},1e3)),this.webSocket.send("?"))});let{url:t=globalThis.__insite?.wss_url||"/",name:o=(ge++).toString(),protocols:a,immediately:s=!0,reconnectAfter:u=2e3,on:d,once:E,quiet:k=!1,signal:S}=e;if(this.url=t,this.name=o,this.protocols=a,this.reconnectAfter=u,d)for(let h in d)d[h]&&this.on(h,d[h]);if(E)for(let h in E)E[h]&&this.once(h,E[h]);l(this,$,k),l(this,M,S),n(this,M)?.addEventListener("abort",n(this,G),{once:!0}),this.url&&s&&this.open().catch(g),n(this,$)||this.on("error",h=>h&&console.error("\u{1F50C}\u2757\uFE0F WS",`${this.name}:`,h))}on(e,t){return super.on(e,t)}get state(){if(!this.webSocket)return"closed";switch(this.webSocket.readyState){case WebSocket.CONNECTING:return"connecting";case WebSocket.OPEN:return n(this,v)?"unresponsive":"open";case WebSocket.CLOSING:return"closing"}return"closed"}get isConnecting(){return this.webSocket?.readyState===WebSocket.CONNECTING}get isOpen(){return this.webSocket?.readyState===WebSocket.OPEN}get isClosing(){return this.webSocket?.readyState===WebSocket.CLOSING}get isClosed(){return!this.webSocket}async open(e={}){if(this.isDestroyed)throw new Error("WS has been destroyed");if(n(this,M)?.aborted)throw new DOMException("Operation aborted","AbortError");if(this.closedWith=null,n(this,p)?.isPending)return n(this,p);this.isUsed?this.close(y.REOPEN,"reopen"):this.isUsed=!0;let t;return e.url&&this.url!==e.url&&(t=this.url,this.url=e.url),e.protocols&&(this.protocols=e.protocols),l(this,p,new A((o,a)=>{if(this.url){let s=new WebSocket(this.url,this.protocols);s.addEventListener("open",n(this,F),{once:!0}),s.addEventListener("message",n(this,V)),s.addEventListener("error",n(this,D)),s.addEventListener("close",n(this,W),{once:!0}),this.webSocket=s,t&&this.emit("server-change",this.url,t),this.emit("connecting"),"navigator"in globalThis&&"addEventListener"in globalThis&&globalThis.addEventListener("offline",n(this,H))}else this.webSocket=null,a(new Error("url prop is not set"))})),n(this,p)}close(e=y.MANUAL,t="manual",o=!0){this.isClosed?x(this,m,ee).call(this,e):(this.webSocket.removeEventListener("close",n(this,W)),this.webSocket.close(e,t),n(this,W).call(this,Object.assign(new Event("close"),{code:e,reason:t,wasClean:o})))}send(e){this.isOpen?this.webSocket.send(e):(n(this,I).length||this.once("open",n(this,Y)),n(this,I).push(e))}sendMessage(...e){return this.send(JSON.stringify(e))}sendRequest(...e){let t=re(this,B)._++;n(this,B)>=ie&&l(this,B,0);let o=`message:${j.RESPONSE}-${t}`,a=e.at(-1);return typeof a=="function"?(this.once(o,a),this.sendMessage(j.REQUEST,t,...e.slice(0,-1)),this):new Promise((s,u)=>{this.once(o,(d,E)=>{if(d){let{message:k,...S}=d;u(Object.assign(new Error(k),S))}else s(E)}),this.sendMessage(j.REQUEST,t,...e)})}addRequestListener(e,t){return n(this,Q).set(e,t),this}removeRequestListener(e){return n(this,Q).delete(e),this}destroy(){this.isDestroyed=!0,n(this,I).length=0,this.close(y.NORMAL,"destroy"),this.emit("destroy"),this.removeAllListeners(),n(this,M)?.removeEventListener("abort",n(this,G))}};$=new WeakMap,M=new WeakMap,m=new WeakSet,_=function(e){if(e!==this.connectionQuality){let t=this.connectionQuality;this.connectionQuality=e,this.emit("connection-quality-change",this.connectionQuality,t)}},R=new WeakMap,Z=function(){clearTimeout(n(this,R)),l(this,R,setTimeout(()=>this.close(y.NO_HEARTBEAT,"no-heartbeat",!1),35e3)),n(this,T)&&(clearTimeout(n(this,T)),l(this,T,void 0)),l(this,C,!1),n(this,O)&&(clearTimeout(n(this,O)),l(this,O,void 0)),n(this,v)&&(l(this,v,!1),this.emit("responsive")),x(this,m,_).call(this,N.CONNECTION_QUALITY.OPEN)},T=new WeakMap,C=new WeakMap,O=new WeakMap,v=new WeakMap,p=new WeakMap,U=new WeakMap,F=new WeakMap,V=new WeakMap,D=new WeakMap,P=new WeakMap,ee=function(e){n(this,P)&&clearTimeout(n(this,P)),this.reconnectAfter&&!se.includes(e)?(process.env.NODE_ENV==="development"&&!n(this,$)&&console.info(`\u{1F50C} WS ${this.name} will try to reconnect in ${Math.round(this.reconnectAfter/1e3)} seconds`),l(this,P,setTimeout(()=>this.open().catch(g),this.reconnectAfter)),x(this,m,_).call(this,N.CONNECTION_QUALITY.RECONNECTING)):(l(this,P,void 0),x(this,m,_).call(this,e===y.REOPEN?N.CONNECTION_QUALITY.RECONNECTING:N.CONNECTION_QUALITY.CLOSED))},W=new WeakMap,G=new WeakMap,I=new WeakMap,Y=new WeakMap,B=new WeakMap,Q=new WeakMap,K=new WeakMap,H=new WeakMap,c(N,"CONNECTION_QUALITY",{CLOSED:0,RECONNECTING:1,UNRESPONSIVE:2,CHECKING_RESPONSIVENESS:3,OPEN:4});var le=N;export{le as WS};
|
|
1
|
+
var ee=Object.defineProperty;var Y=i=>{throw TypeError(i)};var te=(i,n,e)=>n in i?ee(i,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[n]=e;var c=(i,n,e)=>te(i,typeof n!="symbol"?n+"":n,e),V=(i,n,e)=>n.has(i)||Y("Cannot "+e);var t=(i,n,e)=>(V(i,n,"read from private field"),e?e.call(i):n.get(i)),r=(i,n,e)=>n.has(i)?Y("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(i):n.set(i,e),o=(i,n,e,s)=>(V(i,n,"write to private field"),s?s.call(i,e):n.set(i,e),e),S=(i,n,e)=>(V(i,n,"access private method"),e);var j=(i,n,e,s)=>({set _(h){o(i,n,h,e)},get _(){return t(i,n,s)}});import oe from"eventemitter3";import{noop as z,StatefulPromise as re}from"@nesvet/n";var J=Number.MAX_SAFE_INTEGER/2,f={NORMAL:1e3,PROTOCOL_ERROR:1002,ABNORMAL:1006,NO_HEARTBEAT:3e3,OFFLINE:3001,MANUAL:3500,REOPEN:4e3},K=[f.PROTOCOL_ERROR,f.MANUAL,f.REOPEN],L={REQUEST:"~r-q",RESPONSE:"~r-s"};var he=0,y,k,u,w,g,H,O,R,m,b,E,I,q,W,_,A,F,P,x,C,D,U,Q,G,B,p=class p extends oe{constructor(e={}){super();r(this,u);c(this,"isWebSocket",!0);c(this,"isWebSocketServer",!1);c(this,"isWebSocketServerClient",!1);c(this,"url");c(this,"name");c(this,"protocols");c(this,"reconnectAfter");r(this,y);r(this,k);c(this,"isUsed",!1);c(this,"connectionQuality",0);c(this,"webSocket",null);r(this,g);r(this,O);r(this,R,!1);r(this,m);r(this,b,!1);c(this,"isDestroyed",!1);r(this,E);r(this,I,!1);r(this,q,()=>{o(this,I,!0),this.closedWith=null,t(this,E).resolve(),S(this,u,H).call(this),this.emit("open")});r(this,W,({data:e})=>{if(S(this,u,H).call(this),e){if(e!=="!")try{let[s,...h]=JSON.parse(e);s===L.REQUEST?t(this,G).call(this,...h):(this.emit("message",s,...h),this.emit(`message:${s}`,...h))}catch(s){t(this,_).call(this,s)}}else this.webSocket.send("")});r(this,_,e=>{e instanceof Event&&(e=void 0),t(this,E)?.isPending&&t(this,E).reject(e),this.emit("error",e)});r(this,A);r(this,P,e=>{let{code:s,reason:h,wasClean:d}=e;if(this.closedWith={code:s,reason:h,wasClean:d},t(this,g)&&(clearTimeout(t(this,g)),o(this,g,void 0)),t(this,O)&&(clearTimeout(t(this,O)),o(this,O,void 0)),o(this,R,!1),t(this,m)&&(clearTimeout(t(this,m)),o(this,m,void 0)),o(this,b,!1),t(this,E)?.isPending&&t(this,E).reject(new Error("Closed")),process.env.NODE_ENV==="development"&&!t(this,y)){let a=`\u{1F50C} WS ${this.name} is closed`;s&&(a+=` with code ${s}`),s&&h&&(a+=" and"),h&&(a+=` reason "${h}"`),h==="no-heartbeat"&&(a+=". Going offline"),!d||s===f.ABNORMAL?(a+=" [UNEXPECTED]",console.warn(a)):console.info(a)}let l=this.webSocket;l.removeEventListener("open",t(this,q)),l.removeEventListener("message",t(this,W)),l.removeEventListener("error",t(this,_)),t(this,I)&&(this.emit("close",e),o(this,I,!1)),this.webSocket=null,S(this,u,F).call(this,s),"navigator"in globalThis&&"addEventListener"in globalThis&&globalThis.removeEventListener("offline",t(this,B))});r(this,x,()=>t(this,E)?.isPending&&t(this,E).reject(new DOMException("Operation aborted","AbortError")));c(this,"connect",this.open);c(this,"closedWith",null);c(this,"disconnect",this.close);r(this,C,[]);r(this,D,()=>{for(let e of t(this,C))this.webSocket.send(e);t(this,C).length=0});r(this,U,0);r(this,Q,new Map);c(this,"onRequest",this.addRequestListener);c(this,"offRequest",this.removeRequestListener);r(this,G,async(e,s,...h)=>{let d=t(this,Q).get(s),l,a=null;if(d)try{l=await d.apply(this,h)}catch(N){if(N instanceof Error){let{message:v,...M}=N;a={message:v,...M}}}else a={message:`Unknown request kind "${s}"`};this.sendMessage(`${L.RESPONSE}-${e}`,a,l)});r(this,B,()=>{this.isOpen&&!t(this,R)&&(o(this,R,!0),S(this,u,w).call(this,p.CONNECTION_QUALITY.CHECKING_RESPONSIVENESS),o(this,O,setTimeout(()=>{o(this,R,!1),o(this,b,!0),S(this,u,w).call(this,p.CONNECTION_QUALITY.UNRESPONSIVE),this.emit("unresponsive"),o(this,m,setTimeout(()=>{o(this,b,!1),this.close(f.OFFLINE,"offline",!1)},4e3))},1e3)),this.webSocket.send("?"))});let{url:s=globalThis.__insite?.wss_url||"/",name:h=(he++).toString(),protocols:d,immediately:l=!0,reconnectAfter:a=2e3,on:N,once:v,quiet:M=!1,signal:$}=e;if(this.url=s,this.name=h,this.protocols=d,this.reconnectAfter=a,N)for(let T in N)N[T]&&this.on(T,N[T]);if(v)for(let T in v)v[T]&&this.once(T,v[T]);o(this,y,M),o(this,k,$),t(this,k)?.addEventListener("abort",t(this,x),{once:!0}),this.url&&l&&this.open().catch(z),t(this,y)||this.on("error",T=>T&&console.error("\u{1F50C}\u2757\uFE0F WS",`${this.name}:`,T))}on(e,s){return super.on(e,s)}get state(){if(!this.webSocket)return"closed";switch(this.webSocket.readyState){case WebSocket.CONNECTING:return"connecting";case WebSocket.OPEN:return t(this,b)?"unresponsive":"open";case WebSocket.CLOSING:return"closing"}return"closed"}get isConnecting(){return this.webSocket?.readyState===WebSocket.CONNECTING}get isOpen(){return this.webSocket?.readyState===WebSocket.OPEN}get isClosing(){return this.webSocket?.readyState===WebSocket.CLOSING}get isClosed(){return!this.webSocket}async open(e={}){if(this.isDestroyed)throw new Error("WS has been destroyed");if(t(this,k)?.aborted)throw new DOMException("Operation aborted","AbortError");if(this.closedWith=null,t(this,E)?.isPending)return t(this,E);this.isUsed?this.close(f.REOPEN,"reopen"):this.isUsed=!0;let s;return e.url&&this.url!==e.url&&(s=this.url,this.url=e.url),e.protocols&&(this.protocols=e.protocols),o(this,E,new re((h,d)=>{if(this.url){let l=new WebSocket(this.url,this.protocols);l.addEventListener("open",t(this,q),{once:!0}),l.addEventListener("message",t(this,W)),l.addEventListener("error",t(this,_)),l.addEventListener("close",t(this,P),{once:!0}),this.webSocket=l,s&&this.emit("server-change",this.url,s),this.emit("connecting"),"navigator"in globalThis&&"addEventListener"in globalThis&&globalThis.addEventListener("offline",t(this,B))}else this.webSocket=null,d(new Error("url prop is not set"))})),t(this,E)}close(e=f.MANUAL,s="manual",h=!0){this.isClosed?S(this,u,F).call(this,e):(this.webSocket.removeEventListener("close",t(this,P)),this.webSocket.close(e,s),t(this,P).call(this,Object.assign(new Event("close"),{code:e,reason:s,wasClean:h})))}send(e){this.isOpen?this.webSocket.send(e):(t(this,C).length||this.once("open",t(this,D)),t(this,C).push(e))}sendMessage(...e){return this.send(JSON.stringify(e))}sendRequest(...e){let s=j(this,U)._++;t(this,U)>=J&&o(this,U,0);let h=`message:${L.RESPONSE}-${s}`,d=e.at(-1);return typeof d=="function"?(this.once(h,d),this.sendMessage(L.REQUEST,s,...e.slice(0,-1)),this):new Promise((l,a)=>{this.once(h,(N,v)=>{if(N){let{message:M,...$}=N;a(Object.assign(new Error(M),$))}else l(v)}),this.sendMessage(L.REQUEST,s,...e)})}addRequestListener(e,s){return t(this,Q).set(e,s),this}removeRequestListener(e){return t(this,Q).delete(e),this}destroy(){this.isDestroyed=!0,t(this,C).length=0,this.close(f.NORMAL,"destroy"),this.emit("destroy"),this.removeAllListeners(),t(this,k)?.removeEventListener("abort",t(this,x))}};y=new WeakMap,k=new WeakMap,u=new WeakSet,w=function(e){if(e!==this.connectionQuality){let s=this.connectionQuality;this.connectionQuality=e,this.emit("connection-quality-change",this.connectionQuality,s)}},g=new WeakMap,H=function(){clearTimeout(t(this,g)),o(this,g,setTimeout(()=>this.close(f.NO_HEARTBEAT,"no-heartbeat",!1),35e3)),t(this,O)&&(clearTimeout(t(this,O)),o(this,O,void 0)),o(this,R,!1),t(this,m)&&(clearTimeout(t(this,m)),o(this,m,void 0)),t(this,b)&&(o(this,b,!1),this.emit("responsive")),S(this,u,w).call(this,p.CONNECTION_QUALITY.OPEN)},O=new WeakMap,R=new WeakMap,m=new WeakMap,b=new WeakMap,E=new WeakMap,I=new WeakMap,q=new WeakMap,W=new WeakMap,_=new WeakMap,A=new WeakMap,F=function(e){t(this,A)&&clearTimeout(t(this,A)),this.reconnectAfter&&!K.includes(e)?(process.env.NODE_ENV==="development"&&!t(this,y)&&console.info(`\u{1F50C} WS ${this.name} will try to reconnect in ${Math.round(this.reconnectAfter/1e3)} seconds`),o(this,A,setTimeout(()=>this.open().catch(z),this.reconnectAfter)),S(this,u,w).call(this,p.CONNECTION_QUALITY.RECONNECTING)):(o(this,A,void 0),S(this,u,w).call(this,e===f.REOPEN?p.CONNECTION_QUALITY.RECONNECTING:p.CONNECTION_QUALITY.CLOSED))},P=new WeakMap,x=new WeakMap,C=new WeakMap,D=new WeakMap,U=new WeakMap,Q=new WeakMap,G=new WeakMap,B=new WeakMap,c(p,"CONNECTION_QUALITY",{CLOSED:0,RECONNECTING:1,UNRESPONSIVE:2,CHECKING_RESPONSIVENESS:3,OPEN:4});var Z=p;export{Z as WS};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/client/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/client/WS.ts", "
|
|
4
|
-
"sourcesContent": ["import EventEmitter from \"eventemitter3\";\nimport { noop, StatefulPromise } from \"@nesvet/n\";\nimport {\n\tCODES,\n\tHEARTBEAT_GAP,\n\tHEARTBEAT_INTERVAL,\n\tNON_RECONNECTABLE_CODES,\n\tOFFLINE_TIMEOUT,\n\tREQUEST_COUNTER_LIMIT,\n\tREQUEST_HEADERS,\n\tRESPONSIVENESS_TIMEOUT\n} from \"../common\";\nimport type { ConnectionQuality, Options, RequestListener } from \"./types\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nlet i = 0;\n\n\nexport class WS extends EventEmitter {\n\tconstructor(options: Options = {}) {\n\t\tsuper();\n\t\t\n\t\tconst {\n\t\t\turl = globalThis.__insite?.wss_url || \"/\",\n\t\t\tname = (i++).toString(),\n\t\t\tprotocols,\n\t\t\timmediately = true,\n\t\t\treconnectAfter = 2000,\n\t\t\ton,\n\t\t\tonce,\n\t\t\tquiet = false,\n\t\t\tsignal\n\t\t} = options;\n\t\t\n\t\tthis.url = url;\n\t\tthis.name = name;\n\t\t\n\t\tthis.protocols = protocols;\n\t\t\n\t\tthis.reconnectAfter = reconnectAfter;\n\t\t\n\t\tif (on)\n\t\t\tfor (const eventName in on)\n\t\t\t\tif (on[eventName])\n\t\t\t\t\tthis.on(eventName, on[eventName]);\n\t\t\n\t\tif (once)\n\t\t\tfor (const eventName in once)\n\t\t\t\tif (once[eventName])\n\t\t\t\t\tthis.once(eventName, once[eventName]);\n\t\t\n\t\tthis.#isQuiet = quiet;\n\t\t\n\t\tthis.#abortSignal = signal;\n\t\tthis.#abortSignal?.addEventListener(\"abort\", this.#handleAbortSignalAbort, { once: true });\n\t\t\n\t\tif (this.url && immediately)\n\t\t\tthis.open().catch(noop);\n\t\t\n\t\tif (!this.#isQuiet)\n\t\t\tthis.on(\"error\", (error: Error) => error && console.error(\"\uD83D\uDD0C\u2757\uFE0F WS\", `${this.name}:`, error));\n\t\t\n\t}\n\t\n\ton(event: \"connecting\" | \"destroy\" | \"open\" | \"responsive\" | \"unresponsive\", callback: (this: this) => void): this;\n\ton<T extends unknown[]>(event: \"message\", callback: (this: this, kind: string, ...rest: T) => void): this;\n\ton<T extends unknown[]>(event: `message:${string}`, callback: (this: this, ...rest: T) => void): this;\n\ton(event: \"connection-quality-change\", callback: (this: this, connectionQuality: ConnectionQuality, prevConnectionQuality: ConnectionQuality) => void): this;\n\ton(event: \"close\", callback: (this: this, closeEvent: CloseEvent) => void): this;\n\ton(event: \"server-change\", callback: (this: this, url: string, prevURL: string) => void): this;\n\ton(event: \"error\", callback: (this: this, error: Error) => void): this;\n\t\n\ton<T extends string | symbol>(event: T, fn: (...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener);\n\t}\n\t\n\treadonly isWebSocket = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocketServerClient = false;\n\t\n\turl;\n\t\n\treadonly name;\n\t\n\tprotocols?;\n\t\n\treconnectAfter;\n\t\n\t#isQuiet;\n\t\n\t#abortSignal?: AbortSignal;\n\t\n\tisUsed = false;\n\t\n\tconnectionQuality: ConnectionQuality = 0;\n\t\n\t#updateConnectionQuality(connectionQuality: ConnectionQuality) {\n\t\tif (connectionQuality !== this.connectionQuality) {\n\t\t\tconst prevConnectionQuality = this.connectionQuality;\n\t\t\tthis.connectionQuality = connectionQuality;\n\t\t\t\n\t\t\tthis.emit(\"connection-quality-change\", this.connectionQuality, prevConnectionQuality);\n\t\t}\n\t\t\n\t}\n\t\n\twebSocket: WebSocket | null = null;\n\t\n\t#heartbeatTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#defib() {\n\t\t\n\t\tclearTimeout(this.#heartbeatTimeout);\n\t\tthis.#heartbeatTimeout = setTimeout(\n\t\t\t() => this.close(CODES.NO_HEARTBEAT, \"no-heartbeat\", false),\n\t\t\tHEARTBEAT_INTERVAL + HEARTBEAT_GAP\n\t\t);\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#isUnresponsive) {\n\t\t\tthis.#isUnresponsive = false;\n\t\t\t\n\t\t\tthis.emit(\"responsive\");\n\t\t}\n\t\t\n\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.OPEN);\n\t\t\n\t}\n\t\n\t#unresponsiveTimeout?: ReturnType<typeof setTimeout>;\n\t#isCheckingResponsiveness = false;\n\t\n\t#offlineTimeout?: ReturnType<typeof setTimeout>;\n\t#isUnresponsive = false;\n\t\n\tget state() {\n\t\t\n\t\tif (!this.webSocket)\n\t\t\treturn \"closed\";\n\t\t\n\t\tswitch (this.webSocket.readyState) {\n\t\t\tcase WebSocket.CONNECTING:\n\t\t\t\treturn \"connecting\";\n\t\t\t\n\t\t\tcase WebSocket.OPEN:\n\t\t\t\treturn this.#isUnresponsive ? \"unresponsive\" : \"open\";\n\t\t\t\n\t\t\tcase WebSocket.CLOSING:\n\t\t\t\treturn \"closing\";\n\t\t}\n\t\t\n\t\treturn \"closed\";\n\t}\n\t\n\tget isConnecting() {\n\t\treturn this.webSocket?.readyState === WebSocket.CONNECTING;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.webSocket?.readyState === WebSocket.OPEN;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.webSocket?.readyState === WebSocket.CLOSING;\n\t}\n\t\n\tget isClosed() {\n\t\treturn !this.webSocket;\n\t}\n\t\n\tisDestroyed = false;\n\t\n\t#openPromise?: StatefulPromise<void>;\n\t\n\t#wasOpened = false;\n\t\n\t#handleWebSocketOpen = () => {\n\t\t\n\t\tthis.#wasOpened = true;\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tthis.#openPromise!.resolve();\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tthis.emit(\"open\");\n\t\t\n\t};\n\t\n\t#handleWebSocketMessage = ({ data: message }: MessageEvent<string>) => {\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tif (message) {\n\t\t\tif (message !== \"!\")\n\t\t\t\ttry {\n\t\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\t\n\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\tcase REQUEST_HEADERS.REQUEST:\n\t\t\t\t\t\t\tvoid this.#handleRequest(...rest as [ id: number, kind: string, ...rest: unknown[] ]);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthis.emit(\"message\", kind, ...rest);\n\t\t\t\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.#handleWebSocketError(error as Error);\n\t\t\t\t}\n\t\t} else\n\t\t\tthis.webSocket!.send(\"\");\n\t\t\n\t};\n\t\n\t#handleWebSocketError = (error: Error | Event | undefined) => {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(error as Error);\n\t\t\n\t\tthis.emit(\"error\", error);\n\t\t\n\t};\n\t\n\t#reconnectTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#decideReconnect(code: number) {\n\t\t\n\t\tif (this.#reconnectTimeout)\n\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\tif (this.reconnectAfter && !NON_RECONNECTABLE_CODES.includes(code as typeof NON_RECONNECTABLE_CODES[number])) {\n\t\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet)\n\t\t\t\tconsole.info(`\uD83D\uDD0C WS ${this.name} will try to reconnect in ${Math.round(this.reconnectAfter / 1000)} seconds`);\n\t\t\t\n\t\t\tthis.#reconnectTimeout = setTimeout(() => this.open().catch(noop), this.reconnectAfter);\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.RECONNECTING);\n\t\t} else {\n\t\t\tthis.#reconnectTimeout = undefined;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(code === CODES.REOPEN ? WS.CONNECTION_QUALITY.RECONNECTING : WS.CONNECTION_QUALITY.CLOSED);\n\t\t}\n\t\t\n\t}\n\t\n\t#handleWebSocketClose = (event: CloseEvent) => {\n\t\tconst { code, reason, wasClean } = event;\n\t\t\n\t\tthis.closedWith = { code, reason, wasClean };\n\t\t\n\t\tif (this.#heartbeatTimeout) {\n\t\t\tclearTimeout(this.#heartbeatTimeout);\n\t\t\tthis.#heartbeatTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isUnresponsive = false;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(new Error(\"Closed\"));\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet) {\n\t\t\tlet message = `\uD83D\uDD0C WS ${this.name} is closed`;\n\t\t\t\n\t\t\tif (code)\n\t\t\t\tmessage += ` with code ${code}`;\n\t\t\t\n\t\t\tif (code && reason)\n\t\t\t\tmessage += \" and\";\n\t\t\t\n\t\t\tif (reason)\n\t\t\t\tmessage += ` reason \"${reason}\"`;\n\t\t\t\n\t\t\tswitch (reason) {\n\t\t\t\tcase \"no-heartbeat\":\n\t\t\t\t\tmessage += \". Going offline\";\n\t\t\t}\n\t\t\t\n\t\t\tif (!wasClean || code === CODES.ABNORMAL) {\n\t\t\t\tmessage += \" [UNEXPECTED]\";\n\t\t\t\tconsole.warn(message);\n\t\t\t} else\n\t\t\t\tconsole.info(message);\n\t\t}\n\t\t\n\t\tconst webSocket = this.webSocket!;\n\t\t\n\t\twebSocket.removeEventListener(\"open\", this.#handleWebSocketOpen);\n\t\twebSocket.removeEventListener(\"message\", this.#handleWebSocketMessage);\n\t\twebSocket.removeEventListener(\"error\", this.#handleWebSocketError);\n\t\t\n\t\tif (this.#wasOpened) {\n\t\t\tthis.emit(\"close\", event);\n\t\t\t\n\t\t\tthis.#wasOpened = false;\n\t\t}\n\t\t\n\t\tthis.webSocket = null;\n\t\t\n\t\tthis.#decideReconnect(code);\n\t\t\n\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\tglobalThis.removeEventListener(\"offline\", this.#handleOffline);\n\t\t\n\t};\n\t\n\t#handleAbortSignalAbort = () =>\n\t\tthis.#openPromise?.isPending &&\n\t\tthis.#openPromise.reject(new DOMException(\"Operation aborted\", \"AbortError\"));\n\t\n\tasync open(options: Pick<Options, \"protocols\" | \"url\"> = {}): Promise<void> {\n\t\t\n\t\tif (this.isDestroyed)\n\t\t\tthrow new Error(\"WS has been destroyed\");\n\t\t\n\t\tif (this.#abortSignal?.aborted)\n\t\t\tthrow new DOMException(\"Operation aborted\", \"AbortError\");\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\treturn this.#openPromise;\n\t\t\n\t\tif (this.isUsed)\n\t\t\tthis.close(CODES.REOPEN, \"reopen\");\n\t\telse\n\t\t\tthis.isUsed = true;\n\t\t\n\t\tlet prevURL: URL | string | undefined;\n\t\tif (options.url && this.url !== options.url) {\n\t\t\tprevURL = this.url;\n\t\t\tthis.url = options.url;\n\t\t}\n\t\t\n\t\tif (options.protocols)\n\t\t\tthis.protocols = options.protocols;\n\t\t\n\t\tthis.#openPromise = new StatefulPromise((_, reject) => {\n\t\t\t\n\t\t\tif (this.url) {\n\t\t\t\tconst webSocket = new WebSocket(this.url, this.protocols);\n\t\t\t\t\n\t\t\t\twebSocket.addEventListener(\"open\", this.#handleWebSocketOpen, { once: true });\n\t\t\t\twebSocket.addEventListener(\"message\", this.#handleWebSocketMessage);\n\t\t\t\twebSocket.addEventListener(\"error\", this.#handleWebSocketError);\n\t\t\t\twebSocket.addEventListener(\"close\", this.#handleWebSocketClose, { once: true });\n\t\t\t\t\n\t\t\t\tthis.webSocket = webSocket;\n\t\t\t\t\n\t\t\t\tif (prevURL)\n\t\t\t\t\tthis.emit(\"server-change\", this.url, prevURL);\n\t\t\t\t\n\t\t\t\tthis.emit(\"connecting\");\n\t\t\t\t\n\t\t\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\t\t\tglobalThis.addEventListener(\"offline\", this.#handleOffline);\n\t\t\t} else {\n\t\t\t\tthis.webSocket = null;\n\t\t\t\t\n\t\t\t\treject(new Error(\"url prop is not set\"));\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\treturn this.#openPromise;\n\t}\n\t\n\t/**\n\t * Alias for `open()`\n\t */\n\tconnect = this.open;\n\t\n\tclose(code: number = CODES.MANUAL, reason = \"manual\", wasClean: boolean = true) {\n\t\t\n\t\tif (this.isClosed)\n\t\t\tthis.#decideReconnect(code);\n\t\telse {\n\t\t\tthis.webSocket!.removeEventListener(\"close\", this.#handleWebSocketClose);\n\t\t\t\n\t\t\tthis.webSocket!.close(code, reason);\n\t\t\t\n\t\t\tthis.#handleWebSocketClose(Object.assign(new Event(\"close\"), {\n\t\t\t\tcode,\n\t\t\t\treason,\n\t\t\t\twasClean\n\t\t\t}));\n\t\t}\n\t\t\n\t}\n\t\n\tclosedWith: { code: number; reason: string; wasClean: boolean } | null = null;\n\t\n\t/**\n\t * Alias for `close()`\n\t */\n\tdisconnect = this.close;\n\t\n\t#queue: (ArrayBufferLike | ArrayBufferView | Blob | string)[] = [];\n\t\n\t#releaseQueue = () => {\n\t\t\n\t\tfor (const message of this.#queue)\n\t\t\tthis.webSocket!.send(message);\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t};\n\t\n\tsend(data: ArrayBufferLike | ArrayBufferView | Blob | string) {\n\t\t\n\t\tif (this.isOpen)\n\t\t\tthis.webSocket!.send(data);\n\t\telse {\n\t\t\tif (!this.#queue.length)\n\t\t\t\tthis.once(\"open\", this.#releaseQueue);\n\t\t\t\n\t\t\tthis.#queue.push(data);\n\t\t}\n\t\t\n\t}\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\t#requestCounter = 0;\n\t\n\tsendRequest<T>(...args: [...unknown[], callback: (error: Error | null, result: T) => void]): this;\n\tsendRequest<T>(...args: unknown[]): Promise<T>;\n\tsendRequest<T>(...args: unknown[]) {\n\t\t\n\t\tconst id = this.#requestCounter++;\n\t\t\n\t\tif (this.#requestCounter >= REQUEST_COUNTER_LIMIT)\n\t\t\tthis.#requestCounter = 0;\n\t\t\n\t\tconst eventName = `message:${REQUEST_HEADERS.RESPONSE}-${id}`;\n\t\t\n\t\tconst lastArg = args.at(-1);\n\t\t\n\t\tif (typeof lastArg == \"function\") {\n\t\t\tthis.once(eventName, lastArg as (error: Error, result: T) => void);\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args.slice(0, -1));\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result: T) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps) as Error);\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t#requestListeners = new Map<string, RequestListener>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener) {\n\t\tthis.#requestListeners.set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `addRequestListener()`\n\t */\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis.#requestListeners.delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `removeRequestListener()`\n\t */\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleRequest = async (id: number, kind: string, ...rest: unknown[]) => {\n\t\tconst listener = this.#requestListeners.get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.apply(this, rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\tthis.sendMessage(`${REQUEST_HEADERS.RESPONSE}-${id}`, requestError, result);\n\t\t\n\t};\n\t\n\t#handleOffline = () => {\n\t\t\n\t\tif (this.isOpen && !this.#isCheckingResponsiveness) {\n\t\t\tthis.#isCheckingResponsiveness = true;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.CHECKING_RESPONSIVENESS);\n\t\t\t\n\t\t\tthis.#unresponsiveTimeout = setTimeout(() => {\n\t\t\t\t\n\t\t\t\tthis.#isCheckingResponsiveness = false;\n\t\t\t\tthis.#isUnresponsive = true;\n\t\t\t\t\n\t\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.UNRESPONSIVE);\n\t\t\t\t\n\t\t\t\tthis.emit(\"unresponsive\");\n\t\t\t\t\n\t\t\t\tthis.#offlineTimeout = setTimeout(() => {\n\t\t\t\t\t\n\t\t\t\t\tthis.#isUnresponsive = false;\n\t\t\t\t\t\n\t\t\t\t\tthis.close(CODES.OFFLINE, \"offline\", false);\n\t\t\t\t\t\n\t\t\t\t}, OFFLINE_TIMEOUT - RESPONSIVENESS_TIMEOUT);\n\t\t\t\t\n\t\t\t}, RESPONSIVENESS_TIMEOUT);\n\t\t\t\n\t\t\tthis.webSocket!.send(\"?\");\n\t\t}\n\t\t\n\t};\n\t\n\tdestroy() {\n\t\t\n\t\tthis.isDestroyed = true;\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t\tthis.close(CODES.NORMAL, \"destroy\");\n\t\t\n\t\tthis.emit(\"destroy\");\n\t\t\n\t\tthis.removeAllListeners();\n\t\t\n\t\tthis.#abortSignal?.removeEventListener(\"abort\", this.#handleAbortSignalAbort);\n\t\t\n\t}\n\t\n\t\n\tstatic CONNECTION_QUALITY = {\n\t\tCLOSED: 0,\n\t\tRECONNECTING: 1,\n\t\tUNRESPONSIVE: 2,\n\t\tCHECKING_RESPONSIVENESS: 3,\n\t\tOPEN: 4\n\t} as const;\n\t\n}\n", "export function noop() { /**/ }\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\n\ntype Value<T> = PromiseLike<T> | T;\ntype Resolve<T> = (value: Value<T>) => void;\ntype Reject = (reason?: any) => void;\n\ntype Options = {\n\tsignal?: AbortSignal;\n\ttimeout?: number;\n};\n\nconst nativesMap = new WeakMap<StatefulPromise<any>, { resolve: Resolve<any>; reject: Reject }>();\n\n\nexport class StatefulPromise<T> extends Promise<T> {\n\tconstructor(\n\t\texecutor?: (resolve: Resolve<T>, reject: Reject) => void,\n\t\toptions?: Options\n\t) {\n\t\tlet nativeResolve: Resolve<T>;\n\t\tlet nativeReject: Reject;\n\t\t\n\t\tsuper((resolve, reject) => {\n\t\t\tnativeResolve = resolve;\n\t\t\tnativeReject = reject;\n\t\t\t\n\t\t});\n\t\t\n\t\tnativesMap.set(this, { resolve: nativeResolve!, reject: nativeReject! });\n\t\t\n\t\tif (options?.signal)\n\t\t\tif (options.signal.aborted)\n\t\t\t\tthis.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\t\t\telse {\n\t\t\t\tconst abortListener = () => this.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\t\t\t\t\n\t\t\t\toptions.signal.addEventListener(\"abort\", abortListener);\n\t\t\t\t\n\t\t\t\tthis.finally(() => options.signal?.removeEventListener(\"abort\", abortListener));\n\t\t\t}\n\t\t\n\t\tif (typeof options?.timeout === \"number\" && Number.isFinite(options.timeout)) {\n\t\t\tconst timeout = setTimeout(() => this.reject(new DOMException(\"Timeout exceeded\", \"TimeoutError\")), options.timeout);\n\t\t\t\n\t\t\tthis.finally(() => clearTimeout(timeout));\n\t\t}\n\t\t\n\t\texecutor?.(this.resolve, this.reject);\n\t\t\n\t}\n\t\n\tisPending = true;\n\tisFulfilled = false;\n\tisRejected = false;\n\t\n\tstate: \"fulfilled\" | \"pending\" | \"rejected\" = \"pending\";\n\t\n\tresult?: T | unknown;\n\t\n\treadonly resolve = (value: Value<T>) => {\n\t\t\n\t\tif (this.isPending) {\n\t\t\tthis.isPending = false;\n\t\t\tthis.isFulfilled = true;\n\t\t\tthis.state = \"fulfilled\";\n\t\t\tthis.result = value;\n\t\t\t\n\t\t\tconst native = nativesMap.get(this);\n\t\t\t\n\t\t\tif (native) {\n\t\t\t\tnative.resolve.call(this, value);\n\t\t\t\tnativesMap.delete(this);\n\t\t\t}\n\t\t}\n\t\t\n\t};\n\t\n\treadonly reject = (reason?: any) => {\n\t\t\n\t\tif (this.isPending) {\n\t\t\tthis.isPending = false;\n\t\t\tthis.isRejected = true;\n\t\t\tthis.state = \"rejected\";\n\t\t\tthis.result = reason;\n\t\t\t\n\t\t\tconst native = nativesMap.get(this);\n\t\t\t\n\t\t\tif (native) {\n\t\t\t\tnative.reject.call(this, reason);\n\t\t\t\tnativesMap.delete(this);\n\t\t\t}\n\t\t}\n\t\t\n\t};\n\t\n\t\n\tstatic resolved<U>(value: U): StatefulPromise<U> {\n\t\treturn new StatefulPromise<U>(resolve => resolve(value));\n\t}\n\t\n\tstatic rejected(reason: unknown): StatefulPromise<never> {\n\t\treturn new StatefulPromise((_, reject) => reject(reason));\n\t}\n\t\n}\n", "import { noop } from \"./noop.js\";\nimport { StatefulPromise } from \"./StatefulPromise.js\";\n\n\ntype Callback = (...args: any[]) => unknown;// eslint-disable-line @typescript-eslint/no-explicit-any\ntype FunctionOrBoolean = (() => unknown) | boolean;\ntype Options = { leading?: FunctionOrBoolean; maxWait?: number; trailing?: FunctionOrBoolean };\n\ntype DebouncedFunction<C extends Callback> = {\n\t(this: ThisParameterType<C>, ...args: Parameters<C>): Promise<Awaited<ReturnType<C>>>;\n};\n\nexport type Debounced<C extends Callback, R extends ReturnType<C>> = DebouncedFunction<C> & {\n\tcallback: C;\n\tpromise: StatefulPromise<R>;\n\tresolve: (value: R) => void;\n\treject: (reason?: unknown) => void;\n\trun(): Promise<R>;\n\tclear(shouldRun?: boolean): Promise<void>;\n};\n\n\nexport function debounce<C extends Callback, R extends ReturnType<C>>(callback: C, limit = 0, options: Options = {}) {\n\tlet { leading = false, trailing = true } = options;\n\tconst { maxWait = Infinity } = options;\n\t\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\tlet maxWaitTimeout: ReturnType<typeof setTimeout> | undefined;\n\tlet end: number | undefined;\n\tlet context: ThisParameterType<C>;\n\tlet args: unknown[];\n\tlet initial: FunctionOrBoolean;\n\tlet final: FunctionOrBoolean;\n\tlet result: R;\n\t\n\tconst expired = async () => {\n\t\t\n\t\tconst n = Date.now();\n\t\t\n\t\tif (n >= end!) {\n\t\t\ttimeout = undefined;\n\t\t\tend = undefined;\n\t\t\t\n\t\t\tclearTimeout(maxWaitTimeout);\n\t\t\tmaxWaitTimeout = undefined;\n\t\t\t\n\t\t\tif (typeof final == \"function\")\n\t\t\t\tawait final();\n\t\t\t\n\t\t\tdebounced.resolve(result);\n\t\t\t\n\t\t\tinitial = leading;\n\t\t} else {\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = setTimeout(expired, end! - n);\n\t\t}\n\t\t\n\t};\n\t\n\tconst maxWaitExpired = Number.isFinite(maxWait) ? () => {\n\t\t\n\t\tif (final === run)\n\t\t\tfinal = false;\n\t\t\n\t\trun();\n\t\t\n\t\tmaxWaitTimeout = setTimeout(maxWaitExpired as TimerHandler, maxWait);\n\t\t\n\t} : null;\n\t\n\tasync function run() {\n\t\ttry {\n\t\t\tresult = await callback.apply(context, args) as R;\n\t\t\t\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tdebounced.reject(error);\n\t\t\t\n\t\t\tthrow error;\n\t\t}\n\t}\n\t\n\tif (leading && typeof leading == \"boolean\")\n\t\tleading = run;\n\tinitial = leading;\n\t\n\tif (trailing && typeof trailing == \"boolean\")\n\t\ttrailing = run;\n\tfinal = trailing;\n\t\n\tconst debounced: Debounced<C, R> = Object.assign(function (..._args) {\n\t\targs = _args;\n\t\tcontext = this;// eslint-disable-line no-invalid-this\n\t\t\n\t\tend = Date.now() + limit;\n\t\tfinal = trailing;\n\t\t\n\t\tif (!debounced.promise.isPending)\n\t\t\tdebounced.promise = new StatefulPromise<R>((resolve, reject) => {\n\t\t\t\tdebounced.resolve = resolve;\n\t\t\t\tdebounced.reject = reject;\n\t\t\t\t\n\t\t\t\tif (typeof initial == \"function\") {\n\t\t\t\t\tinitial();\n\t\t\t\t\t\n\t\t\t\t\tinitial = false;\n\t\t\t\t\t\n\t\t\t\t\tif (final === run)\n\t\t\t\t\t\tfinal = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!timeout) {\n\t\t\t\t\ttimeout = setTimeout(expired, limit);\n\t\t\t\t\t\n\t\t\t\t\tif (maxWaitExpired)\n\t\t\t\t\t\tmaxWaitTimeout = setTimeout(maxWaitExpired, maxWait);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t});\n\t\t\n\t\treturn debounced.promise;\n\t} as DebouncedFunction<C>, {\n\t\tcallback,\n\t\tpromise: StatefulPromise.resolved(undefined as unknown as R),\n\t\tresolve: noop,\n\t\treject: noop,\n\t\trun,\n\t\tclear: async (shouldRun?: boolean) => {\n\t\t\t\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = undefined;\n\t\t\t\n\t\t\tclearTimeout(maxWaitTimeout);\n\t\t\tmaxWaitTimeout = undefined;\n\t\t\t\n\t\t\tdebounced.resolve(shouldRun ? await run() : result);\n\t\t\t\n\t\t}\n\t});\n\t\n\treturn debounced;\n}\n\n\ndebounce.noop = Object.assign(() => { /**/ }, {\n\tcallback: noop,\n\tpromise: StatefulPromise.resolved(undefined), // eslint-disable-line unicorn/no-useless-undefined\n\tresolve: noop,\n\treject: noop,\n\trun: noop,\n\tclear: noop\n}) as Debounced<() => void, void>;\n\n\nexport function throttle(callback: Callback, limit?: number, options?: Options) {\n\treturn debounce(callback, limit, {\n\t\tmaxWait: limit,\n\t\tleading: true,\n\t\ttrailing: true,\n\t\t...options\n\t});\n}\n", "export function howmuch(number: [] | number, one: string, two: string, five: boolean | string, shouldPrintNumber = true) {\n\tif (Array.isArray(number))\n\t\tnumber = number.length;\n\t\n\tif (typeof five != \"string\") {\n\t\tshouldPrintNumber = five ?? true;\n\t\tfive = two;\n\t}\n\t\n\t\n\treturn (shouldPrintNumber ? `${number}\u00A0` : \"\") + howmuch.raw(number, one, two, five);\n}\n\nhowmuch.raw = (number: number, one: string, two: string, five = two) => {\n\tnumber = Math.abs(number);\n\tconst u = number % 10;\n\tconst d = number % 100;\n\t\n\treturn (\n\t\t(u === 1 && d !== 11) ?\n\t\t\tone :\n\t\t\t((u >= 2 && u <= 4) && !(d >= 12 && d <= 15)) ?\n\t\t\t\ttwo :\n\t\t\t\tfive\n\t);\n};\n", "export const HEARTBEAT_INTERVAL = 5_000;\nexport const HEARTBEAT_GAP = 30_000;\nexport const RESPONSIVENESS_TIMEOUT = 1000;\nexport const OFFLINE_TIMEOUT = 5000;\nexport const REQUEST_COUNTER_LIMIT = Number.MAX_SAFE_INTEGER / 2;\n\nexport const CODES = {\n\tNORMAL: 1000,\n\tPROTOCOL_ERROR: 1002,\n\tABNORMAL: 1006,\n\tNO_HEARTBEAT: 3000,\n\tOFFLINE: 3001,\n\tMANUAL: 3500,\n\tREOPEN: 4000\n} as const;\n\nexport const NON_RECONNECTABLE_CODES = [\n\tCODES.PROTOCOL_ERROR,\n\tCODES.MANUAL,\n\tCODES.REOPEN\n];\n\nexport const REQUEST_HEADERS = {\n\tREQUEST: \"~r-q\",\n\tRESPONSE: \"~r-s\"\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["EventEmitter", "noop", "
|
|
3
|
+
"sources": ["../../src/client/WS.ts", "../../src/common.ts"],
|
|
4
|
+
"sourcesContent": ["import EventEmitter from \"eventemitter3\";\nimport { noop, StatefulPromise } from \"@nesvet/n\";\nimport {\n\tCODES,\n\tHEARTBEAT_GAP,\n\tHEARTBEAT_INTERVAL,\n\tNON_RECONNECTABLE_CODES,\n\tOFFLINE_TIMEOUT,\n\tREQUEST_COUNTER_LIMIT,\n\tREQUEST_HEADERS,\n\tRESPONSIVENESS_TIMEOUT\n} from \"../common\";\nimport type { ConnectionQuality, Options, RequestListener } from \"./types\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nlet i = 0;\n\n\nexport class WS extends EventEmitter {\n\tconstructor(options: Options = {}) {\n\t\tsuper();\n\t\t\n\t\tconst {\n\t\t\turl = globalThis.__insite?.wss_url || \"/\",\n\t\t\tname = (i++).toString(),\n\t\t\tprotocols,\n\t\t\timmediately = true,\n\t\t\treconnectAfter = 2000,\n\t\t\ton,\n\t\t\tonce,\n\t\t\tquiet = false,\n\t\t\tsignal\n\t\t} = options;\n\t\t\n\t\tthis.url = url;\n\t\tthis.name = name;\n\t\t\n\t\tthis.protocols = protocols;\n\t\t\n\t\tthis.reconnectAfter = reconnectAfter;\n\t\t\n\t\tif (on)\n\t\t\tfor (const eventName in on)\n\t\t\t\tif (on[eventName])\n\t\t\t\t\tthis.on(eventName, on[eventName]);\n\t\t\n\t\tif (once)\n\t\t\tfor (const eventName in once)\n\t\t\t\tif (once[eventName])\n\t\t\t\t\tthis.once(eventName, once[eventName]);\n\t\t\n\t\tthis.#isQuiet = quiet;\n\t\t\n\t\tthis.#abortSignal = signal;\n\t\tthis.#abortSignal?.addEventListener(\"abort\", this.#handleAbortSignalAbort, { once: true });\n\t\t\n\t\tif (this.url && immediately)\n\t\t\tthis.open().catch(noop);\n\t\t\n\t\tif (!this.#isQuiet)\n\t\t\tthis.on(\"error\", (error: Error) => error && console.error(\"\uD83D\uDD0C\u2757\uFE0F WS\", `${this.name}:`, error));\n\t\t\n\t}\n\t\n\ton(event: \"connecting\" | \"destroy\" | \"open\" | \"responsive\" | \"unresponsive\", callback: (this: this) => void): this;\n\ton<T extends unknown[]>(event: \"message\", callback: (this: this, kind: string, ...rest: T) => void): this;\n\ton<T extends unknown[]>(event: `message:${string}`, callback: (this: this, ...rest: T) => void): this;\n\ton(event: \"connection-quality-change\", callback: (this: this, connectionQuality: ConnectionQuality, prevConnectionQuality: ConnectionQuality) => void): this;\n\ton(event: \"close\", callback: (this: this, closeEvent: CloseEvent) => void): this;\n\ton(event: \"server-change\", callback: (this: this, url: string, prevURL: string) => void): this;\n\ton(event: \"error\", callback: (this: this, error: Error) => void): this;\n\t\n\ton<T extends string | symbol>(event: T, fn: (...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener);\n\t}\n\t\n\treadonly isWebSocket = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocketServerClient = false;\n\t\n\turl;\n\t\n\treadonly name;\n\t\n\tprotocols?;\n\t\n\treconnectAfter;\n\t\n\t#isQuiet;\n\t\n\t#abortSignal?: AbortSignal;\n\t\n\tisUsed = false;\n\t\n\tconnectionQuality: ConnectionQuality = 0;\n\t\n\t#updateConnectionQuality(connectionQuality: ConnectionQuality) {\n\t\tif (connectionQuality !== this.connectionQuality) {\n\t\t\tconst prevConnectionQuality = this.connectionQuality;\n\t\t\tthis.connectionQuality = connectionQuality;\n\t\t\t\n\t\t\tthis.emit(\"connection-quality-change\", this.connectionQuality, prevConnectionQuality);\n\t\t}\n\t\t\n\t}\n\t\n\twebSocket: WebSocket | null = null;\n\t\n\t#heartbeatTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#defib() {\n\t\t\n\t\tclearTimeout(this.#heartbeatTimeout);\n\t\tthis.#heartbeatTimeout = setTimeout(\n\t\t\t() => this.close(CODES.NO_HEARTBEAT, \"no-heartbeat\", false),\n\t\t\tHEARTBEAT_INTERVAL + HEARTBEAT_GAP\n\t\t);\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#isUnresponsive) {\n\t\t\tthis.#isUnresponsive = false;\n\t\t\t\n\t\t\tthis.emit(\"responsive\");\n\t\t}\n\t\t\n\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.OPEN);\n\t\t\n\t}\n\t\n\t#unresponsiveTimeout?: ReturnType<typeof setTimeout>;\n\t#isCheckingResponsiveness = false;\n\t\n\t#offlineTimeout?: ReturnType<typeof setTimeout>;\n\t#isUnresponsive = false;\n\t\n\tget state() {\n\t\t\n\t\tif (!this.webSocket)\n\t\t\treturn \"closed\";\n\t\t\n\t\tswitch (this.webSocket.readyState) {\n\t\t\tcase WebSocket.CONNECTING:\n\t\t\t\treturn \"connecting\";\n\t\t\t\n\t\t\tcase WebSocket.OPEN:\n\t\t\t\treturn this.#isUnresponsive ? \"unresponsive\" : \"open\";\n\t\t\t\n\t\t\tcase WebSocket.CLOSING:\n\t\t\t\treturn \"closing\";\n\t\t}\n\t\t\n\t\treturn \"closed\";\n\t}\n\t\n\tget isConnecting() {\n\t\treturn this.webSocket?.readyState === WebSocket.CONNECTING;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.webSocket?.readyState === WebSocket.OPEN;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.webSocket?.readyState === WebSocket.CLOSING;\n\t}\n\t\n\tget isClosed() {\n\t\treturn !this.webSocket;\n\t}\n\t\n\tisDestroyed = false;\n\t\n\t#openPromise?: StatefulPromise<void>;\n\t\n\t#wasOpened = false;\n\t\n\t#handleWebSocketOpen = () => {\n\t\t\n\t\tthis.#wasOpened = true;\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tthis.#openPromise!.resolve();\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tthis.emit(\"open\");\n\t\t\n\t};\n\t\n\t#handleWebSocketMessage = ({ data: message }: MessageEvent<string>) => {\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tif (message) {\n\t\t\tif (message !== \"!\")\n\t\t\t\ttry {\n\t\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\t\n\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\tcase REQUEST_HEADERS.REQUEST:\n\t\t\t\t\t\t\tvoid this.#handleRequest(...rest as [ id: number, kind: string, ...rest: unknown[] ]);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthis.emit(\"message\", kind, ...rest);\n\t\t\t\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.#handleWebSocketError(error as Error);\n\t\t\t\t}\n\t\t} else\n\t\t\tthis.webSocket!.send(\"\");\n\t\t\n\t};\n\t\n\t#handleWebSocketError = (error: Error | Event | undefined) => {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(error as Error);\n\t\t\n\t\tthis.emit(\"error\", error);\n\t\t\n\t};\n\t\n\t#reconnectTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#decideReconnect(code: number) {\n\t\t\n\t\tif (this.#reconnectTimeout)\n\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\tif (this.reconnectAfter && !NON_RECONNECTABLE_CODES.includes(code as typeof NON_RECONNECTABLE_CODES[number])) {\n\t\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet)\n\t\t\t\tconsole.info(`\uD83D\uDD0C WS ${this.name} will try to reconnect in ${Math.round(this.reconnectAfter / 1000)} seconds`);\n\t\t\t\n\t\t\tthis.#reconnectTimeout = setTimeout(() => this.open().catch(noop), this.reconnectAfter);\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.RECONNECTING);\n\t\t} else {\n\t\t\tthis.#reconnectTimeout = undefined;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(code === CODES.REOPEN ? WS.CONNECTION_QUALITY.RECONNECTING : WS.CONNECTION_QUALITY.CLOSED);\n\t\t}\n\t\t\n\t}\n\t\n\t#handleWebSocketClose = (event: CloseEvent) => {\n\t\tconst { code, reason, wasClean } = event;\n\t\t\n\t\tthis.closedWith = { code, reason, wasClean };\n\t\t\n\t\tif (this.#heartbeatTimeout) {\n\t\t\tclearTimeout(this.#heartbeatTimeout);\n\t\t\tthis.#heartbeatTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isUnresponsive = false;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(new Error(\"Closed\"));\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet) {\n\t\t\tlet message = `\uD83D\uDD0C WS ${this.name} is closed`;\n\t\t\t\n\t\t\tif (code)\n\t\t\t\tmessage += ` with code ${code}`;\n\t\t\t\n\t\t\tif (code && reason)\n\t\t\t\tmessage += \" and\";\n\t\t\t\n\t\t\tif (reason)\n\t\t\t\tmessage += ` reason \"${reason}\"`;\n\t\t\t\n\t\t\tswitch (reason) {\n\t\t\t\tcase \"no-heartbeat\":\n\t\t\t\t\tmessage += \". Going offline\";\n\t\t\t}\n\t\t\t\n\t\t\tif (!wasClean || code === CODES.ABNORMAL) {\n\t\t\t\tmessage += \" [UNEXPECTED]\";\n\t\t\t\tconsole.warn(message);\n\t\t\t} else\n\t\t\t\tconsole.info(message);\n\t\t}\n\t\t\n\t\tconst webSocket = this.webSocket!;\n\t\t\n\t\twebSocket.removeEventListener(\"open\", this.#handleWebSocketOpen);\n\t\twebSocket.removeEventListener(\"message\", this.#handleWebSocketMessage);\n\t\twebSocket.removeEventListener(\"error\", this.#handleWebSocketError);\n\t\t\n\t\tif (this.#wasOpened) {\n\t\t\tthis.emit(\"close\", event);\n\t\t\t\n\t\t\tthis.#wasOpened = false;\n\t\t}\n\t\t\n\t\tthis.webSocket = null;\n\t\t\n\t\tthis.#decideReconnect(code);\n\t\t\n\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\tglobalThis.removeEventListener(\"offline\", this.#handleOffline);\n\t\t\n\t};\n\t\n\t#handleAbortSignalAbort = () =>\n\t\tthis.#openPromise?.isPending &&\n\t\tthis.#openPromise.reject(new DOMException(\"Operation aborted\", \"AbortError\"));\n\t\n\tasync open(options: Pick<Options, \"protocols\" | \"url\"> = {}): Promise<void> {\n\t\t\n\t\tif (this.isDestroyed)\n\t\t\tthrow new Error(\"WS has been destroyed\");\n\t\t\n\t\tif (this.#abortSignal?.aborted)\n\t\t\tthrow new DOMException(\"Operation aborted\", \"AbortError\");\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\treturn this.#openPromise;\n\t\t\n\t\tif (this.isUsed)\n\t\t\tthis.close(CODES.REOPEN, \"reopen\");\n\t\telse\n\t\t\tthis.isUsed = true;\n\t\t\n\t\tlet prevURL: URL | string | undefined;\n\t\tif (options.url && this.url !== options.url) {\n\t\t\tprevURL = this.url;\n\t\t\tthis.url = options.url;\n\t\t}\n\t\t\n\t\tif (options.protocols)\n\t\t\tthis.protocols = options.protocols;\n\t\t\n\t\tthis.#openPromise = new StatefulPromise((_, reject) => {\n\t\t\t\n\t\t\tif (this.url) {\n\t\t\t\tconst webSocket = new WebSocket(this.url, this.protocols);\n\t\t\t\t\n\t\t\t\twebSocket.addEventListener(\"open\", this.#handleWebSocketOpen, { once: true });\n\t\t\t\twebSocket.addEventListener(\"message\", this.#handleWebSocketMessage);\n\t\t\t\twebSocket.addEventListener(\"error\", this.#handleWebSocketError);\n\t\t\t\twebSocket.addEventListener(\"close\", this.#handleWebSocketClose, { once: true });\n\t\t\t\t\n\t\t\t\tthis.webSocket = webSocket;\n\t\t\t\t\n\t\t\t\tif (prevURL)\n\t\t\t\t\tthis.emit(\"server-change\", this.url, prevURL);\n\t\t\t\t\n\t\t\t\tthis.emit(\"connecting\");\n\t\t\t\t\n\t\t\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\t\t\tglobalThis.addEventListener(\"offline\", this.#handleOffline);\n\t\t\t} else {\n\t\t\t\tthis.webSocket = null;\n\t\t\t\t\n\t\t\t\treject(new Error(\"url prop is not set\"));\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\treturn this.#openPromise;\n\t}\n\t\n\t/**\n\t * Alias for `open()`\n\t */\n\tconnect = this.open;\n\t\n\tclose(code: number = CODES.MANUAL, reason = \"manual\", wasClean: boolean = true) {\n\t\t\n\t\tif (this.isClosed)\n\t\t\tthis.#decideReconnect(code);\n\t\telse {\n\t\t\tthis.webSocket!.removeEventListener(\"close\", this.#handleWebSocketClose);\n\t\t\t\n\t\t\tthis.webSocket!.close(code, reason);\n\t\t\t\n\t\t\tthis.#handleWebSocketClose(Object.assign(new Event(\"close\"), {\n\t\t\t\tcode,\n\t\t\t\treason,\n\t\t\t\twasClean\n\t\t\t}));\n\t\t}\n\t\t\n\t}\n\t\n\tclosedWith: { code: number; reason: string; wasClean: boolean } | null = null;\n\t\n\t/**\n\t * Alias for `close()`\n\t */\n\tdisconnect = this.close;\n\t\n\t#queue: (ArrayBufferLike | ArrayBufferView | Blob | string)[] = [];\n\t\n\t#releaseQueue = () => {\n\t\t\n\t\tfor (const message of this.#queue)\n\t\t\tthis.webSocket!.send(message);\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t};\n\t\n\tsend(data: ArrayBufferLike | ArrayBufferView | Blob | string) {\n\t\t\n\t\tif (this.isOpen)\n\t\t\tthis.webSocket!.send(data);\n\t\telse {\n\t\t\tif (!this.#queue.length)\n\t\t\t\tthis.once(\"open\", this.#releaseQueue);\n\t\t\t\n\t\t\tthis.#queue.push(data);\n\t\t}\n\t\t\n\t}\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\t#requestCounter = 0;\n\t\n\tsendRequest<T>(...args: [...unknown[], callback: (error: Error | null, result: T) => void]): this;\n\tsendRequest<T>(...args: unknown[]): Promise<T>;\n\tsendRequest<T>(...args: unknown[]) {\n\t\t\n\t\tconst id = this.#requestCounter++;\n\t\t\n\t\tif (this.#requestCounter >= REQUEST_COUNTER_LIMIT)\n\t\t\tthis.#requestCounter = 0;\n\t\t\n\t\tconst eventName = `message:${REQUEST_HEADERS.RESPONSE}-${id}`;\n\t\t\n\t\tconst lastArg = args.at(-1);\n\t\t\n\t\tif (typeof lastArg == \"function\") {\n\t\t\tthis.once(eventName, lastArg as (error: Error, result: T) => void);\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args.slice(0, -1));\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result: T) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps) as Error);\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t#requestListeners = new Map<string, RequestListener>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener) {\n\t\tthis.#requestListeners.set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `addRequestListener()`\n\t */\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis.#requestListeners.delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `removeRequestListener()`\n\t */\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleRequest = async (id: number, kind: string, ...rest: unknown[]) => {\n\t\tconst listener = this.#requestListeners.get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.apply(this, rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\tthis.sendMessage(`${REQUEST_HEADERS.RESPONSE}-${id}`, requestError, result);\n\t\t\n\t};\n\t\n\t#handleOffline = () => {\n\t\t\n\t\tif (this.isOpen && !this.#isCheckingResponsiveness) {\n\t\t\tthis.#isCheckingResponsiveness = true;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.CHECKING_RESPONSIVENESS);\n\t\t\t\n\t\t\tthis.#unresponsiveTimeout = setTimeout(() => {\n\t\t\t\t\n\t\t\t\tthis.#isCheckingResponsiveness = false;\n\t\t\t\tthis.#isUnresponsive = true;\n\t\t\t\t\n\t\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.UNRESPONSIVE);\n\t\t\t\t\n\t\t\t\tthis.emit(\"unresponsive\");\n\t\t\t\t\n\t\t\t\tthis.#offlineTimeout = setTimeout(() => {\n\t\t\t\t\t\n\t\t\t\t\tthis.#isUnresponsive = false;\n\t\t\t\t\t\n\t\t\t\t\tthis.close(CODES.OFFLINE, \"offline\", false);\n\t\t\t\t\t\n\t\t\t\t}, OFFLINE_TIMEOUT - RESPONSIVENESS_TIMEOUT);\n\t\t\t\t\n\t\t\t}, RESPONSIVENESS_TIMEOUT);\n\t\t\t\n\t\t\tthis.webSocket!.send(\"?\");\n\t\t}\n\t\t\n\t};\n\t\n\tdestroy() {\n\t\t\n\t\tthis.isDestroyed = true;\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t\tthis.close(CODES.NORMAL, \"destroy\");\n\t\t\n\t\tthis.emit(\"destroy\");\n\t\t\n\t\tthis.removeAllListeners();\n\t\t\n\t\tthis.#abortSignal?.removeEventListener(\"abort\", this.#handleAbortSignalAbort);\n\t\t\n\t}\n\t\n\t\n\tstatic CONNECTION_QUALITY = {\n\t\tCLOSED: 0,\n\t\tRECONNECTING: 1,\n\t\tUNRESPONSIVE: 2,\n\t\tCHECKING_RESPONSIVENESS: 3,\n\t\tOPEN: 4\n\t} as const;\n\t\n}\n", "export const HEARTBEAT_INTERVAL = 5_000;\nexport const HEARTBEAT_GAP = 30_000;\nexport const RESPONSIVENESS_TIMEOUT = 1000;\nexport const OFFLINE_TIMEOUT = 5000;\nexport const REQUEST_COUNTER_LIMIT = Number.MAX_SAFE_INTEGER / 2;\n\nexport const CODES = {\n\tNORMAL: 1000,\n\tPROTOCOL_ERROR: 1002,\n\tABNORMAL: 1006,\n\tNO_HEARTBEAT: 3000,\n\tOFFLINE: 3001,\n\tMANUAL: 3500,\n\tREOPEN: 4000\n} as const;\n\nexport const NON_RECONNECTABLE_CODES = [\n\tCODES.PROTOCOL_ERROR,\n\tCODES.MANUAL,\n\tCODES.REOPEN\n];\n\nexport const REQUEST_HEADERS = {\n\tREQUEST: \"~r-q\",\n\tRESPONSE: \"~r-s\"\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["EventEmitter", "noop", "StatefulPromise", "REQUEST_COUNTER_LIMIT", "CODES", "NON_RECONNECTABLE_CODES", "REQUEST_HEADERS", "i", "_isQuiet", "_abortSignal", "_WS_instances", "updateConnectionQuality_fn", "_heartbeatTimeout", "defib_fn", "_unresponsiveTimeout", "_isCheckingResponsiveness", "_offlineTimeout", "_isUnresponsive", "_openPromise", "_wasOpened", "_handleWebSocketOpen", "_handleWebSocketMessage", "_handleWebSocketError", "_reconnectTimeout", "decideReconnect_fn", "_handleWebSocketClose", "_handleAbortSignalAbort", "_queue", "_releaseQueue", "_requestCounter", "_requestListeners", "_handleRequest", "_handleOffline", "_WS", "EventEmitter", "options", "__privateAdd", "__publicField", "__privateSet", "__privateGet", "__privateMethod", "message", "kind", "rest", "REQUEST_HEADERS", "error", "event", "code", "reason", "wasClean", "CODES", "webSocket", "id", "listener", "result", "requestError", "restProps", "url", "name", "protocols", "immediately", "reconnectAfter", "on", "once", "quiet", "signal", "eventName", "noop", "prevURL", "StatefulPromise", "_", "reject", "data", "args", "__privateWrapper", "REQUEST_COUNTER_LIMIT", "lastArg", "resolve", "connectionQuality", "prevConnectionQuality", "NON_RECONNECTABLE_CODES", "WS"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import m from"ws";globalThis.WebSocket=m;import v from"eventemitter3";import{noop as S,StatefulPromise as R}from"@nesvet/n";var f=Number.MAX_SAFE_INTEGER/2,r={NORMAL:1e3,PROTOCOL_ERROR:1002,ABNORMAL:1006,NO_HEARTBEAT:3e3,OFFLINE:3001,MANUAL:3500,REOPEN:4e3},T=[r.PROTOCOL_ERROR,r.MANUAL,r.REOPEN],E={REQUEST:"~r-q",RESPONSE:"~r-s"};var C=0,O=class a extends v{constructor(e={}){super();let{url:t=globalThis.__insite?.wss_url||"/",name:s=(C++).toString(),protocols:o,immediately:i=!0,reconnectAfter:n=2e3,on:h,once:l,quiet:u=!1,signal:d}=e;if(this.url=t,this.name=s,this.protocols=o,this.reconnectAfter=n,h)for(let c in h)h[c]&&this.on(c,h[c]);if(l)for(let c in l)l[c]&&this.once(c,l[c]);this.#c=u,this.#l=d,this.#l?.addEventListener("abort",this.#p,{once:!0}),this.url&&i&&this.open().catch(S),this.#c||this.on("error",c=>c&&console.error("\u{1F50C}\u2757\uFE0F WS",`${this.name}:`,c))}on(e,t){return super.on(e,t)}isWebSocket=!0;isWebSocketServer=!1;isWebSocketServerClient=!1;url;name;protocols;reconnectAfter;#c;#l;isUsed=!1;connectionQuality=0;#n(e){if(e!==this.connectionQuality){let t=this.connectionQuality;this.connectionQuality=e,this.emit("connection-quality-change",this.connectionQuality,t)}}webSocket=null;#o;#N(){clearTimeout(this.#o),this.#o=setTimeout(()=>this.close(r.NO_HEARTBEAT,"no-heartbeat",!1),35e3),this.#t&&(clearTimeout(this.#t),this.#t=void 0),this.#r=!1,this.#s&&(clearTimeout(this.#s),this.#s=void 0),this.#i&&(this.#i=!1,this.emit("responsive")),this.#n(a.CONNECTION_QUALITY.OPEN)}#t;#r=!1;#s;#i=!1;get state(){if(!this.webSocket)return"closed";switch(this.webSocket.readyState){case WebSocket.CONNECTING:return"connecting";case WebSocket.OPEN:return this.#i?"unresponsive":"open";case WebSocket.CLOSING:return"closing"}return"closed"}get isConnecting(){return this.webSocket?.readyState===WebSocket.CONNECTING}get isOpen(){return this.webSocket?.readyState===WebSocket.OPEN}get isClosing(){return this.webSocket?.readyState===WebSocket.CLOSING}get isClosed(){return!this.webSocket}isDestroyed=!1;#e;#E=!1;#S=()=>{this.#E=!0,this.closedWith=null,this.#e.resolve(),this.#N(),this.emit("open")};#O=({data:e})=>{if(this.#N(),e){if(e!=="!")try{let[t,...s]=JSON.parse(e);t===E.REQUEST?this.#v(...s):(this.emit("message",t,...s),this.emit(`message:${t}`,...s))}catch(t){this.#u(t)}}else this.webSocket.send("")};#u=e=>{e instanceof Event&&(e=void 0),this.#e?.isPending&&this.#e.reject(e),this.emit("error",e)};#a;#m(e){this.#a&&clearTimeout(this.#a),this.reconnectAfter&&!T.includes(e)?(process.env.NODE_ENV==="development"&&!this.#c&&console.info(`\u{1F50C} WS ${this.name} will try to reconnect in ${Math.round(this.reconnectAfter/1e3)} seconds`),this.#a=setTimeout(()=>this.open().catch(S),this.reconnectAfter),this.#n(a.CONNECTION_QUALITY.RECONNECTING)):(this.#a=void 0,this.#n(e===r.REOPEN?a.CONNECTION_QUALITY.RECONNECTING:a.CONNECTION_QUALITY.CLOSED))}#d=e=>{let{code:t,reason:s,wasClean:o}=e;if(this.closedWith={code:t,reason:s,wasClean:o},this.#o&&(clearTimeout(this.#o),this.#o=void 0),this.#t&&(clearTimeout(this.#t),this.#t=void 0),this.#r=!1,this.#s&&(clearTimeout(this.#s),this.#s=void 0),this.#i=!1,this.#e?.isPending&&this.#e.reject(new Error("Closed")),process.env.NODE_ENV==="development"&&!this.#c){let n=`\u{1F50C} WS ${this.name} is closed`;t&&(n+=` with code ${t}`),t&&s&&(n+=" and"),s&&(n+=` reason "${s}"`),s==="no-heartbeat"&&(n+=". Going offline"),!o||t===r.ABNORMAL?(n+=" [UNEXPECTED]",console.warn(n)):console.info(n)}let i=this.webSocket;i.removeEventListener("open",this.#S),i.removeEventListener("message",this.#O),i.removeEventListener("error",this.#u),this.#E&&(this.emit("close",e),this.#E=!1),this.webSocket=null,this.#m(t),"navigator"in globalThis&&"addEventListener"in globalThis&&globalThis.removeEventListener("offline",this.#b)};#p=()=>this.#e?.isPending&&this.#e.reject(new DOMException("Operation aborted","AbortError"));async open(e={}){if(this.isDestroyed)throw new Error("WS has been destroyed");if(this.#l?.aborted)throw new DOMException("Operation aborted","AbortError");if(this.closedWith=null,this.#e?.isPending)return this.#e;this.isUsed?this.close(r.REOPEN,"reopen"):this.isUsed=!0;let t;return e.url&&this.url!==e.url&&(t=this.url,this.url=e.url),e.protocols&&(this.protocols=e.protocols),this.#e=new R((s,o)=>{if(this.url){let i=new WebSocket(this.url,this.protocols);i.addEventListener("open",this.#S,{once:!0}),i.addEventListener("message",this.#O),i.addEventListener("error",this.#u),i.addEventListener("close",this.#d,{once:!0}),this.webSocket=i,t&&this.emit("server-change",this.url,t),this.emit("connecting"),"navigator"in globalThis&&"addEventListener"in globalThis&&globalThis.addEventListener("offline",this.#b)}else this.webSocket=null,o(new Error("url prop is not set"))}),this.#e}connect=this.open;close(e=r.MANUAL,t="manual",s=!0){this.isClosed?this.#m(e):(this.webSocket.removeEventListener("close",this.#d),this.webSocket.close(e,t),this.#d(Object.assign(new Event("close"),{code:e,reason:t,wasClean:s})))}closedWith=null;disconnect=this.close;#h=[];#g=()=>{for(let e of this.#h)this.webSocket.send(e);this.#h.length=0};send(e){this.isOpen?this.webSocket.send(e):(this.#h.length||this.once("open",this.#g),this.#h.push(e))}sendMessage(...e){return this.send(JSON.stringify(e))}#f=0;sendRequest(...e){let t=this.#f++;this.#f>=f&&(this.#f=0);let s=`message:${E.RESPONSE}-${t}`,o=e.at(-1);return typeof o=="function"?(this.once(s,o),this.sendMessage(E.REQUEST,t,...e.slice(0,-1)),this):new Promise((i,n)=>{this.once(s,(h,l)=>{if(h){let{message:u,...d}=h;n(Object.assign(new Error(u),d))}else i(l)}),this.sendMessage(E.REQUEST,t,...e)})}#T=new Map;addRequestListener(e,t){return this.#T.set(e,t),this}onRequest=this.addRequestListener;removeRequestListener(e){return this.#T.delete(e),this}offRequest=this.removeRequestListener;#v=async(e,t,...s)=>{let o=this.#T.get(t),i,n=null;if(o)try{i=await o.apply(this,s)}catch(h){if(h instanceof Error){let{message:l,...u}=h;n={message:l,...u}}}else n={message:`Unknown request kind "${t}"`};this.sendMessage(`${E.RESPONSE}-${e}`,n,i)};#b=()=>{this.isOpen&&!this.#r&&(this.#r=!0,this.#n(a.CONNECTION_QUALITY.CHECKING_RESPONSIVENESS),this.#t=setTimeout(()=>{this.#r=!1,this.#i=!0,this.#n(a.CONNECTION_QUALITY.UNRESPONSIVE),this.emit("unresponsive"),this.#s=setTimeout(()=>{this.#i=!1,this.close(r.OFFLINE,"offline",!1)},4e3)},1e3),this.webSocket.send("?"))};destroy(){this.isDestroyed=!0,this.#h.length=0,this.close(r.NORMAL,"destroy"),this.emit("destroy"),this.removeAllListeners(),this.#l?.removeEventListener("abort",this.#p)}static CONNECTION_QUALITY={CLOSED:0,RECONNECTING:1,UNRESPONSIVE:2,CHECKING_RESPONSIVENESS:3,OPEN:4}};export{O as WS};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/client/node/global.ts", "../../../src/client/WS.ts", "
|
|
4
|
-
"sourcesContent": ["import WebSocket from \"ws\";\n\n\ndeclare global {\n\tvar WebSocket: typeof WebSocket;// eslint-disable-line no-var, @typescript-eslint/naming-convention, no-shadow\n}\n\nglobalThis.WebSocket = WebSocket as any;// eslint-disable-line @typescript-eslint/no-explicit-any\n", "import EventEmitter from \"eventemitter3\";\nimport { noop, StatefulPromise } from \"@nesvet/n\";\nimport {\n\tCODES,\n\tHEARTBEAT_GAP,\n\tHEARTBEAT_INTERVAL,\n\tNON_RECONNECTABLE_CODES,\n\tOFFLINE_TIMEOUT,\n\tREQUEST_COUNTER_LIMIT,\n\tREQUEST_HEADERS,\n\tRESPONSIVENESS_TIMEOUT\n} from \"../common\";\nimport type { ConnectionQuality, Options, RequestListener } from \"./types\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nlet i = 0;\n\n\nexport class WS extends EventEmitter {\n\tconstructor(options: Options = {}) {\n\t\tsuper();\n\t\t\n\t\tconst {\n\t\t\turl = globalThis.__insite?.wss_url || \"/\",\n\t\t\tname = (i++).toString(),\n\t\t\tprotocols,\n\t\t\timmediately = true,\n\t\t\treconnectAfter = 2000,\n\t\t\ton,\n\t\t\tonce,\n\t\t\tquiet = false,\n\t\t\tsignal\n\t\t} = options;\n\t\t\n\t\tthis.url = url;\n\t\tthis.name = name;\n\t\t\n\t\tthis.protocols = protocols;\n\t\t\n\t\tthis.reconnectAfter = reconnectAfter;\n\t\t\n\t\tif (on)\n\t\t\tfor (const eventName in on)\n\t\t\t\tif (on[eventName])\n\t\t\t\t\tthis.on(eventName, on[eventName]);\n\t\t\n\t\tif (once)\n\t\t\tfor (const eventName in once)\n\t\t\t\tif (once[eventName])\n\t\t\t\t\tthis.once(eventName, once[eventName]);\n\t\t\n\t\tthis.#isQuiet = quiet;\n\t\t\n\t\tthis.#abortSignal = signal;\n\t\tthis.#abortSignal?.addEventListener(\"abort\", this.#handleAbortSignalAbort, { once: true });\n\t\t\n\t\tif (this.url && immediately)\n\t\t\tthis.open().catch(noop);\n\t\t\n\t\tif (!this.#isQuiet)\n\t\t\tthis.on(\"error\", (error: Error) => error && console.error(\"\uD83D\uDD0C\u2757\uFE0F WS\", `${this.name}:`, error));\n\t\t\n\t}\n\t\n\ton(event: \"connecting\" | \"destroy\" | \"open\" | \"responsive\" | \"unresponsive\", callback: (this: this) => void): this;\n\ton<T extends unknown[]>(event: \"message\", callback: (this: this, kind: string, ...rest: T) => void): this;\n\ton<T extends unknown[]>(event: `message:${string}`, callback: (this: this, ...rest: T) => void): this;\n\ton(event: \"connection-quality-change\", callback: (this: this, connectionQuality: ConnectionQuality, prevConnectionQuality: ConnectionQuality) => void): this;\n\ton(event: \"close\", callback: (this: this, closeEvent: CloseEvent) => void): this;\n\ton(event: \"server-change\", callback: (this: this, url: string, prevURL: string) => void): this;\n\ton(event: \"error\", callback: (this: this, error: Error) => void): this;\n\t\n\ton<T extends string | symbol>(event: T, fn: (...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener);\n\t}\n\t\n\treadonly isWebSocket = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocketServerClient = false;\n\t\n\turl;\n\t\n\treadonly name;\n\t\n\tprotocols?;\n\t\n\treconnectAfter;\n\t\n\t#isQuiet;\n\t\n\t#abortSignal?: AbortSignal;\n\t\n\tisUsed = false;\n\t\n\tconnectionQuality: ConnectionQuality = 0;\n\t\n\t#updateConnectionQuality(connectionQuality: ConnectionQuality) {\n\t\tif (connectionQuality !== this.connectionQuality) {\n\t\t\tconst prevConnectionQuality = this.connectionQuality;\n\t\t\tthis.connectionQuality = connectionQuality;\n\t\t\t\n\t\t\tthis.emit(\"connection-quality-change\", this.connectionQuality, prevConnectionQuality);\n\t\t}\n\t\t\n\t}\n\t\n\twebSocket: WebSocket | null = null;\n\t\n\t#heartbeatTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#defib() {\n\t\t\n\t\tclearTimeout(this.#heartbeatTimeout);\n\t\tthis.#heartbeatTimeout = setTimeout(\n\t\t\t() => this.close(CODES.NO_HEARTBEAT, \"no-heartbeat\", false),\n\t\t\tHEARTBEAT_INTERVAL + HEARTBEAT_GAP\n\t\t);\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#isUnresponsive) {\n\t\t\tthis.#isUnresponsive = false;\n\t\t\t\n\t\t\tthis.emit(\"responsive\");\n\t\t}\n\t\t\n\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.OPEN);\n\t\t\n\t}\n\t\n\t#unresponsiveTimeout?: ReturnType<typeof setTimeout>;\n\t#isCheckingResponsiveness = false;\n\t\n\t#offlineTimeout?: ReturnType<typeof setTimeout>;\n\t#isUnresponsive = false;\n\t\n\tget state() {\n\t\t\n\t\tif (!this.webSocket)\n\t\t\treturn \"closed\";\n\t\t\n\t\tswitch (this.webSocket.readyState) {\n\t\t\tcase WebSocket.CONNECTING:\n\t\t\t\treturn \"connecting\";\n\t\t\t\n\t\t\tcase WebSocket.OPEN:\n\t\t\t\treturn this.#isUnresponsive ? \"unresponsive\" : \"open\";\n\t\t\t\n\t\t\tcase WebSocket.CLOSING:\n\t\t\t\treturn \"closing\";\n\t\t}\n\t\t\n\t\treturn \"closed\";\n\t}\n\t\n\tget isConnecting() {\n\t\treturn this.webSocket?.readyState === WebSocket.CONNECTING;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.webSocket?.readyState === WebSocket.OPEN;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.webSocket?.readyState === WebSocket.CLOSING;\n\t}\n\t\n\tget isClosed() {\n\t\treturn !this.webSocket;\n\t}\n\t\n\tisDestroyed = false;\n\t\n\t#openPromise?: StatefulPromise<void>;\n\t\n\t#wasOpened = false;\n\t\n\t#handleWebSocketOpen = () => {\n\t\t\n\t\tthis.#wasOpened = true;\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tthis.#openPromise!.resolve();\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tthis.emit(\"open\");\n\t\t\n\t};\n\t\n\t#handleWebSocketMessage = ({ data: message }: MessageEvent<string>) => {\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tif (message) {\n\t\t\tif (message !== \"!\")\n\t\t\t\ttry {\n\t\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\t\n\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\tcase REQUEST_HEADERS.REQUEST:\n\t\t\t\t\t\t\tvoid this.#handleRequest(...rest as [ id: number, kind: string, ...rest: unknown[] ]);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthis.emit(\"message\", kind, ...rest);\n\t\t\t\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.#handleWebSocketError(error as Error);\n\t\t\t\t}\n\t\t} else\n\t\t\tthis.webSocket!.send(\"\");\n\t\t\n\t};\n\t\n\t#handleWebSocketError = (error: Error | Event | undefined) => {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(error as Error);\n\t\t\n\t\tthis.emit(\"error\", error);\n\t\t\n\t};\n\t\n\t#reconnectTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#decideReconnect(code: number) {\n\t\t\n\t\tif (this.#reconnectTimeout)\n\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\tif (this.reconnectAfter && !NON_RECONNECTABLE_CODES.includes(code as typeof NON_RECONNECTABLE_CODES[number])) {\n\t\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet)\n\t\t\t\tconsole.info(`\uD83D\uDD0C WS ${this.name} will try to reconnect in ${Math.round(this.reconnectAfter / 1000)} seconds`);\n\t\t\t\n\t\t\tthis.#reconnectTimeout = setTimeout(() => this.open().catch(noop), this.reconnectAfter);\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.RECONNECTING);\n\t\t} else {\n\t\t\tthis.#reconnectTimeout = undefined;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(code === CODES.REOPEN ? WS.CONNECTION_QUALITY.RECONNECTING : WS.CONNECTION_QUALITY.CLOSED);\n\t\t}\n\t\t\n\t}\n\t\n\t#handleWebSocketClose = (event: CloseEvent) => {\n\t\tconst { code, reason, wasClean } = event;\n\t\t\n\t\tthis.closedWith = { code, reason, wasClean };\n\t\t\n\t\tif (this.#heartbeatTimeout) {\n\t\t\tclearTimeout(this.#heartbeatTimeout);\n\t\t\tthis.#heartbeatTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isUnresponsive = false;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(new Error(\"Closed\"));\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet) {\n\t\t\tlet message = `\uD83D\uDD0C WS ${this.name} is closed`;\n\t\t\t\n\t\t\tif (code)\n\t\t\t\tmessage += ` with code ${code}`;\n\t\t\t\n\t\t\tif (code && reason)\n\t\t\t\tmessage += \" and\";\n\t\t\t\n\t\t\tif (reason)\n\t\t\t\tmessage += ` reason \"${reason}\"`;\n\t\t\t\n\t\t\tswitch (reason) {\n\t\t\t\tcase \"no-heartbeat\":\n\t\t\t\t\tmessage += \". Going offline\";\n\t\t\t}\n\t\t\t\n\t\t\tif (!wasClean || code === CODES.ABNORMAL) {\n\t\t\t\tmessage += \" [UNEXPECTED]\";\n\t\t\t\tconsole.warn(message);\n\t\t\t} else\n\t\t\t\tconsole.info(message);\n\t\t}\n\t\t\n\t\tconst webSocket = this.webSocket!;\n\t\t\n\t\twebSocket.removeEventListener(\"open\", this.#handleWebSocketOpen);\n\t\twebSocket.removeEventListener(\"message\", this.#handleWebSocketMessage);\n\t\twebSocket.removeEventListener(\"error\", this.#handleWebSocketError);\n\t\t\n\t\tif (this.#wasOpened) {\n\t\t\tthis.emit(\"close\", event);\n\t\t\t\n\t\t\tthis.#wasOpened = false;\n\t\t}\n\t\t\n\t\tthis.webSocket = null;\n\t\t\n\t\tthis.#decideReconnect(code);\n\t\t\n\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\tglobalThis.removeEventListener(\"offline\", this.#handleOffline);\n\t\t\n\t};\n\t\n\t#handleAbortSignalAbort = () =>\n\t\tthis.#openPromise?.isPending &&\n\t\tthis.#openPromise.reject(new DOMException(\"Operation aborted\", \"AbortError\"));\n\t\n\tasync open(options: Pick<Options, \"protocols\" | \"url\"> = {}): Promise<void> {\n\t\t\n\t\tif (this.isDestroyed)\n\t\t\tthrow new Error(\"WS has been destroyed\");\n\t\t\n\t\tif (this.#abortSignal?.aborted)\n\t\t\tthrow new DOMException(\"Operation aborted\", \"AbortError\");\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\treturn this.#openPromise;\n\t\t\n\t\tif (this.isUsed)\n\t\t\tthis.close(CODES.REOPEN, \"reopen\");\n\t\telse\n\t\t\tthis.isUsed = true;\n\t\t\n\t\tlet prevURL: URL | string | undefined;\n\t\tif (options.url && this.url !== options.url) {\n\t\t\tprevURL = this.url;\n\t\t\tthis.url = options.url;\n\t\t}\n\t\t\n\t\tif (options.protocols)\n\t\t\tthis.protocols = options.protocols;\n\t\t\n\t\tthis.#openPromise = new StatefulPromise((_, reject) => {\n\t\t\t\n\t\t\tif (this.url) {\n\t\t\t\tconst webSocket = new WebSocket(this.url, this.protocols);\n\t\t\t\t\n\t\t\t\twebSocket.addEventListener(\"open\", this.#handleWebSocketOpen, { once: true });\n\t\t\t\twebSocket.addEventListener(\"message\", this.#handleWebSocketMessage);\n\t\t\t\twebSocket.addEventListener(\"error\", this.#handleWebSocketError);\n\t\t\t\twebSocket.addEventListener(\"close\", this.#handleWebSocketClose, { once: true });\n\t\t\t\t\n\t\t\t\tthis.webSocket = webSocket;\n\t\t\t\t\n\t\t\t\tif (prevURL)\n\t\t\t\t\tthis.emit(\"server-change\", this.url, prevURL);\n\t\t\t\t\n\t\t\t\tthis.emit(\"connecting\");\n\t\t\t\t\n\t\t\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\t\t\tglobalThis.addEventListener(\"offline\", this.#handleOffline);\n\t\t\t} else {\n\t\t\t\tthis.webSocket = null;\n\t\t\t\t\n\t\t\t\treject(new Error(\"url prop is not set\"));\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\treturn this.#openPromise;\n\t}\n\t\n\t/**\n\t * Alias for `open()`\n\t */\n\tconnect = this.open;\n\t\n\tclose(code: number = CODES.MANUAL, reason = \"manual\", wasClean: boolean = true) {\n\t\t\n\t\tif (this.isClosed)\n\t\t\tthis.#decideReconnect(code);\n\t\telse {\n\t\t\tthis.webSocket!.removeEventListener(\"close\", this.#handleWebSocketClose);\n\t\t\t\n\t\t\tthis.webSocket!.close(code, reason);\n\t\t\t\n\t\t\tthis.#handleWebSocketClose(Object.assign(new Event(\"close\"), {\n\t\t\t\tcode,\n\t\t\t\treason,\n\t\t\t\twasClean\n\t\t\t}));\n\t\t}\n\t\t\n\t}\n\t\n\tclosedWith: { code: number; reason: string; wasClean: boolean } | null = null;\n\t\n\t/**\n\t * Alias for `close()`\n\t */\n\tdisconnect = this.close;\n\t\n\t#queue: (ArrayBufferLike | ArrayBufferView | Blob | string)[] = [];\n\t\n\t#releaseQueue = () => {\n\t\t\n\t\tfor (const message of this.#queue)\n\t\t\tthis.webSocket!.send(message);\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t};\n\t\n\tsend(data: ArrayBufferLike | ArrayBufferView | Blob | string) {\n\t\t\n\t\tif (this.isOpen)\n\t\t\tthis.webSocket!.send(data);\n\t\telse {\n\t\t\tif (!this.#queue.length)\n\t\t\t\tthis.once(\"open\", this.#releaseQueue);\n\t\t\t\n\t\t\tthis.#queue.push(data);\n\t\t}\n\t\t\n\t}\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\t#requestCounter = 0;\n\t\n\tsendRequest<T>(...args: [...unknown[], callback: (error: Error | null, result: T) => void]): this;\n\tsendRequest<T>(...args: unknown[]): Promise<T>;\n\tsendRequest<T>(...args: unknown[]) {\n\t\t\n\t\tconst id = this.#requestCounter++;\n\t\t\n\t\tif (this.#requestCounter >= REQUEST_COUNTER_LIMIT)\n\t\t\tthis.#requestCounter = 0;\n\t\t\n\t\tconst eventName = `message:${REQUEST_HEADERS.RESPONSE}-${id}`;\n\t\t\n\t\tconst lastArg = args.at(-1);\n\t\t\n\t\tif (typeof lastArg == \"function\") {\n\t\t\tthis.once(eventName, lastArg as (error: Error, result: T) => void);\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args.slice(0, -1));\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result: T) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps) as Error);\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t#requestListeners = new Map<string, RequestListener>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener) {\n\t\tthis.#requestListeners.set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `addRequestListener()`\n\t */\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis.#requestListeners.delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `removeRequestListener()`\n\t */\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleRequest = async (id: number, kind: string, ...rest: unknown[]) => {\n\t\tconst listener = this.#requestListeners.get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.apply(this, rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\tthis.sendMessage(`${REQUEST_HEADERS.RESPONSE}-${id}`, requestError, result);\n\t\t\n\t};\n\t\n\t#handleOffline = () => {\n\t\t\n\t\tif (this.isOpen && !this.#isCheckingResponsiveness) {\n\t\t\tthis.#isCheckingResponsiveness = true;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.CHECKING_RESPONSIVENESS);\n\t\t\t\n\t\t\tthis.#unresponsiveTimeout = setTimeout(() => {\n\t\t\t\t\n\t\t\t\tthis.#isCheckingResponsiveness = false;\n\t\t\t\tthis.#isUnresponsive = true;\n\t\t\t\t\n\t\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.UNRESPONSIVE);\n\t\t\t\t\n\t\t\t\tthis.emit(\"unresponsive\");\n\t\t\t\t\n\t\t\t\tthis.#offlineTimeout = setTimeout(() => {\n\t\t\t\t\t\n\t\t\t\t\tthis.#isUnresponsive = false;\n\t\t\t\t\t\n\t\t\t\t\tthis.close(CODES.OFFLINE, \"offline\", false);\n\t\t\t\t\t\n\t\t\t\t}, OFFLINE_TIMEOUT - RESPONSIVENESS_TIMEOUT);\n\t\t\t\t\n\t\t\t}, RESPONSIVENESS_TIMEOUT);\n\t\t\t\n\t\t\tthis.webSocket!.send(\"?\");\n\t\t}\n\t\t\n\t};\n\t\n\tdestroy() {\n\t\t\n\t\tthis.isDestroyed = true;\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t\tthis.close(CODES.NORMAL, \"destroy\");\n\t\t\n\t\tthis.emit(\"destroy\");\n\t\t\n\t\tthis.removeAllListeners();\n\t\t\n\t\tthis.#abortSignal?.removeEventListener(\"abort\", this.#handleAbortSignalAbort);\n\t\t\n\t}\n\t\n\t\n\tstatic CONNECTION_QUALITY = {\n\t\tCLOSED: 0,\n\t\tRECONNECTING: 1,\n\t\tUNRESPONSIVE: 2,\n\t\tCHECKING_RESPONSIVENESS: 3,\n\t\tOPEN: 4\n\t} as const;\n\t\n}\n", "export function noop() { /**/ }\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\n\ntype Value<T> = PromiseLike<T> | T;\ntype Resolve<T> = (value: Value<T>) => void;\ntype Reject = (reason?: any) => void;\n\ntype Options = {\n\tsignal?: AbortSignal;\n\ttimeout?: number;\n};\n\nconst nativesMap = new WeakMap<StatefulPromise<any>, { resolve: Resolve<any>; reject: Reject }>();\n\n\nexport class StatefulPromise<T> extends Promise<T> {\n\tconstructor(\n\t\texecutor?: (resolve: Resolve<T>, reject: Reject) => void,\n\t\toptions?: Options\n\t) {\n\t\tlet nativeResolve: Resolve<T>;\n\t\tlet nativeReject: Reject;\n\t\t\n\t\tsuper((resolve, reject) => {\n\t\t\tnativeResolve = resolve;\n\t\t\tnativeReject = reject;\n\t\t\t\n\t\t});\n\t\t\n\t\tnativesMap.set(this, { resolve: nativeResolve!, reject: nativeReject! });\n\t\t\n\t\tif (options?.signal)\n\t\t\tif (options.signal.aborted)\n\t\t\t\tthis.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\t\t\telse {\n\t\t\t\tconst abortListener = () => this.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\t\t\t\t\n\t\t\t\toptions.signal.addEventListener(\"abort\", abortListener);\n\t\t\t\t\n\t\t\t\tthis.finally(() => options.signal?.removeEventListener(\"abort\", abortListener));\n\t\t\t}\n\t\t\n\t\tif (typeof options?.timeout === \"number\" && Number.isFinite(options.timeout)) {\n\t\t\tconst timeout = setTimeout(() => this.reject(new DOMException(\"Timeout exceeded\", \"TimeoutError\")), options.timeout);\n\t\t\t\n\t\t\tthis.finally(() => clearTimeout(timeout));\n\t\t}\n\t\t\n\t\texecutor?.(this.resolve, this.reject);\n\t\t\n\t}\n\t\n\tisPending = true;\n\tisFulfilled = false;\n\tisRejected = false;\n\t\n\tstate: \"fulfilled\" | \"pending\" | \"rejected\" = \"pending\";\n\t\n\tresult?: T | unknown;\n\t\n\treadonly resolve = (value: Value<T>) => {\n\t\t\n\t\tif (this.isPending) {\n\t\t\tthis.isPending = false;\n\t\t\tthis.isFulfilled = true;\n\t\t\tthis.state = \"fulfilled\";\n\t\t\tthis.result = value;\n\t\t\t\n\t\t\tconst native = nativesMap.get(this);\n\t\t\t\n\t\t\tif (native) {\n\t\t\t\tnative.resolve.call(this, value);\n\t\t\t\tnativesMap.delete(this);\n\t\t\t}\n\t\t}\n\t\t\n\t};\n\t\n\treadonly reject = (reason?: any) => {\n\t\t\n\t\tif (this.isPending) {\n\t\t\tthis.isPending = false;\n\t\t\tthis.isRejected = true;\n\t\t\tthis.state = \"rejected\";\n\t\t\tthis.result = reason;\n\t\t\t\n\t\t\tconst native = nativesMap.get(this);\n\t\t\t\n\t\t\tif (native) {\n\t\t\t\tnative.reject.call(this, reason);\n\t\t\t\tnativesMap.delete(this);\n\t\t\t}\n\t\t}\n\t\t\n\t};\n\t\n\t\n\tstatic resolved<U>(value: U): StatefulPromise<U> {\n\t\treturn new StatefulPromise<U>(resolve => resolve(value));\n\t}\n\t\n\tstatic rejected(reason: unknown): StatefulPromise<never> {\n\t\treturn new StatefulPromise((_, reject) => reject(reason));\n\t}\n\t\n}\n", "import { noop } from \"./noop.js\";\nimport { StatefulPromise } from \"./StatefulPromise.js\";\n\n\ntype Callback = (...args: any[]) => unknown;// eslint-disable-line @typescript-eslint/no-explicit-any\ntype FunctionOrBoolean = (() => unknown) | boolean;\ntype Options = { leading?: FunctionOrBoolean; maxWait?: number; trailing?: FunctionOrBoolean };\n\ntype DebouncedFunction<C extends Callback> = {\n\t(this: ThisParameterType<C>, ...args: Parameters<C>): Promise<Awaited<ReturnType<C>>>;\n};\n\nexport type Debounced<C extends Callback, R extends ReturnType<C>> = DebouncedFunction<C> & {\n\tcallback: C;\n\tpromise: StatefulPromise<R>;\n\tresolve: (value: R) => void;\n\treject: (reason?: unknown) => void;\n\trun(): Promise<R>;\n\tclear(shouldRun?: boolean): Promise<void>;\n};\n\n\nexport function debounce<C extends Callback, R extends ReturnType<C>>(callback: C, limit = 0, options: Options = {}) {\n\tlet { leading = false, trailing = true } = options;\n\tconst { maxWait = Infinity } = options;\n\t\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\tlet maxWaitTimeout: ReturnType<typeof setTimeout> | undefined;\n\tlet end: number | undefined;\n\tlet context: ThisParameterType<C>;\n\tlet args: unknown[];\n\tlet initial: FunctionOrBoolean;\n\tlet final: FunctionOrBoolean;\n\tlet result: R;\n\t\n\tconst expired = async () => {\n\t\t\n\t\tconst n = Date.now();\n\t\t\n\t\tif (n >= end!) {\n\t\t\ttimeout = undefined;\n\t\t\tend = undefined;\n\t\t\t\n\t\t\tclearTimeout(maxWaitTimeout);\n\t\t\tmaxWaitTimeout = undefined;\n\t\t\t\n\t\t\tif (typeof final == \"function\")\n\t\t\t\tawait final();\n\t\t\t\n\t\t\tdebounced.resolve(result);\n\t\t\t\n\t\t\tinitial = leading;\n\t\t} else {\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = setTimeout(expired, end! - n);\n\t\t}\n\t\t\n\t};\n\t\n\tconst maxWaitExpired = Number.isFinite(maxWait) ? () => {\n\t\t\n\t\tif (final === run)\n\t\t\tfinal = false;\n\t\t\n\t\trun();\n\t\t\n\t\tmaxWaitTimeout = setTimeout(maxWaitExpired as TimerHandler, maxWait);\n\t\t\n\t} : null;\n\t\n\tasync function run() {\n\t\ttry {\n\t\t\tresult = await callback.apply(context, args) as R;\n\t\t\t\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tdebounced.reject(error);\n\t\t\t\n\t\t\tthrow error;\n\t\t}\n\t}\n\t\n\tif (leading && typeof leading == \"boolean\")\n\t\tleading = run;\n\tinitial = leading;\n\t\n\tif (trailing && typeof trailing == \"boolean\")\n\t\ttrailing = run;\n\tfinal = trailing;\n\t\n\tconst debounced: Debounced<C, R> = Object.assign(function (..._args) {\n\t\targs = _args;\n\t\tcontext = this;// eslint-disable-line no-invalid-this\n\t\t\n\t\tend = Date.now() + limit;\n\t\tfinal = trailing;\n\t\t\n\t\tif (!debounced.promise.isPending)\n\t\t\tdebounced.promise = new StatefulPromise<R>((resolve, reject) => {\n\t\t\t\tdebounced.resolve = resolve;\n\t\t\t\tdebounced.reject = reject;\n\t\t\t\t\n\t\t\t\tif (typeof initial == \"function\") {\n\t\t\t\t\tinitial();\n\t\t\t\t\t\n\t\t\t\t\tinitial = false;\n\t\t\t\t\t\n\t\t\t\t\tif (final === run)\n\t\t\t\t\t\tfinal = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!timeout) {\n\t\t\t\t\ttimeout = setTimeout(expired, limit);\n\t\t\t\t\t\n\t\t\t\t\tif (maxWaitExpired)\n\t\t\t\t\t\tmaxWaitTimeout = setTimeout(maxWaitExpired, maxWait);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t});\n\t\t\n\t\treturn debounced.promise;\n\t} as DebouncedFunction<C>, {\n\t\tcallback,\n\t\tpromise: StatefulPromise.resolved(undefined as unknown as R),\n\t\tresolve: noop,\n\t\treject: noop,\n\t\trun,\n\t\tclear: async (shouldRun?: boolean) => {\n\t\t\t\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = undefined;\n\t\t\t\n\t\t\tclearTimeout(maxWaitTimeout);\n\t\t\tmaxWaitTimeout = undefined;\n\t\t\t\n\t\t\tdebounced.resolve(shouldRun ? await run() : result);\n\t\t\t\n\t\t}\n\t});\n\t\n\treturn debounced;\n}\n\n\ndebounce.noop = Object.assign(() => { /**/ }, {\n\tcallback: noop,\n\tpromise: StatefulPromise.resolved(undefined), // eslint-disable-line unicorn/no-useless-undefined\n\tresolve: noop,\n\treject: noop,\n\trun: noop,\n\tclear: noop\n}) as Debounced<() => void, void>;\n\n\nexport function throttle(callback: Callback, limit?: number, options?: Options) {\n\treturn debounce(callback, limit, {\n\t\tmaxWait: limit,\n\t\tleading: true,\n\t\ttrailing: true,\n\t\t...options\n\t});\n}\n", "export function howmuch(number: [] | number, one: string, two: string, five: boolean | string, shouldPrintNumber = true) {\n\tif (Array.isArray(number))\n\t\tnumber = number.length;\n\t\n\tif (typeof five != \"string\") {\n\t\tshouldPrintNumber = five ?? true;\n\t\tfive = two;\n\t}\n\t\n\t\n\treturn (shouldPrintNumber ? `${number}\u00A0` : \"\") + howmuch.raw(number, one, two, five);\n}\n\nhowmuch.raw = (number: number, one: string, two: string, five = two) => {\n\tnumber = Math.abs(number);\n\tconst u = number % 10;\n\tconst d = number % 100;\n\t\n\treturn (\n\t\t(u === 1 && d !== 11) ?\n\t\t\tone :\n\t\t\t((u >= 2 && u <= 4) && !(d >= 12 && d <= 15)) ?\n\t\t\t\ttwo :\n\t\t\t\tfive\n\t);\n};\n", "export const HEARTBEAT_INTERVAL = 5_000;\nexport const HEARTBEAT_GAP = 30_000;\nexport const RESPONSIVENESS_TIMEOUT = 1000;\nexport const OFFLINE_TIMEOUT = 5000;\nexport const REQUEST_COUNTER_LIMIT = Number.MAX_SAFE_INTEGER / 2;\n\nexport const CODES = {\n\tNORMAL: 1000,\n\tPROTOCOL_ERROR: 1002,\n\tABNORMAL: 1006,\n\tNO_HEARTBEAT: 3000,\n\tOFFLINE: 3001,\n\tMANUAL: 3500,\n\tREOPEN: 4000\n} as const;\n\nexport const NON_RECONNECTABLE_CODES = [\n\tCODES.PROTOCOL_ERROR,\n\tCODES.MANUAL,\n\tCODES.REOPEN\n];\n\nexport const REQUEST_HEADERS = {\n\tREQUEST: \"~r-q\",\n\tRESPONSE: \"~r-s\"\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["WebSocket", "EventEmitter", "noop", "
|
|
3
|
+
"sources": ["../../../src/client/node/global.ts", "../../../src/client/WS.ts", "../../../src/common.ts"],
|
|
4
|
+
"sourcesContent": ["import WebSocket from \"ws\";\n\n\ndeclare global {\n\tvar WebSocket: typeof WebSocket;// eslint-disable-line @typescript-eslint/naming-convention\n}\n\nglobalThis.WebSocket = WebSocket as any;// eslint-disable-line @typescript-eslint/no-explicit-any\n", "import EventEmitter from \"eventemitter3\";\nimport { noop, StatefulPromise } from \"@nesvet/n\";\nimport {\n\tCODES,\n\tHEARTBEAT_GAP,\n\tHEARTBEAT_INTERVAL,\n\tNON_RECONNECTABLE_CODES,\n\tOFFLINE_TIMEOUT,\n\tREQUEST_COUNTER_LIMIT,\n\tREQUEST_HEADERS,\n\tRESPONSIVENESS_TIMEOUT\n} from \"../common\";\nimport type { ConnectionQuality, Options, RequestListener } from \"./types\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nlet i = 0;\n\n\nexport class WS extends EventEmitter {\n\tconstructor(options: Options = {}) {\n\t\tsuper();\n\t\t\n\t\tconst {\n\t\t\turl = globalThis.__insite?.wss_url || \"/\",\n\t\t\tname = (i++).toString(),\n\t\t\tprotocols,\n\t\t\timmediately = true,\n\t\t\treconnectAfter = 2000,\n\t\t\ton,\n\t\t\tonce,\n\t\t\tquiet = false,\n\t\t\tsignal\n\t\t} = options;\n\t\t\n\t\tthis.url = url;\n\t\tthis.name = name;\n\t\t\n\t\tthis.protocols = protocols;\n\t\t\n\t\tthis.reconnectAfter = reconnectAfter;\n\t\t\n\t\tif (on)\n\t\t\tfor (const eventName in on)\n\t\t\t\tif (on[eventName])\n\t\t\t\t\tthis.on(eventName, on[eventName]);\n\t\t\n\t\tif (once)\n\t\t\tfor (const eventName in once)\n\t\t\t\tif (once[eventName])\n\t\t\t\t\tthis.once(eventName, once[eventName]);\n\t\t\n\t\tthis.#isQuiet = quiet;\n\t\t\n\t\tthis.#abortSignal = signal;\n\t\tthis.#abortSignal?.addEventListener(\"abort\", this.#handleAbortSignalAbort, { once: true });\n\t\t\n\t\tif (this.url && immediately)\n\t\t\tthis.open().catch(noop);\n\t\t\n\t\tif (!this.#isQuiet)\n\t\t\tthis.on(\"error\", (error: Error) => error && console.error(\"\uD83D\uDD0C\u2757\uFE0F WS\", `${this.name}:`, error));\n\t\t\n\t}\n\t\n\ton(event: \"connecting\" | \"destroy\" | \"open\" | \"responsive\" | \"unresponsive\", callback: (this: this) => void): this;\n\ton<T extends unknown[]>(event: \"message\", callback: (this: this, kind: string, ...rest: T) => void): this;\n\ton<T extends unknown[]>(event: `message:${string}`, callback: (this: this, ...rest: T) => void): this;\n\ton(event: \"connection-quality-change\", callback: (this: this, connectionQuality: ConnectionQuality, prevConnectionQuality: ConnectionQuality) => void): this;\n\ton(event: \"close\", callback: (this: this, closeEvent: CloseEvent) => void): this;\n\ton(event: \"server-change\", callback: (this: this, url: string, prevURL: string) => void): this;\n\ton(event: \"error\", callback: (this: this, error: Error) => void): this;\n\t\n\ton<T extends string | symbol>(event: T, fn: (...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener);\n\t}\n\t\n\treadonly isWebSocket = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocketServerClient = false;\n\t\n\turl;\n\t\n\treadonly name;\n\t\n\tprotocols?;\n\t\n\treconnectAfter;\n\t\n\t#isQuiet;\n\t\n\t#abortSignal?: AbortSignal;\n\t\n\tisUsed = false;\n\t\n\tconnectionQuality: ConnectionQuality = 0;\n\t\n\t#updateConnectionQuality(connectionQuality: ConnectionQuality) {\n\t\tif (connectionQuality !== this.connectionQuality) {\n\t\t\tconst prevConnectionQuality = this.connectionQuality;\n\t\t\tthis.connectionQuality = connectionQuality;\n\t\t\t\n\t\t\tthis.emit(\"connection-quality-change\", this.connectionQuality, prevConnectionQuality);\n\t\t}\n\t\t\n\t}\n\t\n\twebSocket: WebSocket | null = null;\n\t\n\t#heartbeatTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#defib() {\n\t\t\n\t\tclearTimeout(this.#heartbeatTimeout);\n\t\tthis.#heartbeatTimeout = setTimeout(\n\t\t\t() => this.close(CODES.NO_HEARTBEAT, \"no-heartbeat\", false),\n\t\t\tHEARTBEAT_INTERVAL + HEARTBEAT_GAP\n\t\t);\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#isUnresponsive) {\n\t\t\tthis.#isUnresponsive = false;\n\t\t\t\n\t\t\tthis.emit(\"responsive\");\n\t\t}\n\t\t\n\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.OPEN);\n\t\t\n\t}\n\t\n\t#unresponsiveTimeout?: ReturnType<typeof setTimeout>;\n\t#isCheckingResponsiveness = false;\n\t\n\t#offlineTimeout?: ReturnType<typeof setTimeout>;\n\t#isUnresponsive = false;\n\t\n\tget state() {\n\t\t\n\t\tif (!this.webSocket)\n\t\t\treturn \"closed\";\n\t\t\n\t\tswitch (this.webSocket.readyState) {\n\t\t\tcase WebSocket.CONNECTING:\n\t\t\t\treturn \"connecting\";\n\t\t\t\n\t\t\tcase WebSocket.OPEN:\n\t\t\t\treturn this.#isUnresponsive ? \"unresponsive\" : \"open\";\n\t\t\t\n\t\t\tcase WebSocket.CLOSING:\n\t\t\t\treturn \"closing\";\n\t\t}\n\t\t\n\t\treturn \"closed\";\n\t}\n\t\n\tget isConnecting() {\n\t\treturn this.webSocket?.readyState === WebSocket.CONNECTING;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.webSocket?.readyState === WebSocket.OPEN;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.webSocket?.readyState === WebSocket.CLOSING;\n\t}\n\t\n\tget isClosed() {\n\t\treturn !this.webSocket;\n\t}\n\t\n\tisDestroyed = false;\n\t\n\t#openPromise?: StatefulPromise<void>;\n\t\n\t#wasOpened = false;\n\t\n\t#handleWebSocketOpen = () => {\n\t\t\n\t\tthis.#wasOpened = true;\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tthis.#openPromise!.resolve();\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tthis.emit(\"open\");\n\t\t\n\t};\n\t\n\t#handleWebSocketMessage = ({ data: message }: MessageEvent<string>) => {\n\t\t\n\t\tthis.#defib();\n\t\t\n\t\tif (message) {\n\t\t\tif (message !== \"!\")\n\t\t\t\ttry {\n\t\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\t\n\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\tcase REQUEST_HEADERS.REQUEST:\n\t\t\t\t\t\t\tvoid this.#handleRequest(...rest as [ id: number, kind: string, ...rest: unknown[] ]);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthis.emit(\"message\", kind, ...rest);\n\t\t\t\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.#handleWebSocketError(error as Error);\n\t\t\t\t}\n\t\t} else\n\t\t\tthis.webSocket!.send(\"\");\n\t\t\n\t};\n\t\n\t#handleWebSocketError = (error: Error | Event | undefined) => {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(error as Error);\n\t\t\n\t\tthis.emit(\"error\", error);\n\t\t\n\t};\n\t\n\t#reconnectTimeout?: ReturnType<typeof setTimeout>;\n\t\n\t#decideReconnect(code: number) {\n\t\t\n\t\tif (this.#reconnectTimeout)\n\t\t\tclearTimeout(this.#reconnectTimeout);\n\t\t\n\t\tif (this.reconnectAfter && !NON_RECONNECTABLE_CODES.includes(code as typeof NON_RECONNECTABLE_CODES[number])) {\n\t\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet)\n\t\t\t\tconsole.info(`\uD83D\uDD0C WS ${this.name} will try to reconnect in ${Math.round(this.reconnectAfter / 1000)} seconds`);\n\t\t\t\n\t\t\tthis.#reconnectTimeout = setTimeout(() => this.open().catch(noop), this.reconnectAfter);\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.RECONNECTING);\n\t\t} else {\n\t\t\tthis.#reconnectTimeout = undefined;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(code === CODES.REOPEN ? WS.CONNECTION_QUALITY.RECONNECTING : WS.CONNECTION_QUALITY.CLOSED);\n\t\t}\n\t\t\n\t}\n\t\n\t#handleWebSocketClose = (event: CloseEvent) => {\n\t\tconst { code, reason, wasClean } = event;\n\t\t\n\t\tthis.closedWith = { code, reason, wasClean };\n\t\t\n\t\tif (this.#heartbeatTimeout) {\n\t\t\tclearTimeout(this.#heartbeatTimeout);\n\t\t\tthis.#heartbeatTimeout = undefined;\n\t\t}\n\t\t\n\t\tif (this.#unresponsiveTimeout) {\n\t\t\tclearTimeout(this.#unresponsiveTimeout);\n\t\t\tthis.#unresponsiveTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isCheckingResponsiveness = false;\n\t\t\n\t\tif (this.#offlineTimeout) {\n\t\t\tclearTimeout(this.#offlineTimeout);\n\t\t\tthis.#offlineTimeout = undefined;\n\t\t}\n\t\t\n\t\tthis.#isUnresponsive = false;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\tthis.#openPromise.reject(new Error(\"Closed\"));\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\" && !this.#isQuiet) {\n\t\t\tlet message = `\uD83D\uDD0C WS ${this.name} is closed`;\n\t\t\t\n\t\t\tif (code)\n\t\t\t\tmessage += ` with code ${code}`;\n\t\t\t\n\t\t\tif (code && reason)\n\t\t\t\tmessage += \" and\";\n\t\t\t\n\t\t\tif (reason)\n\t\t\t\tmessage += ` reason \"${reason}\"`;\n\t\t\t\n\t\t\tswitch (reason) {\n\t\t\t\tcase \"no-heartbeat\":\n\t\t\t\t\tmessage += \". Going offline\";\n\t\t\t}\n\t\t\t\n\t\t\tif (!wasClean || code === CODES.ABNORMAL) {\n\t\t\t\tmessage += \" [UNEXPECTED]\";\n\t\t\t\tconsole.warn(message);\n\t\t\t} else\n\t\t\t\tconsole.info(message);\n\t\t}\n\t\t\n\t\tconst webSocket = this.webSocket!;\n\t\t\n\t\twebSocket.removeEventListener(\"open\", this.#handleWebSocketOpen);\n\t\twebSocket.removeEventListener(\"message\", this.#handleWebSocketMessage);\n\t\twebSocket.removeEventListener(\"error\", this.#handleWebSocketError);\n\t\t\n\t\tif (this.#wasOpened) {\n\t\t\tthis.emit(\"close\", event);\n\t\t\t\n\t\t\tthis.#wasOpened = false;\n\t\t}\n\t\t\n\t\tthis.webSocket = null;\n\t\t\n\t\tthis.#decideReconnect(code);\n\t\t\n\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\tglobalThis.removeEventListener(\"offline\", this.#handleOffline);\n\t\t\n\t};\n\t\n\t#handleAbortSignalAbort = () =>\n\t\tthis.#openPromise?.isPending &&\n\t\tthis.#openPromise.reject(new DOMException(\"Operation aborted\", \"AbortError\"));\n\t\n\tasync open(options: Pick<Options, \"protocols\" | \"url\"> = {}): Promise<void> {\n\t\t\n\t\tif (this.isDestroyed)\n\t\t\tthrow new Error(\"WS has been destroyed\");\n\t\t\n\t\tif (this.#abortSignal?.aborted)\n\t\t\tthrow new DOMException(\"Operation aborted\", \"AbortError\");\n\t\t\n\t\tthis.closedWith = null;\n\t\t\n\t\tif (this.#openPromise?.isPending)\n\t\t\treturn this.#openPromise;\n\t\t\n\t\tif (this.isUsed)\n\t\t\tthis.close(CODES.REOPEN, \"reopen\");\n\t\telse\n\t\t\tthis.isUsed = true;\n\t\t\n\t\tlet prevURL: URL | string | undefined;\n\t\tif (options.url && this.url !== options.url) {\n\t\t\tprevURL = this.url;\n\t\t\tthis.url = options.url;\n\t\t}\n\t\t\n\t\tif (options.protocols)\n\t\t\tthis.protocols = options.protocols;\n\t\t\n\t\tthis.#openPromise = new StatefulPromise((_, reject) => {\n\t\t\t\n\t\t\tif (this.url) {\n\t\t\t\tconst webSocket = new WebSocket(this.url, this.protocols);\n\t\t\t\t\n\t\t\t\twebSocket.addEventListener(\"open\", this.#handleWebSocketOpen, { once: true });\n\t\t\t\twebSocket.addEventListener(\"message\", this.#handleWebSocketMessage);\n\t\t\t\twebSocket.addEventListener(\"error\", this.#handleWebSocketError);\n\t\t\t\twebSocket.addEventListener(\"close\", this.#handleWebSocketClose, { once: true });\n\t\t\t\t\n\t\t\t\tthis.webSocket = webSocket;\n\t\t\t\t\n\t\t\t\tif (prevURL)\n\t\t\t\t\tthis.emit(\"server-change\", this.url, prevURL);\n\t\t\t\t\n\t\t\t\tthis.emit(\"connecting\");\n\t\t\t\t\n\t\t\t\tif (\"navigator\" in globalThis && \"addEventListener\" in globalThis)\n\t\t\t\t\tglobalThis.addEventListener(\"offline\", this.#handleOffline);\n\t\t\t} else {\n\t\t\t\tthis.webSocket = null;\n\t\t\t\t\n\t\t\t\treject(new Error(\"url prop is not set\"));\n\t\t\t}\n\t\t\t\n\t\t});\n\t\t\n\t\treturn this.#openPromise;\n\t}\n\t\n\t/**\n\t * Alias for `open()`\n\t */\n\tconnect = this.open;\n\t\n\tclose(code: number = CODES.MANUAL, reason = \"manual\", wasClean: boolean = true) {\n\t\t\n\t\tif (this.isClosed)\n\t\t\tthis.#decideReconnect(code);\n\t\telse {\n\t\t\tthis.webSocket!.removeEventListener(\"close\", this.#handleWebSocketClose);\n\t\t\t\n\t\t\tthis.webSocket!.close(code, reason);\n\t\t\t\n\t\t\tthis.#handleWebSocketClose(Object.assign(new Event(\"close\"), {\n\t\t\t\tcode,\n\t\t\t\treason,\n\t\t\t\twasClean\n\t\t\t}));\n\t\t}\n\t\t\n\t}\n\t\n\tclosedWith: { code: number; reason: string; wasClean: boolean } | null = null;\n\t\n\t/**\n\t * Alias for `close()`\n\t */\n\tdisconnect = this.close;\n\t\n\t#queue: (ArrayBufferLike | ArrayBufferView | Blob | string)[] = [];\n\t\n\t#releaseQueue = () => {\n\t\t\n\t\tfor (const message of this.#queue)\n\t\t\tthis.webSocket!.send(message);\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t};\n\t\n\tsend(data: ArrayBufferLike | ArrayBufferView | Blob | string) {\n\t\t\n\t\tif (this.isOpen)\n\t\t\tthis.webSocket!.send(data);\n\t\telse {\n\t\t\tif (!this.#queue.length)\n\t\t\t\tthis.once(\"open\", this.#releaseQueue);\n\t\t\t\n\t\t\tthis.#queue.push(data);\n\t\t}\n\t\t\n\t}\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\t#requestCounter = 0;\n\t\n\tsendRequest<T>(...args: [...unknown[], callback: (error: Error | null, result: T) => void]): this;\n\tsendRequest<T>(...args: unknown[]): Promise<T>;\n\tsendRequest<T>(...args: unknown[]) {\n\t\t\n\t\tconst id = this.#requestCounter++;\n\t\t\n\t\tif (this.#requestCounter >= REQUEST_COUNTER_LIMIT)\n\t\t\tthis.#requestCounter = 0;\n\t\t\n\t\tconst eventName = `message:${REQUEST_HEADERS.RESPONSE}-${id}`;\n\t\t\n\t\tconst lastArg = args.at(-1);\n\t\t\n\t\tif (typeof lastArg == \"function\") {\n\t\t\tthis.once(eventName, lastArg as (error: Error, result: T) => void);\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args.slice(0, -1));\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result: T) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps) as Error);\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t#requestListeners = new Map<string, RequestListener>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener) {\n\t\tthis.#requestListeners.set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `addRequestListener()`\n\t */\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis.#requestListeners.delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `removeRequestListener()`\n\t */\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleRequest = async (id: number, kind: string, ...rest: unknown[]) => {\n\t\tconst listener = this.#requestListeners.get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.apply(this, rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\tthis.sendMessage(`${REQUEST_HEADERS.RESPONSE}-${id}`, requestError, result);\n\t\t\n\t};\n\t\n\t#handleOffline = () => {\n\t\t\n\t\tif (this.isOpen && !this.#isCheckingResponsiveness) {\n\t\t\tthis.#isCheckingResponsiveness = true;\n\t\t\t\n\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.CHECKING_RESPONSIVENESS);\n\t\t\t\n\t\t\tthis.#unresponsiveTimeout = setTimeout(() => {\n\t\t\t\t\n\t\t\t\tthis.#isCheckingResponsiveness = false;\n\t\t\t\tthis.#isUnresponsive = true;\n\t\t\t\t\n\t\t\t\tthis.#updateConnectionQuality(WS.CONNECTION_QUALITY.UNRESPONSIVE);\n\t\t\t\t\n\t\t\t\tthis.emit(\"unresponsive\");\n\t\t\t\t\n\t\t\t\tthis.#offlineTimeout = setTimeout(() => {\n\t\t\t\t\t\n\t\t\t\t\tthis.#isUnresponsive = false;\n\t\t\t\t\t\n\t\t\t\t\tthis.close(CODES.OFFLINE, \"offline\", false);\n\t\t\t\t\t\n\t\t\t\t}, OFFLINE_TIMEOUT - RESPONSIVENESS_TIMEOUT);\n\t\t\t\t\n\t\t\t}, RESPONSIVENESS_TIMEOUT);\n\t\t\t\n\t\t\tthis.webSocket!.send(\"?\");\n\t\t}\n\t\t\n\t};\n\t\n\tdestroy() {\n\t\t\n\t\tthis.isDestroyed = true;\n\t\t\n\t\tthis.#queue.length = 0;\n\t\t\n\t\tthis.close(CODES.NORMAL, \"destroy\");\n\t\t\n\t\tthis.emit(\"destroy\");\n\t\t\n\t\tthis.removeAllListeners();\n\t\t\n\t\tthis.#abortSignal?.removeEventListener(\"abort\", this.#handleAbortSignalAbort);\n\t\t\n\t}\n\t\n\t\n\tstatic CONNECTION_QUALITY = {\n\t\tCLOSED: 0,\n\t\tRECONNECTING: 1,\n\t\tUNRESPONSIVE: 2,\n\t\tCHECKING_RESPONSIVENESS: 3,\n\t\tOPEN: 4\n\t} as const;\n\t\n}\n", "export const HEARTBEAT_INTERVAL = 5_000;\nexport const HEARTBEAT_GAP = 30_000;\nexport const RESPONSIVENESS_TIMEOUT = 1000;\nexport const OFFLINE_TIMEOUT = 5000;\nexport const REQUEST_COUNTER_LIMIT = Number.MAX_SAFE_INTEGER / 2;\n\nexport const CODES = {\n\tNORMAL: 1000,\n\tPROTOCOL_ERROR: 1002,\n\tABNORMAL: 1006,\n\tNO_HEARTBEAT: 3000,\n\tOFFLINE: 3001,\n\tMANUAL: 3500,\n\tREOPEN: 4000\n} as const;\n\nexport const NON_RECONNECTABLE_CODES = [\n\tCODES.PROTOCOL_ERROR,\n\tCODES.MANUAL,\n\tCODES.REOPEN\n];\n\nexport const REQUEST_HEADERS = {\n\tREQUEST: \"~r-q\",\n\tRESPONSE: \"~r-s\"\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["WebSocket", "EventEmitter", "noop", "StatefulPromise", "REQUEST_COUNTER_LIMIT", "CODES", "NON_RECONNECTABLE_CODES", "REQUEST_HEADERS", "i", "WS", "_WS", "EventEmitter", "options", "url", "name", "protocols", "immediately", "reconnectAfter", "on", "once", "quiet", "signal", "eventName", "#isQuiet", "#abortSignal", "#handleAbortSignalAbort", "noop", "error", "event", "listener", "#updateConnectionQuality", "connectionQuality", "prevConnectionQuality", "#heartbeatTimeout", "#defib", "CODES", "#unresponsiveTimeout", "#isCheckingResponsiveness", "#offlineTimeout", "#isUnresponsive", "#openPromise", "#wasOpened", "#handleWebSocketOpen", "#handleWebSocketMessage", "message", "kind", "rest", "REQUEST_HEADERS", "#handleRequest", "#handleWebSocketError", "#reconnectTimeout", "#decideReconnect", "code", "NON_RECONNECTABLE_CODES", "#handleWebSocketClose", "reason", "wasClean", "webSocket", "#handleOffline", "prevURL", "StatefulPromise", "_", "reject", "#queue", "#releaseQueue", "data", "args", "#requestCounter", "id", "REQUEST_COUNTER_LIMIT", "lastArg", "resolve", "result", "restProps", "#requestListeners", "requestError"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AbilitiesSchema } from "insite-common";
|
|
2
|
+
import type { WSServerClient } from "./WSServerClient";
|
|
3
|
+
export type WSSCWithUser<_AS extends AbilitiesSchema, U = unknown, S = unknown> = WSServerClient & {
|
|
4
|
+
user?: U;
|
|
5
|
+
session?: S;
|
|
6
|
+
sessionProps?: Record<string, unknown>;
|
|
7
|
+
isRejected?: boolean;
|
|
8
|
+
lastUserId?: string;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=WSSCWithUser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WSSCWithUser.d.ts","sourceRoot":"","sources":["../../src/server/WSSCWithUser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvD,MAAM,MAAM,YAAY,CAAC,GAAG,SAAS,eAAe,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,cAAc,GAAG;IAClG,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WSServerClient.d.ts","sourceRoot":"","sources":["../../src/server/WSServerClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AASxC,OAAO,EACN,WAAW,EACX,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EAEjB,oBAAoB,EAEpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAMtC,qBAAa,cAAe,SAAQ,SAAS;IAC5C,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IACtF,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IACtE,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IACpF,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAC5F,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,IAAI;IACvD,EAAE,CAAC,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IACzH,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI;IAKhF,IAAI,YAAY,YAEf;IAED,IAAI,MAAM,YAET;IAED,IAAI,SAAS,YAEZ;IAED,IAAI,QAAQ,YAEX;IAED,QAAQ,CAAC,uBAAuB,QAAQ;IACxC,QAAQ,CAAC,iBAAiB,SAAS;IACnC,QAAQ,CAAC,WAAW,SAAS;IAE7B,GAAG,EAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAErB,SAAS,SAAM;IAEf,aAAa,SAAM;IAEnB,CAAC,sBAAsB,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IAEzD,CAAC,WAAW,CAAC;IAWb,OAAO,SAAK;IAEZ,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC;IAE7B,CAAC,uBAAuB,CAAC,iBAAmD;IAE5E,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAI9B,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAK;IAEnC,WAAW,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE;IAkC9B,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,cAAc;IAWjD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"WSServerClient.d.ts","sourceRoot":"","sources":["../../src/server/WSServerClient.ts"],"names":[],"mappings":"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"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
import{WebSocketServer as
|
|
2
|
-
`).map(o=>`${n}${o}`).join(`
|
|
3
|
-
`)}function W(r){try{let e=("writeErrors"in r?r.writeErrors:[r.errorResponse]).filter(t=>t.errmsg==="Document failed validation");e.length&&(r.message+=`
|
|
4
|
-
${e.map(t=>N(`failingDocumentId: ${t.errInfo?.failingDocumentId}
|
|
5
|
-
schemaRulesNotSatisfied: ${JSON.stringify(t.errInfo?.details?.schemaRulesNotSatisfied,null," ")}`," ")).join(`
|
|
6
|
-
`)}`),r.isMongoServerError=!0}catch{}return r}function I(r,e,t,n,o=!0){return Array.isArray(r)&&(r=r.length),typeof n!="string"&&(o=n??!0,n=t),(o?`${r}\xA0`:"")+I.raw(r,e,t,n)}I.raw=(r,e,t,n=t)=>{r=Math.abs(r);let o=r%10,s=r%100;return o===1&&s!==11?e:o>=2&&o<=4&&!(s>=12&&s<=15)?t:n};var S=class r extends U{on(e,t){return super.on(e,t)}get isConnecting(){return this.readyState===this.CONNECTING}get isOpen(){return this.readyState===this.OPEN}get isClosing(){return this.readyState===this.CLOSING}get isClosed(){return this.readyState===this.CLOSED}isWebSocketServerClient=!0;isWebSocketServer=!1;isWebSocket=!1;wss;userAgent="";remoteAddress="";[O];[E](){clearTimeout(this[O]),this[O]=setTimeout(()=>this.terminate(),35e3)}latency=0;[v];[C]=r.makeHeartbeatInterval.call(this);sendMessage(...e){return this.send(JSON.stringify(e))}[T]=0;sendRequest(...e){let t=this[T]++;this[T]>=A&&(this[T]=0);let n=`message:${g.RESPONSE}-${t}`;return typeof e.at(-1)=="function"?(this.once(n,e.splice(-1,1)[0]),this.sendMessage(g.REQUEST,t,...e),this):new Promise((o,s)=>{this.once(n,(i,c)=>{if(i){let{message:a,...l}=i;s(Object.assign(new Error(a),l))}else o(c)}),this.sendMessage(g.REQUEST,t,...e)})}static makeHeartbeatInterval(){return setInterval(()=>{this[v]=Date.now(),this.send("")},5e3)}static extend(){Object.defineProperties(this,{isConnecting:{get:Object.getOwnPropertyDescriptor(r.prototype,"isConnecting").get},isOpen:{get:Object.getOwnPropertyDescriptor(r.prototype,"isOpen").get},isClosing:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosing").get},isClosed:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosed").get}});let{terminate:e}=this;Object.assign(this,{isWebSocketServerClient:!0,isWebSocketServer:!1,isWebSocket:!1,[E]:r.prototype[E],latency:0,[C]:r.makeHeartbeatInterval.call(this),sendMessage:r.prototype.sendMessage,sendRequest:r.prototype.sendRequest,terminate(){try{e.call(this)}catch(t){console.error(t)}}})}static handleConnect(){this.on("message",r.handleMessage),this.on("error",r.handleError),this.on("close",r.handleClose),this[E]()}static handleMessage(e){let t=e.toString();if(this[E](),t)if(t==="?")this.send("!");else try{let[n,...o]=JSON.parse(t);switch(n){case g.REQUEST:r.handleRequest.call(this,...o);break;default:this.emit(`message:${n}`,...o),this.wss.emit("client-message",this,n,...o),this.wss.emit(`client-message:${n}`,this,...o)}}catch(n){r.handleError.call(this,n)}else this[v]&&(this.latency=Date.now()-this[v],this[v]=void 0)}static async handleRequest(e,t,...n){let o=this.wss[y].get(t),s,i=null;if(o)try{s=await o.call(this.wss,this,...n)}catch(c){if(process.env.NODE_ENV==="development"&&W(c),c instanceof Error){let{message:a,...l}=c;i={message:a,...l}}process.env.NODE_ENV==="development"&&!this.wss[h]&&console.error(`${this.wss.icon}\u2757\uFE0F WS Server request "${t}" (${e}):`,c)}else i={message:`Unknown request kind "${t}"`};this.sendMessage(`${g.RESPONSE}-${e}`,i,s)}static handleError(e){e instanceof Event&&(e=void 0),this.wss[h]||console.error(`${this.wss.icon}\u2757\uFE0F WS Server client`,"user"in this?`\x1B[1m${this.user.email}\x1B[0m:`:"\x1B[3manonymous\x1B[0m:",e),this.wss.emit("client-error",this,e)}static handleClose(e,t){if(process.env.NODE_ENV==="development"){let n=t.toString();this.wss[h]||console.info(`${this.wss.icon} WS Server:`,"user"in this?`\x1B[1m${this.user.email}\x1B[0m`:"\x1B[3manonymous\x1B[0m",`disconnected ${e?`with code ${e}`:""} ${e&&n?"and ":""}${n?`reason "${n}"`:""}`)}clearTimeout(this[O]),clearInterval(this[C]),this.wss.emit("client-close",this)}static CLOSE_CODES=x};var L=class r extends V{constructor(e){let{icon:t="\u{1F50C}",name:n="WS",ssl:o,port:s,server:i=Q(r.makeProps(e)),quiet:c=!1,...a}=e;super({WebSocket:S,...a,server:i}),this.icon=t,this.name=n,this.server=i,e.server?new Promise(l=>void(i.listening?l():i.on("listening",l))).then(()=>D(this)):this.server.listen(typeof s=="string"?Number.parseInt(s):s??(this.isS?443:80),()=>D(this)),this[h]=c,this.on("connection",this.#e),this[h]||(this.on("error",l=>console.error(`${this.icon}\u2757\uFE0F WS Server:`,l)),this.on("close",()=>console.error(`${this.icon}\u2757\uFE0F WS Server closed`)))}on(e,t){return super.on(e,t)}isWebSocketServer=!0;isWebSocketServerClient=!1;isWebSocket=!1;icon;name;get protocol(){return`ws${this.isS?"s":""}`}server;get isS(){return"setSecureContext"in this.server}[h];[y]=new Map;addRequestListener(e,t){return this[y].set(e,t),this}onRequest=this.addRequestListener;removeRequestListener(e){return this[y].delete(e),this}offRequest=this.removeRequestListener;#e(e,t){e instanceof S||S.extend.call(e),Object.assign(e,{wss:this,userAgent:t.headers["user-agent"]??"",remoteAddress:H(t)}),S.handleConnect.call(e),this.emit("client-connect",e,t),process.env.NODE_ENV==="development"&&!this[h]&&console.info(`${this.icon} WS Server:`,"user"in e?`\x1B[1m${e.user.email}\x1B[0m`:"\x1B[3manonymous\x1B[0m","connected")}static makeProps({ssl:e}){return{...J(e)}}static CLOSE_CODES=x};export{L as WSServer,S as WSServerClient};
|
|
1
|
+
import{WebSocketServer as x}from"ws";import{createServer as N,getRemoteAddress as w,resolveSSL as k,showServerListeningMessage as O}from"insite-common/backend";var y=Number.MAX_SAFE_INTEGER/2,c={NORMAL:1e3,PROTOCOL_ERROR:1002,ABNORMAL:1006,NO_HEARTBEAT:3e3,OFFLINE:3001,MANUAL:3500,REOPEN:4e3},q=[c.PROTOCOL_ERROR,c.MANUAL,c.REOPEN],m={REQUEST:"~r-q",RESPONSE:"~r-s"};var o=Symbol("isQuiet"),p=Symbol("requestListeners"),b=Symbol("heartbeatInterval"),E=Symbol("heartbeatTimeout"),d=Symbol("defib"),u=Symbol("heartbeatTs"),v=Symbol("requestCounter");import{WebSocket as W}from"ws";import{handleMongoError as T}from"@nesvet/n";var S=class r extends W{on(e,t){return super.on(e,t)}get isConnecting(){return this.readyState===this.CONNECTING}get isOpen(){return this.readyState===this.OPEN}get isClosing(){return this.readyState===this.CLOSING}get isClosed(){return this.readyState===this.CLOSED}isWebSocketServerClient=!0;isWebSocketServer=!1;isWebSocket=!1;wss;userAgent="";remoteAddress="";[E];[d](){clearTimeout(this[E]),this[E]=setTimeout(()=>this.terminate(),35e3)}latency=0;[u];[b]=r.makeHeartbeatInterval.call(this);sendMessage(...e){return this.send(JSON.stringify(e))}[v]=0;sendRequest(...e){let t=this[v]++;this[v]>=y&&(this[v]=0);let s=`message:${m.RESPONSE}-${t}`;return typeof e.at(-1)=="function"?(this.once(s,e.splice(-1,1)[0]),this.sendMessage(m.REQUEST,t,...e),this):new Promise((n,a)=>{this.once(s,(i,h)=>{if(i){let{message:g,...l}=i;a(Object.assign(new Error(g),l))}else n(h)}),this.sendMessage(m.REQUEST,t,...e)})}static makeHeartbeatInterval(){return setInterval(()=>{this[u]=Date.now(),this.send("")},5e3)}static extend(){Object.defineProperties(this,{isConnecting:{get:Object.getOwnPropertyDescriptor(r.prototype,"isConnecting").get},isOpen:{get:Object.getOwnPropertyDescriptor(r.prototype,"isOpen").get},isClosing:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosing").get},isClosed:{get:Object.getOwnPropertyDescriptor(r.prototype,"isClosed").get}}),Object.assign(this,{isWebSocketServerClient:!0,isWebSocketServer:!1,isWebSocket:!1,[d]:r.prototype[d],latency:0,[v]:0,[b]:r.makeHeartbeatInterval.call(this),sendMessage:r.prototype.sendMessage,sendRequest:r.prototype.sendRequest})}static handleConnect(){this.on("message",r.handleMessage),this.on("error",r.handleError),this.on("close",r.handleClose),this[d]()}static handleMessage(e){let t=e.toString();if(this[d](),t)if(t==="?")this.send("!");else try{let[s,...n]=JSON.parse(t);s===m.REQUEST?r.handleRequest.call(this,...n):(this.emit(`message:${s}`,...n),this.wss.emit("client-message",this,s,...n),this.wss.emit(`client-message:${s}`,this,...n))}catch(s){r.handleError.call(this,s)}else this[u]&&(this.latency=Date.now()-this[u],this[u]=void 0)}static async handleRequest(e,t,...s){let n=this.wss[p].get(t),a,i=null;if(n)try{a=await n.call(this.wss,this,...s)}catch(h){if(process.env.NODE_ENV==="development"&&T(h),h instanceof Error){let{message:g,...l}=h;i={message:g,...l}}process.env.NODE_ENV==="development"&&!this.wss[o]&&console.error(`${this.wss.icon}\u2757\uFE0F WS Server request "${t}" (${e}):`,h)}else i={message:`Unknown request kind "${t}"`};this.sendMessage(`${m.RESPONSE}-${e}`,i,a)}static handleError(e){e instanceof Event&&(e=void 0),this.wss[o]||console.error(`${this.wss.icon}\u2757\uFE0F WS Server client`,"user"in this?`\x1B[1m${this.user.email}\x1B[0m:`:"\x1B[3manonymous\x1B[0m:",e),this.wss.emit("client-error",this,e)}static handleClose(e,t){if(process.env.NODE_ENV==="development"){let s=t.toString();this.wss[o]||console.info(`${this.wss.icon} WS Server:`,"user"in this?`\x1B[1m${this.user.email}\x1B[0m`:"\x1B[3manonymous\x1B[0m",`disconnected ${e?`with code ${e}`:""} ${e&&s?"and ":""}${s?`reason "${s}"`:""}`)}clearTimeout(this[E]),clearInterval(this[b]),this.wss.emit("client-close",this)}static CLOSE_CODES=c};var C=class r extends x{constructor(e){let{icon:t="\u{1F50C}",name:s="WS",ssl:n,port:a,server:i=N(r.makeProps(e)),quiet:h=!1,...g}=e;super({WebSocket:S,...g,server:i}),this.icon=t,this.name=s,this.server=i,e.server?new Promise(l=>{i.listening?l():i.on("listening",l)}).then(()=>O(this)):this.server.listen(typeof a=="string"?Number.parseInt(a):a??(this.isS?443:80),()=>O(this)),this[o]=h,this.on("connection",this.#e),this[o]||(this.on("error",l=>console.error(`${this.icon}\u2757\uFE0F WS Server:`,l)),this.on("close",()=>console.error(`${this.icon}\u2757\uFE0F WS Server closed`)))}on(e,t){return super.on(e,t)}isWebSocketServer=!0;isWebSocketServerClient=!1;isWebSocket=!1;icon;name;get protocol(){return`ws${this.isS?"s":""}`}server;get isS(){return"setSecureContext"in this.server}[o];[p]=new Map;addRequestListener(e,t){return this[p].set(e,t),this}onRequest=this.addRequestListener;removeRequestListener(e){return this[p].delete(e),this}offRequest=this.removeRequestListener;#e(e,t){e instanceof S||S.extend.call(e),Object.assign(e,{wss:this,userAgent:t.headers["user-agent"]??"",remoteAddress:w(t)}),S.handleConnect.call(e),this.emit("client-connect",e,t),process.env.NODE_ENV==="development"&&!this[o]&&console.info(`${this.icon} WS Server:`,"user"in e?`\x1B[1m${e.user.email}\x1B[0m`:"\x1B[3manonymous\x1B[0m","connected")}static makeProps({ssl:e}){return{...k(e)}}static CLOSE_CODES=c};export{C as WSServer,S as WSServerClient};
|
|
7
2
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/server/WSServer.ts", "../../src/common.ts", "../../src/server/symbols.ts", "../../src/server/WSServerClient.ts"
|
|
4
|
-
"sourcesContent": ["import type http from \"node:http\";\nimport type https from \"node:https\";\nimport { WebSocketServer } from \"ws\";\nimport {\n\tcreateServer,\n\tgetRemoteAddress,\n\tresolveSSL,\n\tshowServerListeningMessage\n} from \"insite-common/backend\";\nimport { CODES } from \"../common\";\nimport { isQuietSymbol, requestListenersSymbol } from \"./symbols\";\nimport { WSServerClient } from \"./WSServerClient\";\nimport type { Options, RequestListener } from \"./types\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nexport class WSServer<WSSC extends WSServerClient = WSServerClient> extends WebSocketServer<typeof WSServerClient> {\n\tconstructor(options: Options<WSSC>) {\n\t\tconst {\n\t\t\ticon = \"\uD83D\uDD0C\",\n\t\t\tname = \"WS\",\n\t\t\tssl: _,\n\t\t\tport,\n\t\t\tserver = createServer(WSServer.makeProps(options)),\n\t\t\tquiet = false,\n\t\t\t...wssOptions\n\t\t} = options;\n\t\t\n\t\tsuper({\n\t\t\tWebSocket: WSServerClient,\n\t\t\t...wssOptions,\n\t\t\tserver\n\t\t});\n\t\t\n\t\tthis.icon = icon;\n\t\tthis.name = name;\n\t\t\n\t\tthis.server = server;\n\t\t\n\t\tif (options.server)\n\t\t\tvoid new Promise<void>(resolve => void (\n\t\t\t\tserver.listening ?\n\t\t\t\t\tresolve() :\n\t\t\t\t\tserver.on(\"listening\", resolve)\n\t\t\t)).then(() => showServerListeningMessage(this));\n\t\telse\n\t\t\tthis.server.listen(\n\t\t\t\ttypeof port == \"string\" ?\n\t\t\t\t\tNumber.parseInt(port) :\n\t\t\t\t\tport ?? (this.isS ? 443 : 80),\n\t\t\t\t() => showServerListeningMessage(this)\n\t\t\t);\n\t\t\n\t\tthis[isQuietSymbol] = quiet;\n\t\t\n\t\tthis.on(\"connection\", this.#handleConnection);\n\t\t\n\t\tif (!this[isQuietSymbol]) {\n\t\t\tthis.on(\"error\", (error: Error) => console.error(`${this.icon}\u2757\uFE0F WS Server:`, error));\n\t\t\t\n\t\t\tthis.on(\"close\", () => console.error(`${this.icon}\u2757\uFE0F WS Server closed`));\n\t\t}\n\t\t\n\t}\n\t\n\ton(event: \"connection\", callback: (this: this, socket: WSSC, request: http.IncomingMessage) => void): this;\n\ton(event: \"error\", callback: (this: this, error: Error) => void): this;\n\ton(event: \"headers\", callback: (this: this, headers: string[], request: http.IncomingMessage) => void): this;\n\ton(event: \"close\" | \"listening\", callback: (this: this) => void): this;\n\t\n\ton(event: \"client-connect\", listener: (this: this, wscc: WSSC, request: http.IncomingMessage) => void): this;\n\ton(event: \"client-error\", listener: (this: this, wscc: WSSC, error: Error | undefined) => void): this;\n\ton(event: `client-${string}`, listener: (this: this, wscc: WSSC, ...args: any[]) => void): this;\n\ton(event: \"client-close\", listener: (this: this, wscc: WSSC) => void): this;\n\t\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener as (this: WebSocketServer, ...args: any[]) => void);\n\t}\n\t\n\treadonly isWebSocketServer = true;\n\treadonly isWebSocketServerClient = false;\n\treadonly isWebSocket = false;\n\t\n\ticon;\n\tname;\n\tget protocol() {\n\t\treturn `ws${this.isS ? \"s\" : \"\"}`;\n\t}\n\t\n\tserver;\n\t\n\tget isS() {\n\t\treturn \"setSecureContext\" in this.server;\n\t}\n\t\n\t[isQuietSymbol]: boolean;\n\t\n\t[requestListenersSymbol] = new Map<string, RequestListener<WSSC>>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener<WSSC>) {\n\t\tthis[requestListenersSymbol].set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `addRequestListener()`\n\t */\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis[requestListenersSymbol].delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `removeRequestListener()`\n\t */\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleConnection(wssc: WSSC, request: http.IncomingMessage) {\n\t\t\n\t\t/* Compatibility with Bun */\n\t\tif (!(wssc instanceof WSServerClient))\n\t\t\tWSServerClient.extend.call(wssc);\n\t\t\n\t\tObject.assign(wssc, {\n\t\t\twss: this,\n\t\t\tuserAgent: request.headers[\"user-agent\"] ?? \"\",\n\t\t\tremoteAddress: getRemoteAddress(request)\n\t\t});\n\t\t\n\t\tWSServerClient.handleConnect.call(wssc);\n\t\t\n\t\tthis.emit(\"client-connect\", wssc, request);\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\" && !this[isQuietSymbol])\n\t\t\tconsole.info(\n\t\t\t\t`${this.icon} WS Server:`,\n\t\t\t\t\"user\" in wssc ? `\\x1B[1m${(wssc.user as { email: string }).email}\\x1B[0m` : \"\\x1B[3manonymous\\x1B[0m\",\n\t\t\t\t\"connected\"\n\t\t\t);\n\t\t\n\t}\n\t\n\t\n\tstatic makeProps<SWSSC extends WSServerClient>({ ssl }: Options<SWSSC>): http.ServerOptions | https.ServerOptions {\n\t\treturn {\n\t\t\t...resolveSSL(ssl)\n\t\t};\n\t}\n\t\n\tstatic CLOSE_CODES = CODES;\n\t\n}\n", "export const HEARTBEAT_INTERVAL = 5_000;\nexport const HEARTBEAT_GAP = 30_000;\nexport const RESPONSIVENESS_TIMEOUT = 1000;\nexport const OFFLINE_TIMEOUT = 5000;\nexport const REQUEST_COUNTER_LIMIT = Number.MAX_SAFE_INTEGER / 2;\n\nexport const CODES = {\n\tNORMAL: 1000,\n\tPROTOCOL_ERROR: 1002,\n\tABNORMAL: 1006,\n\tNO_HEARTBEAT: 3000,\n\tOFFLINE: 3001,\n\tMANUAL: 3500,\n\tREOPEN: 4000\n} as const;\n\nexport const NON_RECONNECTABLE_CODES = [\n\tCODES.PROTOCOL_ERROR,\n\tCODES.MANUAL,\n\tCODES.REOPEN\n];\n\nexport const REQUEST_HEADERS = {\n\tREQUEST: \"~r-q\",\n\tRESPONSE: \"~r-s\"\n};\n", "export const isQuietSymbol = Symbol(\"isQuiet\");\nexport const requestListenersSymbol = Symbol(\"requestListeners\");\nexport const heartbeatIntervalSymbol = Symbol(\"heartbeatInterval\");\nexport const heartbeatTimeoutSymbol = Symbol(\"heartbeatTimeout\");\nexport const defibSymbol = Symbol(\"defib\");\nexport const heartbeatTsSymbol = Symbol(\"heartbeatTs\");\nexport const requestCounterSymbol = Symbol(\"requestCounter\");\n", "import { ClientRequest, IncomingMessage } from \"node:http\";\nimport { RawData, WebSocket } from \"ws\";\nimport { handleMongoError } from \"@nesvet/n\";\nimport {\n\tCODES,\n\tHEARTBEAT_GAP,\n\tHEARTBEAT_INTERVAL,\n\tREQUEST_COUNTER_LIMIT,\n\tREQUEST_HEADERS\n} from \"../common\";\nimport {\n\tdefibSymbol,\n\theartbeatIntervalSymbol,\n\theartbeatTimeoutSymbol,\n\theartbeatTsSymbol,\n\tisQuietSymbol,\n\trequestCounterSymbol,\n\trequestListenersSymbol\n} from \"./symbols\";\nimport { WSServer } from \"./WSServer\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nexport class WSServerClient extends WebSocket {\n\ton(event: \"close\", listener: (this: this, code: number, reason: Buffer) => void): this;\n\ton(event: \"error\", listener: (this: this, error: Error) => void): this;\n\ton(event: \"upgrade\", listener: (this: this, request: IncomingMessage) => void): this;\n\ton(event: \"message\", listener: (this: this, data: RawData, isBinary: boolean) => void): this;\n\ton(event: \"open\", listener: (this: this) => void): this;\n\ton(event: \"unexpected-response\", listener: (this: this, request: ClientRequest, response: IncomingMessage) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener as (this: WebSocket, ...args: any[]) => void);\n\t}\n\t\n\tget isConnecting() {\n\t\treturn this.readyState === this.CONNECTING;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.readyState === this.OPEN;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.readyState === this.CLOSING;\n\t}\n\t\n\tget isClosed() {\n\t\treturn this.readyState === this.CLOSED;\n\t}\n\t\n\treadonly isWebSocketServerClient = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocket = false;\n\t\n\twss!: WSServer<this>;\n\t\n\tuserAgent = \"\";\n\t\n\tremoteAddress = \"\";\n\t\n\t[heartbeatTimeoutSymbol]?: ReturnType<typeof setTimeout>;\n\t\n\t[defibSymbol]() {\n\t\t\n\t\tclearTimeout(this[heartbeatTimeoutSymbol]);\n\t\t\n\t\tthis[heartbeatTimeoutSymbol] = setTimeout(\n\t\t\t() => this.terminate(),\n\t\t\tHEARTBEAT_INTERVAL + HEARTBEAT_GAP\n\t\t);\n\t\t\n\t}\n\t\n\tlatency = 0;\n\t\n\t[heartbeatTsSymbol]?: number;\n\t\n\t[heartbeatIntervalSymbol] = WSServerClient.makeHeartbeatInterval.call(this);\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\t[requestCounterSymbol]: number = 0;\n\t\n\tsendRequest(...args: unknown[]) {\n\t\t\n\t\tconst id = this[requestCounterSymbol]++;\n\t\t\n\t\tif (this[requestCounterSymbol] >= REQUEST_COUNTER_LIMIT)\n\t\t\tthis[requestCounterSymbol] = 0;\n\t\t\n\t\tconst eventName = `message:${REQUEST_HEADERS.RESPONSE}-${id}`;\n\t\t\n\t\tif (typeof args.at(-1) == \"function\") {\n\t\t\tthis.once(eventName, args.splice(-1, 1)[0] as () => void);\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps) as Error);\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t\n\tstatic makeHeartbeatInterval(this: WSServerClient) {\n\t\treturn setInterval(() => {\n\t\t\t\n\t\t\tthis[heartbeatTsSymbol] = Date.now();\n\t\t\t\n\t\t\tthis.send(\"\");\n\t\t\t\n\t\t}, HEARTBEAT_INTERVAL);\n\t}\n\t\n\t/* Compatibility with Bun */\n\tstatic extend(this: WSServerClient) {\n\t\t\n\t\tObject.defineProperties(this, {\n\t\t\tisConnecting: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isConnecting\")!.get\n\t\t\t},\n\t\t\tisOpen: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isOpen\")!.get\n\t\t\t},\n\t\t\tisClosing: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isClosing\")!.get\n\t\t\t},\n\t\t\tisClosed: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isClosed\")!.get\n\t\t\t}\n\t\t});\n\t\t\n\t\tconst { terminate } = this;\n\t\t\n\t\tObject.assign(this, {\n\t\t\tisWebSocketServerClient: true,\n\t\t\tisWebSocketServer: false,\n\t\t\tisWebSocket: false,\n\t\t\t[defibSymbol]: WSServerClient.prototype[defibSymbol],\n\t\t\tlatency: 0,\n\t\t\t[heartbeatIntervalSymbol]: WSServerClient.makeHeartbeatInterval.call(this),\n\t\t\tsendMessage: WSServerClient.prototype.sendMessage,\n\t\t\tsendRequest: WSServerClient.prototype.sendRequest,\n\t\t\tterminate() { /* Workaround Bun's WebSocket#terminate bug */\n\t\t\t\t\n\t\t\t\ttry {\n\t\t\t\t\tterminate.call(this);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(error);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t});\n\t\t\n\t}\n\t\n\tstatic handleConnect(this: WSServerClient) {\n\t\t\n\t\tthis.on(\"message\", WSServerClient.handleMessage);\n\t\tthis.on(\"error\", WSServerClient.handleError);\n\t\tthis.on(\"close\", WSServerClient.handleClose);\n\t\t\n\t\tthis[defibSymbol]();\n\t\t\n\t}\n\t\n\tstatic handleMessage(this: WSServerClient, data: RawData) {\n\t\tconst message = data.toString();// eslint-disable-line @typescript-eslint/no-base-to-string\n\t\t\n\t\tthis[defibSymbol]();\n\t\t\n\t\tif (message)\n\t\t\tif (message === \"?\")\n\t\t\t\tthis.send(\"!\");\n\t\t\telse\n\t\t\t\ttry {\n\t\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\t\n\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\tcase REQUEST_HEADERS.REQUEST:\n\t\t\t\t\t\t\tvoid WSServerClient.handleRequest.call(this, ...rest as [ id: number, kind: string, ...rest: unknown[] ]);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t\t\t\t\tthis.wss.emit(\"client-message\", this, kind, ...rest);\n\t\t\t\t\t\t\tthis.wss.emit(`client-message:${kind}`, this, ...rest);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tWSServerClient.handleError.call(this, error as Error);\n\t\t\t\t}\n\t\telse if (this[heartbeatTsSymbol]) {\n\t\t\tthis.latency = Date.now() - this[heartbeatTsSymbol];\n\t\t\tthis[heartbeatTsSymbol] = undefined;\n\t\t}\n\t\t\n\t}\n\t\n\tstatic async handleRequest(this: WSServerClient, id: number, kind: string, ...rest: unknown[]) {\n\t\tconst listener = this.wss[requestListenersSymbol].get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.call(this.wss, this, ...rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (process.env.NODE_ENV === \"development\")\n\t\t\t\t\thandleMongoError(error);\n\t\t\t\t\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (process.env.NODE_ENV === \"development\" && !this.wss[isQuietSymbol])\n\t\t\t\t\tconsole.error(`${this.wss.icon}\u2757\uFE0F WS Server request \"${kind}\" (${id}):`, error);\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\tthis.sendMessage(`${REQUEST_HEADERS.RESPONSE}-${id}`, requestError, result);\n\t\t\n\t}\n\t\n\tstatic handleError(this: WSServerClient, error: Error | Event | undefined) {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (!this.wss[isQuietSymbol])\n\t\t\tconsole.error(\n\t\t\t\t`${this.wss.icon}\u2757\uFE0F WS Server client`,\n\t\t\t\t\"user\" in this ? `\\x1B[1m${(this.user as { email: string }).email}\\x1B[0m:` : \"\\x1B[3manonymous\\x1B[0m:\",\n\t\t\t\terror\n\t\t\t);\n\t\t\n\t\tthis.wss.emit(\"client-error\", this, error);\n\t\t\n\t}\n\t\n\tstatic handleClose(this: WSServerClient, code: number, reason: Buffer) {\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\") {\n\t\t\tconst reasonString = reason.toString();\n\t\t\t\n\t\t\tif (!this.wss[isQuietSymbol])\n\t\t\t\tconsole.info(\n\t\t\t\t\t`${this.wss.icon} WS Server:`,\n\t\t\t\t\t\"user\" in this ? `\\x1B[1m${(this.user as { email: string }).email}\\x1B[0m` : \"\\x1B[3manonymous\\x1B[0m\",\n\t\t\t\t\t`disconnected ${code ? `with code ${code}` : \"\"} ${code && reasonString ? \"and \" : \"\"}${reasonString ? `reason \"${reasonString}\"` : \"\"}`\n\t\t\t\t);\n\t\t}\n\t\t\n\t\tclearTimeout(this[heartbeatTimeoutSymbol]);\n\t\tclearInterval(this[heartbeatIntervalSymbol]);\n\t\t\n\t\tthis.wss.emit(\"client-close\", this);\n\t\t\n\t}\n\t\n\tstatic CLOSE_CODES = CODES;\n\t\n}\n", "export function noop() { /**/ }\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\n\ntype Value<T> = PromiseLike<T> | T;\ntype Resolve<T> = (value: Value<T>) => void;\ntype Reject = (reason?: any) => void;\n\ntype Options = {\n\tsignal?: AbortSignal;\n\ttimeout?: number;\n};\n\nconst nativesMap = new WeakMap<StatefulPromise<any>, { resolve: Resolve<any>; reject: Reject }>();\n\n\nexport class StatefulPromise<T> extends Promise<T> {\n\tconstructor(\n\t\texecutor?: (resolve: Resolve<T>, reject: Reject) => void,\n\t\toptions?: Options\n\t) {\n\t\tlet nativeResolve: Resolve<T>;\n\t\tlet nativeReject: Reject;\n\t\t\n\t\tsuper((resolve, reject) => {\n\t\t\tnativeResolve = resolve;\n\t\t\tnativeReject = reject;\n\t\t\t\n\t\t});\n\t\t\n\t\tnativesMap.set(this, { resolve: nativeResolve!, reject: nativeReject! });\n\t\t\n\t\tif (options?.signal)\n\t\t\tif (options.signal.aborted)\n\t\t\t\tthis.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\t\t\telse {\n\t\t\t\tconst abortListener = () => this.reject(new DOMException(\"Aborted\", \"AbortError\"));\n\t\t\t\t\n\t\t\t\toptions.signal.addEventListener(\"abort\", abortListener);\n\t\t\t\t\n\t\t\t\tthis.finally(() => options.signal?.removeEventListener(\"abort\", abortListener));\n\t\t\t}\n\t\t\n\t\tif (typeof options?.timeout === \"number\" && Number.isFinite(options.timeout)) {\n\t\t\tconst timeout = setTimeout(() => this.reject(new DOMException(\"Timeout exceeded\", \"TimeoutError\")), options.timeout);\n\t\t\t\n\t\t\tthis.finally(() => clearTimeout(timeout));\n\t\t}\n\t\t\n\t\texecutor?.(this.resolve, this.reject);\n\t\t\n\t}\n\t\n\tisPending = true;\n\tisFulfilled = false;\n\tisRejected = false;\n\t\n\tstate: \"fulfilled\" | \"pending\" | \"rejected\" = \"pending\";\n\t\n\tresult?: T | unknown;\n\t\n\treadonly resolve = (value: Value<T>) => {\n\t\t\n\t\tif (this.isPending) {\n\t\t\tthis.isPending = false;\n\t\t\tthis.isFulfilled = true;\n\t\t\tthis.state = \"fulfilled\";\n\t\t\tthis.result = value;\n\t\t\t\n\t\t\tconst native = nativesMap.get(this);\n\t\t\t\n\t\t\tif (native) {\n\t\t\t\tnative.resolve.call(this, value);\n\t\t\t\tnativesMap.delete(this);\n\t\t\t}\n\t\t}\n\t\t\n\t};\n\t\n\treadonly reject = (reason?: any) => {\n\t\t\n\t\tif (this.isPending) {\n\t\t\tthis.isPending = false;\n\t\t\tthis.isRejected = true;\n\t\t\tthis.state = \"rejected\";\n\t\t\tthis.result = reason;\n\t\t\t\n\t\t\tconst native = nativesMap.get(this);\n\t\t\t\n\t\t\tif (native) {\n\t\t\t\tnative.reject.call(this, reason);\n\t\t\t\tnativesMap.delete(this);\n\t\t\t}\n\t\t}\n\t\t\n\t};\n\t\n\t\n\tstatic resolved<U>(value: U): StatefulPromise<U> {\n\t\treturn new StatefulPromise<U>(resolve => resolve(value));\n\t}\n\t\n\tstatic rejected(reason: unknown): StatefulPromise<never> {\n\t\treturn new StatefulPromise((_, reject) => reject(reason));\n\t}\n\t\n}\n", "import { noop } from \"./noop.js\";\nimport { StatefulPromise } from \"./StatefulPromise.js\";\n\n\ntype Callback = (...args: any[]) => unknown;// eslint-disable-line @typescript-eslint/no-explicit-any\ntype FunctionOrBoolean = (() => unknown) | boolean;\ntype Options = { leading?: FunctionOrBoolean; maxWait?: number; trailing?: FunctionOrBoolean };\n\ntype DebouncedFunction<C extends Callback> = {\n\t(this: ThisParameterType<C>, ...args: Parameters<C>): Promise<Awaited<ReturnType<C>>>;\n};\n\nexport type Debounced<C extends Callback, R extends ReturnType<C>> = DebouncedFunction<C> & {\n\tcallback: C;\n\tpromise: StatefulPromise<R>;\n\tresolve: (value: R) => void;\n\treject: (reason?: unknown) => void;\n\trun(): Promise<R>;\n\tclear(shouldRun?: boolean): Promise<void>;\n};\n\n\nexport function debounce<C extends Callback, R extends ReturnType<C>>(callback: C, limit = 0, options: Options = {}) {\n\tlet { leading = false, trailing = true } = options;\n\tconst { maxWait = Infinity } = options;\n\t\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\tlet maxWaitTimeout: ReturnType<typeof setTimeout> | undefined;\n\tlet end: number | undefined;\n\tlet context: ThisParameterType<C>;\n\tlet args: unknown[];\n\tlet initial: FunctionOrBoolean;\n\tlet final: FunctionOrBoolean;\n\tlet result: R;\n\t\n\tconst expired = async () => {\n\t\t\n\t\tconst n = Date.now();\n\t\t\n\t\tif (n >= end!) {\n\t\t\ttimeout = undefined;\n\t\t\tend = undefined;\n\t\t\t\n\t\t\tclearTimeout(maxWaitTimeout);\n\t\t\tmaxWaitTimeout = undefined;\n\t\t\t\n\t\t\tif (typeof final == \"function\")\n\t\t\t\tawait final();\n\t\t\t\n\t\t\tdebounced.resolve(result);\n\t\t\t\n\t\t\tinitial = leading;\n\t\t} else {\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = setTimeout(expired, end! - n);\n\t\t}\n\t\t\n\t};\n\t\n\tconst maxWaitExpired = Number.isFinite(maxWait) ? () => {\n\t\t\n\t\tif (final === run)\n\t\t\tfinal = false;\n\t\t\n\t\trun();\n\t\t\n\t\tmaxWaitTimeout = setTimeout(maxWaitExpired as TimerHandler, maxWait);\n\t\t\n\t} : null;\n\t\n\tasync function run() {\n\t\ttry {\n\t\t\tresult = await callback.apply(context, args) as R;\n\t\t\t\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tdebounced.reject(error);\n\t\t\t\n\t\t\tthrow error;\n\t\t}\n\t}\n\t\n\tif (leading && typeof leading == \"boolean\")\n\t\tleading = run;\n\tinitial = leading;\n\t\n\tif (trailing && typeof trailing == \"boolean\")\n\t\ttrailing = run;\n\tfinal = trailing;\n\t\n\tconst debounced: Debounced<C, R> = Object.assign(function (..._args) {\n\t\targs = _args;\n\t\tcontext = this;// eslint-disable-line no-invalid-this\n\t\t\n\t\tend = Date.now() + limit;\n\t\tfinal = trailing;\n\t\t\n\t\tif (!debounced.promise.isPending)\n\t\t\tdebounced.promise = new StatefulPromise<R>((resolve, reject) => {\n\t\t\t\tdebounced.resolve = resolve;\n\t\t\t\tdebounced.reject = reject;\n\t\t\t\t\n\t\t\t\tif (typeof initial == \"function\") {\n\t\t\t\t\tinitial();\n\t\t\t\t\t\n\t\t\t\t\tinitial = false;\n\t\t\t\t\t\n\t\t\t\t\tif (final === run)\n\t\t\t\t\t\tfinal = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!timeout) {\n\t\t\t\t\ttimeout = setTimeout(expired, limit);\n\t\t\t\t\t\n\t\t\t\t\tif (maxWaitExpired)\n\t\t\t\t\t\tmaxWaitTimeout = setTimeout(maxWaitExpired, maxWait);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t});\n\t\t\n\t\treturn debounced.promise;\n\t} as DebouncedFunction<C>, {\n\t\tcallback,\n\t\tpromise: StatefulPromise.resolved(undefined as unknown as R),\n\t\tresolve: noop,\n\t\treject: noop,\n\t\trun,\n\t\tclear: async (shouldRun?: boolean) => {\n\t\t\t\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = undefined;\n\t\t\t\n\t\t\tclearTimeout(maxWaitTimeout);\n\t\t\tmaxWaitTimeout = undefined;\n\t\t\t\n\t\t\tdebounced.resolve(shouldRun ? await run() : result);\n\t\t\t\n\t\t}\n\t});\n\t\n\treturn debounced;\n}\n\n\ndebounce.noop = Object.assign(() => { /**/ }, {\n\tcallback: noop,\n\tpromise: StatefulPromise.resolved(undefined), // eslint-disable-line unicorn/no-useless-undefined\n\tresolve: noop,\n\treject: noop,\n\trun: noop,\n\tclear: noop\n}) as Debounced<() => void, void>;\n\n\nexport function throttle(callback: Callback, limit?: number, options?: Options) {\n\treturn debounce(callback, limit, {\n\t\tmaxWait: limit,\n\t\tleading: true,\n\t\ttrailing: true,\n\t\t...options\n\t});\n}\n", "export function indent(string: string, indentation: string = \"\\t\", times: number = 1): string {\n\tif (!string)\n\t\treturn string;\n\t\n\tconst prefix = indentation.repeat(times);\n\t\n\treturn string.split(\"\\n\").map(line => `${prefix}${line}`).join(\"\\n\");\n}\n", "import { indent } from \"./indent.js\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\ntype MongoServerError = {\n\terrorResponse: {\n\t\terrmsg: string;\n\t\terrInfo?: {\n\t\t\t[key: string]: any;\n\t\t};\n\t};\n\tisMongoServerError?: true;\n\t[key: string]: any;\n};\n\nexport function handleMongoError<E extends MongoServerError>(error: E): E;\nexport function handleMongoError(error: any): any;\nexport function handleMongoError(error: any) {\n\t\n\ttry {\n\t\tconst documentFailedValidationResponses =\n\t\t\t(\"writeErrors\" in error ? error.writeErrors : [ error.errorResponse ])\n\t\t\t\t.filter((errorResponse: MongoServerError[\"errorResponse\"]) => errorResponse.errmsg === \"Document failed validation\");\n\t\t\n\t\tif (documentFailedValidationResponses.length)\n\t\t\terror.message += `\\n${\n\t\t\t\tdocumentFailedValidationResponses.map(\n\t\t\t\t\t(errorResponse: MongoServerError[\"errorResponse\"]) =>\n\t\t\t\t\t\tindent(\n\t\t\t\t\t\t\t`failingDocumentId: ${errorResponse.errInfo?.failingDocumentId}\\n` +\n\t\t\t\t\t\t\t`schemaRulesNotSatisfied: ${JSON.stringify(errorResponse.errInfo?.details?.schemaRulesNotSatisfied, null, \" \")}`,\n\t\t\t\t\t\t\t\" \"\n\t\t\t\t\t\t)\n\t\t\t\t).join(\"\\n\")\n\t\t\t}`;\n\t\t\n\t\terror.isMongoServerError = true;\n\t} catch {}\n\t\n\treturn error;\n}\n", "export function howmuch(number: [] | number, one: string, two: string, five: boolean | string, shouldPrintNumber = true) {\n\tif (Array.isArray(number))\n\t\tnumber = number.length;\n\t\n\tif (typeof five != \"string\") {\n\t\tshouldPrintNumber = five ?? true;\n\t\tfive = two;\n\t}\n\t\n\t\n\treturn (shouldPrintNumber ? `${number}\u00A0` : \"\") + howmuch.raw(number, one, two, five);\n}\n\nhowmuch.raw = (number: number, one: string, two: string, five = two) => {\n\tnumber = Math.abs(number);\n\tconst u = number % 10;\n\tconst d = number % 100;\n\t\n\treturn (\n\t\t(u === 1 && d !== 11) ?\n\t\t\tone :\n\t\t\t((u >= 2 && u <= 4) && !(d >= 12 && d <= 15)) ?\n\t\t\t\ttwo :\n\t\t\t\tfive\n\t);\n};\n"],
|
|
5
|
-
"mappings": "AAEA,OAAS,mBAAAA,MAAuB,KAChC,OACC,gBAAAC,EACA,oBAAAC,EACA,cAAAC,EACA,8BAAAC,MACM,wBCJA,IAAMC,EAAwB,OAAO,iBAAmB,EAElDC,EAAQ,CACpB,OAAQ,IACR,eAAgB,KAChB,SAAU,KACV,aAAc,IACd,QAAS,KACT,OAAQ,KACR,OAAQ,GACT,EAEaC,EAA0B,CACtCD,EAAM,eACNA,EAAM,OACNA,EAAM,MACP,EAEaE,EAAkB,CAC9B,QAAS,OACT,SAAU,MACX,ECzBO,IAAMC,EAAgB,OAAO,SAAS,EAChCC,EAAyB,OAAO,kBAAkB,EAClDC,EAA0B,OAAO,mBAAmB,EACpDC,EAAyB,OAAO,kBAAkB,EAClDC,EAAc,OAAO,OAAO,EAC5BC,EAAoB,OAAO,aAAa,EACxCC,EAAuB,OAAO,gBAAgB,ECL3D,OAAkB,aAAAC,MAAiB,
|
|
6
|
-
"names": ["WebSocketServer", "createServer", "getRemoteAddress", "resolveSSL", "showServerListeningMessage", "REQUEST_COUNTER_LIMIT", "CODES", "NON_RECONNECTABLE_CODES", "REQUEST_HEADERS", "isQuietSymbol", "requestListenersSymbol", "heartbeatIntervalSymbol", "heartbeatTimeoutSymbol", "defibSymbol", "heartbeatTsSymbol", "requestCounterSymbol", "WebSocket", "
|
|
3
|
+
"sources": ["../../src/server/WSServer.ts", "../../src/common.ts", "../../src/server/symbols.ts", "../../src/server/WSServerClient.ts"],
|
|
4
|
+
"sourcesContent": ["import type http from \"node:http\";\nimport type https from \"node:https\";\nimport { WebSocketServer } from \"ws\";\nimport {\n\tcreateServer,\n\tgetRemoteAddress,\n\tresolveSSL,\n\tshowServerListeningMessage\n} from \"insite-common/backend\";\nimport { CODES } from \"../common\";\nimport { isQuietSymbol, requestListenersSymbol } from \"./symbols\";\nimport { WSServerClient } from \"./WSServerClient\";\nimport type { Options, RequestListener } from \"./types\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nexport class WSServer<WSSC extends WSServerClient = WSServerClient> extends WebSocketServer<typeof WSServerClient> {\n\tconstructor(options: Options<WSSC>) {\n\t\tconst {\n\t\t\ticon = \"\uD83D\uDD0C\",\n\t\t\tname = \"WS\",\n\t\t\tssl: _,\n\t\t\tport,\n\t\t\tserver = createServer(WSServer.makeProps(options)),\n\t\t\tquiet = false,\n\t\t\t...wssOptions\n\t\t} = options;\n\t\t\n\t\tsuper({\n\t\t\tWebSocket: WSServerClient,\n\t\t\t...wssOptions,\n\t\t\tserver\n\t\t});\n\t\t\n\t\tthis.icon = icon;\n\t\tthis.name = name;\n\t\t\n\t\tthis.server = server;\n\t\t\n\t\tif (options.server)\n\t\t\tvoid new Promise<void>(resolve => void (\n\t\t\t\tserver.listening ?\n\t\t\t\t\tresolve() :\n\t\t\t\t\tserver.on(\"listening\", resolve)\n\t\t\t)).then(() => showServerListeningMessage(this));\n\t\telse\n\t\t\tthis.server.listen(\n\t\t\t\ttypeof port == \"string\" ?\n\t\t\t\t\tNumber.parseInt(port) :\n\t\t\t\t\tport ?? (this.isS ? 443 : 80),\n\t\t\t\t() => showServerListeningMessage(this)\n\t\t\t);\n\t\t\n\t\tthis[isQuietSymbol] = quiet;\n\t\t\n\t\tthis.on(\"connection\", this.#handleConnection);\n\t\t\n\t\tif (!this[isQuietSymbol]) {\n\t\t\tthis.on(\"error\", (error: Error) => console.error(`${this.icon}\u2757\uFE0F WS Server:`, error));\n\t\t\t\n\t\t\tthis.on(\"close\", () => console.error(`${this.icon}\u2757\uFE0F WS Server closed`));\n\t\t}\n\t\t\n\t}\n\t\n\ton(event: \"connection\", callback: (this: this, socket: WSSC, request: http.IncomingMessage) => void): this;\n\ton(event: \"error\", callback: (this: this, error: Error) => void): this;\n\ton(event: \"headers\", callback: (this: this, headers: string[], request: http.IncomingMessage) => void): this;\n\ton(event: \"close\" | \"listening\", callback: (this: this) => void): this;\n\t\n\ton(event: \"client-connect\", listener: (this: this, wscc: WSSC, request: http.IncomingMessage) => void): this;\n\ton(event: \"client-error\", listener: (this: this, wscc: WSSC, error: Error | undefined) => void): this;\n\ton(event: `client-${string}`, listener: (this: this, wscc: WSSC, ...args: any[]) => void): this;\n\ton(event: \"client-close\", listener: (this: this, wscc: WSSC) => void): this;\n\t\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener as (this: WebSocketServer, ...args: any[]) => void);\n\t}\n\t\n\treadonly isWebSocketServer = true;\n\treadonly isWebSocketServerClient = false;\n\treadonly isWebSocket = false;\n\t\n\ticon;\n\tname;\n\tget protocol() {\n\t\treturn `ws${this.isS ? \"s\" : \"\"}`;\n\t}\n\t\n\tserver;\n\t\n\tget isS() {\n\t\treturn \"setSecureContext\" in this.server;\n\t}\n\t\n\t[isQuietSymbol]: boolean;\n\t\n\t[requestListenersSymbol] = new Map<string, RequestListener<WSSC>>();\n\t\n\taddRequestListener(kind: string, listener: RequestListener<WSSC>) {\n\t\tthis[requestListenersSymbol].set(kind, listener);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `addRequestListener()`\n\t */\n\tonRequest = this.addRequestListener;\n\t\n\tremoveRequestListener(kind: string) {\n\t\tthis[requestListenersSymbol].delete(kind);\n\t\t\n\t\treturn this;\n\t}\n\t\n\t/**\n\t * Alias for `removeRequestListener()`\n\t */\n\toffRequest = this.removeRequestListener;\n\t\n\t#handleConnection(wssc: WSSC, request: http.IncomingMessage) {\n\t\t\n\t\t/* Compatibility with Bun */\n\t\tif (!(wssc instanceof WSServerClient))\n\t\t\tWSServerClient.extend.call(wssc);\n\t\t\n\t\tObject.assign(wssc, {\n\t\t\twss: this,\n\t\t\tuserAgent: request.headers[\"user-agent\"] ?? \"\",\n\t\t\tremoteAddress: getRemoteAddress(request)\n\t\t});\n\t\t\n\t\tWSServerClient.handleConnect.call(wssc);\n\t\t\n\t\tthis.emit(\"client-connect\", wssc, request);\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\" && !this[isQuietSymbol])\n\t\t\tconsole.info(\n\t\t\t\t`${this.icon} WS Server:`,\n\t\t\t\t\"user\" in wssc ? `\\x1B[1m${(wssc.user as { email: string }).email}\\x1B[0m` : \"\\x1B[3manonymous\\x1B[0m\",\n\t\t\t\t\"connected\"\n\t\t\t);\n\t\t\n\t}\n\t\n\t\n\tstatic makeProps<SWSSC extends WSServerClient>({ ssl }: Options<SWSSC>): http.ServerOptions | https.ServerOptions {\n\t\treturn {\n\t\t\t...resolveSSL(ssl)\n\t\t};\n\t}\n\t\n\tstatic CLOSE_CODES = CODES;\n\t\n}\n", "export const HEARTBEAT_INTERVAL = 5_000;\nexport const HEARTBEAT_GAP = 30_000;\nexport const RESPONSIVENESS_TIMEOUT = 1000;\nexport const OFFLINE_TIMEOUT = 5000;\nexport const REQUEST_COUNTER_LIMIT = Number.MAX_SAFE_INTEGER / 2;\n\nexport const CODES = {\n\tNORMAL: 1000,\n\tPROTOCOL_ERROR: 1002,\n\tABNORMAL: 1006,\n\tNO_HEARTBEAT: 3000,\n\tOFFLINE: 3001,\n\tMANUAL: 3500,\n\tREOPEN: 4000\n} as const;\n\nexport const NON_RECONNECTABLE_CODES = [\n\tCODES.PROTOCOL_ERROR,\n\tCODES.MANUAL,\n\tCODES.REOPEN\n];\n\nexport const REQUEST_HEADERS = {\n\tREQUEST: \"~r-q\",\n\tRESPONSE: \"~r-s\"\n};\n", "export const isQuietSymbol = Symbol(\"isQuiet\");\nexport const requestListenersSymbol = Symbol(\"requestListeners\");\nexport const heartbeatIntervalSymbol = Symbol(\"heartbeatInterval\");\nexport const heartbeatTimeoutSymbol = Symbol(\"heartbeatTimeout\");\nexport const defibSymbol = Symbol(\"defib\");\nexport const heartbeatTsSymbol = Symbol(\"heartbeatTs\");\nexport const requestCounterSymbol = Symbol(\"requestCounter\");\n", "import { ClientRequest, IncomingMessage } from \"node:http\";\nimport { RawData, WebSocket } from \"ws\";\nimport { handleMongoError } from \"@nesvet/n\";\nimport {\n\tCODES,\n\tHEARTBEAT_GAP,\n\tHEARTBEAT_INTERVAL,\n\tREQUEST_COUNTER_LIMIT,\n\tREQUEST_HEADERS\n} from \"../common\";\nimport {\n\tdefibSymbol,\n\theartbeatIntervalSymbol,\n\theartbeatTimeoutSymbol,\n\theartbeatTsSymbol,\n\tisQuietSymbol,\n\trequestCounterSymbol,\n\trequestListenersSymbol\n} from \"./symbols\";\nimport { WSServer } from \"./WSServer\";\n\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n\nexport class WSServerClient extends WebSocket {\n\ton(event: \"close\", listener: (this: this, code: number, reason: Buffer) => void): this;\n\ton(event: \"error\", listener: (this: this, error: Error) => void): this;\n\ton(event: \"upgrade\", listener: (this: this, request: IncomingMessage) => void): this;\n\ton(event: \"message\", listener: (this: this, data: RawData, isBinary: boolean) => void): this;\n\ton(event: \"open\", listener: (this: this) => void): this;\n\ton(event: \"unexpected-response\", listener: (this: this, request: ClientRequest, response: IncomingMessage) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this;\n\ton(event: string | symbol, listener: (this: this, ...args: any[]) => void): this {\n\t\treturn super.on(event, listener as (this: WebSocket, ...args: any[]) => void);\n\t}\n\t\n\tget isConnecting() {\n\t\treturn this.readyState === this.CONNECTING;\n\t}\n\t\n\tget isOpen() {\n\t\treturn this.readyState === this.OPEN;\n\t}\n\t\n\tget isClosing() {\n\t\treturn this.readyState === this.CLOSING;\n\t}\n\t\n\tget isClosed() {\n\t\treturn this.readyState === this.CLOSED;\n\t}\n\t\n\treadonly isWebSocketServerClient = true;\n\treadonly isWebSocketServer = false;\n\treadonly isWebSocket = false;\n\t\n\twss!: WSServer<this>;\n\t\n\tuserAgent = \"\";\n\t\n\tremoteAddress = \"\";\n\t\n\t[heartbeatTimeoutSymbol]?: ReturnType<typeof setTimeout>;\n\t\n\t[defibSymbol]() {\n\t\t\n\t\tclearTimeout(this[heartbeatTimeoutSymbol]);\n\t\t\n\t\tthis[heartbeatTimeoutSymbol] = setTimeout(\n\t\t\t() => this.terminate(),\n\t\t\tHEARTBEAT_INTERVAL + HEARTBEAT_GAP\n\t\t);\n\t\t\n\t}\n\t\n\tlatency = 0;\n\t\n\t[heartbeatTsSymbol]?: number;\n\t\n\t[heartbeatIntervalSymbol] = WSServerClient.makeHeartbeatInterval.call(this);\n\t\n\tsendMessage(...args: unknown[]) {\n\t\treturn this.send(JSON.stringify(args));\n\t}\n\t\n\t[requestCounterSymbol]: number = 0;\n\t\n\tsendRequest(...args: unknown[]) {\n\t\t\n\t\tconst id = this[requestCounterSymbol]++;\n\t\t\n\t\tif (this[requestCounterSymbol] >= REQUEST_COUNTER_LIMIT)\n\t\t\tthis[requestCounterSymbol] = 0;\n\t\t\n\t\tconst eventName = `message:${REQUEST_HEADERS.RESPONSE}-${id}`;\n\t\t\n\t\tif (typeof args.at(-1) == \"function\") {\n\t\t\tthis.once(eventName, args.splice(-1, 1)[0] as () => void);\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t\treturn this;\n\t\t}\n\t\t\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t\n\t\t\tthis.once(eventName, (error, result) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\treject(Object.assign(new Error(message), restProps) as Error);\n\t\t\t\t} else\n\t\t\t\t\tresolve(result);\n\t\t\t\t\n\t\t\t});\n\t\t\t\n\t\t\tthis.sendMessage(REQUEST_HEADERS.REQUEST, id, ...args);\n\t\t\t\n\t\t});\n\t}\n\t\n\t\n\tstatic makeHeartbeatInterval(this: WSServerClient) {\n\t\treturn setInterval(() => {\n\t\t\t\n\t\t\tthis[heartbeatTsSymbol] = Date.now();\n\t\t\t\n\t\t\tthis.send(\"\");\n\t\t\t\n\t\t}, HEARTBEAT_INTERVAL);\n\t}\n\t\n\t/* Compatibility with Bun */\n\tstatic extend(this: WSServerClient) {\n\t\t\n\t\tObject.defineProperties(this, {\n\t\t\tisConnecting: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isConnecting\")!.get\n\t\t\t},\n\t\t\tisOpen: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isOpen\")!.get\n\t\t\t},\n\t\t\tisClosing: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isClosing\")!.get\n\t\t\t},\n\t\t\tisClosed: {\n\t\t\t\tget: Object.getOwnPropertyDescriptor(WSServerClient.prototype, \"isClosed\")!.get\n\t\t\t}\n\t\t});\n\t\t\n\t\tObject.assign(this, {\n\t\t\tisWebSocketServerClient: true,\n\t\t\tisWebSocketServer: false,\n\t\t\tisWebSocket: false,\n\t\t\t[defibSymbol]: WSServerClient.prototype[defibSymbol],\n\t\t\tlatency: 0,\n\t\t\t[requestCounterSymbol]: 0,\n\t\t\t[heartbeatIntervalSymbol]: WSServerClient.makeHeartbeatInterval.call(this),\n\t\t\tsendMessage: WSServerClient.prototype.sendMessage,\n\t\t\tsendRequest: WSServerClient.prototype.sendRequest\n\t\t});\n\t\t\n\t}\n\t\n\tstatic handleConnect(this: WSServerClient) {\n\t\t\n\t\tthis.on(\"message\", WSServerClient.handleMessage);\n\t\tthis.on(\"error\", WSServerClient.handleError);\n\t\tthis.on(\"close\", WSServerClient.handleClose);\n\t\t\n\t\tthis[defibSymbol]();\n\t\t\n\t}\n\t\n\tstatic handleMessage(this: WSServerClient, data: RawData) {\n\t\tconst message = data.toString();// eslint-disable-line @typescript-eslint/no-base-to-string\n\t\t\n\t\tthis[defibSymbol]();\n\t\t\n\t\tif (message)\n\t\t\tif (message === \"?\")\n\t\t\t\tthis.send(\"!\");\n\t\t\telse\n\t\t\t\ttry {\n\t\t\t\t\tconst [ kind, ...rest ] = JSON.parse(message);\n\t\t\t\t\t\n\t\t\t\t\tswitch (kind) {\n\t\t\t\t\t\tcase REQUEST_HEADERS.REQUEST:\n\t\t\t\t\t\t\tvoid WSServerClient.handleRequest.call(this, ...rest as [ id: number, kind: string, ...rest: unknown[] ]);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthis.emit(`message:${kind}`, ...rest);\n\t\t\t\t\t\t\tthis.wss.emit(\"client-message\", this, kind, ...rest);\n\t\t\t\t\t\t\tthis.wss.emit(`client-message:${kind}`, this, ...rest);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tWSServerClient.handleError.call(this, error as Error);\n\t\t\t\t}\n\t\telse if (this[heartbeatTsSymbol]) {\n\t\t\tthis.latency = Date.now() - this[heartbeatTsSymbol];\n\t\t\tthis[heartbeatTsSymbol] = undefined;\n\t\t}\n\t\t\n\t}\n\t\n\tstatic async handleRequest(this: WSServerClient, id: number, kind: string, ...rest: unknown[]) {\n\t\tconst listener = this.wss[requestListenersSymbol].get(kind);\n\t\t\n\t\tlet result;\n\t\tlet requestError = null;\n\t\t\n\t\tif (listener)\n\t\t\ttry {\n\t\t\t\tresult = await listener.call(this.wss, this, ...rest);\n\t\t\t} catch (error) {\n\t\t\t\tif (process.env.NODE_ENV === \"development\")\n\t\t\t\t\thandleMongoError(error);\n\t\t\t\t\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tconst { message, ...restProps } = error;\n\t\t\t\t\trequestError = { message, ...restProps };\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (process.env.NODE_ENV === \"development\" && !this.wss[isQuietSymbol])\n\t\t\t\t\tconsole.error(`${this.wss.icon}\u2757\uFE0F WS Server request \"${kind}\" (${id}):`, error);\n\t\t\t}\n\t\telse\n\t\t\trequestError = { message: `Unknown request kind \"${kind}\"` };\n\t\t\n\t\tthis.sendMessage(`${REQUEST_HEADERS.RESPONSE}-${id}`, requestError, result);\n\t\t\n\t}\n\t\n\tstatic handleError(this: WSServerClient, error: Error | Event | undefined) {\n\t\tif (error instanceof Event)\n\t\t\terror = undefined;\n\t\t\n\t\tif (!this.wss[isQuietSymbol])\n\t\t\tconsole.error(\n\t\t\t\t`${this.wss.icon}\u2757\uFE0F WS Server client`,\n\t\t\t\t\"user\" in this ? `\\x1B[1m${(this.user as { email: string }).email}\\x1B[0m:` : \"\\x1B[3manonymous\\x1B[0m:\",\n\t\t\t\terror\n\t\t\t);\n\t\t\n\t\tthis.wss.emit(\"client-error\", this, error);\n\t\t\n\t}\n\t\n\tstatic handleClose(this: WSServerClient, code: number, reason: Buffer) {\n\t\t\n\t\tif (process.env.NODE_ENV === \"development\") {\n\t\t\tconst reasonString = reason.toString();\n\t\t\t\n\t\t\tif (!this.wss[isQuietSymbol])\n\t\t\t\tconsole.info(\n\t\t\t\t\t`${this.wss.icon} WS Server:`,\n\t\t\t\t\t\"user\" in this ? `\\x1B[1m${(this.user as { email: string }).email}\\x1B[0m` : \"\\x1B[3manonymous\\x1B[0m\",\n\t\t\t\t\t`disconnected ${code ? `with code ${code}` : \"\"} ${code && reasonString ? \"and \" : \"\"}${reasonString ? `reason \"${reasonString}\"` : \"\"}`\n\t\t\t\t);\n\t\t}\n\t\t\n\t\tclearTimeout(this[heartbeatTimeoutSymbol]);\n\t\tclearInterval(this[heartbeatIntervalSymbol]);\n\t\t\n\t\tthis.wss.emit(\"client-close\", this);\n\t\t\n\t}\n\t\n\tstatic CLOSE_CODES = CODES;\n\t\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["WebSocketServer", "createServer", "getRemoteAddress", "resolveSSL", "showServerListeningMessage", "REQUEST_COUNTER_LIMIT", "CODES", "NON_RECONNECTABLE_CODES", "REQUEST_HEADERS", "isQuietSymbol", "requestListenersSymbol", "heartbeatIntervalSymbol", "heartbeatTimeoutSymbol", "defibSymbol", "heartbeatTsSymbol", "requestCounterSymbol", "WebSocket", "handleMongoError", "WSServerClient", "_WSServerClient", "WebSocket", "event", "listener", "heartbeatTimeoutSymbol", "defibSymbol", "heartbeatTsSymbol", "heartbeatIntervalSymbol", "args", "requestCounterSymbol", "id", "REQUEST_COUNTER_LIMIT", "eventName", "REQUEST_HEADERS", "resolve", "reject", "error", "result", "message", "restProps", "data", "kind", "rest", "requestListenersSymbol", "requestError", "handleMongoError", "isQuietSymbol", "code", "reason", "reasonString", "CODES", "WSServer", "_WSServer", "WebSocketServer", "options", "icon", "name", "_", "port", "server", "createServer", "quiet", "wssOptions", "WSServerClient", "resolve", "showServerListeningMessage", "isQuietSymbol", "#handleConnection", "error", "event", "listener", "requestListenersSymbol", "kind", "wssc", "request", "getRemoteAddress", "ssl", "resolveSSL", "CODES"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,41 +1,54 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
2
|
+
"name": "insite-ws",
|
|
3
|
+
"version": "2.4.1",
|
|
4
|
+
"description": "WebSocket abstraction (server + client, heartbeat, RPC)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"insite",
|
|
7
|
+
"websocket",
|
|
8
|
+
"ws",
|
|
9
|
+
"rpc"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/nesvet/insite#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/nesvet/insite/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/nesvet/insite.git",
|
|
18
|
+
"directory": "packages/ws"
|
|
19
|
+
},
|
|
20
|
+
"funding": {
|
|
21
|
+
"type": "patreon",
|
|
22
|
+
"url": "https://www.patreon.com/nesvet"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"author": "Eugene Nesvetaev <dev@nesvet.dev> (https://nesvet.dev/)",
|
|
26
|
+
"type": "module",
|
|
27
|
+
"exports": {
|
|
28
|
+
"./server": "./dist/server/index.js",
|
|
29
|
+
"./client": "./dist/client/index.js",
|
|
30
|
+
"./client/node": "./dist/client/node/index.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "bun .conveyer.js",
|
|
39
|
+
"postbuild": "tsc -p .",
|
|
40
|
+
"clean": "rm -rf dist",
|
|
41
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
42
|
+
"typecheck": "tsc --noEmit"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@nesvet/n": "^1.2.1",
|
|
46
|
+
"eventemitter3": "^5.0.4",
|
|
47
|
+
"insite-common": "^2.4.0",
|
|
48
|
+
"ws": "^8.19.0"
|
|
49
|
+
},
|
|
50
|
+
"packageManager": "bun@1.3.9",
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20.0.0"
|
|
53
|
+
}
|
|
41
54
|
}
|
package/dist/server/common.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/server/common.ts"],"names":[],"mappings":""}
|