@naeemo/capnp 0.9.1 → 0.9.3

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.
@@ -67,6 +67,432 @@ function checkEnvVar() {
67
67
  }
68
68
  if (checkEnvVar()) debugState.enabled = true;
69
69
 
70
+ //#endregion
71
+ //#region node_modules/.pnpm/lz4js@0.2.0/node_modules/lz4js/util.js
72
+ var require_util = /* @__PURE__ */ __commonJSMin(((exports) => {
73
+ exports.hashU32 = function hashU32(a) {
74
+ a = a | 0;
75
+ a = a + 2127912214 + (a << 12) | 0;
76
+ a = a ^ -949894596 ^ a >>> 19;
77
+ a = a + 374761393 + (a << 5) | 0;
78
+ a = a + -744332180 ^ a << 9;
79
+ a = a + -42973499 + (a << 3) | 0;
80
+ return a ^ -1252372727 ^ a >>> 16 | 0;
81
+ };
82
+ exports.readU64 = function readU64(b, n) {
83
+ var x = 0;
84
+ x |= b[n++] << 0;
85
+ x |= b[n++] << 8;
86
+ x |= b[n++] << 16;
87
+ x |= b[n++] << 24;
88
+ x |= b[n++] << 32;
89
+ x |= b[n++] << 40;
90
+ x |= b[n++] << 48;
91
+ x |= b[n++] << 56;
92
+ return x;
93
+ };
94
+ exports.readU32 = function readU32(b, n) {
95
+ var x = 0;
96
+ x |= b[n++] << 0;
97
+ x |= b[n++] << 8;
98
+ x |= b[n++] << 16;
99
+ x |= b[n++] << 24;
100
+ return x;
101
+ };
102
+ exports.writeU32 = function writeU32(b, n, x) {
103
+ b[n++] = x >> 0 & 255;
104
+ b[n++] = x >> 8 & 255;
105
+ b[n++] = x >> 16 & 255;
106
+ b[n++] = x >> 24 & 255;
107
+ };
108
+ exports.imul = function imul(a, b) {
109
+ var ah = a >>> 16;
110
+ var al = a & 65535;
111
+ var bh = b >>> 16;
112
+ var bl = b & 65535;
113
+ return al * bl + (ah * bl + al * bh << 16) | 0;
114
+ };
115
+ }));
116
+
117
+ //#endregion
118
+ //#region node_modules/.pnpm/lz4js@0.2.0/node_modules/lz4js/xxh32.js
119
+ var require_xxh32 = /* @__PURE__ */ __commonJSMin(((exports) => {
120
+ var util = require_util();
121
+ var prime1 = 2654435761;
122
+ var prime2 = 2246822519;
123
+ var prime3 = 3266489917;
124
+ var prime4 = 668265263;
125
+ var prime5 = 374761393;
126
+ function rotl32(x, r) {
127
+ x = x | 0;
128
+ r = r | 0;
129
+ return x >>> (32 - r | 0) | x << r | 0;
130
+ }
131
+ function rotmul32(h, r, m) {
132
+ h = h | 0;
133
+ r = r | 0;
134
+ m = m | 0;
135
+ return util.imul(h >>> (32 - r | 0) | h << r, m) | 0;
136
+ }
137
+ function shiftxor32(h, s) {
138
+ h = h | 0;
139
+ s = s | 0;
140
+ return h >>> s ^ h | 0;
141
+ }
142
+ function xxhapply(h, src, m0, s, m1) {
143
+ return rotmul32(util.imul(src, m0) + h, s, m1);
144
+ }
145
+ function xxh1(h, src, index) {
146
+ return rotmul32(h + util.imul(src[index], prime5), 11, prime1);
147
+ }
148
+ function xxh4(h, src, index) {
149
+ return xxhapply(h, util.readU32(src, index), prime3, 17, prime4);
150
+ }
151
+ function xxh16(h, src, index) {
152
+ return [
153
+ xxhapply(h[0], util.readU32(src, index + 0), prime2, 13, prime1),
154
+ xxhapply(h[1], util.readU32(src, index + 4), prime2, 13, prime1),
155
+ xxhapply(h[2], util.readU32(src, index + 8), prime2, 13, prime1),
156
+ xxhapply(h[3], util.readU32(src, index + 12), prime2, 13, prime1)
157
+ ];
158
+ }
159
+ function xxh32(seed, src, index, len) {
160
+ var h, l = len;
161
+ if (len >= 16) {
162
+ h = [
163
+ seed + prime1 + prime2,
164
+ seed + prime2,
165
+ seed,
166
+ seed - prime1
167
+ ];
168
+ while (len >= 16) {
169
+ h = xxh16(h, src, index);
170
+ index += 16;
171
+ len -= 16;
172
+ }
173
+ h = rotl32(h[0], 1) + rotl32(h[1], 7) + rotl32(h[2], 12) + rotl32(h[3], 18) + l;
174
+ } else h = seed + prime5 + len >>> 0;
175
+ while (len >= 4) {
176
+ h = xxh4(h, src, index);
177
+ index += 4;
178
+ len -= 4;
179
+ }
180
+ while (len > 0) {
181
+ h = xxh1(h, src, index);
182
+ index++;
183
+ len--;
184
+ }
185
+ h = shiftxor32(util.imul(shiftxor32(util.imul(shiftxor32(h, 15), prime2), 13), prime3), 16);
186
+ return h >>> 0;
187
+ }
188
+ exports.hash = xxh32;
189
+ }));
190
+
191
+ //#endregion
192
+ //#region node_modules/.pnpm/lz4js@0.2.0/node_modules/lz4js/lz4.js
193
+ var require_lz4 = /* @__PURE__ */ __commonJSMin(((exports) => {
194
+ var xxhash = require_xxh32();
195
+ var util = require_util();
196
+ var minMatch = 4;
197
+ var minLength = 13;
198
+ var searchLimit = 5;
199
+ var skipTrigger = 6;
200
+ var hashSize = 65536;
201
+ var mlBits = 4;
202
+ var mlMask = (1 << mlBits) - 1;
203
+ var runMask = 15;
204
+ var blockBuf = makeBuffer(5 << 20);
205
+ var hashTable = makeHashTable();
206
+ var magicNum = 407708164;
207
+ var fdContentChksum = 4;
208
+ var fdContentSize = 8;
209
+ var fdBlockChksum = 16;
210
+ var fdVersion = 64;
211
+ var fdVersionMask = 192;
212
+ var bsUncompressed = 2147483648;
213
+ var bsDefault = 7;
214
+ var bsShift = 4;
215
+ var bsMask = 7;
216
+ var bsMap = {
217
+ 4: 65536,
218
+ 5: 262144,
219
+ 6: 1048576,
220
+ 7: 4194304
221
+ };
222
+ function makeHashTable() {
223
+ try {
224
+ return new Uint32Array(hashSize);
225
+ } catch (error) {
226
+ var hashTable = new Array(hashSize);
227
+ for (var i = 0; i < hashSize; i++) hashTable[i] = 0;
228
+ return hashTable;
229
+ }
230
+ }
231
+ function clearHashTable(table) {
232
+ for (var i = 0; i < hashSize; i++) hashTable[i] = 0;
233
+ }
234
+ function makeBuffer(size) {
235
+ try {
236
+ return new Uint8Array(size);
237
+ } catch (error) {
238
+ var buf = new Array(size);
239
+ for (var i = 0; i < size; i++) buf[i] = 0;
240
+ return buf;
241
+ }
242
+ }
243
+ function sliceArray(array, start, end) {
244
+ if (Uint8Array.prototype.slice) return array.slice(start, end);
245
+ else {
246
+ var len = array.length;
247
+ start = start | 0;
248
+ start = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
249
+ end = end === void 0 ? len : end | 0;
250
+ end = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);
251
+ var arraySlice = new Uint8Array(end - start);
252
+ for (var i = start, n = 0; i < end;) arraySlice[n++] = array[i++];
253
+ return arraySlice;
254
+ }
255
+ }
256
+ exports.compressBound = function compressBound(n) {
257
+ return n + n / 255 + 16 | 0;
258
+ };
259
+ exports.decompressBound = function decompressBound(src) {
260
+ var sIndex = 0;
261
+ if (util.readU32(src, sIndex) !== magicNum) throw new Error("invalid magic number");
262
+ sIndex += 4;
263
+ var descriptor = src[sIndex++];
264
+ if ((descriptor & fdVersionMask) !== fdVersion) throw new Error("incompatible descriptor version " + (descriptor & fdVersionMask));
265
+ var useBlockSum = (descriptor & fdBlockChksum) !== 0;
266
+ var useContentSize = (descriptor & fdContentSize) !== 0;
267
+ var bsIdx = src[sIndex++] >> bsShift & bsMask;
268
+ if (bsMap[bsIdx] === void 0) throw new Error("invalid block size " + bsIdx);
269
+ var maxBlockSize = bsMap[bsIdx];
270
+ if (useContentSize) return util.readU64(src, sIndex);
271
+ sIndex++;
272
+ var maxSize = 0;
273
+ while (true) {
274
+ var blockSize = util.readU32(src, sIndex);
275
+ sIndex += 4;
276
+ if (blockSize & bsUncompressed) {
277
+ blockSize &= ~bsUncompressed;
278
+ maxSize += blockSize;
279
+ } else maxSize += maxBlockSize;
280
+ if (blockSize === 0) return maxSize;
281
+ if (useBlockSum) sIndex += 4;
282
+ sIndex += blockSize;
283
+ }
284
+ };
285
+ exports.makeBuffer = makeBuffer;
286
+ exports.decompressBlock = function decompressBlock(src, dst, sIndex, sLength, dIndex) {
287
+ var mLength, mOffset, sEnd = sIndex + sLength, n, i;
288
+ while (sIndex < sEnd) {
289
+ var token = src[sIndex++];
290
+ var literalCount = token >> 4;
291
+ if (literalCount > 0) {
292
+ if (literalCount === 15) while (true) {
293
+ literalCount += src[sIndex];
294
+ if (src[sIndex++] !== 255) break;
295
+ }
296
+ for (n = sIndex + literalCount; sIndex < n;) dst[dIndex++] = src[sIndex++];
297
+ }
298
+ if (sIndex >= sEnd) break;
299
+ mLength = token & 15;
300
+ mOffset = src[sIndex++] | src[sIndex++] << 8;
301
+ if (mLength === 15) while (true) {
302
+ mLength += src[sIndex];
303
+ if (src[sIndex++] !== 255) break;
304
+ }
305
+ mLength += minMatch;
306
+ for (i = dIndex - mOffset, n = i + mLength; i < n;) dst[dIndex++] = dst[i++] | 0;
307
+ }
308
+ return dIndex;
309
+ };
310
+ exports.compressBlock = function compressBlock(src, dst, sIndex, sLength, hashTable) {
311
+ var mIndex, mAnchor, mLength, mOffset, mStep;
312
+ var literalCount, dIndex = 0, sEnd = sLength + sIndex, n;
313
+ mAnchor = sIndex;
314
+ if (sLength >= minLength) {
315
+ var searchMatchCount = (1 << skipTrigger) + 3;
316
+ while (sIndex + minMatch < sEnd - searchLimit) {
317
+ var seq = util.readU32(src, sIndex);
318
+ var hash = util.hashU32(seq) >>> 0;
319
+ hash = (hash >> 16 ^ hash) >>> 0 & 65535;
320
+ mIndex = hashTable[hash] - 1;
321
+ hashTable[hash] = sIndex + 1;
322
+ if (mIndex < 0 || sIndex - mIndex >>> 16 > 0 || util.readU32(src, mIndex) !== seq) {
323
+ mStep = searchMatchCount++ >> skipTrigger;
324
+ sIndex += mStep;
325
+ continue;
326
+ }
327
+ searchMatchCount = (1 << skipTrigger) + 3;
328
+ literalCount = sIndex - mAnchor;
329
+ mOffset = sIndex - mIndex;
330
+ sIndex += minMatch;
331
+ mIndex += minMatch;
332
+ mLength = sIndex;
333
+ while (sIndex < sEnd - searchLimit && src[sIndex] === src[mIndex]) {
334
+ sIndex++;
335
+ mIndex++;
336
+ }
337
+ mLength = sIndex - mLength;
338
+ var token = mLength < mlMask ? mLength : mlMask;
339
+ if (literalCount >= runMask) {
340
+ dst[dIndex++] = (runMask << mlBits) + token;
341
+ for (n = literalCount - runMask; n >= 255; n -= 255) dst[dIndex++] = 255;
342
+ dst[dIndex++] = n;
343
+ } else dst[dIndex++] = (literalCount << mlBits) + token;
344
+ for (var i = 0; i < literalCount; i++) dst[dIndex++] = src[mAnchor + i];
345
+ dst[dIndex++] = mOffset;
346
+ dst[dIndex++] = mOffset >> 8;
347
+ if (mLength >= mlMask) {
348
+ for (n = mLength - mlMask; n >= 255; n -= 255) dst[dIndex++] = 255;
349
+ dst[dIndex++] = n;
350
+ }
351
+ mAnchor = sIndex;
352
+ }
353
+ }
354
+ if (mAnchor === 0) return 0;
355
+ literalCount = sEnd - mAnchor;
356
+ if (literalCount >= runMask) {
357
+ dst[dIndex++] = runMask << mlBits;
358
+ for (n = literalCount - runMask; n >= 255; n -= 255) dst[dIndex++] = 255;
359
+ dst[dIndex++] = n;
360
+ } else dst[dIndex++] = literalCount << mlBits;
361
+ sIndex = mAnchor;
362
+ while (sIndex < sEnd) dst[dIndex++] = src[sIndex++];
363
+ return dIndex;
364
+ };
365
+ exports.decompressFrame = function decompressFrame(src, dst) {
366
+ var useBlockSum, useContentSum, useContentSize, descriptor;
367
+ var sIndex = 0;
368
+ var dIndex = 0;
369
+ if (util.readU32(src, sIndex) !== magicNum) throw new Error("invalid magic number");
370
+ sIndex += 4;
371
+ descriptor = src[sIndex++];
372
+ if ((descriptor & fdVersionMask) !== fdVersion) throw new Error("incompatible descriptor version");
373
+ useBlockSum = (descriptor & fdBlockChksum) !== 0;
374
+ useContentSum = (descriptor & fdContentChksum) !== 0;
375
+ useContentSize = (descriptor & fdContentSize) !== 0;
376
+ if (bsMap[src[sIndex++] >> bsShift & bsMask] === void 0) throw new Error("invalid block size");
377
+ if (useContentSize) sIndex += 8;
378
+ sIndex++;
379
+ while (true) {
380
+ var compSize = util.readU32(src, sIndex);
381
+ sIndex += 4;
382
+ if (compSize === 0) break;
383
+ if (useBlockSum) sIndex += 4;
384
+ if ((compSize & bsUncompressed) !== 0) {
385
+ compSize &= ~bsUncompressed;
386
+ for (var j = 0; j < compSize; j++) dst[dIndex++] = src[sIndex++];
387
+ } else {
388
+ dIndex = exports.decompressBlock(src, dst, sIndex, compSize, dIndex);
389
+ sIndex += compSize;
390
+ }
391
+ }
392
+ if (useContentSum) sIndex += 4;
393
+ return dIndex;
394
+ };
395
+ exports.compressFrame = function compressFrame(src, dst) {
396
+ var dIndex = 0;
397
+ util.writeU32(dst, dIndex, magicNum);
398
+ dIndex += 4;
399
+ dst[dIndex++] = fdVersion;
400
+ dst[dIndex++] = bsDefault << bsShift;
401
+ dst[dIndex] = xxhash.hash(0, dst, 4, dIndex - 4) >> 8;
402
+ dIndex++;
403
+ var maxBlockSize = bsMap[bsDefault];
404
+ var remaining = src.length;
405
+ var sIndex = 0;
406
+ clearHashTable(hashTable);
407
+ while (remaining > 0) {
408
+ var compSize = 0;
409
+ var blockSize = remaining > maxBlockSize ? maxBlockSize : remaining;
410
+ compSize = exports.compressBlock(src, blockBuf, sIndex, blockSize, hashTable);
411
+ if (compSize > blockSize || compSize === 0) {
412
+ util.writeU32(dst, dIndex, 2147483648 | blockSize);
413
+ dIndex += 4;
414
+ for (var z = sIndex + blockSize; sIndex < z;) dst[dIndex++] = src[sIndex++];
415
+ remaining -= blockSize;
416
+ } else {
417
+ util.writeU32(dst, dIndex, compSize);
418
+ dIndex += 4;
419
+ for (var j = 0; j < compSize;) dst[dIndex++] = blockBuf[j++];
420
+ sIndex += blockSize;
421
+ remaining -= blockSize;
422
+ }
423
+ }
424
+ util.writeU32(dst, dIndex, 0);
425
+ dIndex += 4;
426
+ return dIndex;
427
+ };
428
+ exports.decompress = function decompress(src, maxSize) {
429
+ var dst, size;
430
+ if (maxSize === void 0) maxSize = exports.decompressBound(src);
431
+ dst = exports.makeBuffer(maxSize);
432
+ size = exports.decompressFrame(src, dst);
433
+ if (size !== maxSize) dst = sliceArray(dst, 0, size);
434
+ return dst;
435
+ };
436
+ exports.compress = function compress(src, maxSize) {
437
+ var dst, size;
438
+ if (maxSize === void 0) maxSize = exports.compressBound(src.length);
439
+ dst = exports.makeBuffer(maxSize);
440
+ size = exports.compressFrame(src, dst);
441
+ if (size !== maxSize) dst = sliceArray(dst, 0, size);
442
+ return dst;
443
+ };
444
+ }));
445
+
446
+ //#endregion
447
+ //#region src/compression/lz4.ts
448
+ var import_lz4 = require_lz4();
449
+ /**
450
+ * Default compression options
451
+ */
452
+ const DEFAULT_COMPRESSION_OPTIONS = {
453
+ threshold: 1024,
454
+ acceleration: 1,
455
+ level: 0
456
+ };
457
+ /**
458
+ * Compress data using LZ4
459
+ * @param data - Data to compress
460
+ * @param options - Compression options
461
+ * @returns Compressed data, or null if compression failed or not beneficial
462
+ */
463
+ function compress(data, options = {}) {
464
+ const opts = {
465
+ ...DEFAULT_COMPRESSION_OPTIONS,
466
+ ...options
467
+ };
468
+ if (data.length < opts.threshold) return null;
469
+ try {
470
+ const compressed = (0, import_lz4.compress)(Array.from(data));
471
+ if (compressed.length >= data.length) return null;
472
+ return new Uint8Array(compressed);
473
+ } catch (_error) {
474
+ return null;
475
+ }
476
+ }
477
+ /**
478
+ * Decompress LZ4 compressed data
479
+ * @param data - Compressed data
480
+ * @param originalSize - Original uncompressed size
481
+ * @returns Decompressed data, or null if decompression failed
482
+ */
483
+ function decompress(data, originalSize) {
484
+ try {
485
+ const decompressed = (0, import_lz4.decompress)(Array.from(data), originalSize);
486
+ return new Uint8Array(decompressed);
487
+ } catch (_error) {
488
+ return null;
489
+ }
490
+ }
491
+ /**
492
+ * Alias for decompress - same function, different name for API compatibility
493
+ */
494
+ const uncompress = decompress;
495
+
70
496
  //#endregion
