stelar-time-real 3.3.2 → 3.3.4
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/package.json +16 -4
- package/src/client.d.ts.map +1 -1
- package/src/client.js +35 -4
- package/src/client.ts +32 -4
- package/src/websocket.browser.js +46 -0
- package/src/websocket.d.ts.map +1 -1
- package/src/websocket.js +4 -1
- package/src/websocket.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stelar-time-real",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.4",
|
|
4
4
|
"description": "Zero-dependency production real-time library. Custom binary TCP + manual WebSocket. No ws package. Rate limiting (custom/per-event/per-client), hooks, custom IP tracker, custom health check, runtime config, rooms, ACKs, middleware, TLS/SSL.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -35,9 +35,21 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/foxytp/stelar-time-real#readme",
|
|
37
37
|
"exports": {
|
|
38
|
-
".":
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
".": {
|
|
39
|
+
"browser": "./src/index.js",
|
|
40
|
+
"default": "./src/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./client": {
|
|
43
|
+
"browser": "./src/client.js",
|
|
44
|
+
"default": "./src/client.js"
|
|
45
|
+
},
|
|
46
|
+
"./client.js": {
|
|
47
|
+
"browser": "./src/client.js",
|
|
48
|
+
"default": "./src/client.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"browser": {
|
|
52
|
+
"./src/websocket.js": "./src/websocket.browser.js"
|
|
41
53
|
},
|
|
42
54
|
"files": [
|
|
43
55
|
"src"
|
package/src/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAiBnE,OAAO,EAAE,MAAM,EAAe,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIjE,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,GAAG,IAAI,CAAC;IACvE,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,eAAe,CAAC;QAAC,EAAE,EAAE,eAAe,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5E,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,GAAG,IAAI,CAAC;IACnF,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnF,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAClF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC/E,IAAI,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IAC7E,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IACxF,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAAG,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAAE;AAC7E,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;AACzD,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"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"}
|
package/src/client.js
CHANGED
|
@@ -48,6 +48,36 @@ function parseWSBinary(payload) {
|
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
/** Browser-safe version of encodeWSBinary — no Buffer dependency */
|
|
52
|
+
function encodeWSBinaryBrowser(event, data) {
|
|
53
|
+
const hdrJson = JSON.stringify({ event });
|
|
54
|
+
const hdrBytes = new TextEncoder().encode(hdrJson);
|
|
55
|
+
const payload = new Uint8Array(data);
|
|
56
|
+
const frame = new ArrayBuffer(4 + hdrBytes.length + payload.length);
|
|
57
|
+
const view = new DataView(frame);
|
|
58
|
+
view.setUint32(0, hdrBytes.length, false); // big-endian
|
|
59
|
+
new Uint8Array(frame, 4, hdrBytes.length).set(hdrBytes);
|
|
60
|
+
new Uint8Array(frame, 4 + hdrBytes.length).set(payload);
|
|
61
|
+
return frame;
|
|
62
|
+
}
|
|
63
|
+
/** Browser-safe version of parseWSBinary — no Buffer dependency */
|
|
64
|
+
function parseWSBinaryBrowser(payload) {
|
|
65
|
+
if (payload.byteLength < 4)
|
|
66
|
+
return null;
|
|
67
|
+
const view = new DataView(payload);
|
|
68
|
+
const hdrLen = view.getUint32(0, false); // big-endian
|
|
69
|
+
if (hdrLen > payload.byteLength - 4)
|
|
70
|
+
return null;
|
|
71
|
+
try {
|
|
72
|
+
const hdrBytes = new Uint8Array(payload, 4, hdrLen);
|
|
73
|
+
const hdr = JSON.parse(new TextDecoder().decode(hdrBytes));
|
|
74
|
+
const buffer = payload.slice(4 + hdrLen);
|
|
75
|
+
return { event: hdr.event, buffer };
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
51
81
|
class StelarClient {
|
|
52
82
|
constructor(urlOrPort = 'localhost:3000', o = {}) {
|
|
53
83
|
this.events = new Map();
|
|
@@ -198,15 +228,17 @@ class StelarClient {
|
|
|
198
228
|
if (this._state !== 'connected')
|
|
199
229
|
return this;
|
|
200
230
|
try {
|
|
201
|
-
const safeCopy = Buffer.from(new Uint8Array(data));
|
|
202
231
|
if (this.opts.mode === 'tcp' && this._tcpSock && !this._tcpSock.destroyed) {
|
|
232
|
+
const safeCopy = Buffer.from(new Uint8Array(data));
|
|
203
233
|
this._writeTCP(encodeBinaryFrame(event, safeCopy, this.opts.maxFrameSize));
|
|
204
234
|
}
|
|
205
235
|
else if (this._nodeSock && !this._nodeSock.destroyed) {
|
|
236
|
+
const safeCopy = Buffer.from(new Uint8Array(data));
|
|
206
237
|
this._writeNodeWS(createWSBinaryFrameMasked(encodeWSBinary(event, safeCopy)));
|
|
207
238
|
}
|
|
208
239
|
else if (this._ws && this._ws.readyState === WebSocket.OPEN) {
|
|
209
|
-
|
|
240
|
+
// Browser path: use ArrayBuffer-based encoding (no Buffer dependency)
|
|
241
|
+
const frame = encodeWSBinaryBrowser(event, data);
|
|
210
242
|
this._ws.send(frame);
|
|
211
243
|
}
|
|
212
244
|
this._sent++;
|
|
@@ -468,8 +500,7 @@ class StelarClient {
|
|
|
468
500
|
_handleBrowserMsg(e) {
|
|
469
501
|
try {
|
|
470
502
|
if (e.data instanceof ArrayBuffer) {
|
|
471
|
-
const
|
|
472
|
-
const parsed = parseWSBinary(buf);
|
|
503
|
+
const parsed = parseWSBinaryBrowser(e.data);
|
|
473
504
|
if (!parsed)
|
|
474
505
|
return;
|
|
475
506
|
this.opts.hooks.onMessage?.({ event: parsed.event, data: parsed.buffer, isBinary: true });
|
package/src/client.ts
CHANGED
|
@@ -84,6 +84,33 @@ function parseWSBinary(payload: Buffer): { event: string; buffer: ArrayBuffer }
|
|
|
84
84
|
} catch { return null; }
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/** Browser-safe version of encodeWSBinary — no Buffer dependency */
|
|
88
|
+
function encodeWSBinaryBrowser(event: string, data: ArrayBuffer): ArrayBuffer {
|
|
89
|
+
const hdrJson = JSON.stringify({ event });
|
|
90
|
+
const hdrBytes = new TextEncoder().encode(hdrJson);
|
|
91
|
+
const payload = new Uint8Array(data);
|
|
92
|
+
const frame = new ArrayBuffer(4 + hdrBytes.length + payload.length);
|
|
93
|
+
const view = new DataView(frame);
|
|
94
|
+
view.setUint32(0, hdrBytes.length, false); // big-endian
|
|
95
|
+
new Uint8Array(frame, 4, hdrBytes.length).set(hdrBytes);
|
|
96
|
+
new Uint8Array(frame, 4 + hdrBytes.length).set(payload);
|
|
97
|
+
return frame;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Browser-safe version of parseWSBinary — no Buffer dependency */
|
|
101
|
+
function parseWSBinaryBrowser(payload: ArrayBuffer): { event: string; buffer: ArrayBuffer } | null {
|
|
102
|
+
if (payload.byteLength < 4) return null;
|
|
103
|
+
const view = new DataView(payload);
|
|
104
|
+
const hdrLen = view.getUint32(0, false); // big-endian
|
|
105
|
+
if (hdrLen > payload.byteLength - 4) return null;
|
|
106
|
+
try {
|
|
107
|
+
const hdrBytes = new Uint8Array(payload, 4, hdrLen);
|
|
108
|
+
const hdr = JSON.parse(new TextDecoder().decode(hdrBytes));
|
|
109
|
+
const buffer = payload.slice(4 + hdrLen);
|
|
110
|
+
return { event: hdr.event, buffer };
|
|
111
|
+
} catch { return null; }
|
|
112
|
+
}
|
|
113
|
+
|
|
87
114
|
class StelarClient {
|
|
88
115
|
private url: string;
|
|
89
116
|
private opts: Required<Omit<StelarClientOptions, 'customReconnectDelay' | 'hooks'>> & {
|
|
@@ -207,13 +234,15 @@ class StelarClient {
|
|
|
207
234
|
if (this.opts.hooks.onBeforeEmit?.({ event, data }) === false) return this;
|
|
208
235
|
if (this._state !== 'connected') return this;
|
|
209
236
|
try {
|
|
210
|
-
const safeCopy = Buffer.from(new Uint8Array(data));
|
|
211
237
|
if (this.opts.mode === 'tcp' && this._tcpSock && !this._tcpSock.destroyed) {
|
|
238
|
+
const safeCopy = Buffer.from(new Uint8Array(data));
|
|
212
239
|
this._writeTCP(encodeBinaryFrame(event, safeCopy, this.opts.maxFrameSize));
|
|
213
240
|
} else if (this._nodeSock && !this._nodeSock.destroyed) {
|
|
241
|
+
const safeCopy = Buffer.from(new Uint8Array(data));
|
|
214
242
|
this._writeNodeWS(createWSBinaryFrameMasked(encodeWSBinary(event, safeCopy)));
|
|
215
243
|
} else if (this._ws && this._ws.readyState === WebSocket.OPEN) {
|
|
216
|
-
|
|
244
|
+
// Browser path: use ArrayBuffer-based encoding (no Buffer dependency)
|
|
245
|
+
const frame = encodeWSBinaryBrowser(event, data);
|
|
217
246
|
this._ws.send(frame);
|
|
218
247
|
}
|
|
219
248
|
this._sent++;
|
|
@@ -388,8 +417,7 @@ class StelarClient {
|
|
|
388
417
|
private _handleBrowserMsg(e: MessageEvent) {
|
|
389
418
|
try {
|
|
390
419
|
if (e.data instanceof ArrayBuffer) {
|
|
391
|
-
const
|
|
392
|
-
const parsed = parseWSBinary(buf);
|
|
420
|
+
const parsed = parseWSBinaryBrowser(e.data);
|
|
393
421
|
if (!parsed) return;
|
|
394
422
|
this.opts.hooks.onMessage?.({ event: parsed.event, data: parsed.buffer, isBinary: true });
|
|
395
423
|
this.events.get(parsed.event)?.(parsed.buffer);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** @stelar-time-real WebSocket browser stub — browser clients use native WebSocket, no manual framing needed */
|
|
2
|
+
|
|
3
|
+
export const DEFAULT_MAX_WS_FRAME_SIZE = 10 * 1024 * 1024;
|
|
4
|
+
export const OP_CONTINUATION = 0x0, OP_TEXT = 0x1, OP_BINARY = 0x2,
|
|
5
|
+
OP_CLOSE = 0x8, OP_PING = 0x9, OP_PONG = 0xA;
|
|
6
|
+
export const CLOSE_NORMAL = 1000, CLOSE_GOING_AWAY = 1001, CLOSE_PROTOCOL_ERROR = 1002,
|
|
7
|
+
CLOSE_UNSUPPORTED = 1003, CLOSE_INVALID_PAYLOAD = 1007, CLOSE_POLICY_VIOLATION = 1008,
|
|
8
|
+
CLOSE_MESSAGE_TOO_BIG = 1009, CLOSE_INTERNAL_ERROR = 1011;
|
|
9
|
+
|
|
10
|
+
export class WebSocketError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
constructor(message, code = CLOSE_INTERNAL_ERROR) { super(message); this.name = 'WebSocketError'; this.code = code; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* ── Node.js-only functions — stubs that throw if accidentally called in browser ── */
|
|
16
|
+
const nodeOnly = (name) => () => { throw new Error(`stelar-time-real: ${name}() is Node.js only — browser clients use native WebSocket`); };
|
|
17
|
+
|
|
18
|
+
export const computeAcceptKey = nodeOnly('computeAcceptKey');
|
|
19
|
+
export const generateWSKey = nodeOnly('generateWSKey');
|
|
20
|
+
export const validateWSKey = nodeOnly('validateWSKey');
|
|
21
|
+
export const buildUpgradeResponse = nodeOnly('buildUpgradeResponse');
|
|
22
|
+
export const clientWantsCompression = () => false;
|
|
23
|
+
export const parseWSFrame = nodeOnly('parseWSFrame');
|
|
24
|
+
export const createWSFrame = nodeOnly('createWSFrame');
|
|
25
|
+
export const wsCompress = nodeOnly('wsCompress');
|
|
26
|
+
export const wsDecompress = nodeOnly('wsDecompress');
|
|
27
|
+
|
|
28
|
+
/* Server (unmasked) */
|
|
29
|
+
export const createWSTextFrame = nodeOnly('createWSTextFrame');
|
|
30
|
+
export const createWSBinaryFrame = nodeOnly('createWSBinaryFrame');
|
|
31
|
+
export const createWSCloseFrame = nodeOnly('createWSCloseFrame');
|
|
32
|
+
export const createWSPingFrame = nodeOnly('createWSPingFrame');
|
|
33
|
+
export const createWSPongFrame = nodeOnly('createWSPongFrame');
|
|
34
|
+
|
|
35
|
+
/* Client (masked) */
|
|
36
|
+
export const createWSTextFrameMasked = nodeOnly('createWSTextFrameMasked');
|
|
37
|
+
export const createWSBinaryFrameMasked = nodeOnly('createWSBinaryFrameMasked');
|
|
38
|
+
export const createWSCloseFrameMasked = nodeOnly('createWSCloseFrameMasked');
|
|
39
|
+
export const createWSPingFrameMasked = nodeOnly('createWSPingFrameMasked');
|
|
40
|
+
export const createWSPongFrameMasked = nodeOnly('createWSPongFrameMasked');
|
|
41
|
+
|
|
42
|
+
export class WSFrameParser {
|
|
43
|
+
feed() { throw new Error('stelar-time-real: WSFrameParser is Node.js only — browser clients use native WebSocket'); }
|
|
44
|
+
reset() {}
|
|
45
|
+
getBytesReceived() { return 0; }
|
|
46
|
+
}
|
package/src/websocket.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["websocket.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAM7E,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAE1D,eAAO,MAAM,eAAe,IAAM,EAAE,OAAO,IAAM,EAAE,SAAS,IAAM,EAChE,QAAQ,IAAM,EAAE,OAAO,IAAM,EAAE,OAAO,KAAM,CAAC;AAE/C,eAAO,MAAM,YAAY,OAAO,EAAE,gBAAgB,OAAO,EAAE,oBAAoB,OAAO,EACpF,iBAAiB,OAAO,EAAE,qBAAqB,OAAO,EAAE,sBAAsB,OAAO,EACrF,qBAAqB,OAAO,EAAE,oBAAoB,OAAO,CAAC;AAE5D,qBAAa,cAAe,SAAQ,KAAK;IACvC,IAAI,EAAE,MAAM,CAAC;gBACD,OAAO,EAAE,MAAM,EAAE,IAAI,SAAuB;CACzD;AAED,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,WAA+D,CAAC;AAC5G,eAAO,MAAM,aAAa,cAA2C,CAAC;AACtE,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,OAA8E,CAAC;AAE3H,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAM5G;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGpF;AAED,MAAM,WAAW,OAAO;IAAG,GAAG,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;CAAE;
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["websocket.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAM7E,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAE1D,eAAO,MAAM,eAAe,IAAM,EAAE,OAAO,IAAM,EAAE,SAAS,IAAM,EAChE,QAAQ,IAAM,EAAE,OAAO,IAAM,EAAE,OAAO,KAAM,CAAC;AAE/C,eAAO,MAAM,YAAY,OAAO,EAAE,gBAAgB,OAAO,EAAE,oBAAoB,OAAO,EACpF,iBAAiB,OAAO,EAAE,qBAAqB,OAAO,EAAE,sBAAsB,OAAO,EACrF,qBAAqB,OAAO,EAAE,oBAAoB,OAAO,CAAC;AAE5D,qBAAa,cAAe,SAAQ,KAAK;IACvC,IAAI,EAAE,MAAM,CAAC;gBACD,OAAO,EAAE,MAAM,EAAE,IAAI,SAAuB;CACzD;AAED,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,WAA+D,CAAC;AAC5G,eAAO,MAAM,aAAa,cAA2C,CAAC;AACtE,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,OAA8E,CAAC;AAE3H,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAM5G;AAED,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGpF;AAED,MAAM,WAAW,OAAO;IAAG,GAAG,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;CAAE;AAM3G,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAA4B,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAetH;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,UAAQ,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAqBhH;AAGD,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,EAAE,kBAAgB,4BAAiD,CAAC;AACjH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,4BAAmC,CAAC;AACpF,eAAO,MAAM,kBAAkB,GAAI,aAAmB,EAAE,eAAW,4BAElE,CAAC;AACF,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,4BAAoD,CAAC;AACpG,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,4BAAoD,CAAC;AAGpG,eAAO,MAAM,uBAAuB,GAAI,KAAK,MAAM,EAAE,kBAAgB,4BAAgD,CAAC;AACtH,eAAO,MAAM,yBAAyB,GAAI,MAAM,MAAM,4BAAyC,CAAC;AAChG,eAAO,MAAM,wBAAwB,GAAI,aAAmB,EAAE,eAAW,4BAExE,CAAC;AACF,eAAO,MAAM,uBAAuB,+BAAsD,CAAC;AAC3F,eAAO,MAAM,uBAAuB,+BAAsD,CAAC;AAE3F,0EAA0E;AAC1E,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,QAAQ,CAAK;gBAET,GAAG,SAA4B;IAE3C,OAAO,CAAC,QAAQ;IAOhB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE;IAyB7B,KAAK;IACL,gBAAgB;CACjB"}
|
package/src/websocket.js
CHANGED
|
@@ -28,12 +28,15 @@ export function clientWantsCompression(extensionsHeader) {
|
|
|
28
28
|
return /permessage-deflate/.test(extensionsHeader);
|
|
29
29
|
}
|
|
30
30
|
const TAIL = Buffer.from([0x00, 0x00, 0xFF, 0xFF]);
|
|
31
|
+
let _TAIL = null;
|
|
32
|
+
function getTAIL() { if (!_TAIL)
|
|
33
|
+
_TAIL = Buffer.from([0x00, 0x00, 0xFF, 0xFF]); return _TAIL; }
|
|
31
34
|
export function wsCompress(data) {
|
|
32
35
|
const deflated = deflateRawSync(data);
|
|
33
36
|
return deflated.subarray(0, deflated.length - 4);
|
|
34
37
|
}
|
|
35
38
|
export function wsDecompress(data) {
|
|
36
|
-
return inflateRawSync(Buffer.concat([data,
|
|
39
|
+
return inflateRawSync(Buffer.concat([data, getTAIL()]));
|
|
37
40
|
}
|
|
38
41
|
export function parseWSFrame(buf, max = DEFAULT_MAX_WS_FRAME_SIZE) {
|
|
39
42
|
if (buf.length < 2)
|
package/src/websocket.ts
CHANGED
|
@@ -39,6 +39,8 @@ export function clientWantsCompression(extensionsHeader: string | undefined): bo
|
|
|
39
39
|
export interface WSFrame { fin: boolean; opcode: number; payload: Buffer; masked: boolean; rsv1: boolean; }
|
|
40
40
|
|
|
41
41
|
const TAIL = Buffer.from([0x00, 0x00, 0xFF, 0xFF]);
|
|
42
|
+
let _TAIL: Buffer | null = null;
|
|
43
|
+
function getTAIL(): Buffer { if (!_TAIL) _TAIL = Buffer.from([0x00, 0x00, 0xFF, 0xFF]); return _TAIL; }
|
|
42
44
|
|
|
43
45
|
export function wsCompress(data: Buffer): Buffer {
|
|
44
46
|
const deflated = deflateRawSync(data);
|
|
@@ -46,7 +48,7 @@ export function wsCompress(data: Buffer): Buffer {
|
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
export function wsDecompress(data: Buffer): Buffer {
|
|
49
|
-
return inflateRawSync(Buffer.concat([data,
|
|
51
|
+
return inflateRawSync(Buffer.concat([data, getTAIL()]));
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
export function parseWSFrame(buf: Buffer, max = DEFAULT_MAX_WS_FRAME_SIZE): { frame: WSFrame; consumed: number } | null {
|