@resolveio/server-lib 20.14.24 → 20.14.25

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.
@@ -14,9 +14,21 @@ export declare class WebSocketManager {
14
14
  private _chunkThresholdBytes;
15
15
  private _chunkSizeBytes;
16
16
  private readonly _chunkMetaFlag;
17
+ private _chunkingEnabled;
18
+ private readonly _textDecoder;
19
+ private _wsSendDebug;
20
+ private _wsSendLogThresholdMs;
21
+ private _wsSendLogBytes;
22
+ private _wsSendLogBufferedBytes;
17
23
  constructor();
18
24
  static create(mainServer: any, maxMessageSize?: number, messageDelay?: number, chunkThresholdBytes?: number, chunkSizeBytes?: number): WebSocketManager;
19
25
  initialize(mainServer: any, maxMessageSize?: number, messageDelay?: number, chunkThresholdBytes?: number, chunkSizeBytes?: number): void;
26
+ private parseDebugFlag;
27
+ private parseBoolean;
28
+ private parsePositiveInt;
29
+ private shouldLogSend;
30
+ private getBufferedAmount;
31
+ private logWsSend;
20
32
  addWebSocket(ws: WebSocket): void;
21
33
  removeWebSocket(ws: WebSocket): void;
22
34
  getWebSocket(id_socket: string): WebSocket | undefined;
@@ -27,6 +39,7 @@ export declare class WebSocketManager {
27
39
  private handleSendError;
28
40
  closeConnection(ws: WebSocket): void;
29
41
  private prepareChunkContext;
42
+ private decodePackedPayload;
30
43
  private sendChunkSequence;
31
44
  private transmitBatch;
32
45
  private generateChunkId;
@@ -14,12 +14,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.WebSocketManager = void 0;
15
15
  var crypto_1 = require("crypto");
16
16
  var msgpackr_1 = require("msgpackr");
17
+ var util_1 = require("util");
17
18
  var WebSocketManager = /** @class */ (function () {
18
19
  function WebSocketManager() {
19
20
  this._messageBuffers = new Map();
20
21
  this._batchingTimers = new Map();
21
22
  this._webSockets = new Map();
22
23
  this._chunkMetaFlag = '__chunked';
24
+ this._textDecoder = new util_1.TextDecoder();
25
+ this._wsSendDebug = false;
26
+ this._wsSendLogThresholdMs = 2000;
27
+ this._wsSendLogBytes = 2 * 1024 * 1024;
28
+ this._wsSendLogBufferedBytes = 4 * 1024 * 1024;
23
29
  }
24
30
  WebSocketManager.create = function (mainServer, maxMessageSize, messageDelay, chunkThresholdBytes, chunkSizeBytes) {
25
31
  if (maxMessageSize === void 0) { maxMessageSize = 20480; }
@@ -38,8 +44,76 @@ var WebSocketManager = /** @class */ (function () {
38
44
  this._mainServer = mainServer;
39
45
  this._maxMessageSize = maxMessageSize;
40
46
  this._messageDelay = messageDelay;
41
- this._chunkThresholdBytes = chunkThresholdBytes;
42
- this._chunkSizeBytes = chunkSizeBytes;
47
+ this._chunkingEnabled = this.parseBoolean(process.env.WS_CHUNKING_ENABLED, true);
48
+ this._chunkThresholdBytes = this.parsePositiveInt(process.env.WS_CHUNK_THRESHOLD_BYTES, chunkThresholdBytes);
49
+ this._chunkSizeBytes = this.parsePositiveInt(process.env.WS_CHUNK_SIZE_BYTES, chunkSizeBytes);
50
+ this._wsSendDebug = this.parseDebugFlag(process.env.WS_SEND_DEBUG);
51
+ this._wsSendLogThresholdMs = this.parsePositiveInt(process.env.WS_SEND_LOG_THRESHOLD_MS, this._wsSendLogThresholdMs);
52
+ this._wsSendLogBytes = this.parsePositiveInt(process.env.WS_SEND_LOG_BYTES, this._wsSendLogBytes);
53
+ this._wsSendLogBufferedBytes = this.parsePositiveInt(process.env.WS_SEND_LOG_BUFFERED_BYTES, this._wsSendLogBufferedBytes);
54
+ };
55
+ WebSocketManager.prototype.parseDebugFlag = function (value) {
56
+ if (value === true) {
57
+ return true;
58
+ }
59
+ if (value === false || value === null || value === undefined) {
60
+ return false;
61
+ }
62
+ if (typeof value === 'number') {
63
+ return value === 1;
64
+ }
65
+ if (typeof value === 'string') {
66
+ var normalized = value.trim().toLowerCase();
67
+ return ['1', 'true', 'yes', 'y', 'on'].includes(normalized);
68
+ }
69
+ return false;
70
+ };
71
+ WebSocketManager.prototype.parseBoolean = function (value, fallback) {
72
+ if (value === null || value === undefined) {
73
+ return fallback;
74
+ }
75
+ return this.parseDebugFlag(value);
76
+ };
77
+ WebSocketManager.prototype.parsePositiveInt = function (value, fallback) {
78
+ var parsed = parseInt(value !== null && value !== void 0 ? value : '', 10);
79
+ if (Number.isNaN(parsed) || parsed <= 0) {
80
+ return fallback;
81
+ }
82
+ return parsed;
83
+ };
84
+ WebSocketManager.prototype.shouldLogSend = function (durationMs, totalBytes, bufferedAmount) {
85
+ if (this._wsSendDebug) {
86
+ return true;
87
+ }
88
+ if (durationMs !== null && durationMs >= this._wsSendLogThresholdMs) {
89
+ return true;
90
+ }
91
+ if (totalBytes !== null && totalBytes >= this._wsSendLogBytes) {
92
+ return true;
93
+ }
94
+ if (bufferedAmount !== null && bufferedAmount >= this._wsSendLogBufferedBytes) {
95
+ return true;
96
+ }
97
+ return false;
98
+ };
99
+ WebSocketManager.prototype.getBufferedAmount = function (ws) {
100
+ if (!ws) {
101
+ return null;
102
+ }
103
+ var buffered = ws.bufferedAmount;
104
+ return typeof buffered === 'number' ? buffered : null;
105
+ };
106
+ WebSocketManager.prototype.logWsSend = function (event, ws, details) {
107
+ if (!this._wsSendDebug) {
108
+ return;
109
+ }
110
+ var payload = Object.assign({
111
+ ts: new Date().toISOString(),
112
+ event: event,
113
+ id_ws: ws ? ws['id_socket'] : null,
114
+ user: ws ? ws['user'] : null
115
+ }, details);
116
+ console.log(JSON.stringify(payload));
43
117
  };
44
118
  WebSocketManager.prototype.addWebSocket = function (ws) {
45
119
  var wsId = ws['id_socket'];
@@ -94,9 +168,32 @@ var WebSocketManager = /** @class */ (function () {
94
168
  if (!ws || ws.readyState !== ws.OPEN || !packedData || !packedData.byteLength) {
95
169
  return;
96
170
  }
171
+ var shouldChunk = this._chunkingEnabled && packedData.byteLength > this._chunkThresholdBytes;
172
+ if (!shouldChunk) {
173
+ var decoded = this.decodePackedPayload(packedData, encoding);
174
+ if (decoded !== undefined) {
175
+ this.send(ws, { messageId: messageId, hasError: hasError, data: decoded });
176
+ return;
177
+ }
178
+ if (!this._chunkingEnabled) {
179
+ return;
180
+ }
181
+ }
182
+ var sendStartMs = Date.now();
183
+ var bufferedStart = this.getBufferedAmount(ws);
97
184
  var chunkId = this.generateChunkId();
98
185
  var totalChunks = Math.max(1, Math.ceil(packedData.byteLength / this._chunkSizeBytes));
99
186
  var chunkSize = this._chunkSizeBytes;
187
+ if (this.shouldLogSend(null, packedData.byteLength, bufferedStart)) {
188
+ this.logWsSend('wsSendStart', ws, {
189
+ messageId: messageId,
190
+ totalBytes: packedData.byteLength,
191
+ totalChunks: totalChunks,
192
+ chunkSize: chunkSize,
193
+ encoding: encoding,
194
+ bufferedAmount: bufferedStart
195
+ });
196
+ }
100
197
  // Flush any buffered messages so the chunk stream starts immediately.
101
198
  this.flushMessages(ws);
102
199
  var startMessage = {
@@ -129,6 +226,19 @@ var WebSocketManager = /** @class */ (function () {
129
226
  _a)
130
227
  };
131
228
  _this.transmitBatch(ws, [endMessage]);
229
+ var durationMs = Date.now() - sendStartMs;
230
+ var bufferedEnd = _this.getBufferedAmount(ws);
231
+ if (_this.shouldLogSend(durationMs, packedData.byteLength, bufferedEnd)) {
232
+ _this.logWsSend('wsSendEnd', ws, {
233
+ messageId: messageId,
234
+ totalBytes: packedData.byteLength,
235
+ totalChunks: totalChunks,
236
+ chunkSize: chunkSize,
237
+ encoding: encoding,
238
+ durationMs: durationMs,
239
+ bufferedAmount: bufferedEnd
240
+ });
241
+ }
132
242
  return;
133
243
  }
134
244
  var start = index * chunkSize;
@@ -233,6 +343,9 @@ var WebSocketManager = /** @class */ (function () {
233
343
  };
234
344
  WebSocketManager.prototype.prepareChunkContext = function (message) {
235
345
  var _a;
346
+ if (!this._chunkingEnabled) {
347
+ return null;
348
+ }
236
349
  if (!message || message.hasError) {
237
350
  return null;
238
351
  }
@@ -253,6 +366,23 @@ var WebSocketManager = /** @class */ (function () {
253
366
  }
254
367
  return null;
255
368
  };
369
+ WebSocketManager.prototype.decodePackedPayload = function (packedData, encoding) {
370
+ var _a;
371
+ try {
372
+ var source = packedData;
373
+ if (encoding === 'msgpack') {
374
+ return (0, msgpackr_1.unpack)(source);
375
+ }
376
+ var text = this._textDecoder.decode(source);
377
+ return JSON.parse(text);
378
+ }
379
+ catch (err) {
380
+ if ((_a = this._mainServer.getSubscriptionManager()) === null || _a === void 0 ? void 0 : _a.getEnableDebug()) {
381
+ console.log(new Date(), 'WebSocketManager', 'Packed decode failed', (err === null || err === void 0 ? void 0 : err.message) || err);
382
+ }
383
+ return undefined;
384
+ }
385
+ };
256
386
  WebSocketManager.prototype.sendChunkSequence = function (ws, original, chunkContext) {
257
387
  var _a, _b, _c;
258
388
  var chunkId = this.generateChunkId();
@@ -310,6 +440,7 @@ var WebSocketManager = /** @class */ (function () {
310
440
  var isChunkEnvelope = batch.length === 1 && ((_a = batch[0]) === null || _a === void 0 ? void 0 : _a.data) && typeof batch[0].data === 'object' && batch[0].data[this._chunkMetaFlag];
311
441
  var packedData = Buffer.from((0, msgpackr_1.pack)(batch));
312
442
  var dataSize = packedData.byteLength;
443
+ var bufferedAmount = this.getBufferedAmount(ws);
313
444
  if (!isChunkEnvelope && dataSize > this._maxMessageSize) {
314
445
  this.sendMessagesInChunksBinary(ws, batch);
315
446
  }
@@ -320,6 +451,14 @@ var WebSocketManager = /** @class */ (function () {
320
451
  }
321
452
  });
322
453
  }
454
+ if (this.shouldLogSend(null, dataSize, bufferedAmount)) {
455
+ this.logWsSend('wsBatchSend', ws, {
456
+ batchSize: batch.length,
457
+ dataSize: dataSize,
458
+ isChunkEnvelope: isChunkEnvelope,
459
+ bufferedAmount: bufferedAmount
460
+ });
461
+ }
323
462
  };
324
463
  WebSocketManager.prototype.generateChunkId = function () {
325
464
  return (0, crypto_1.randomBytes)(8).toString('hex');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/managers/websocket.manager.ts"],"names":[],"mappings":"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","file":"websocket.manager.js","sourcesContent":["import { randomBytes } from 'crypto';\nimport { pack } from 'msgpackr';\nimport { WebSocket } from 'ws';\n\ninterface ServerResponseModel {\n\tmessageId: number;\n\thasError: boolean;\n\tdata: any;\n}\n\nexport class WebSocketManager {\n\tprivate _mainServer;\n\tprivate _messageBuffers: Map<string, ServerResponseModel[]> = new Map();\n\tprivate _batchingTimers: Map<string, NodeJS.Timeout> = new Map();\n\tprivate _maxMessageSize: number;\n\tprivate _messageDelay: number;\n\tprivate _webSockets: Map<string, WebSocket> = new Map();\n\tprivate _chunkThresholdBytes: number;\n\tprivate _chunkSizeBytes: number;\n\tprivate readonly _chunkMetaFlag = '__chunked';\n\n\tconstructor() {}\n\t\n\tstatic create(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25, chunkThresholdBytes: number = 512 * 1024, chunkSizeBytes: number = 1024 * 1024) {\n\t\tconst websocketManager = new WebSocketManager();\n\t\twebsocketManager.initialize(mainServer, maxMessageSize, messageDelay, chunkThresholdBytes, chunkSizeBytes);\n\t\treturn websocketManager;\n\t}\n\n\tpublic initialize(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25, chunkThresholdBytes: number = 3 * 1024 * 1024, chunkSizeBytes: number = 4 * 1024 * 1024) {\n\t\tthis._mainServer = mainServer;\n\t\tthis._maxMessageSize = maxMessageSize;\n\t\tthis._messageDelay = messageDelay;\n\t\tthis._chunkThresholdBytes = chunkThresholdBytes;\n\t\tthis._chunkSizeBytes = chunkSizeBytes;\n\t}\n\n\tpublic addWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.set(wsId, ws);\n\t}\n\n\tpublic removeWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.delete(wsId);\n\t\tthis.closeConnection(ws);\n\t}\n\n\tpublic getWebSocket(id_socket: string): WebSocket | undefined {\n\t\treturn this._webSockets.get(id_socket);\n\t}\n\n\tpublic send(ws: WebSocket, data: ServerResponseModel | string): void {\n\t\tconst wsId = ws['id_socket'];\n\n\t\tif (!this._messageBuffers.has(wsId)) {\n\t\t\tthis._messageBuffers.set(wsId, []);\n\t\t}\n\n\t\tif (typeof data === 'string') {\n\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\tws.send(data, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\t// Handle string messages like 'ping' or 'pong'\n\t\t\tconst chunkContext = this.prepareChunkContext(data);\n\t\t\tif (chunkContext) {\n\t\t\t\tthis.flushMessages(ws);\n\t\t\t\tthis.sendChunkSequence(ws, data, chunkContext);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._messageBuffers.get(wsId).push(data);\n\t\t}\n\n\t\tif (!this._batchingTimers.has(wsId)) {\n\t\t\t// Set a timer to send the batch after a short delay\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.flushMessages(ws);\n\t\t\t}, this._messageDelay);\n\t\t\tthis._batchingTimers.set(wsId, timer);\n\t\t}\n\t}\n\n\tpublic sendPackedBuffer(ws: WebSocket, messageId: number, hasError: boolean, packedData: Uint8Array | Buffer, encoding: 'msgpack' | 'json' = 'msgpack'): void {\n\t\tif (!ws || ws.readyState !== ws.OPEN || !packedData || !packedData.byteLength) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst chunkId = this.generateChunkId();\n\t\tconst totalChunks = Math.max(1, Math.ceil(packedData.byteLength / this._chunkSizeBytes));\n\t\tconst chunkSize = this._chunkSizeBytes;\n\n\t\t// Flush any buffered messages so the chunk stream starts immediately.\n\t\tthis.flushMessages(ws);\n\n\t\tconst startMessage: ServerResponseModel = {\n\t\t\tmessageId: messageId,\n\t\t\thasError: hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'start',\n\t\t\t\ttotalChunks: totalChunks,\n\t\t\t\ttotalBytes: packedData.byteLength,\n\t\t\t\tchunkSize: chunkSize,\n\t\t\t\tencoding: encoding\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [startMessage]);\n\n\t\tconst sendChunk = (index: number) => {\n\t\t\tif (!ws || ws.readyState !== ws.OPEN) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (index >= totalChunks) {\n\t\t\t\tconst endMessage: ServerResponseModel = {\n\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\thasError: hasError,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\t\t\tchunkId: chunkId,\n\t\t\t\t\t\tchunkStatus: 'end'\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tthis.transmitBatch(ws, [endMessage]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst start = index * chunkSize;\n\t\t\tconst end = Math.min(packedData.byteLength, start + chunkSize);\n\t\t\tconst slice = packedData.subarray(start, end);\n\t\t\tconst payload = encoding === 'msgpack' ? slice : this.toBase64(slice);\n\n\t\t\tconst chunkMessage: ServerResponseModel = {\n\t\t\t\tmessageId: messageId,\n\t\t\t\thasError: hasError,\n\t\t\t\tdata: {\n\t\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\t\tchunkId: chunkId,\n\t\t\t\t\tchunkStatus: 'chunk',\n\t\t\t\t\tchunkIndex: index,\n\t\t\t\t\tpayload: payload,\n\t\t\t\t\tencoding: encoding\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.transmitBatch(ws, [chunkMessage]);\n\n\t\t\tsetImmediate(() => sendChunk(index + 1));\n\t\t};\n\n\t\tsetImmediate(() => sendChunk(0));\n\t}\n\n\tprivate flushMessages(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tconst messages = this._messageBuffers.get(wsId);\n\n\t\tif (messages && messages.length > 0) {\n\t\t\t// Combine messages into one payload\n\t\t\tthis.transmitBatch(ws, messages);\n\n\t\t\tthis._messageBuffers.delete(wsId);\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n\t}\n\n\tprivate sendMessagesInChunksBinary(ws: WebSocket, messages: ServerResponseModel[]): void {\n\t\tlet chunk: ServerResponseModel[] = [];\n\t\tlet chunkSize = 0;\n\n\t\tfor (const message of messages) {\n\t\t\tconst packedMessage = Buffer.from(<any>pack([message]));\n\t\t\tconst messageSize = packedMessage.byteLength;\n\n\t\t\tif (chunkSize + messageSize > this._maxMessageSize) {\n\t\t\t\tconst packedChunk = Buffer.from(<any>pack(chunk));\n\t\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tchunk = [message];\n\t\t\t\tchunkSize = messageSize;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tchunk.push(message);\n\t\t\t\tchunkSize += messageSize;\n\t\t\t}\n\t\t}\n\n\t\tif (chunk.length > 0) {\n\t\t\tconst packedChunk = Buffer.from(<any>pack(chunk));\n\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleSendError(ws: WebSocket, error: Error): void {\n\t\tif (this._mainServer.getSubscriptionManager()) {\n\t\t\t// Handle send error, e.g., unsubscribe, close connection\n\t\t\tif (this._mainServer.getSubscriptionManager().getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Unsub WS', ws['user'], ws['id_socket'], error);\n\t\t\t}\n\t\t\tthis._mainServer.getSubscriptionManager().unsubscribeAll(ws);\n\t\t\tthis.removeWebSocket(ws);\n\t\t}\n\t}\n\n\tpublic closeConnection(ws: WebSocket): void {\n\t\tws.close();\n\t\tconst wsId = ws['id_socket'];\n\t\t// Clean up buffers and timers\n\t\tthis._messageBuffers.delete(wsId);\n\t\tif (this._batchingTimers.has(wsId)) {\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n \n process.nextTick(() => {\n if ([ws.OPEN, ws.CLOSING].includes(<any>ws.readyState)) {\n // Socket still hangs, hard close\n ws.terminate();\n }\n });\n\t}\n\n\tprivate prepareChunkContext(message: ServerResponseModel): { buffer: Buffer, encoding: 'msgpack' | 'json' } | null {\n\t\tif (!message || message.hasError) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = message.data;\n\t\tif (data === undefined || data === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst packed = Buffer.from(<any>pack(data));\n\t\t\tif (packed.byteLength > this._chunkThresholdBytes) {\n\t\t\t\treturn { buffer: packed, encoding: 'msgpack' };\n\t\t\t}\n\t\t}\n\t\tcatch (err) {\n\t\t\tif (this._mainServer.getSubscriptionManager()?.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Chunking pack failed', err?.message || err);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate sendChunkSequence(ws: WebSocket, original: ServerResponseModel, chunkContext: { buffer: Buffer, encoding: 'msgpack' | 'json' }): void {\n\t\tconst chunkId = this.generateChunkId();\n\t\tconst totalChunks = Math.ceil(chunkContext.buffer.byteLength / this._chunkSizeBytes);\n\n\t\tconst startMessage: ServerResponseModel = {\n\t\t\tmessageId: original.messageId,\n\t\t\thasError: original.hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'start',\n\t\t\t\ttotalChunks: totalChunks,\n\t\t\t\ttotalBytes: chunkContext.buffer.byteLength,\n\t\t\t\tchunkSize: this._chunkSizeBytes,\n\t\t\t\tencoding: chunkContext.encoding\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [startMessage]);\n\n\t\tfor (let index = 0; index < totalChunks; index++) {\n\t\t\tconst start = index * this._chunkSizeBytes;\n\t\t\tconst end = Math.min(chunkContext.buffer.byteLength, start + this._chunkSizeBytes);\n\t\t\tconst slice = chunkContext.buffer.subarray(start, end);\n\t\t\tconst chunkPayload = slice;\n\n\t\t\tconst chunkMessage: ServerResponseModel = {\n\t\t\t\tmessageId: original.messageId,\n\t\t\t\thasError: original.hasError,\n\t\t\t\tdata: {\n\t\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\t\tchunkId: chunkId,\n\t\t\t\t\tchunkStatus: 'chunk',\n\t\t\t\t\tchunkIndex: index,\n\t\t\t\t\tpayload: chunkPayload,\n\t\t\t\t\tencoding: chunkContext.encoding\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.transmitBatch(ws, [chunkMessage]);\n\t\t}\n\n\t\tconst endMessage: ServerResponseModel = {\n\t\t\tmessageId: original.messageId,\n\t\t\thasError: original.hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'end'\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [endMessage]);\n\t}\n\n\tprivate transmitBatch(ws: WebSocket, batch: ServerResponseModel[]): void {\n\t\tif (!batch || !batch.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isChunkEnvelope = batch.length === 1 && batch[0]?.data && typeof batch[0].data === 'object' && batch[0].data[this._chunkMetaFlag];\n\n\t\tconst packedData = Buffer.from(<any>pack(batch));\n\t\tconst dataSize = packedData.byteLength;\n\n\t\tif (!isChunkEnvelope && dataSize > this._maxMessageSize) {\n\t\t\tthis.sendMessagesInChunksBinary(ws, batch);\n\t\t}\n\t\telse {\n\t\t\tws.send(packedData, (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate generateChunkId(): string {\n\t\treturn randomBytes(8).toString('hex');\n\t}\n\n\tprivate toBase64(data: Uint8Array | Buffer): string {\n\t\tif (Buffer.isBuffer(data)) {\n\t\t\treturn data.toString('base64');\n\t\t}\n\n\t\treturn Buffer.from(data).toString('base64');\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../../src/managers/websocket.manager.ts"],"names":[],"mappings":"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","file":"websocket.manager.js","sourcesContent":["import { randomBytes } from 'crypto';\nimport { pack, unpack } from 'msgpackr';\nimport { TextDecoder } from 'util';\nimport { WebSocket } from 'ws';\n\ninterface ServerResponseModel {\n\tmessageId: number;\n\thasError: boolean;\n\tdata: any;\n}\n\nexport class WebSocketManager {\n\tprivate _mainServer;\n\tprivate _messageBuffers: Map<string, ServerResponseModel[]> = new Map();\n\tprivate _batchingTimers: Map<string, NodeJS.Timeout> = new Map();\n\tprivate _maxMessageSize: number;\n\tprivate _messageDelay: number;\n\tprivate _webSockets: Map<string, WebSocket> = new Map();\n\tprivate _chunkThresholdBytes: number;\n\tprivate _chunkSizeBytes: number;\n\tprivate readonly _chunkMetaFlag = '__chunked';\n\tprivate _chunkingEnabled: boolean;\n\tprivate readonly _textDecoder = new TextDecoder();\n\tprivate _wsSendDebug = false;\n\tprivate _wsSendLogThresholdMs = 2000;\n\tprivate _wsSendLogBytes = 2 * 1024 * 1024;\n\tprivate _wsSendLogBufferedBytes = 4 * 1024 * 1024;\n\n\tconstructor() {}\n\t\n\tstatic create(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25, chunkThresholdBytes: number = 512 * 1024, chunkSizeBytes: number = 1024 * 1024) {\n\t\tconst websocketManager = new WebSocketManager();\n\t\twebsocketManager.initialize(mainServer, maxMessageSize, messageDelay, chunkThresholdBytes, chunkSizeBytes);\n\t\treturn websocketManager;\n\t}\n\n\tpublic initialize(mainServer, maxMessageSize: number = 20480, messageDelay: number = 25, chunkThresholdBytes: number = 3 * 1024 * 1024, chunkSizeBytes: number = 4 * 1024 * 1024) {\n\t\tthis._mainServer = mainServer;\n\t\tthis._maxMessageSize = maxMessageSize;\n\t\tthis._messageDelay = messageDelay;\n\t\tthis._chunkingEnabled = this.parseBoolean(process.env.WS_CHUNKING_ENABLED, true);\n\t\tthis._chunkThresholdBytes = this.parsePositiveInt(process.env.WS_CHUNK_THRESHOLD_BYTES, chunkThresholdBytes);\n\t\tthis._chunkSizeBytes = this.parsePositiveInt(process.env.WS_CHUNK_SIZE_BYTES, chunkSizeBytes);\n\t\tthis._wsSendDebug = this.parseDebugFlag(process.env.WS_SEND_DEBUG);\n\t\tthis._wsSendLogThresholdMs = this.parsePositiveInt(process.env.WS_SEND_LOG_THRESHOLD_MS, this._wsSendLogThresholdMs);\n\t\tthis._wsSendLogBytes = this.parsePositiveInt(process.env.WS_SEND_LOG_BYTES, this._wsSendLogBytes);\n\t\tthis._wsSendLogBufferedBytes = this.parsePositiveInt(process.env.WS_SEND_LOG_BUFFERED_BYTES, this._wsSendLogBufferedBytes);\n\t}\n\n\tprivate parseDebugFlag(value: any): boolean {\n\t\tif (value === true) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (value === false || value === null || value === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (typeof value === 'number') {\n\t\t\treturn value === 1;\n\t\t}\n\n\t\tif (typeof value === 'string') {\n\t\t\tconst normalized = value.trim().toLowerCase();\n\t\t\treturn ['1', 'true', 'yes', 'y', 'on'].includes(normalized);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate parseBoolean(value: any, fallback: boolean): boolean {\n\t\tif (value === null || value === undefined) {\n\t\t\treturn fallback;\n\t\t}\n\n\t\treturn this.parseDebugFlag(value);\n\t}\n\n\tprivate parsePositiveInt(value: any, fallback: number): number {\n\t\tconst parsed = parseInt(value ?? '', 10);\n\t\tif (Number.isNaN(parsed) || parsed <= 0) {\n\t\t\treturn fallback;\n\t\t}\n\t\treturn parsed;\n\t}\n\n\tprivate shouldLogSend(durationMs: number | null, totalBytes: number | null, bufferedAmount: number | null): boolean {\n\t\tif (this._wsSendDebug) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (durationMs !== null && durationMs >= this._wsSendLogThresholdMs) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (totalBytes !== null && totalBytes >= this._wsSendLogBytes) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (bufferedAmount !== null && bufferedAmount >= this._wsSendLogBufferedBytes) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate getBufferedAmount(ws: WebSocket): number | null {\n\t\tif (!ws) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst buffered = (ws as any).bufferedAmount;\n\t\treturn typeof buffered === 'number' ? buffered : null;\n\t}\n\n\tprivate logWsSend(event: string, ws: WebSocket, details: Record<string, any>): void {\n\t\tif (!this._wsSendDebug) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst payload = Object.assign({\n\t\t\tts: new Date().toISOString(),\n\t\t\tevent,\n\t\t\tid_ws: ws ? ws['id_socket'] : null,\n\t\t\tuser: ws ? ws['user'] : null\n\t\t}, details);\n\n\t\tconsole.log(JSON.stringify(payload));\n\t}\n\n\tpublic addWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.set(wsId, ws);\n\t}\n\n\tpublic removeWebSocket(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tthis._webSockets.delete(wsId);\n\t\tthis.closeConnection(ws);\n\t}\n\n\tpublic getWebSocket(id_socket: string): WebSocket | undefined {\n\t\treturn this._webSockets.get(id_socket);\n\t}\n\n\tpublic send(ws: WebSocket, data: ServerResponseModel | string): void {\n\t\tconst wsId = ws['id_socket'];\n\n\t\tif (!this._messageBuffers.has(wsId)) {\n\t\t\tthis._messageBuffers.set(wsId, []);\n\t\t}\n\n\t\tif (typeof data === 'string') {\n\t\t\tif (ws && ws.readyState === ws.OPEN) {\n\t\t\t\tws.send(data, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\t// Handle string messages like 'ping' or 'pong'\n\t\t\tconst chunkContext = this.prepareChunkContext(data);\n\t\t\tif (chunkContext) {\n\t\t\t\tthis.flushMessages(ws);\n\t\t\t\tthis.sendChunkSequence(ws, data, chunkContext);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._messageBuffers.get(wsId).push(data);\n\t\t}\n\n\t\tif (!this._batchingTimers.has(wsId)) {\n\t\t\t// Set a timer to send the batch after a short delay\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.flushMessages(ws);\n\t\t\t}, this._messageDelay);\n\t\t\tthis._batchingTimers.set(wsId, timer);\n\t\t}\n\t}\n\n\tpublic sendPackedBuffer(ws: WebSocket, messageId: number, hasError: boolean, packedData: Uint8Array | Buffer, encoding: 'msgpack' | 'json' = 'msgpack'): void {\n\t\tif (!ws || ws.readyState !== ws.OPEN || !packedData || !packedData.byteLength) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst shouldChunk = this._chunkingEnabled && packedData.byteLength > this._chunkThresholdBytes;\n\t\tif (!shouldChunk) {\n\t\t\tconst decoded = this.decodePackedPayload(packedData, encoding);\n\t\t\tif (decoded !== undefined) {\n\t\t\t\tthis.send(ws, { messageId, hasError, data: decoded });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!this._chunkingEnabled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst sendStartMs = Date.now();\n\t\tconst bufferedStart = this.getBufferedAmount(ws);\n\t\tconst chunkId = this.generateChunkId();\n\t\tconst totalChunks = Math.max(1, Math.ceil(packedData.byteLength / this._chunkSizeBytes));\n\t\tconst chunkSize = this._chunkSizeBytes;\n\n\t\tif (this.shouldLogSend(null, packedData.byteLength, bufferedStart)) {\n\t\t\tthis.logWsSend('wsSendStart', ws, {\n\t\t\t\tmessageId,\n\t\t\t\ttotalBytes: packedData.byteLength,\n\t\t\t\ttotalChunks,\n\t\t\t\tchunkSize,\n\t\t\t\tencoding,\n\t\t\t\tbufferedAmount: bufferedStart\n\t\t\t});\n\t\t}\n\n\t\t// Flush any buffered messages so the chunk stream starts immediately.\n\t\tthis.flushMessages(ws);\n\n\t\tconst startMessage: ServerResponseModel = {\n\t\t\tmessageId: messageId,\n\t\t\thasError: hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'start',\n\t\t\t\ttotalChunks: totalChunks,\n\t\t\t\ttotalBytes: packedData.byteLength,\n\t\t\t\tchunkSize: chunkSize,\n\t\t\t\tencoding: encoding\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [startMessage]);\n\n\t\tconst sendChunk = (index: number) => {\n\t\t\tif (!ws || ws.readyState !== ws.OPEN) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (index >= totalChunks) {\n\t\t\t\tconst endMessage: ServerResponseModel = {\n\t\t\t\t\tmessageId: messageId,\n\t\t\t\t\thasError: hasError,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\t\t\tchunkId: chunkId,\n\t\t\t\t\t\tchunkStatus: 'end'\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tthis.transmitBatch(ws, [endMessage]);\n\t\t\t\tconst durationMs = Date.now() - sendStartMs;\n\t\t\t\tconst bufferedEnd = this.getBufferedAmount(ws);\n\t\t\t\tif (this.shouldLogSend(durationMs, packedData.byteLength, bufferedEnd)) {\n\t\t\t\t\tthis.logWsSend('wsSendEnd', ws, {\n\t\t\t\t\t\tmessageId,\n\t\t\t\t\t\ttotalBytes: packedData.byteLength,\n\t\t\t\t\t\ttotalChunks,\n\t\t\t\t\t\tchunkSize,\n\t\t\t\t\t\tencoding,\n\t\t\t\t\t\tdurationMs,\n\t\t\t\t\t\tbufferedAmount: bufferedEnd\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst start = index * chunkSize;\n\t\t\tconst end = Math.min(packedData.byteLength, start + chunkSize);\n\t\t\tconst slice = packedData.subarray(start, end);\n\t\t\tconst payload = encoding === 'msgpack' ? slice : this.toBase64(slice);\n\n\t\t\tconst chunkMessage: ServerResponseModel = {\n\t\t\t\tmessageId: messageId,\n\t\t\t\thasError: hasError,\n\t\t\t\tdata: {\n\t\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\t\tchunkId: chunkId,\n\t\t\t\t\tchunkStatus: 'chunk',\n\t\t\t\t\tchunkIndex: index,\n\t\t\t\t\tpayload: payload,\n\t\t\t\t\tencoding: encoding\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.transmitBatch(ws, [chunkMessage]);\n\n\t\t\tsetImmediate(() => sendChunk(index + 1));\n\t\t};\n\n\t\tsetImmediate(() => sendChunk(0));\n\t}\n\n\tprivate flushMessages(ws: WebSocket): void {\n\t\tconst wsId = ws['id_socket'];\n\t\tconst messages = this._messageBuffers.get(wsId);\n\n\t\tif (messages && messages.length > 0) {\n\t\t\t// Combine messages into one payload\n\t\t\tthis.transmitBatch(ws, messages);\n\n\t\t\tthis._messageBuffers.delete(wsId);\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n\t}\n\n\tprivate sendMessagesInChunksBinary(ws: WebSocket, messages: ServerResponseModel[]): void {\n\t\tlet chunk: ServerResponseModel[] = [];\n\t\tlet chunkSize = 0;\n\n\t\tfor (const message of messages) {\n\t\t\tconst packedMessage = Buffer.from(<any>pack([message]));\n\t\t\tconst messageSize = packedMessage.byteLength;\n\n\t\t\tif (chunkSize + messageSize > this._maxMessageSize) {\n\t\t\t\tconst packedChunk = Buffer.from(<any>pack(chunk));\n\t\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\t\tif (error) {\n\t\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tchunk = [message];\n\t\t\t\tchunkSize = messageSize;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tchunk.push(message);\n\t\t\t\tchunkSize += messageSize;\n\t\t\t}\n\t\t}\n\n\t\tif (chunk.length > 0) {\n\t\t\tconst packedChunk = Buffer.from(<any>pack(chunk));\n\t\t\tws.send(packedChunk, (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleSendError(ws: WebSocket, error: Error): void {\n\t\tif (this._mainServer.getSubscriptionManager()) {\n\t\t\t// Handle send error, e.g., unsubscribe, close connection\n\t\t\tif (this._mainServer.getSubscriptionManager().getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Unsub WS', ws['user'], ws['id_socket'], error);\n\t\t\t}\n\t\t\tthis._mainServer.getSubscriptionManager().unsubscribeAll(ws);\n\t\t\tthis.removeWebSocket(ws);\n\t\t}\n\t}\n\n\tpublic closeConnection(ws: WebSocket): void {\n\t\tws.close();\n\t\tconst wsId = ws['id_socket'];\n\t\t// Clean up buffers and timers\n\t\tthis._messageBuffers.delete(wsId);\n\t\tif (this._batchingTimers.has(wsId)) {\n\t\t\tclearTimeout(this._batchingTimers.get(wsId));\n\t\t\tthis._batchingTimers.delete(wsId);\n\t\t}\n \n process.nextTick(() => {\n if ([ws.OPEN, ws.CLOSING].includes(<any>ws.readyState)) {\n // Socket still hangs, hard close\n ws.terminate();\n }\n });\n\t}\n\n\tprivate prepareChunkContext(message: ServerResponseModel): { buffer: Buffer, encoding: 'msgpack' | 'json' } | null {\n\t\tif (!this._chunkingEnabled) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!message || message.hasError) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = message.data;\n\t\tif (data === undefined || data === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst packed = Buffer.from(<any>pack(data));\n\t\t\tif (packed.byteLength > this._chunkThresholdBytes) {\n\t\t\t\treturn { buffer: packed, encoding: 'msgpack' };\n\t\t\t}\n\t\t}\n\t\tcatch (err) {\n\t\t\tif (this._mainServer.getSubscriptionManager()?.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Chunking pack failed', err?.message || err);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate decodePackedPayload(packedData: Uint8Array | Buffer, encoding: 'msgpack' | 'json'): any | undefined {\n\t\ttry {\n\t\t\tconst source = packedData as Uint8Array;\n\t\t\tif (encoding === 'msgpack') {\n\t\t\t\treturn unpack(source);\n\t\t\t}\n\n\t\t\tconst text = this._textDecoder.decode(source);\n\t\t\treturn JSON.parse(text);\n\t\t}\n\t\tcatch (err) {\n\t\t\tif (this._mainServer.getSubscriptionManager()?.getEnableDebug()) {\n\t\t\t\tconsole.log(new Date(), 'WebSocketManager', 'Packed decode failed', err?.message || err);\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate sendChunkSequence(ws: WebSocket, original: ServerResponseModel, chunkContext: { buffer: Buffer, encoding: 'msgpack' | 'json' }): void {\n\t\tconst chunkId = this.generateChunkId();\n\t\tconst totalChunks = Math.ceil(chunkContext.buffer.byteLength / this._chunkSizeBytes);\n\n\t\tconst startMessage: ServerResponseModel = {\n\t\t\tmessageId: original.messageId,\n\t\t\thasError: original.hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'start',\n\t\t\t\ttotalChunks: totalChunks,\n\t\t\t\ttotalBytes: chunkContext.buffer.byteLength,\n\t\t\t\tchunkSize: this._chunkSizeBytes,\n\t\t\t\tencoding: chunkContext.encoding\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [startMessage]);\n\n\t\tfor (let index = 0; index < totalChunks; index++) {\n\t\t\tconst start = index * this._chunkSizeBytes;\n\t\t\tconst end = Math.min(chunkContext.buffer.byteLength, start + this._chunkSizeBytes);\n\t\t\tconst slice = chunkContext.buffer.subarray(start, end);\n\t\t\tconst chunkPayload = slice;\n\n\t\t\tconst chunkMessage: ServerResponseModel = {\n\t\t\t\tmessageId: original.messageId,\n\t\t\t\thasError: original.hasError,\n\t\t\t\tdata: {\n\t\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\t\tchunkId: chunkId,\n\t\t\t\t\tchunkStatus: 'chunk',\n\t\t\t\t\tchunkIndex: index,\n\t\t\t\t\tpayload: chunkPayload,\n\t\t\t\t\tencoding: chunkContext.encoding\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.transmitBatch(ws, [chunkMessage]);\n\t\t}\n\n\t\tconst endMessage: ServerResponseModel = {\n\t\t\tmessageId: original.messageId,\n\t\t\thasError: original.hasError,\n\t\t\tdata: {\n\t\t\t\t[this._chunkMetaFlag]: true,\n\t\t\t\tchunkId: chunkId,\n\t\t\t\tchunkStatus: 'end'\n\t\t\t}\n\t\t};\n\n\t\tthis.transmitBatch(ws, [endMessage]);\n\t}\n\n\tprivate transmitBatch(ws: WebSocket, batch: ServerResponseModel[]): void {\n\t\tif (!batch || !batch.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isChunkEnvelope = batch.length === 1 && batch[0]?.data && typeof batch[0].data === 'object' && batch[0].data[this._chunkMetaFlag];\n\n\t\tconst packedData = Buffer.from(<any>pack(batch));\n\t\tconst dataSize = packedData.byteLength;\n\t\tconst bufferedAmount = this.getBufferedAmount(ws);\n\n\t\tif (!isChunkEnvelope && dataSize > this._maxMessageSize) {\n\t\t\tthis.sendMessagesInChunksBinary(ws, batch);\n\t\t}\n\t\telse {\n\t\t\tws.send(packedData, (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\tthis.handleSendError(ws, error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif (this.shouldLogSend(null, dataSize, bufferedAmount)) {\n\t\t\tthis.logWsSend('wsBatchSend', ws, {\n\t\t\t\tbatchSize: batch.length,\n\t\t\t\tdataSize,\n\t\t\t\tisChunkEnvelope,\n\t\t\t\tbufferedAmount\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate generateChunkId(): string {\n\t\treturn randomBytes(8).toString('hex');\n\t}\n\n\tprivate toBase64(data: Uint8Array | Buffer): string {\n\t\tif (Buffer.isBuffer(data)) {\n\t\t\treturn data.toString('base64');\n\t\t}\n\n\t\treturn Buffer.from(data).toString('base64');\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resolveio/server-lib",
3
- "version": "20.14.24",
3
+ "version": "20.14.25",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "package": "./build_package.sh",