@discordjs/ws 1.2.0-dev.1721822666-fcd35ea2e → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,10 +50,7 @@ const manager = new WebSocketManager({
50
50
  intents: 0, // for no intents
51
51
  rest,
52
52
  // uncomment if you have zlib-sync installed and want to use compression
53
- // compression: CompressionMethod.ZlibSync,
54
-
55
- // alternatively, we support compression using node's native `node:zlib` module:
56
- // compression: CompressionMethod.ZlibNative,
53
+ // compression: CompressionMethod.ZlibStream,
57
54
  });
58
55
 
59
56
  manager.on(WebSocketShardEvents.Dispatch, (event) => {
@@ -141,6 +141,7 @@ var import_node_timers = require("timers");
141
141
  var import_promises2 = require("timers/promises");
142
142
  var import_node_url = require("url");
143
143
  var import_node_util = require("util");
144
+ var import_node_zlib = require("zlib");
144
145
  var import_collection6 = require("@discordjs/collection");
145
146
  var import_util2 = require("@discordjs/util");
146
147
  var import_async_queue2 = require("@sapphire/async-queue");
@@ -279,7 +280,7 @@ var SimpleIdentifyThrottler = class {
279
280
  await state.queue.wait({ signal });
280
281
  try {
281
282
  const diff = state.resetsAt - Date.now();
282
- if (diff <= 5e3) {
283
+ if (diff > 0 && diff <= 5e3) {
283
284
  const time = diff + Math.random() * 1500;
284
285
  await (0, import_promises.setTimeout)(time);
285
286
  }
@@ -291,17 +292,8 @@ var SimpleIdentifyThrottler = class {
291
292
  };
292
293
 
293
294
  // src/utils/constants.ts
294
- var CompressionMethod = /* @__PURE__ */ ((CompressionMethod2) => {
295
- CompressionMethod2[CompressionMethod2["ZlibNative"] = 0] = "ZlibNative";
296
- CompressionMethod2[CompressionMethod2["ZlibSync"] = 1] = "ZlibSync";
297
- return CompressionMethod2;
298
- })(CompressionMethod || {});
299
295
  var DefaultDeviceProperty = `@discordjs/ws [VI]{{inject}}[/VI]`;
300
296
  var getDefaultSessionStore = (0, import_util.lazy)(() => new import_collection5.Collection());
301
- var CompressionParameterMap = {
302
- [0 /* ZlibNative */]: "zlib-stream",
303
- [1 /* ZlibSync */]: "zlib-stream"
304
- };
305
297
  var DefaultWebSocketManagerOptions = {
306
298
  async buildIdentifyThrottler(manager) {
307
299
  const info = await manager.fetchGatewayInformation();
@@ -320,7 +312,6 @@ var DefaultWebSocketManagerOptions = {
320
312
  version: import_v10.APIVersion,
321
313
  encoding: "json" /* JSON */,
322
314
  compression: null,
323
- useIdentifyCompression: false,
324
315
  retrieveSessionInfo(shardId) {
325
316
  const store = getDefaultSessionStore();
326
317
  return store.get(shardId) ?? null;
@@ -353,7 +344,6 @@ var KnownNetworkErrorCodes = /* @__PURE__ */ new Set(["ECONNRESET", "ECONNREFUSE
353
344
 
354
345
  // src/ws/WebSocketShard.ts
355
346
  var getZlibSync = (0, import_util2.lazy)(async () => import("zlib-sync").then((mod) => mod.default).catch(() => null));
356
- var getNativeZlib = (0, import_util2.lazy)(async () => import("zlib").then((mod) => mod).catch(() => null));
357
347
  var WebSocketShardEvents = /* @__PURE__ */ ((WebSocketShardEvents2) => {
358
348
  WebSocketShardEvents2["Closed"] = "closed";
359
349
  WebSocketShardEvents2["Debug"] = "debug";
@@ -376,8 +366,8 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
376
366
  __name(this, "WebSocketShard");
377
367
  }
378
368
  connection = null;
379
- nativeInflate = null;
380
- zLibSyncInflate = null;
369
+ useIdentifyCompress = false;
370
+ inflate = null;
381
371
  textDecoder = new import_node_util.TextDecoder();
382
372
  replayedEvents = 0;
383
373
  isAck = true;
@@ -394,16 +384,6 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
394
384
  strategy;
395
385
  id;
396
386
  #status = 0 /* Idle */;
397
- identifyCompressionEnabled = false;
398
- /**
399
- * @privateRemarks
400
- *
401
- * This is needed because `this.strategy.options.compression` is not an actual reflection of the compression method
402
- * used, but rather the compression method that the user wants to use. This is because the libraries could just be missing.
403
- */
404
- get transportCompressionEnabled() {
405
- return this.strategy.options.compression !== null && (this.nativeInflate ?? this.zLibSyncInflate) !== null;
406
- }
407
387
  get status() {
408
388
  return this.#status;
409
389
  }
@@ -435,53 +415,21 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
435
415
  if (this.#status !== 0 /* Idle */) {
436
416
  throw new Error("Tried to connect a shard that wasn't idle");
437
417
  }
438
- const { version, encoding, compression, useIdentifyCompression } = this.strategy.options;
439
- this.identifyCompressionEnabled = useIdentifyCompression;
418
+ const { version, encoding, compression } = this.strategy.options;
440
419
  const params = new import_node_url.URLSearchParams({ v: version, encoding });
441
- if (compression !== null) {
442
- if (useIdentifyCompression) {
443
- console.warn("WebSocketShard: transport compression is enabled, disabling identify compression");
444
- this.identifyCompressionEnabled = false;
445
- }
446
- params.append("compress", CompressionParameterMap[compression]);
447
- switch (compression) {
448
- case 0 /* ZlibNative */: {
449
- const zlib = await getNativeZlib();
450
- if (zlib) {
451
- const inflate = zlib.createInflate({
452
- chunkSize: 65535,
453
- flush: zlib.constants.Z_SYNC_FLUSH
454
- });
455
- inflate.on("error", (error) => {
456
- this.emit("error" /* Error */, { error });
457
- });
458
- this.nativeInflate = inflate;
459
- } else {
460
- console.warn("WebSocketShard: Compression is set to native but node:zlib is not available.");
461
- params.delete("compress");
462
- }
463
- break;
464
- }
465
- case 1 /* ZlibSync */: {
466
- const zlib = await getZlibSync();
467
- if (zlib) {
468
- this.zLibSyncInflate = new zlib.Inflate({
469
- chunkSize: 65535,
470
- to: "string"
471
- });
472
- } else {
473
- console.warn("WebSocketShard: Compression is set to zlib-sync, but it is not installed.");
474
- params.delete("compress");
475
- }
476
- break;
477
- }
478
- }
479
- }
480
- if (this.identifyCompressionEnabled) {
481
- const zlib = await getNativeZlib();
482
- if (!zlib) {
483
- console.warn("WebSocketShard: Identify compression is enabled, but node:zlib is not available.");
484
- this.identifyCompressionEnabled = false;
420
+ if (compression) {
421
+ const zlib = await getZlibSync();
422
+ if (zlib) {
423
+ params.append("compress", compression);
424
+ this.inflate = new zlib.Inflate({
425
+ chunkSize: 65535,
426
+ to: "string"
427
+ });
428
+ } else if (!this.useIdentifyCompress) {
429
+ this.useIdentifyCompress = true;
430
+ console.warn(
431
+ "WebSocketShard: Compression is enabled but zlib-sync is not installed, falling back to identify compress"
432
+ );
485
433
  }
486
434
  }
487
435
  const session = await this.strategy.retrieveSessionInfo(this.id);
@@ -675,25 +623,24 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
675
623
  `shard id: ${this.id.toString()}`,
676
624
  `shard count: ${this.strategy.options.shardCount}`,
677
625
  `intents: ${this.strategy.options.intents}`,
678
- `compression: ${this.transportCompressionEnabled ? CompressionParameterMap[this.strategy.options.compression] : this.identifyCompressionEnabled ? "identify" : "none"}`
626
+ `compression: ${this.inflate ? "zlib-stream" : this.useIdentifyCompress ? "identify" : "none"}`
679
627
  ]);
680
- const data = {
628
+ const d = {
681
629
  token: this.strategy.options.token,
682
630
  properties: this.strategy.options.identifyProperties,
683
631
  intents: this.strategy.options.intents,
684
- compress: this.identifyCompressionEnabled,
632
+ compress: this.useIdentifyCompress,
685
633
  shard: [this.id, this.strategy.options.shardCount]
686
634
  };
687
635
  if (this.strategy.options.largeThreshold) {
688
- data.large_threshold = this.strategy.options.largeThreshold;
636
+ d.large_threshold = this.strategy.options.largeThreshold;
689
637
  }
690
638
  if (this.strategy.options.initialPresence) {
691
- data.presence = this.strategy.options.initialPresence;
639
+ d.presence = this.strategy.options.initialPresence;
692
640
  }
693
641
  await this.send({
694
642
  op: import_v102.GatewayOpcodes.Identify,
695
- // eslint-disable-next-line id-length
696
- d: data
643
+ d
697
644
  });
698
645
  await this.waitForEvent("ready" /* Ready */, this.strategy.options.readyTimeout);
699
646
  }
@@ -708,7 +655,6 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
708
655
  this.replayedEvents = 0;
709
656
  return this.send({
710
657
  op: import_v102.GatewayOpcodes.Resume,
711
- // eslint-disable-next-line id-length
712
658
  d: {
713
659
  token: this.strategy.options.token,
714
660
  seq: session.sequence,
@@ -723,18 +669,11 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
723
669
  const session = await this.strategy.retrieveSessionInfo(this.id);
724
670
  await this.send({
725
671
  op: import_v102.GatewayOpcodes.Heartbeat,
726
- // eslint-disable-next-line id-length
727
672
  d: session?.sequence ?? null
728
673
  });
729
674
  this.lastHeartbeatAt = Date.now();
730
675
  this.isAck = false;
731
676
  }
732
- parseInflateResult(result) {
733
- if (!result) {
734
- return null;
735
- }
736
- return JSON.parse(typeof result === "string" ? result : this.textDecoder.decode(result));
737
- }
738
677
  async unpackMessage(data, isBinary) {
739
678
  if (!isBinary) {
740
679
  try {
@@ -744,10 +683,9 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
744
683
  }
745
684
  }
746
685
  const decompressable = new Uint8Array(data);
747
- if (this.identifyCompressionEnabled) {
748
- return new Promise(async (resolve2, reject) => {
749
- const zlib = await getNativeZlib();
750
- zlib.inflate(decompressable, { chunkSize: 65535 }, (err, result) => {
686
+ if (this.useIdentifyCompress) {
687
+ return new Promise((resolve2, reject) => {
688
+ (0, import_node_zlib.inflate)(decompressable, { chunkSize: 65535 }, (err, result) => {
751
689
  if (err) {
752
690
  reject(err);
753
691
  return;
@@ -756,37 +694,30 @@ var WebSocketShard = class extends import_async_event_emitter.AsyncEventEmitter
756
694
  });
757
695
  });
758
696
  }
759
- if (this.transportCompressionEnabled) {
760
- const flush = decompressable.length >= 4 && decompressable.at(-4) === 0 && decompressable.at(-3) === 0 && decompressable.at(-2) === 255 && decompressable.at(-1) === 255;
761
- if (this.nativeInflate) {
762
- this.nativeInflate.write(decompressable, "binary");
763
- if (!flush) {
764
- return null;
765
- }
766
- const [result] = await (0, import_node_events2.once)(this.nativeInflate, "data");
767
- return this.parseInflateResult(result);
768
- } else if (this.zLibSyncInflate) {
769
- const zLibSync = await getZlibSync();
770
- this.zLibSyncInflate.push(import_node_buffer.Buffer.from(decompressable), flush ? zLibSync.Z_SYNC_FLUSH : zLibSync.Z_NO_FLUSH);
771
- if (this.zLibSyncInflate.err) {
772
- this.emit("error" /* Error */, {
773
- error: new Error(
774
- `${this.zLibSyncInflate.err}${this.zLibSyncInflate.msg ? `: ${this.zLibSyncInflate.msg}` : ""}`
775
- )
776
- });
777
- }
778
- if (!flush) {
779
- return null;
780
- }
781
- const { result } = this.zLibSyncInflate;
782
- return this.parseInflateResult(result);
697
+ if (this.inflate) {
698
+ const l = decompressable.length;
699
+ const flush = l >= 4 && decompressable[l - 4] === 0 && decompressable[l - 3] === 0 && decompressable[l - 2] === 255 && decompressable[l - 1] === 255;
700
+ const zlib = await getZlibSync();
701
+ this.inflate.push(import_node_buffer.Buffer.from(decompressable), flush ? zlib.Z_SYNC_FLUSH : zlib.Z_NO_FLUSH);
702
+ if (this.inflate.err) {
703
+ this.emit("error" /* Error */, {
704
+ error: new Error(`${this.inflate.err}${this.inflate.msg ? `: ${this.inflate.msg}` : ""}`)
705
+ });
706
+ }
707
+ if (!flush) {
708
+ return null;
709
+ }
710
+ const { result } = this.inflate;
711
+ if (!result) {
712
+ return null;
783
713
  }
714
+ return JSON.parse(typeof result === "string" ? result : this.textDecoder.decode(result));
784
715
  }
785
716
  this.debug([
786
717
  "Received a message we were unable to decompress",
787
718
  `isBinary: ${isBinary.toString()}`,
788
- `identifyCompressionEnabled: ${this.identifyCompressionEnabled.toString()}`,
789
- `inflate: ${this.transportCompressionEnabled ? CompressionMethod[this.strategy.options.compression] : "none"}`
719
+ `useIdentifyCompress: ${this.useIdentifyCompress.toString()}`,
720
+ `inflate: ${Boolean(this.inflate).toString()}`
790
721
  ]);
791
722
  return null;
792
723
  }