@bakit/gateway 3.0.1 → 3.0.2

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/dist/index.cjs CHANGED
@@ -10,6 +10,8 @@ var child_process = require('child_process');
10
10
  var path = require('path');
11
11
  var url = require('url');
12
12
  var utils = require('@bakit/utils');
13
+ var collection = require('@discordjs/collection');
14
+ var PQueue = require('p-queue');
13
15
  var rest = require('@bakit/rest');
14
16
 
15
17
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
@@ -17,6 +19,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
19
 
18
20
  var EventEmitter__default = /*#__PURE__*/_interopDefault(EventEmitter);
19
21
  var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
22
+ var PQueue__default = /*#__PURE__*/_interopDefault(PQueue);
20
23
 
21
24
  // src/lib/Shard.ts
22
25
  var MIN_HEARTBEAT_INTERVAL = 1e3, MAX_HEARTBEAT_INTERVAL = 6e4, SAFE_HEARTBEAT_INTERVAL = 45e3, ShardState = /* @__PURE__ */ ((ShardState2) => (ShardState2[ShardState2.Idle = 0] = "Idle", ShardState2[ShardState2.Connecting = 1] = "Connecting", ShardState2[ShardState2.Ready = 2] = "Ready", ShardState2[ShardState2.Resuming = 3] = "Resuming", ShardState2[ShardState2.Disconnecting = 4] = "Disconnecting", ShardState2[ShardState2.Disconnected = 5] = "Disconnected", ShardState2))(ShardState || {}), ShardStrategy = /* @__PURE__ */ ((ShardStrategy2) => (ShardStrategy2[ShardStrategy2.Resume = 0] = "Resume", ShardStrategy2[ShardStrategy2.Reconnect = 1] = "Reconnect", ShardStrategy2[ShardStrategy2.Shutdown = 2] = "Shutdown", ShardStrategy2))(ShardStrategy || {}), Shard = class extends EventEmitter__default.default {
@@ -283,6 +286,10 @@ var ClusterProcess = class _ClusterProcess extends EventEmitter__default.default
283
286
  }
284
287
  process;
285
288
  #pendingEvals = /* @__PURE__ */ new Map();
289
+ #shards = /* @__PURE__ */ new Set();
290
+ get shards() {
291
+ return new Set(this.#shards);
292
+ }
286
293
  get killed() {
287
294
  return this.process.killed || !this.process.connected;
288
295
  }
@@ -351,7 +358,7 @@ var ClusterProcess = class _ClusterProcess extends EventEmitter__default.default
351
358
  #handleIPC(message) {
352
359
  if (this.#isValidPayload(message)) {
353
360
  if (isDispatchPayload(message)) {
354
- this.emit(message.t, ...message.d);
361
+ this.#handleDispatchPayload(message);
355
362
  return;
356
363
  }
357
364
  if (isEvalResponsePayload(message)) {
@@ -360,6 +367,9 @@ var ClusterProcess = class _ClusterProcess extends EventEmitter__default.default
360
367
  }
361
368
  }
362
369
  }
370
+ #handleDispatchPayload(payload) {
371
+ payload.t === "shardAdd" && this.#shards.add(payload.d[0]), this.emit(payload.t, ...payload.d);
372
+ }
363
373
  #handleEvalResponse(payload) {
364
374
  let pending = this.#pendingEvals.get(payload.d.nonce);
