@discordjs/ws 0.1.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +191 -0
  3. package/README.md +124 -0
  4. package/dist/index.cjs +39 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.ts +12 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.mjs +11 -0
  9. package/dist/index.mjs.map +1 -0
  10. package/dist/strategies/context/IContextFetchingStrategy.cjs +15 -0
  11. package/dist/strategies/context/IContextFetchingStrategy.cjs.map +1 -0
  12. package/dist/strategies/context/IContextFetchingStrategy.d.ts +17 -0
  13. package/dist/strategies/context/IContextFetchingStrategy.d.ts.map +1 -0
  14. package/dist/strategies/context/IContextFetchingStrategy.mjs +11 -0
  15. package/dist/strategies/context/IContextFetchingStrategy.mjs.map +1 -0
  16. package/dist/strategies/context/SimpleContextFetchingStrategy.cjs +19 -0
  17. package/dist/strategies/context/SimpleContextFetchingStrategy.cjs.map +1 -0
  18. package/dist/strategies/context/SimpleContextFetchingStrategy.d.ts +10 -0
  19. package/dist/strategies/context/SimpleContextFetchingStrategy.d.ts.map +1 -0
  20. package/dist/strategies/context/SimpleContextFetchingStrategy.mjs +15 -0
  21. package/dist/strategies/context/SimpleContextFetchingStrategy.mjs.map +1 -0
  22. package/dist/strategies/context/WorkerContextFetchingStrategy.cjs +46 -0
  23. package/dist/strategies/context/WorkerContextFetchingStrategy.cjs.map +1 -0
  24. package/dist/strategies/context/WorkerContextFetchingStrategy.d.ts +10 -0
  25. package/dist/strategies/context/WorkerContextFetchingStrategy.d.ts.map +1 -0
  26. package/dist/strategies/context/WorkerContextFetchingStrategy.mjs +42 -0
  27. package/dist/strategies/context/WorkerContextFetchingStrategy.mjs.map +1 -0
  28. package/dist/strategies/sharding/IShardingStrategy.d.ts +25 -0
  29. package/dist/strategies/sharding/IShardingStrategy.d.ts.map +1 -0
  30. package/dist/strategies/sharding/SimpleShardingStrategy.cjs +53 -0
  31. package/dist/strategies/sharding/SimpleShardingStrategy.cjs.map +1 -0
  32. package/dist/strategies/sharding/SimpleShardingStrategy.d.ts +18 -0
  33. package/dist/strategies/sharding/SimpleShardingStrategy.d.ts.map +1 -0
  34. package/dist/strategies/sharding/SimpleShardingStrategy.mjs +49 -0
  35. package/dist/strategies/sharding/SimpleShardingStrategy.mjs.map +1 -0
  36. package/dist/strategies/sharding/WorkerShardingStrategy.cjs +162 -0
  37. package/dist/strategies/sharding/WorkerShardingStrategy.cjs.map +1 -0
  38. package/dist/strategies/sharding/WorkerShardingStrategy.d.ts +84 -0
  39. package/dist/strategies/sharding/WorkerShardingStrategy.d.ts.map +1 -0
  40. package/dist/strategies/sharding/WorkerShardingStrategy.mjs +165 -0
  41. package/dist/strategies/sharding/WorkerShardingStrategy.mjs.map +1 -0
  42. package/dist/strategies/sharding/worker.cjs +78 -0
  43. package/dist/strategies/sharding/worker.cjs.map +1 -0
  44. package/dist/strategies/sharding/worker.d.ts +2 -0
  45. package/dist/strategies/sharding/worker.d.ts.map +1 -0
  46. package/dist/strategies/sharding/worker.mjs +76 -0
  47. package/dist/strategies/sharding/worker.mjs.map +1 -0
  48. package/dist/utils/IdentifyThrottler.cjs +33 -0
  49. package/dist/utils/IdentifyThrottler.cjs.map +1 -0
  50. package/dist/utils/IdentifyThrottler.d.ts +8 -0
  51. package/dist/utils/IdentifyThrottler.d.ts.map +1 -0
  52. package/dist/utils/IdentifyThrottler.mjs +29 -0
  53. package/dist/utils/IdentifyThrottler.mjs.map +1 -0
  54. package/dist/utils/constants.cjs +63 -0
  55. package/dist/utils/constants.cjs.map +1 -0
  56. package/dist/utils/constants.d.ts +21 -0
  57. package/dist/utils/constants.d.ts.map +1 -0
  58. package/dist/utils/constants.mjs +64 -0
  59. package/dist/utils/constants.mjs.map +1 -0
  60. package/dist/utils/utils.cjs +15 -0
  61. package/dist/utils/utils.cjs.map +1 -0
  62. package/dist/utils/utils.d.ts +13 -0
  63. package/dist/utils/utils.d.ts.map +1 -0
  64. package/dist/utils/utils.mjs +10 -0
  65. package/dist/utils/utils.mjs.map +1 -0
  66. package/dist/ws/WebSocketManager.cjs +81 -0
  67. package/dist/ws/WebSocketManager.cjs.map +1 -0
  68. package/dist/ws/WebSocketManager.d.ts +186 -0
  69. package/dist/ws/WebSocketManager.d.ts.map +1 -0
  70. package/dist/ws/WebSocketManager.mjs +77 -0
  71. package/dist/ws/WebSocketManager.mjs.map +1 -0
  72. package/dist/ws/WebSocketShard.cjs +414 -0
  73. package/dist/ws/WebSocketShard.cjs.map +1 -0
  74. package/dist/ws/WebSocketShard.d.ts +71 -0
  75. package/dist/ws/WebSocketShard.d.ts.map +1 -0
  76. package/dist/ws/WebSocketShard.mjs +406 -0
  77. package/dist/ws/WebSocketShard.mjs.map +1 -0
  78. package/package.json +87 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils/utils.ts"],"sourcesContent":["import type { ShardRange } from '../ws/WebSocketManager';\n\nexport type Awaitable<T> = T | Promise<T>;\n\n/**\n * Yields the numbers in the given range as an array\n * @example\n * range({ start: 3, end: 5 }); // [3, 4, 5]\n */\nexport function range({ start, end }: ShardRange): number[] {\n\treturn Array.from({ length: end - start + 1 }, (_, i) => i + start);\n}\n\n/**\n * Lazily evaluate a callback, storing its result\n */\nexport function lazy<T>(cb: () => T): () => T {\n\tlet defaultValue: T;\n\treturn () => (defaultValue ??= cb());\n}\n"],"names":[],"mappings":";;;;AAAO,SAAS,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;AACtC,EAAE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;AACtE,CAAC;AACM,SAAS,IAAI,CAAC,EAAE,EAAE;AACzB,EAAE,IAAI,YAAY,CAAC;AACnB,EAAE,OAAO,MAAM,YAAY,KAAK,YAAY,GAAG,EAAE,EAAE,CAAC,CAAC;AACrD;;;;;"}