71
497
  //#region src/debug/index.ts
72
498
  /**
@@ -3870,6 +4296,115 @@ var import_sender = /* @__PURE__ */ __toESM(require_sender(), 1);
3870
4296
  var import_websocket = /* @__PURE__ */ __toESM(require_websocket(), 1);
3871
4297
  var import_websocket_server = /* @__PURE__ */ __toESM(require_websocket_server(), 1);
3872
4298
 
4299
+ //#endregion
4300
+ //#region src/compression/frame.ts
4301
+ /**
4302
+ * LZ4 Frame Format Module
4303
+ *
4304
+ * Frame format: Magic(4) + Flags(1) + Length(4) + Payload
4305
+ * - Magic: 0x4C5A3401 (LZ4\0\x01)
4306
+ * - Flags: compression options and metadata
4307
+ * - Length: uncompressed data length (4 bytes, little-endian)
4308
+ * - Payload: compressed or uncompressed data
4309
+ */
4310
+ /**
4311
+ * Frame format constants
4312
+ */
4313
+ const LZ4_FRAME_MAGIC = 1280979969;
4314
+ const LZ4_FRAME_HEADER_SIZE = 9;
4315
+ /**
4316
+ * Frame flags
4317
+ */
4318
+ let FrameFlags = /* @__PURE__ */ function(FrameFlags) {
4319
+ /** Data is compressed */
4320
+ FrameFlags[FrameFlags["COMPRESSED"] = 1] = "COMPRESSED";
4321
+ /** Reserved for future use */
4322
+ FrameFlags[FrameFlags["RESERVED_1"] = 2] = "RESERVED_1";
4323
+ /** Reserved for future use */
4324
+ FrameFlags[FrameFlags["RESERVED_2"] = 4] = "RESERVED_2";
4325
+ /** Reserved for future use */
4326
+ FrameFlags[FrameFlags["RESERVED_3"] = 8] = "RESERVED_3";
4327
+ /** Reserved for future use */
4328
+ FrameFlags[FrameFlags["RESERVED_4"] = 16] = "RESERVED_4";
4329
+ /** Reserved for future use */
4330
+ FrameFlags[FrameFlags["RESERVED_5"] = 32] = "RESERVED_5";
4331
+ /** Reserved for future use */
4332
+ FrameFlags[FrameFlags["RESERVED_6"] = 64] = "RESERVED_6";
4333
+ /** Reserved for future use */
4334
+ FrameFlags[FrameFlags["RESERVED_7"] = 128] = "RESERVED_7";
4335
+ return FrameFlags;
4336
+ }({});
4337
+ /**
4338
+ * Check if data has LZ4 frame magic header
4339
+ */
4340
+ function hasFrameMagic(data) {
4341
+ if (data.length < 4) return false;
4342
+ return new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) === LZ4_FRAME_MAGIC;
4343
+ }
4344
+ /**
4345
+ * Parse frame header from data
4346
+ * @returns FrameHeader if valid, null otherwise
4347
+ */
4348
+ function parseFrameHeader(data) {
4349
+ if (data.length < LZ4_FRAME_HEADER_SIZE) return null;
4350
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
4351
+ const magic = view.getUint32(0, true);
4352
+ if (magic !== LZ4_FRAME_MAGIC) return null;
4353
+ return {
4354
+ magic,
4355
+ flags: view.getUint8(4),
4356
+ length: view.getUint32(5, true)
4357
+ };
4358
+ }
4359
+ /**
4360
+ * Decompress framed data
4361
+ * @param data - Framed data (with or without frame header)
4362
+ * @param decompressFn - Decompression function for compressed payloads
4363
+ * @returns Decompressed data, or null if invalid
4364
+ */
4365
+ function decompressFrame(data, decompressFn) {
4366
+ const header = parseFrameHeader(data);
4367
+ if (!header) return data;
4368
+ const payloadOffset = LZ4_FRAME_HEADER_SIZE;
4369
+ if (data.length - payloadOffset < 0) return null;
4370
+ const payload = data.subarray(payloadOffset);
4371
+ if (header.flags & FrameFlags.COMPRESSED) return decompressFn(payload, header.length);
4372
+ return payload;
4373
+ }
4374
+
4375
+ //#endregion
4376
+ //#region src/compression/index.ts
4377
+ /**
4378
+ * Create default compression config
4379
+ */
4380
+ function createCompressionConfig(config) {
4381
+ return {
4382
+ enabled: false,
4383
+ algorithm: "lz4",
4384
+ threshold: 1024,
4385
+ level: 0,
4386
+ highCompression: false,
4387
+ ...config
4388
+ };
4389
+ }
4390
+ /**
4391
+ * Create empty compression stats
4392
+ */
4393
+ function createCompressionStats() {
4394
+ return {
4395
+ messagesCompressed: 0,
4396
+ messagesDecompressed: 0,
4397
+ bytesOriginal: 0,
4398
+ bytesCompressed: 0,
4399
+ compressionRatio: 1,
4400
+ savingsPercent: 0
4401
+ };
4402
+ }
4403
+ /**
4404
+ * Default compression configuration
4405
+ */
4406
+ const DEFAULT_COMPRESSION_CONFIG = createCompressionConfig();
4407
+
3873
4408
  //#endregion