365
375
  if (!pending) {
@@ -452,7 +462,7 @@ var Cluster = class extends EventEmitter__default.default {
452
462
  this.id = id;
453
463
  this.options = options;
454
464
  }
455
- shards = new utils.Collection();
465
+ shards = new collection.Collection();
456
466
  #readyCount = 0;
457
467
  #starting = false;
458
468
  get size() {
@@ -515,7 +525,7 @@ var Cluster = class extends EventEmitter__default.default {
515
525
  }
516
526
  };
517
527
  var ShardingManager = class extends EventEmitter__default.default {
518
- clusters = new utils.Collection();
528
+ clusters = new collection.Collection();
519
529
  options;
520
530
  rest;
521
531
  #gatewayInfo;
@@ -537,22 +547,21 @@ var ShardingManager = class extends EventEmitter__default.default {
537
547
  return this.#totalShards;
538
548
  }
539
549
  get ready() {
540
- return this.#readyCount === this.totalClusters;
550
+ return this.totalClusters > 0 && this.#readyCount === this.totalClusters;
541
551
  }
542
552
  async spawn() {
543
553
  this.#gatewayInfo = await this.rest.get("/gateway/bot");
544
554
  let { session_start_limit: limit } = this.#gatewayInfo;
545
- this.#totalShards = typeof this.options.totalShards == "number" ? this.options.totalShards : this.#gatewayInfo.shards, this.#identifyQueue = new utils.Queue({
555
+ this.#totalShards = typeof this.options.totalShards == "number" ? this.options.totalShards : this.#gatewayInfo.shards, this.#identifyQueue = new PQueue__default.default({
546
556
  concurrency: limit.max_concurrency,
547
557
  intervalCap: limit.max_concurrency,
548
558
  interval: 5e3
549
559
  });
550
560
  let { totalShards, totalClusters } = this;
551
561
  this.emit("debug", `Spawning ${totalClusters} clusters (${totalShards} total shards)...`);
552
- let promises = [];
553
562
  for (let i = 0; i < totalClusters; i++)
554
- promises.push(this.#spawnCluster(i));
555
- await Promise.all(promises), this.emit("debug", "All clusters spawned");
563
+ this.#spawnCluster(i);
564
+ this.emit("debug", "All clusters spawned");
556
565
  }
557
566
  async kill(signal = "SIGTERM") {
558
567
  this.emit("debug", "Shutting down all clusters...");
@@ -573,6 +582,12 @@ var ShardingManager = class extends EventEmitter__default.default {
573
582
  let promises = this.clusters.map((cluster) => cluster.eval(fn));
574
583
  return Promise.all(promises);
575
584
  }
585
+ send(shardId, payload) {
586
+ let cluster = this.clusters.find((cluster2) => cluster2.shards.has(shardId));
587
+ if (!cluster)
588
+ throw new Error(`Shard ${shardId} not found`);
589
+ cluster.send(payload);
590
+ }
576
591
  requestIdentify(cluster, shardId) {
577
592
  this.#identifyQueue?.add(() => cluster.identifyShard(shardId));
578
593
  }
@@ -580,7 +595,7 @@ var ShardingManager = class extends EventEmitter__default.default {
580
595
  let start = clusterId * this.options.shardsPerCluster, end = Math.min(start + this.options.shardsPerCluster, this.totalShards);
581
596
  return Array.from({ length: end - start }, (_, i) => start + i);
582
597
  }
583
- async #spawnCluster(id) {
598
+ #spawnCluster(id) {
584
599
  let shardIds = this.#getShardIdsForCluster(id), firstShardId = shardIds[0], lastShardId = shardIds[shardIds.length - 1];
585
600
  this.emit("debug", `Spawning cluster ${id} (shards ${firstShardId}-${lastShardId})`);
586
601
  let env = {
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import EventEmitter from 'node:events';
2
2
  import { GatewayReadyDispatchData, GatewayReceivePayload, GatewayDispatchPayload, GatewaySendPayload } from 'discord-api-types/v10';
3
3
  import { ChildProcess } from 'node:child_process';
4
- import { Collection } from '@bakit/utils';
5
- import { REST, RESTProxy } from '@bakit/rest';
4
+ import { Collection } from '@discordjs/collection';
5
+ import { RESTLike } from '@bakit/rest';
6
6
 
7
7
  declare enum ShardState {
8
8
  Idle = 0,
@@ -115,8 +115,8 @@ declare class ShardingManager extends EventEmitter<ShardingManagerEvents> {
115
115
  #private;
116
116
  readonly clusters: Collection<number, ClusterProcess>;
117
117
  readonly options: Required<ShardingManagerOptions>;
118
- readonly rest: REST | RESTProxy;
119
- constructor(options: ShardingManagerOptions, rest?: REST | RESTProxy);
118
+ readonly rest: RESTLike;
119
+ constructor(options: ShardingManagerOptions, rest?: RESTLike);
120
120
  get totalClusters(): number;
121
121
  get totalShards(): number;
122
122
  get ready(): boolean;
@@ -124,6 +124,7 @@ declare class ShardingManager extends EventEmitter<ShardingManagerEvents> {
124
124
  kill(signal?: NodeJS.Signals): Promise<void>;
125
125
  broadcast(payload: GatewaySendPayload): void;
126
126
  broadcastEval<T>(fn: (cluster: Cluster) => T | Promise<T>): Promise<EvalResult<T>[]>;
127
+ send(shardId: number, payload: GatewaySendPayload): void;
127
128
  protected requestIdentify(cluster: ClusterProcess, shardId: number): void;
128
129
  }
129
130
 
@@ -188,6 +189,7 @@ declare class ClusterProcess extends EventEmitter<ClusterEvents> {
188
189
  readonly id: number;
189
190
  readonly process: ChildProcess;
190
191
  constructor(manager: ShardingManager, id: number, options?: ClusterProcessOptions);
192
+ get shards(): Set<number>;
191
193
  get killed(): boolean;
192
194
  kill(signal?: NodeJS.Signals): void;
193
195
  eval<T, C = unknown>(fn: (cluster: Cluster, ctx: C) => T | Promise<T>, ctx?: C): Promise<EvalResult<T>>;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import EventEmitter from 'node:events';
2
2
  import { GatewayReadyDispatchData, GatewayReceivePayload, GatewayDispatchPayload, GatewaySendPayload } from 'discord-api-types/v10';
3
3
  import { ChildProcess } from 'node:child_process';
4
- import { Collection } from '@bakit/utils';
5
- import { REST, RESTProxy } from '@bakit/rest';
4
+ import { Collection } from '@discordjs/collection';
5
+ import { RESTLike } from '@bakit/rest';
6
6
 
7
7
  declare enum ShardState {
8
8
  Idle = 0,
@@ -115,8 +115,8 @@ declare class ShardingManager extends EventEmitter<ShardingManagerEvents> {
115
115
  #private;
116
116
  readonly clusters: Collection<number, ClusterProcess>;
117
117
  readonly options: Required<ShardingManagerOptions>;
118
- readonly rest: REST | RESTProxy;
119
- constructor(options: ShardingManagerOptions, rest?: REST | RESTProxy);
118
+ readonly rest: RESTLike;
119
+ constructor(options: ShardingManagerOptions, rest?: RESTLike);
120
120
  get totalClusters(): number;
121
121
  get totalShards(): number;
122
122
  get ready(): boolean;
@@ -124,6 +124,7 @@ declare class ShardingManager extends EventEmitter<ShardingManagerEvents> {
124
124
  kill(signal?: NodeJS.Signals): Promise<void>;
125
125
  broadcast(payload: GatewaySendPayload): void;
126
126
  broadcastEval<T>(fn: (cluster: Cluster) => T | Promise<T>): Promise<EvalResult<T>[]>;
127
+ send(shardId: number, payload: GatewaySendPayload): void;
127
128
  protected requestIdentify(cluster: ClusterProcess, shardId: number): void;
128
129
  }
129
130
 
@@ -188,6 +189,7 @@ declare class ClusterProcess extends EventEmitter<ClusterEvents> {
188
189
  readonly id: number;
189
190
  readonly process: ChildProcess;
190
191
  constructor(manager: ShardingManager, id: number, options?: ClusterProcessOptions);
192
+ get shards(): Set<number>;
191
193
  get killed(): boolean;
192
194
  kill(signal?: NodeJS.Signals): void;
193
195
  eval<T, C = unknown>(fn: (cluster: Cluster, ctx: C) => T | Promise<T>, ctx?: C): Promise<EvalResult<T>>;
package/dist/index.js CHANGED
@@ -7,7 +7,9 @@ import { GatewayOpcodes, GatewayDispatchEvents, GatewayCloseCodes } from 'discor
7
7
  import { fork } from 'child_process';
8
8
  import { dirname, resolve } from 'path';
9
9
  import { fileURLToPath } from 'url';
10
- import { isCommonJS, Collection, Queue } from '@bakit/utils';
10
+ import { isCommonJS } from '@bakit/utils';
11
+ import { Collection } from '@discordjs/collection';
12
+ import PQueue from 'p-queue';
11
13
  import { REST } from '@bakit/rest';
12
14
 
13
15
  // src/lib/Shard.ts
@@ -275,6 +277,10 @@ var ClusterProcess = class _ClusterProcess extends EventEmitter {
275
277
  }
276
278
  process;
277
279
  #pendingEvals = /* @__PURE__ */ new Map();
280
+ #shards = /* @__PURE__ */ new Set();
281
+ get shards() {
282
+ return new Set(this.#shards);
283
+ }
278
284
  get killed() {
279
285
  return this.process.killed || !this.process.connected;
280
286
  }
@@ -343,7 +349,7 @@ var ClusterProcess = class _ClusterProcess extends EventEmitter {
343
349
  #handleIPC(message) {
344
350
  if (this.#isValidPayload(message)) {
345
351
  if (isDispatchPayload(message)) {
346
- this.emit(message.t, ...message.d);
352
+ this.#handleDispatchPayload(message);
347
353
  return;
348
354
  }
349
355
  if (isEvalResponsePayload(message)) {
@@ -352,6 +358,9 @@ var ClusterProcess = class _ClusterProcess extends EventEmitter {
352
358
  }
353
359
  }
354
360
  }
361
+ #handleDispatchPayload(payload) {
362
+ payload.t === "shardAdd" && this.#shards.add(payload.d[0]), this.emit(payload.t, ...payload.d);
363
+ }
355
364
  #handleEvalResponse(payload) {
356
365
  let pending = this.#pendingEvals.get(payload.d.nonce);
357
366
  if (!pending) {
@@ -529,22 +538,21 @@ var ShardingManager = class extends EventEmitter {
529
538
  return this.#totalShards;
530
539
  }
531
540
  get ready() {
532
- return this.#readyCount === this.totalClusters;
541
+ return this.totalClusters > 0 && this.#readyCount === this.totalClusters;
533
542
  }
534
543
  async spawn() {
535
544
  this.#gatewayInfo = await this.rest.get("/gateway/bot");
536
545
  let { session_start_limit: limit } = this.#gatewayInfo;
537
- this.#totalShards = typeof this.options.totalShards == "number" ? this.options.totalShards : this.#gatewayInfo.shards, this.#identifyQueue = new Queue({
546
+ this.#totalShards = typeof this.options.totalShards == "number" ? this.options.totalShards : this.#gatewayInfo.shards, this.#identifyQueue = new PQueue({
538
547
  concurrency: limit.max_concurrency,
539
548
  intervalCap: limit.max_concurrency,
540
549
  interval: 5e3
541
550
  });
542
551
  let { totalShards, totalClusters } = this;
543
552
  this.emit("debug", `Spawning ${totalClusters} clusters (${totalShards} total shards)...`);
544
- let promises = [];
545
553
  for (let i = 0; i < totalClusters; i++)
546
- promises.push(this.#spawnCluster(i));
547
- await Promise.all(promises), this.emit("debug", "All clusters spawned");
554
+ this.#spawnCluster(i);
555
+ this.emit("debug", "All clusters spawned");
548
556
  }
549
557
  async kill(signal = "SIGTERM") {
550
558
  this.emit("debug", "Shutting down all clusters...");
@@ -565,6 +573,12 @@ var ShardingManager = class extends EventEmitter {
565
573
  let promises = this.clusters.map((cluster) => cluster.eval(fn));
566
574
  return Promise.all(promises);
567
575
  }
576
+ send(shardId, payload) {
577
+ let cluster = this.clusters.find((cluster2) => cluster2.shards.has(shardId));
578
+ if (!cluster)
579
+ throw new Error(`Shard ${shardId} not found`);
580
+ cluster.send(payload);
581
+ }
568
582
  requestIdentify(cluster, shardId) {
569
583
  this.#identifyQueue?.add(() => cluster.identifyShard(shardId));
570
584
  }
@@ -572,7 +586,7 @@ var ShardingManager = class extends EventEmitter {
572
586
  let start = clusterId * this.options.shardsPerCluster, end = Math.min(start + this.options.shardsPerCluster, this.totalShards);
573
587
  return Array.from({ length: end - start }, (_, i) => start + i);
574
588
  }
575
- async #spawnCluster(id) {
589
+ #spawnCluster(id) {
576
590
  let shardIds = this.#getShardIdsForCluster(id), firstShardId = shardIds[0], lastShardId = shardIds[shardIds.length - 1];
577
591
  this.emit("debug", `Spawning cluster ${id} (shards ${firstShardId}-${lastShardId})`);
578
592
  let env = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bakit/gateway",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Gateway manager for bakit framework",
5
5
  "type": "module",
6
6
  "exports": {
@@ -34,11 +34,13 @@
34
34
  "author": "louiszn",
35
35
  "license": "MIT",
36
36
  "dependencies": {
37
+ "@discordjs/collection": "^2.1.1",
37
38
  "discord-api-types": "^0.38.38",
39
+ "p-queue": "^9.1.0",
38
40
  "type-fest": "^4.41.0",
39
41
  "ws": "^8.19.0",
40
- "@bakit/rest": "^3.0.1",
41
- "@bakit/utils": "^2.3.0"
42
+ "@bakit/rest": "^3.0.2",
43
+ "@bakit/utils": "^3.0.0"
42
44
  },
43
45
  "devDependencies": {
44
46
  "@types/ws": "^8.18.1"