@@ -0,0 +1,13 @@
1
+ import type { ShardRange } from '../ws/WebSocketManager';
2
+ export declare type Awaitable<T> = T | Promise<T>;
3
+ /**
4
+ * Yields the numbers in the given range as an array
5
+ * @example
6
+ * range({ start: 3, end: 5 }); // [3, 4, 5]
7
+ */
8
+ export declare function range({ start, end }: ShardRange): number[];
9
+ /**
10
+ * Lazily evaluate a callback, storing its result
11
+ */
12
+ export declare function lazy<T>(cb: () => T): () => T;
13
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,oBAAY,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,UAAU,GAAG,MAAM,EAAE,CAE1D;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,CAG5C"}
@@ -0,0 +1,10 @@
1
+ function range({ start, end }) {
2
+ return Array.from({ length: end - start + 1 }, (_, i) => i + start);
3
+ }
4
+ function lazy(cb) {
5
+ let defaultValue;
6
+ return () => defaultValue ?? (defaultValue = cb());
7
+ }
8
+
9
+ export { lazy, range };
10
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","sources":["../../src/utils/utils.ts"],"sourcesContent":["import type { ShardRange } from '../ws/WebSocketManager';\n\nexport type Awaitable<T> = T | Promise<T>;\n\n/**\n * Yields the numbers in the given range as an array\n * @example\n * range({ start: 3, end: 5 }); // [3, 4, 5]\n */\nexport function range({ start, end }: ShardRange): number[] {\n\treturn Array.from({ length: end - start + 1 }, (_, i) => i + start);\n}\n\n/**\n * Lazily evaluate a callback, storing its result\n */\nexport function lazy<T>(cb: () => T): () => T {\n\tlet defaultValue: T;\n\treturn () => (defaultValue ??= cb());\n}\n"],"names":[],"mappings":"AAAO,SAAS,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;AACtC,EAAE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;AACtE,CAAC;AACM,SAAS,IAAI,CAAC,EAAE,EAAE;AACzB,EAAE,IAAI,YAAY,CAAC;AACnB,EAAE,OAAO,MAAM,YAAY,KAAK,YAAY,GAAG,EAAE,EAAE,CAAC,CAAC;AACrD;;;;"}
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const async_event_emitter = require('@vladfrangu/async_event_emitter');
6
+ const v10 = require('discord-api-types/v10');
7
+ const SimpleShardingStrategy = require('../strategies/sharding/SimpleShardingStrategy.cjs');
8
+ const constants = require('../utils/constants.cjs');
9
+ const utils = require('../utils/utils.cjs');
10
+
11
+ class WebSocketManager extends async_event_emitter.AsyncEventEmitter {
12
+ constructor(options) {
13
+ super();
14
+ this.gatewayInformation = null;
15
+ this.shardIds = null;
16
+ this.strategy = new SimpleShardingStrategy.SimpleShardingStrategy(this);
17
+ this.options = { ...constants.DefaultWebSocketManagerOptions, ...options };
18
+ }
19
+ setStrategy(strategy) {
20
+ this.strategy = strategy;
21
+ return this;
22
+ }
23
+ async fetchGatewayInformation(force = false) {
24
+ if (this.gatewayInformation) {
25
+ if (this.gatewayInformation.expiresAt <= Date.now()) {
26
+ this.gatewayInformation = null;
27
+ } else if (!force) {
28
+ return this.gatewayInformation.data;
29
+ }
30
+ }
31
+ const data = await this.options.rest.get(v10.Routes.gatewayBot());
32
+ this.gatewayInformation = { data, expiresAt: Date.now() + data.session_start_limit.reset_after };
33
+ return this.gatewayInformation.data;
34
+ }
35
+ async updateShardCount(shardCount) {
36
+ await this.strategy.destroy({ reason: "User is adjusting their shards" });
37
+ this.options.shardCount = shardCount;
38
+ const shardIds = await this.getShardIds(true);
39
+ await this.strategy.spawn(shardIds);
40
+ return this;
41
+ }
42
+ async getShardCount() {
43
+ if (this.options.shardCount) {
44
+ return this.options.shardCount;
45
+ }
46
+ const shardIds = await this.getShardIds();
47
+ return Math.max(...shardIds) + 1;
48
+ }
49
+ async getShardIds(force = false) {
50
+ if (this.shardIds && !force) {
51
+ return this.shardIds;
52
+ }
53
+ let shardIds;
54
+ if (this.options.shardIds) {
55
+ if (Array.isArray(this.options.shardIds)) {
56
+ shardIds = this.options.shardIds;
57
+ } else {
58
+ shardIds = utils.range(this.options.shardIds);
59
+ }
60
+ } else {
61
+ const data = await this.fetchGatewayInformation();
62
+ shardIds = utils.range({ start: 0, end: (this.options.shardCount ?? data.shards) - 1 });
63
+ }
64
+ this.shardIds = shardIds;
65
+ return shardIds;
66
+ }
67
+ async connect() {
68
+ const shardCount = await this.getShardCount();
69
+ await this.updateShardCount(shardCount);
70
+ await this.strategy.connect();
71
+ }
72
+ destroy(options) {
73
+ return this.strategy.destroy(options);
74
+ }
75
+ send(shardId, payload) {
76
+ return this.strategy.send(shardId, payload);
77
+ }
78
+ }
79
+
80
+ exports.WebSocketManager = WebSocketManager;
81
+ //# sourceMappingURL=WebSocketManager.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketManager.cjs","sources":["../../src/ws/WebSocketManager.ts"],"sourcesContent":["import type { REST } from '@discordjs/rest';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tAPIGatewayBotInfo,\n\tGatewayIdentifyProperties,\n\tGatewayPresenceUpdateData,\n\tRESTGetAPIGatewayBotResult,\n\tGatewayIntentBits,\n\tRoutes,\n\tGatewaySendPayload,\n} from 'discord-api-types/v10';\nimport type { WebSocketShardDestroyOptions, WebSocketShardEventsMap } from './WebSocketShard';\nimport type { IShardingStrategy } from '../strategies/sharding/IShardingStrategy';\nimport { SimpleShardingStrategy } from '../strategies/sharding/SimpleShardingStrategy';\nimport { CompressionMethod, DefaultWebSocketManagerOptions, Encoding } from '../utils/constants';\nimport { Awaitable, range } from '../utils/utils';\n\n/**\n * Represents a range of shard ids\n */\nexport interface ShardRange {\n\tstart: number;\n\tend: number;\n}\n\n/**\n * Session information for a given shard, used to resume a session\n */\nexport interface SessionInfo {\n\t/**\n\t * Session id for this shard\n\t */\n\tsessionId: string;\n\t/**\n\t * The sequence number of the last message sent by the shard\n\t */\n\tsequence: number;\n\t/**\n\t * The id of the shard\n\t */\n\tshardId: number;\n\t/**\n\t * The total number of shards at the time of this shard identifying\n\t */\n\tshardCount: number;\n}\n\n/**\n * Required options for the WebSocketManager\n */\nexport interface RequiredWebSocketManagerOptions {\n\t/**\n\t * The token to use for identifying with the gateway\n\t */\n\ttoken: string;\n\t/**\n\t * The intents to request\n\t */\n\tintents: GatewayIntentBits;\n\t/**\n\t * The REST instance to use for fetching gateway information\n\t */\n\trest: REST;\n}\n\n/**\n * Optional additional configuration for the WebSocketManager\n */\nexport interface OptionalWebSocketManagerOptions {\n\t/**\n\t * The total number of shards across all WebsocketManagers you intend to instantiate.\n\t * Use `null` to use Discord's recommended shard count\n\t */\n\tshardCount: number | null;\n\t/**\n\t * The ids of the shards this WebSocketManager should manage.\n\t * Use `null` to simply spawn 0 through `shardCount - 1`\n\t * @example\n\t * const manager = new WebSocketManager({\n\t * shardIds: [1, 3, 7], // spawns shard 1, 3, and 7, nothing else\n\t * });\n\t * @example\n\t * const manager = new WebSocketManager({\n\t * shardIds: {\n\t * start: 3,\n\t * end: 6,\n\t * }, // spawns shards 3, 4, 5, and 6\n\t * });\n\t */\n\tshardIds: number[] | ShardRange | null;\n\t/**\n\t * Value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list\n\t */\n\tlargeThreshold: number | null;\n\t/**\n\t * Initial presence data to send to the gateway when identifying\n\t */\n\tinitialPresence: GatewayPresenceUpdateData | null;\n\t/**\n\t * Properties to send to the gateway when identifying\n\t */\n\tidentifyProperties: GatewayIdentifyProperties;\n\t/**\n\t * The gateway version to use\n\t * @default '10'\n\t */\n\tversion: string;\n\t/**\n\t * The encoding to use\n\t * @default 'json'\n\t */\n\tencoding: Encoding;\n\t/**\n\t * The compression method to use\n\t * @default null (no compression)\n\t */\n\tcompression: CompressionMethod | null;\n\t/**\n\t * Function used to retrieve session information (and attempt to resume) for a given shard\n\t * @example\n\t * const manager = new WebSocketManager({\n\t * async retrieveSessionInfo(shardId): Awaitable<SessionInfo | null> {\n\t * // Fetch this info from redis or similar\n\t * return { sessionId: string, sequence: number };\n\t * // Return null if no information is found\n\t * },\n\t * });\n\t */\n\tretrieveSessionInfo: (shardId: number) => Awaitable<SessionInfo | null>;\n\t/**\n\t * Function used to store session information for a given shard\n\t */\n\tupdateSessionInfo: (shardId: number, sessionInfo: SessionInfo | null) => Awaitable<void>;\n\t/**\n\t * How long to wait for a shard to connect before giving up\n\t */\n\thandshakeTimeout: number | null;\n\t/**\n\t * How long to wait for a shard's HELLO packet before giving up\n\t */\n\thelloTimeout: number | null;\n\t/**\n\t * How long to wait for a shard's READY packet before giving up\n\t */\n\treadyTimeout: number | null;\n}\n\nexport type WebSocketManagerOptions = RequiredWebSocketManagerOptions & OptionalWebSocketManagerOptions;\n\nexport type ManagerShardEventsMap = {\n\t[K in keyof WebSocketShardEventsMap]: [\n\t\tWebSocketShardEventsMap[K] extends [] ? { shardId: number } : WebSocketShardEventsMap[K][0] & { shardId: number },\n\t];\n};\n\nexport class WebSocketManager extends AsyncEventEmitter<ManagerShardEventsMap> {\n\t/**\n\t * The options being used by this manager\n\t */\n\tpublic readonly options: WebSocketManagerOptions;\n\n\t/**\n\t * Internal cache for a GET /gateway/bot result\n\t */\n\tprivate gatewayInformation: {\n\t\tdata: APIGatewayBotInfo;\n\t\texpiresAt: number;\n\t} | null = null;\n\n\t/**\n\t * Internal cache for the shard ids\n\t */\n\tprivate shardIds: number[] | null = null;\n\n\t/**\n\t * Strategy used to manage shards\n\t * @default SimpleManagerToShardStrategy\n\t */\n\tprivate strategy: IShardingStrategy = new SimpleShardingStrategy(this);\n\n\tpublic constructor(options: RequiredWebSocketManagerOptions & Partial<OptionalWebSocketManagerOptions>) {\n\t\tsuper();\n\t\tthis.options = { ...DefaultWebSocketManagerOptions, ...options };\n\t}\n\n\tpublic setStrategy(strategy: IShardingStrategy) {\n\t\tthis.strategy = strategy;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Fetches the gateway information from Discord - or returns it from cache if available\n\t * @param force Whether to ignore the cache and force a fresh fetch\n\t */\n\tpublic async fetchGatewayInformation(force = false) {\n\t\tif (this.gatewayInformation) {\n\t\t\tif (this.gatewayInformation.expiresAt <= Date.now()) {\n\t\t\t\tthis.gatewayInformation = null;\n\t\t\t} else if (!force) {\n\t\t\t\treturn this.gatewayInformation.data;\n\t\t\t}\n\t\t}\n\n\t\tconst data = (await this.options.rest.get(Routes.gatewayBot())) as RESTGetAPIGatewayBotResult;\n\n\t\tthis.gatewayInformation = { data, expiresAt: Date.now() + data.session_start_limit.reset_after };\n\t\treturn this.gatewayInformation.data;\n\t}\n\n\t/**\n\t * Updates your total shard count on-the-fly, spawning shards as needed\n\t * @param shardCount The new shard count to use\n\t */\n\tpublic async updateShardCount(shardCount: number | null) {\n\t\tawait this.strategy.destroy({ reason: 'User is adjusting their shards' });\n\t\tthis.options.shardCount = shardCount;\n\n\t\tconst shardIds = await this.getShardIds(true);\n\t\tawait this.strategy.spawn(shardIds);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Yields the total number of shards across for your bot, accounting for Discord recommendations\n\t */\n\tpublic async getShardCount(): Promise<number> {\n\t\tif (this.options.shardCount) {\n\t\t\treturn this.options.shardCount;\n\t\t}\n\n\t\tconst shardIds = await this.getShardIds();\n\t\treturn Math.max(...shardIds) + 1;\n\t}\n\n\t/**\n\t * Yields the ids of the shards this manager should manage\n\t */\n\tpublic async getShardIds(force = false): Promise<number[]> {\n\t\tif (this.shardIds && !force) {\n\t\t\treturn this.shardIds;\n\t\t}\n\n\t\tlet shardIds: number[];\n\t\tif (this.options.shardIds) {\n\t\t\tif (Array.isArray(this.options.shardIds)) {\n\t\t\t\tshardIds = this.options.shardIds;\n\t\t\t} else {\n\t\t\t\tshardIds = range(this.options.shardIds);\n\t\t\t}\n\t\t} else {\n\t\t\tconst data = await this.fetchGatewayInformation();\n\t\t\tshardIds = range({ start: 0, end: (this.options.shardCount ?? data.shards) - 1 });\n\t\t}\n\n\t\tthis.shardIds = shardIds;\n\t\treturn shardIds;\n\t}\n\n\tpublic async connect() {\n\t\tconst shardCount = await this.getShardCount();\n\t\t// First, make sure all our shards are spawned\n\t\tawait this.updateShardCount(shardCount);\n\t\tawait this.strategy.connect();\n\t}\n\n\tpublic destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\treturn this.strategy.destroy(options);\n\t}\n\n\tpublic send(shardId: number, payload: GatewaySendPayload) {\n\t\treturn this.strategy.send(shardId, payload);\n\t}\n}\n"],"names":["AsyncEventEmitter","SimpleShardingStrategy","DefaultWebSocketManagerOptions","Routes","range"],"mappings":"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"}
@@ -0,0 +1,186 @@
1
+ import type { REST } from '@discordjs/rest';
2
+ import { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';
3
+ import { APIGatewayBotInfo, GatewayIdentifyProperties, GatewayPresenceUpdateData, GatewayIntentBits, GatewaySendPayload } from 'discord-api-types/v10';
4
+ import type { WebSocketShardDestroyOptions, WebSocketShardEventsMap } from './WebSocketShard';
5
+ import type { IShardingStrategy } from '../strategies/sharding/IShardingStrategy';
6
+ import { CompressionMethod, Encoding } from '../utils/constants';
7
+ import { Awaitable } from '../utils/utils';
8
+ /**
9
+ * Represents a range of shard ids
10
+ */
11
+ export interface ShardRange {
12
+ start: number;
13
+ end: number;
14
+ }
15
+ /**
16
+ * Session information for a given shard, used to resume a session
17
+ */
18
+ export interface SessionInfo {
19
+ /**
20
+ * Session id for this shard
21
+ */
22
+ sessionId: string;
23
+ /**
24
+ * The sequence number of the last message sent by the shard
25
+ */
26
+ sequence: number;
27
+ /**
28
+ * The id of the shard
29
+ */
30
+ shardId: number;
31
+ /**
32
+ * The total number of shards at the time of this shard identifying
33
+ */
34
+ shardCount: number;
35
+ }
36
+ /**
37
+ * Required options for the WebSocketManager
38
+ */
39
+ export interface RequiredWebSocketManagerOptions {
40
+ /**
41
+ * The token to use for identifying with the gateway
42
+ */
43
+ token: string;
44
+ /**
45
+ * The intents to request
46
+ */
47
+ intents: GatewayIntentBits;
48
+ /**
49
+ * The REST instance to use for fetching gateway information
50
+ */
51
+ rest: REST;
52
+ }
53
+ /**
54
+ * Optional additional configuration for the WebSocketManager
55
+ */
56
+ export interface OptionalWebSocketManagerOptions {
57
+ /**
58
+ * The total number of shards across all WebsocketManagers you intend to instantiate.
59
+ * Use `null` to use Discord's recommended shard count
60
+ */
61
+ shardCount: number | null;
62
+ /**
63
+ * The ids of the shards this WebSocketManager should manage.
64
+ * Use `null` to simply spawn 0 through `shardCount - 1`
65
+ * @example
66
+ * const manager = new WebSocketManager({
67
+ * shardIds: [1, 3, 7], // spawns shard 1, 3, and 7, nothing else
68
+ * });
69
+ * @example
70
+ * const manager = new WebSocketManager({
71
+ * shardIds: {
72
+ * start: 3,
73
+ * end: 6,
74
+ * }, // spawns shards 3, 4, 5, and 6
75
+ * });
76
+ */
77
+ shardIds: number[] | ShardRange | null;
78
+ /**
79
+ * Value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list
80
+ */
81
+ largeThreshold: number | null;
82
+ /**
83
+ * Initial presence data to send to the gateway when identifying
84
+ */
85
+ initialPresence: GatewayPresenceUpdateData | null;
86
+ /**
87
+ * Properties to send to the gateway when identifying
88
+ */
89
+ identifyProperties: GatewayIdentifyProperties;
90
+ /**
91
+ * The gateway version to use
92
+ * @default '10'
93
+ */
94
+ version: string;
95
+ /**
96
+ * The encoding to use
97
+ * @default 'json'
98
+ */
99
+ encoding: Encoding;
100
+ /**
101
+ * The compression method to use
102
+ * @default null (no compression)
103
+ */
104
+ compression: CompressionMethod | null;
105
+ /**
106
+ * Function used to retrieve session information (and attempt to resume) for a given shard
107
+ * @example
108
+ * const manager = new WebSocketManager({
109
+ * async retrieveSessionInfo(shardId): Awaitable<SessionInfo | null> {
110
+ * // Fetch this info from redis or similar
111
+ * return { sessionId: string, sequence: number };
112
+ * // Return null if no information is found
113
+ * },
114
+ * });
115
+ */
116
+ retrieveSessionInfo: (shardId: number) => Awaitable<SessionInfo | null>;
117
+ /**
118
+ * Function used to store session information for a given shard
119
+ */
120
+ updateSessionInfo: (shardId: number, sessionInfo: SessionInfo | null) => Awaitable<void>;
121
+ /**
122
+ * How long to wait for a shard to connect before giving up
123
+ */
124
+ handshakeTimeout: number | null;
125
+ /**
126
+ * How long to wait for a shard's HELLO packet before giving up
127
+ */
128
+ helloTimeout: number | null;
129
+ /**
130
+ * How long to wait for a shard's READY packet before giving up
131
+ */
132
+ readyTimeout: number | null;
133
+ }
134
+ export declare type WebSocketManagerOptions = RequiredWebSocketManagerOptions & OptionalWebSocketManagerOptions;
135
+ export declare type ManagerShardEventsMap = {
136
+ [K in keyof WebSocketShardEventsMap]: [
137
+ WebSocketShardEventsMap[K] extends [] ? {
138
+ shardId: number;
139
+ } : WebSocketShardEventsMap[K][0] & {
140
+ shardId: number;
141
+ }
142
+ ];
143
+ };
144
+ export declare class WebSocketManager extends AsyncEventEmitter<ManagerShardEventsMap> {
145
+ /**
146
+ * The options being used by this manager
147
+ */
148
+ readonly options: WebSocketManagerOptions;
149
+ /**
150
+ * Internal cache for a GET /gateway/bot result
151
+ */
152
+ private gatewayInformation;
153
+ /**
154
+ * Internal cache for the shard ids
155
+ */
156
+ private shardIds;
157
+ /**
158
+ * Strategy used to manage shards
159
+ * @default SimpleManagerToShardStrategy
160
+ */
161
+ private strategy;
162
+ constructor(options: RequiredWebSocketManagerOptions & Partial<OptionalWebSocketManagerOptions>);
163
+ setStrategy(strategy: IShardingStrategy): this;
164
+ /**
165
+ * Fetches the gateway information from Discord - or returns it from cache if available
166
+ * @param force Whether to ignore the cache and force a fresh fetch
167
+ */
168
+ fetchGatewayInformation(force?: boolean): Promise<APIGatewayBotInfo>;
169
+ /**
170
+ * Updates your total shard count on-the-fly, spawning shards as needed
171
+ * @param shardCount The new shard count to use
172
+ */
173
+ updateShardCount(shardCount: number | null): Promise<this>;
174
+ /**
175
+ * Yields the total number of shards across for your bot, accounting for Discord recommendations
176
+ */
177
+ getShardCount(): Promise<number>;
178
+ /**
179
+ * Yields the ids of the shards this manager should manage
180
+ */
181
+ getShardIds(force?: boolean): Promise<number[]>;
182
+ connect(): Promise<void>;
183
+ destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>): Awaitable<void>;
184
+ send(shardId: number, payload: GatewaySendPayload): Awaitable<void>;
185
+ }
186
+ //# sourceMappingURL=WebSocketManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketManager.d.ts","sourceRoot":"","sources":["../../src/ws/WebSocketManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';
2
+ import { Routes } from 'discord-api-types/v10';
3
+ import { SimpleShardingStrategy } from '../strategies/sharding/SimpleShardingStrategy.mjs';
4
+ import { DefaultWebSocketManagerOptions } from '../utils/constants.mjs';
5
+ import { range } from '../utils/utils.mjs';
6
+
7
+ class WebSocketManager extends AsyncEventEmitter {
8
+ constructor(options) {
9
+ super();
10
+ this.gatewayInformation = null;
11
+ this.shardIds = null;
12
+ this.strategy = new SimpleShardingStrategy(this);
13
+ this.options = { ...DefaultWebSocketManagerOptions, ...options };
14
+ }
15
+ setStrategy(strategy) {
16
+ this.strategy = strategy;
17
+ return this;
18
+ }
19
+ async fetchGatewayInformation(force = false) {
20
+ if (this.gatewayInformation) {
21
+ if (this.gatewayInformation.expiresAt <= Date.now()) {
22
+ this.gatewayInformation = null;
23
+ } else if (!force) {
24
+ return this.gatewayInformation.data;
25
+ }
26
+ }
27
+ const data = await this.options.rest.get(Routes.gatewayBot());
28
+ this.gatewayInformation = { data, expiresAt: Date.now() + data.session_start_limit.reset_after };
29
+ return this.gatewayInformation.data;
30
+ }
31
+ async updateShardCount(shardCount) {
32
+ await this.strategy.destroy({ reason: "User is adjusting their shards" });
33
+ this.options.shardCount = shardCount;
34
+ const shardIds = await this.getShardIds(true);
35
+ await this.strategy.spawn(shardIds);
36
+ return this;
37
+ }
38
+ async getShardCount() {
39
+ if (this.options.shardCount) {
40
+ return this.options.shardCount;
41
+ }
42
+ const shardIds = await this.getShardIds();
43
+ return Math.max(...shardIds) + 1;
44
+ }
45
+ async getShardIds(force = false) {
46
+ if (this.shardIds && !force) {
47
+ return this.shardIds;
48
+ }
49
+ let shardIds;
50
+ if (this.options.shardIds) {
51
+ if (Array.isArray(this.options.shardIds)) {
52
+ shardIds = this.options.shardIds;
53
+ } else {
54
+ shardIds = range(this.options.shardIds);
55
+ }
56
+ } else {
57
+ const data = await this.fetchGatewayInformation();
58
+ shardIds = range({ start: 0, end: (this.options.shardCount ?? data.shards) - 1 });
59
+ }
60
+ this.shardIds = shardIds;
61
+ return shardIds;
62
+ }
63
+ async connect() {
64
+ const shardCount = await this.getShardCount();
65
+ await this.updateShardCount(shardCount);
66
+ await this.strategy.connect();
67
+ }
68
+ destroy(options) {
69
+ return this.strategy.destroy(options);
70
+ }
71
+ send(shardId, payload) {
72
+ return this.strategy.send(shardId, payload);
73
+ }
74
+ }
75
+
76
+ export { WebSocketManager };
77
+ //# sourceMappingURL=WebSocketManager.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketManager.mjs","sources":["../../src/ws/WebSocketManager.ts"],"sourcesContent":["import type { REST } from '@discordjs/rest';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport {\n\tAPIGatewayBotInfo,\n\tGatewayIdentifyProperties,\n\tGatewayPresenceUpdateData,\n\tRESTGetAPIGatewayBotResult,\n\tGatewayIntentBits,\n\tRoutes,\n\tGatewaySendPayload,\n} from 'discord-api-types/v10';\nimport type { WebSocketShardDestroyOptions, WebSocketShardEventsMap } from './WebSocketShard';\nimport type { IShardingStrategy } from '../strategies/sharding/IShardingStrategy';\nimport { SimpleShardingStrategy } from '../strategies/sharding/SimpleShardingStrategy';\nimport { CompressionMethod, DefaultWebSocketManagerOptions, Encoding } from '../utils/constants';\nimport { Awaitable, range } from '../utils/utils';\n\n/**\n * Represents a range of shard ids\n */\nexport interface ShardRange {\n\tstart: number;\n\tend: number;\n}\n\n/**\n * Session information for a given shard, used to resume a session\n */\nexport interface SessionInfo {\n\t/**\n\t * Session id for this shard\n\t */\n\tsessionId: string;\n\t/**\n\t * The sequence number of the last message sent by the shard\n\t */\n\tsequence: number;\n\t/**\n\t * The id of the shard\n\t */\n\tshardId: number;\n\t/**\n\t * The total number of shards at the time of this shard identifying\n\t */\n\tshardCount: number;\n}\n\n/**\n * Required options for the WebSocketManager\n */\nexport interface RequiredWebSocketManagerOptions {\n\t/**\n\t * The token to use for identifying with the gateway\n\t */\n\ttoken: string;\n\t/**\n\t * The intents to request\n\t */\n\tintents: GatewayIntentBits;\n\t/**\n\t * The REST instance to use for fetching gateway information\n\t */\n\trest: REST;\n}\n\n/**\n * Optional additional configuration for the WebSocketManager\n */\nexport interface OptionalWebSocketManagerOptions {\n\t/**\n\t * The total number of shards across all WebsocketManagers you intend to instantiate.\n\t * Use `null` to use Discord's recommended shard count\n\t */\n\tshardCount: number | null;\n\t/**\n\t * The ids of the shards this WebSocketManager should manage.\n\t * Use `null` to simply spawn 0 through `shardCount - 1`\n\t * @example\n\t * const manager = new WebSocketManager({\n\t * shardIds: [1, 3, 7], // spawns shard 1, 3, and 7, nothing else\n\t * });\n\t * @example\n\t * const manager = new WebSocketManager({\n\t * shardIds: {\n\t * start: 3,\n\t * end: 6,\n\t * }, // spawns shards 3, 4, 5, and 6\n\t * });\n\t */\n\tshardIds: number[] | ShardRange | null;\n\t/**\n\t * Value between 50 and 250, total number of members where the gateway will stop sending offline members in the guild member list\n\t */\n\tlargeThreshold: number | null;\n\t/**\n\t * Initial presence data to send to the gateway when identifying\n\t */\n\tinitialPresence: GatewayPresenceUpdateData | null;\n\t/**\n\t * Properties to send to the gateway when identifying\n\t */\n\tidentifyProperties: GatewayIdentifyProperties;\n\t/**\n\t * The gateway version to use\n\t * @default '10'\n\t */\n\tversion: string;\n\t/**\n\t * The encoding to use\n\t * @default 'json'\n\t */\n\tencoding: Encoding;\n\t/**\n\t * The compression method to use\n\t * @default null (no compression)\n\t */\n\tcompression: CompressionMethod | null;\n\t/**\n\t * Function used to retrieve session information (and attempt to resume) for a given shard\n\t * @example\n\t * const manager = new WebSocketManager({\n\t * async retrieveSessionInfo(shardId): Awaitable<SessionInfo | null> {\n\t * // Fetch this info from redis or similar\n\t * return { sessionId: string, sequence: number };\n\t * // Return null if no information is found\n\t * },\n\t * });\n\t */\n\tretrieveSessionInfo: (shardId: number) => Awaitable<SessionInfo | null>;\n\t/**\n\t * Function used to store session information for a given shard\n\t */\n\tupdateSessionInfo: (shardId: number, sessionInfo: SessionInfo | null) => Awaitable<void>;\n\t/**\n\t * How long to wait for a shard to connect before giving up\n\t */\n\thandshakeTimeout: number | null;\n\t/**\n\t * How long to wait for a shard's HELLO packet before giving up\n\t */\n\thelloTimeout: number | null;\n\t/**\n\t * How long to wait for a shard's READY packet before giving up\n\t */\n\treadyTimeout: number | null;\n}\n\nexport type WebSocketManagerOptions = RequiredWebSocketManagerOptions & OptionalWebSocketManagerOptions;\n\nexport type ManagerShardEventsMap = {\n\t[K in keyof WebSocketShardEventsMap]: [\n\t\tWebSocketShardEventsMap[K] extends [] ? { shardId: number } : WebSocketShardEventsMap[K][0] & { shardId: number },\n\t];\n};\n\nexport class WebSocketManager extends AsyncEventEmitter<ManagerShardEventsMap> {\n\t/**\n\t * The options being used by this manager\n\t */\n\tpublic readonly options: WebSocketManagerOptions;\n\n\t/**\n\t * Internal cache for a GET /gateway/bot result\n\t */\n\tprivate gatewayInformation: {\n\t\tdata: APIGatewayBotInfo;\n\t\texpiresAt: number;\n\t} | null = null;\n\n\t/**\n\t * Internal cache for the shard ids\n\t */\n\tprivate shardIds: number[] | null = null;\n\n\t/**\n\t * Strategy used to manage shards\n\t * @default SimpleManagerToShardStrategy\n\t */\n\tprivate strategy: IShardingStrategy = new SimpleShardingStrategy(this);\n\n\tpublic constructor(options: RequiredWebSocketManagerOptions & Partial<OptionalWebSocketManagerOptions>) {\n\t\tsuper();\n\t\tthis.options = { ...DefaultWebSocketManagerOptions, ...options };\n\t}\n\n\tpublic setStrategy(strategy: IShardingStrategy) {\n\t\tthis.strategy = strategy;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Fetches the gateway information from Discord - or returns it from cache if available\n\t * @param force Whether to ignore the cache and force a fresh fetch\n\t */\n\tpublic async fetchGatewayInformation(force = false) {\n\t\tif (this.gatewayInformation) {\n\t\t\tif (this.gatewayInformation.expiresAt <= Date.now()) {\n\t\t\t\tthis.gatewayInformation = null;\n\t\t\t} else if (!force) {\n\t\t\t\treturn this.gatewayInformation.data;\n\t\t\t}\n\t\t}\n\n\t\tconst data = (await this.options.rest.get(Routes.gatewayBot())) as RESTGetAPIGatewayBotResult;\n\n\t\tthis.gatewayInformation = { data, expiresAt: Date.now() + data.session_start_limit.reset_after };\n\t\treturn this.gatewayInformation.data;\n\t}\n\n\t/**\n\t * Updates your total shard count on-the-fly, spawning shards as needed\n\t * @param shardCount The new shard count to use\n\t */\n\tpublic async updateShardCount(shardCount: number | null) {\n\t\tawait this.strategy.destroy({ reason: 'User is adjusting their shards' });\n\t\tthis.options.shardCount = shardCount;\n\n\t\tconst shardIds = await this.getShardIds(true);\n\t\tawait this.strategy.spawn(shardIds);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Yields the total number of shards across for your bot, accounting for Discord recommendations\n\t */\n\tpublic async getShardCount(): Promise<number> {\n\t\tif (this.options.shardCount) {\n\t\t\treturn this.options.shardCount;\n\t\t}\n\n\t\tconst shardIds = await this.getShardIds();\n\t\treturn Math.max(...shardIds) + 1;\n\t}\n\n\t/**\n\t * Yields the ids of the shards this manager should manage\n\t */\n\tpublic async getShardIds(force = false): Promise<number[]> {\n\t\tif (this.shardIds && !force) {\n\t\t\treturn this.shardIds;\n\t\t}\n\n\t\tlet shardIds: number[];\n\t\tif (this.options.shardIds) {\n\t\t\tif (Array.isArray(this.options.shardIds)) {\n\t\t\t\tshardIds = this.options.shardIds;\n\t\t\t} else {\n\t\t\t\tshardIds = range(this.options.shardIds);\n\t\t\t}\n\t\t} else {\n\t\t\tconst data = await this.fetchGatewayInformation();\n\t\t\tshardIds = range({ start: 0, end: (this.options.shardCount ?? data.shards) - 1 });\n\t\t}\n\n\t\tthis.shardIds = shardIds;\n\t\treturn shardIds;\n\t}\n\n\tpublic async connect() {\n\t\tconst shardCount = await this.getShardCount();\n\t\t// First, make sure all our shards are spawned\n\t\tawait this.updateShardCount(shardCount);\n\t\tawait this.strategy.connect();\n\t}\n\n\tpublic destroy(options?: Omit<WebSocketShardDestroyOptions, 'recover'>) {\n\t\treturn this.strategy.destroy(options);\n\t}\n\n\tpublic send(shardId: number, payload: GatewaySendPayload) {\n\t\treturn this.strategy.send(shardId, payload);\n\t}\n}\n"],"names":[],"mappings":"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"}