3874
4409
  //#region src/proxy/websocket-proxy.ts
3875
4410
  /**
@@ -3878,6 +4413,27 @@ var import_websocket_server = /* @__PURE__ */ __toESM(require_websocket_server()
3878
4413
  * Allows browsers to connect to native Cap'n Proto services (C++, etc.)
3879
4414
  * via WebSocket. Handles the protocol bridging between WebSocket (browser)
3880
4415
  * and raw TCP (Cap'n Proto services).
4416
+ *
4417
+ * Features:
4418
+ * - Independent compression configuration for WebSocket and TCP sides
4419
+ * - Automatic compression/decompression bridging
4420
+ * - Support for different compression settings on each side
4421
+ * - Backward compatibility with non-compressed peers
4422
+ */
4423
+ /**
4424
+ * Convert Buffer to Uint8Array without copying if possible
4425
+ */
4426
+ function bufferToUint8Array(buffer) {
4427
+ return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
4428
+ }
4429
+ /**
4430
+ * Convert Uint8Array to Buffer without copying if possible
4431
+ */
4432
+ function uint8ArrayToBuffer(arr) {
4433
+ return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength);
4434
+ }
4435
+ /**
4436
+ * Represents a single proxy connection between WebSocket client and TCP server
3881
4437
  */
3882
4438
  var ProxyConnection = class extends EventEmitter {
3883
4439
  ws;
@@ -3885,16 +4441,22 @@ var ProxyConnection = class extends EventEmitter {
3885
4441
  stats;
3886
4442
  options;
3887
4443
  closed = false;
4444
+ wsCompressionConfig;
4445
+ tcpCompressionConfig;
3888
4446
  constructor(ws, options) {
3889
4447
  super();
3890
4448
  this.ws = ws;
3891
4449
  this.options = options;
4450
+ this.wsCompressionConfig = createCompressionConfig(options.compression?.ws);
4451
+ this.tcpCompressionConfig = createCompressionConfig(options.compression?.tcp);
3892
4452
  this.stats = {
3893
4453
  wsMessagesIn: 0,
3894
4454
  wsMessagesOut: 0,
3895
4455
  tcpBytesIn: 0,
3896
4456
  tcpBytesOut: 0,
3897
- connectedAt: /* @__PURE__ */ new Date()
4457
+ connectedAt: /* @__PURE__ */ new Date(),
4458
+ wsCompression: createCompressionStats(),
4459
+ tcpCompression: createCompressionStats()
3898
4460
  };
3899
4461
  this.setupWebSocket();
3900
4462
  }
@@ -3922,6 +4484,7 @@ var ProxyConnection = class extends EventEmitter {
3922
4484
  });
3923
4485
  this.tcpSocket.on("connect", () => {
3924
4486
  this.log("Connected to target TCP service");
4487
+ this.log(`Compression - WS: ${this.wsCompressionConfig.enabled ? "enabled" : "disabled"}, TCP: ${this.tcpCompressionConfig.enabled ? "enabled" : "disabled"}`);
3925
4488
  this.emit("connected");
3926
4489
  });
3927
4490
  this.tcpSocket.on("data", (data) => {
@@ -3941,29 +4504,78 @@ var ProxyConnection = class extends EventEmitter {
3941
4504
  this.close();
3942
4505
  });
3943
4506
  }
4507
+ /**
4508
+ * Handle incoming message from WebSocket client
4509
+ * - Decompress if compressed (from browser)
4510
+ * - Re-compress for TCP side if TCP compression is enabled
4511
+ * - Forward to TCP server
4512
+ */
3944
4513
  handleWebSocketMessage(data) {
3945
4514
  if (this.closed) return;
3946
4515
  const buffer = Buffer.isBuffer(data) ? data : Array.isArray(data) ? Buffer.concat(data) : Buffer.from(data);
3947
4516
  const maxSize = this.options.maxMessageSize ?? 16 * 1024 * 1024;
3948
- if (buffer.length > maxSize) {
3949
- this.log(`Message too large: ${buffer.length} bytes`);
4517
+ const uint8Data = bufferToUint8Array(buffer);
4518
+ const frameInfo = parseFrameHeader(uint8Data);
4519
+ const uncompressedSize = frameInfo ? frameInfo.length : buffer.length;
4520
+ if (uncompressedSize > maxSize) {
4521
+ this.log(`Message too large: ${uncompressedSize} bytes (max: ${maxSize})`);
3950
4522
  this.close();
3951
4523
  return;
3952
4524
  }
3953
4525
  this.stats.wsMessagesIn++;
3954
- this.stats.tcpBytesOut += buffer.length;
4526
+ let decompressedData;
4527
+ if (hasFrameMagic(uint8Data)) {
4528
+ const decompressed = decompressFrame(uint8Data, uncompress);
4529
+ if (decompressed !== null) {
4530
+ decompressedData = decompressed;
4531
+ this.log(`Decompressed WS message: ${buffer.length} -> ${decompressedData.length} bytes`);
4532
+ } else decompressedData = uint8Data;
4533
+ } else decompressedData = uint8Data;
4534
+ let dataToSend = decompressedData;
4535
+ if (this.tcpCompressionConfig.enabled) {
4536
+ const compressed = compress(decompressedData, { threshold: this.tcpCompressionConfig.threshold });
4537
+ if (compressed !== null) {
4538
+ dataToSend = compressed;
4539
+ this.log(`Compressed for TCP: ${decompressedData.length} -> ${dataToSend.length} bytes`);
4540
+ }
4541
+ }
4542
+ this.stats.tcpBytesOut += uint8ArrayToBuffer(dataToSend).length;
3955
4543
  if (this.tcpSocket?.writable) {
3956
- this.tcpSocket.write(buffer);
3957
- this.log(`Forwarded ${buffer.length} bytes to TCP`);
4544
+ const bufferToSend = uint8ArrayToBuffer(dataToSend);
4545
+ this.tcpSocket.write(bufferToSend);
4546
+ this.log(`Forwarded ${dataToSend.length} bytes to TCP (original: ${decompressedData.length})`);
3958
4547
  }
3959
4548
  }
4549
+ /**
4550
+ * Handle incoming data from TCP server
4551
+ * - Decompress if compressed (from native Cap'n Proto service)
4552
+ * - Re-compress for WebSocket side if WS compression is enabled
4553
+ * - Forward to WebSocket client
4554
+ */
3960
4555
  handleTcpData(data) {
3961
4556
  if (this.closed) return;
3962
4557
  this.stats.tcpBytesIn += data.length;
4558
+ const uint8Data = bufferToUint8Array(data);
4559
+ let decompressedData;
4560
+ if (hasFrameMagic(uint8Data)) {
4561
+ const decompressed = decompressFrame(uint8Data, uncompress);
4562
+ if (decompressed !== null) {
4563
+ decompressedData = decompressed;
4564
+ this.log(`Decompressed TCP message: ${data.length} -> ${decompressedData.length} bytes`);
4565
+ } else decompressedData = uint8Data;
4566
+ } else decompressedData = uint8Data;
4567
+ let dataToSend = decompressedData;
4568
+ if (this.wsCompressionConfig.enabled) {
4569
+ const compressed = compress(decompressedData, { threshold: this.wsCompressionConfig.threshold });
4570
+ if (compressed !== null) {
4571
+ dataToSend = compressed;
4572
+ this.log(`Compressed for WS: ${decompressedData.length} -> ${dataToSend.length} bytes`);
4573
+ }
4574
+ }
3963
4575
  this.stats.wsMessagesOut++;
3964
4576
  if (this.ws.readyState === import_websocket.default.OPEN) {
3965
- this.ws.send(data);
3966
- this.log(`Forwarded ${data.length} bytes to WebSocket`);
4577
+ this.ws.send(dataToSend);
4578
+ this.log(`Forwarded ${dataToSend.length} bytes to WebSocket (original: ${decompressedData.length})`);
3967
4579
  }
3968
4580
  }
3969
4581
  log(...args) {
@@ -3980,6 +4592,10 @@ var ProxyConnection = class extends EventEmitter {
3980
4592
  this.emit("closed");
3981
4593
  }
3982
4594
  };
4595
+ /**
4596
+ * WebSocket-to-TCP Proxy server
4597
+ * Manages multiple proxy connections
4598
+ */
3983
4599
  var CapnpWebSocketProxy = class extends EventEmitter {
3984
4600
  wss;
3985
4601
  connections = /* @__PURE__ */ new Map();
@@ -4037,6 +4653,9 @@ if (import.meta.url === `file://${process.argv[1]}`) {
4037
4653
  let targetHost = "localhost";
4038
4654
  let targetPort = 8081;
4039
4655
  let debug = false;
4656
+ let wsCompression = false;
4657
+ let tcpCompression = false;
4658
+ let compressionThreshold = 1024;
4040
4659
  for (let i = 0; i < args.length; i++) switch (args[i]) {
4041
4660
  case "--ws-port":
4042
4661
  case "-p":
@@ -4053,6 +4672,17 @@ if (import.meta.url === `file://${process.argv[1]}`) {
4053
4672
  case "-d":
4054
4673
  debug = true;
4055
4674
  break;
4675
+ case "--ws-compression":
4676
+ case "-w":
4677
+ wsCompression = true;
4678
+ break;
4679
+ case "--tcp-compression":
4680
+ case "-c":
4681
+ tcpCompression = true;
4682
+ break;
4683
+ case "--compression-threshold":
4684
+ compressionThreshold = Number.parseInt(args[++i], 10);
4685
+ break;
4056
4686
  case "--help":
4057
4687
  case "-h":
4058
4688
  console.log(`
@@ -4061,13 +4691,25 @@ Cap'n Proto WebSocket-to-TCP Proxy
4061
4691
  Usage: npx @naeemo/capnp proxy [options]
4062
4692
 
4063
4693
  Options:
4064
- -p, --ws-port <port> WebSocket server port (default: 8080)
4065
- -t, --target <host:port> Target TCP service (default: localhost:8081)
4066
- -d, --debug Enable debug logging
4067
- -h, --help Show this help
4694
+ -p, --ws-port <port> WebSocket server port (default: 8080)
4695
+ -t, --target <host:port> Target TCP service (default: localhost:8081)
4696
+ -d, --debug Enable debug logging
4697
+ -w, --ws-compression Enable WebSocket side compression
4698
+ -c, --tcp-compression Enable TCP side compression
4699
+ --compression-threshold <n> Minimum size to compress (default: 1024)
4700
+ -h, --help Show this help
4068
4701
 
4069
- Example:
4702
+ Examples:
4070
4703
  npx @naeemo/capnp proxy -p 9000 -t 192.168.1.100:7000
4704
+
4705
+ # Enable compression on WebSocket side only (for browser clients)
4706
+ npx @naeemo/capnp proxy -p 9000 -t localhost:7000 -w
4707
+
4708
+ # Enable compression on both sides
4709
+ npx @naeemo/capnp proxy -p 9000 -t localhost:7000 -w -c
4710
+
4711
+ # Enable compression with lower threshold
4712
+ npx @naeemo/capnp proxy -p 9000 -t localhost:7000 -w --compression-threshold 512
4071
4713
  `);
4072
4714
  process.exit(0);
4073
4715
  }
@@ -4075,11 +4717,26 @@ Example:
4075
4717
  wsPort,
4076
4718
  targetHost,
4077
4719
  targetPort,
4078
- debug
4720
+ debug,
4721
+ compression: {
4722
+ ws: {
4723
+ enabled: wsCompression,
4724
+ threshold: compressionThreshold
4725
+ },
4726
+ tcp: {
4727
+ enabled: tcpCompression,
4728
+ threshold: compressionThreshold
4729
+ }
4730
+ }
4079
4731
  });
4080
4732
  console.log("WebSocket-to-TCP Proxy started");
4081
4733
  console.log(` WebSocket: ws://localhost:${wsPort}`);
4082
4734
  console.log(` Target: ${targetHost}:${targetPort}`);
4735
+ if (wsCompression || tcpCompression) {
4736
+ console.log(" Compression:");
4737
+ console.log(` WebSocket: ${wsCompression ? "enabled" : "disabled"} (threshold: ${compressionThreshold})`);
4738
+ console.log(` TCP: ${tcpCompression ? "enabled" : "disabled"} (threshold: ${compressionThreshold})`);
4739
+ }
4083
4740
  proxy.on("connection", () => {
4084
4741
  console.log(`Active connections: ${proxy.getConnectionCount()}`);
4085
4742
  });
@@ -4525,4 +5182,4 @@ async function run(args) {
4525
5182
 
4526
5183
  //#endregion
4527
5184
  export { run };
4528
- //# sourceMappingURL=cli-bench-bkR1vGK8.js.map
5185
+ //# sourceMappingURL=cli-bench-BRKmxDEn.js.map