From eb2ab1aed562a8fe4a86a201c2b671a2b9912c5b Mon Sep 17 00:00:00 2001 From: Bsian Date: Wed, 7 Oct 2020 00:44:28 +0100 Subject: [PATCH 1/6] JSDoc tidy up and TS docs --- index.d.ts | 168 +++++++++++++++++++++++++ src/sharding/cluster.js | 31 +++-- src/sharding/clustermanager.js | 83 ++++++++---- src/structures/Base.js | 14 +++ src/structures/IPC.js | 58 ++++++++- src/structures/SyncedRequestHandler.js | 23 ++++ src/utils/logger.js | 38 ++---- src/utils/queue.js | 22 +++- 8 files changed, 371 insertions(+), 66 deletions(-) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..e739366 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,168 @@ +import Eris from "eris"; +import EventEmitter from "events" + +type Callback = (...args: any[]) => void; + +interface ShardStats { + id: number; + ready: boolean; + latency: number; + status: "disconnected" | "connecting" | "handshaking" | "ready" | "resuming"; +} + +interface ClusterStatsInfo { + guilds: number; + users: number; + totalRam: number; + voice: number; + exclusiveGuilds: number; + largeGuilds: number; + clusters: ClusterDataStats[]; +} + +interface ClusterDataStats extends Exclude { + cluster: number; + shards: number; + ram: number; + uptime: number; + shardStats: ShardStats; +} + +interface ClusterStats { + stats: ClusterStatsInfo; + clustersCounted: number; +} + +interface ClusterData { + item: number; + value: { + id: number; + clusterCount: number; + name: string; + firstShardID: number; + lastShardID: number; + maxShards: number; + token: string; + file: string; + clientOptions: Eris.ClientOptions; + } +} + +interface Webhook { + id: string; + token: string; +} + +interface Webhooks { + shard?: Webhook; + cluster?: Webhook; +} + +interface ClusterManagerOptions { + shards?: number; + firstShardID?: number; + lastShardID?: number; + clusters?: number; + clusterTimeout?: number; + stats?: boolean; + debug?: boolean; + statsInterval?: number; + name?: string; + guildsPerShard?: number; + webhooks?: Webhooks; + clientOptions: Eris.ClientOptions; +} + +declare class IPC extends EventEmitter { + events: Map; + register(event: string, callback: Callback): void; + unregister(name: string): void; + broadcast(name: string, message?: any): void; + sendTo(cluster: number, name: string, message?: any): void; + fetchUser(id: string): Promise; + fetchGuild(id: string): Promise; + fetchChannel(id: string): Promise; + fetchMember(guildID: string, memberID: string): Promise; +} + +declare class Cluster { + shards: number; + maxShards: number; + firstShardID: number; + lastShardID: number; + mainFile: string | null; + clusterID: number; + clusterCount: number; + guilds: number; + users: number; + uptime: number; + exclusiveGuilds: number; + largeGuilds: number; + voiceChannels: number; + shardsStats: ShardStats[]; + app: T | null; + bot: C; + test: boolean; + ipc: IPC; + logOverride(message: unknown): string; + spawn(): void; + connect(firstShardID: number, lastShardID: number, maxShards: number, token: string, type: unknown, clientOptions: Eris.ClientOptions): void; + loadCode(bot: C): void; + startsStats(bot: C): void; +} + +class Queue extends EventEmitter { + queue: ClusterData[]; + executeQueue(): void; + queueItem(item: ClusterData): void; +} + +declare class ClusterManager extends EventEmitter { + shardCount: number | "auto"; + firstShardID: number; + lastShardID: number; + clusterCount: number; + clusterTimeout: number; + token: string | false; + clusters: Map>; + workers: Map; + queue: Queue; + callbacks: Map; + options: { stats: boolean; debug: boolean }; + statsInterval: number; + mainFile: string; + name: string; + guildsPerShard: number; + webhooks: Webhooks; + clientOptions: Eris.ClientOptions; + status: ClusterStats; + eris: Eris.Client; + constructor(token: string, mainFile: string, options: ClusterManagerOptions); + isMaster(): boolean; + startStats(): void; + executeStats(clusters: [string, Worker][], start: number): void; + start(clusterID: number): void; + launch(): void; + chunk(shards: number[], clusterCount: number): number[][]; + connectShards(): void; + sendWebhook(type: "shard" | "cluster", embed: Eris.EmbedOptions): void; + printLogo(): void; + restartCluster(worker: Worker, code: number): void; + calculateShards(): Promise; + fetchInfo(start: number, type: string, value: any): void; + broadcast(start: number, message: any): void; + sendTo(cluster: number, message: any): void; +} + +declare module "eris-sharder" { + export const Master: typeof ClusterManager; + + class Base { + bot: Eris.Client; + clusterID: number; + ipc: IPC; + constructor(setup: { bot: Eris.Client; clusterID: number; ipc: IPC }); + restartCluster(clusterID: number): void; + abstract launch(): any; + } +} \ No newline at end of file diff --git a/src/sharding/cluster.js b/src/sharding/cluster.js index 86c1bff..3ccb131 100644 --- a/src/sharding/cluster.js +++ b/src/sharding/cluster.js @@ -10,10 +10,9 @@ const Base = require("../structures/Base.js"); const SyncedRequestHandler = require('../structures/SyncedRequestHandler.js'); const { inspect } = require('util'); const IPC = require("../structures/IPC.js"); +const Eris = require("eris"); /** - * - * * @class Cluster */ class Cluster { @@ -53,11 +52,18 @@ class Cluster { } + /** + * @returns {String} + * @memberof Cluster + */ logOverride(message) { if (typeof message == 'object') return inspect(message); else return message; } + /** + * @memberof Cluster + */ spawn() { process.on('uncaughtException', (err) => { process.send({ name: "error", msg: err.stack }); @@ -168,13 +174,12 @@ class Cluster { } /** - * - * - * @param {any} firstShardID - * @param {any} lastShardID - * @param {any} maxShards - * @param {any} token - * @param {any} type + * @param {Number} firstShardID + * @param {Number} lastShardID + * @param {Number} maxShards + * @param {String} token + * @param {unknown} type + * @param {Eris.ClientOptions} clientOptions * @memberof Cluster */ connect(firstShardID, lastShardID, maxShards, token, type, clientOptions) { @@ -259,6 +264,10 @@ class Cluster { } } + /** + * @param {Eris.Client} bot + * @memberof Cluster + */ loadCode(bot) { let rootPath = process.cwd(); rootPath = rootPath.replace(`\\`, "/"); @@ -275,6 +284,10 @@ class Cluster { } } + /** + * @param {Eris.Client} bot + * @memberof Cluster + */ startStats(bot) { setInterval(() => { this.guilds = bot.guilds.size; diff --git a/src/sharding/clustermanager.js b/src/sharding/clustermanager.js index a5d463e..c5fee89 100644 --- a/src/sharding/clustermanager.js +++ b/src/sharding/clustermanager.js @@ -5,20 +5,37 @@ const logger = require("../utils/logger.js"); const EventEmitter = require("events"); const Eris = require("eris"); const Queue = require("../utils/queue.js"); -const pkg = require("../../package.json") +const pkg = require("../../package.json"); +const Eris = require("eris"); /** - * - * * @class ClusterManager * @extends {EventEmitter} */ class ClusterManager extends EventEmitter { /** * Creates an instance of ClusterManager. - * @param {any} token - * @param {any} mainFile - * @param {any} options + * @param {String} token + * @param {String} mainFile + * @param {Object} options + * @param {Number} [options.shards] + * @param {Number} [options.firstShardID] + * @param {Number} [options.lastShardID] + * @param {Number} [options.clusters] + * @param {Number} [options.clusterTimeout] + * @param {Boolean} [options.stats] + * @param {Boolean} [options.debug] + * @param {Number} [options.statsInterval] + * @param {String} [options.name] + * @param {Number} [options.guildsPerShard] + * @param {Object} [options.webhooks] + * @param {Object} [options.webhooks.shard] + * @param {String} options.webhooks.shard.id + * @param {String} options.webhooks.shard.token + * @param {Object} [options.webhooks.cluster] + * @param {String} options.webhooks.cluster.id + * @param {String} options.webhooks.cluster.token + * @param {Eris.ClientOptions} [options.clientOptions] * @memberof ClusterManager */ constructor(token, mainFile, options) { @@ -103,9 +120,8 @@ class ClusterManager extends EventEmitter { } /** - * - * - * @param {any} start + * @param {Array<[String, Worker]>} clusters + * @param {Number} start * @memberof ClusterManager */ executeStats(clusters, start) { @@ -121,10 +137,7 @@ class ClusterManager extends EventEmitter { /** - * - * - * @param {any} amount - * @param {any} numSpawned + * @param {Number} clusterID * @memberof ClusterManager */ start(clusterID) { @@ -161,11 +174,9 @@ class ClusterManager extends EventEmitter { } /** - * - * * @memberof ClusterManager */ - launch(test) { + launch() { if (master.isMaster) { process.on("uncaughtException", err => { logger.error("Cluster Manager", err.stack); @@ -362,6 +373,11 @@ class ClusterManager extends EventEmitter { }); } + /** + * @param {Array} shards + * @param {Number} clusterCount + * @memberof ClusterManager + */ chunk(shards, clusterCount) { if (clusterCount < 2) return [shards]; @@ -387,6 +403,9 @@ class ClusterManager extends EventEmitter { return out; } + /** + * @memberof ClusterManager + */ connectShards() { for (let clusterID in [...Array(this.clusterCount).keys()]) { clusterID = parseInt(clusterID); @@ -419,10 +438,8 @@ class ClusterManager extends EventEmitter { } /** - * - * - * @param {any} type - * @param {any} embed + * @param {String} type "shard" or "cluster" + * @param {Eris.EmbedOptions} embed * @memberof ClusterManager */ sendWebhook(type, embed) { @@ -452,7 +469,12 @@ class ClusterManager extends EventEmitter { ); } - restartCluster(worker, code, signal) { + /** + * @param {Worker} worker + * @param {Number} code + * @memberof ClusterManager + */ + restartCluster(worker, code) { const clusterID = this.workers.get(worker.id); logger.warn("Cluster Manager", `cluster ${clusterID} died`); @@ -495,6 +517,9 @@ class ClusterManager extends EventEmitter { }); } + /** + * @memberof ClusterManager + */ async calculateShards() { let shards = this.shardCount; @@ -512,6 +537,12 @@ class ClusterManager extends EventEmitter { } } + /** + * @param {Number} start + * @param {String} type + * @param {any} value + * @memberof ClusterManager + */ fetchInfo(start, type, value) { let cluster = this.clusters.get(start); if (cluster) { @@ -520,6 +551,11 @@ class ClusterManager extends EventEmitter { } } + /** + * @param {Number} start + * @param {any} message + * @memberof ClusterManager + */ broadcast(start, message) { let cluster = this.clusters.get(start); if (cluster) { @@ -528,6 +564,11 @@ class ClusterManager extends EventEmitter { } } + /** + * @param {Number} cluster + * @param {any} message + * @memberof ClusterManager + */ sendTo(cluster, message) { let worker = master.workers[this.clusters.get(cluster).workerID]; if (worker) { diff --git a/src/structures/Base.js b/src/structures/Base.js index 4b45186..5368a9a 100644 --- a/src/structures/Base.js +++ b/src/structures/Base.js @@ -1,10 +1,24 @@ +/** + * @class Base + */ class Base { + /** + * Creates an instance of Base. + * @param {Object} setup + * @param {import("eris").Client} setup.bot + * @param {Number} setup.clusterID + * @param {import("./IPC")} setup.ipc + */ constructor(setup) { this.bot = setup.bot; this.clusterID = setup.clusterID; this.ipc = setup.ipc; } + /** + * @param {Number} clusterID + * @memberof Base + */ restartCluster(clusterID) { this.ipc.sendTo(clusterID, "restart", { name: "restart" }); } diff --git a/src/structures/IPC.js b/src/structures/IPC.js index 7c19f32..f34a349 100644 --- a/src/structures/IPC.js +++ b/src/structures/IPC.js @@ -1,5 +1,13 @@ const EventEmitter = require("events"); + +/** + * @class IPC + * @extends EventEmitter + */ class IPC extends EventEmitter { + /** + * Creates an instance of IPC. + */ constructor() { super(); this.events = new Map(); @@ -12,28 +20,53 @@ class IPC extends EventEmitter { }); } + /** + * @param {String} event + * @param {(...args) => void} callback + * @memberof IPC + */ register(event, callback) { this.events.set(event, { fn: callback }); } + /** + * @param {String} name + * @memberof IPC + */ unregister(name) { this.events.delete(name); } + /** + * @param {String} name + * @param {any} message + * @memberof IPC + */ broadcast(name, message = {}) { message._eventName = name; process.send({ name: "broadcast", msg: message }); } + /** + * @param {Number} cluster + * @param {String} name + * @param {any} message + * @memberof IPC + */ sendTo(cluster, name, message = {}) { message._eventName = name; process.send({ name: "send", cluster: cluster, msg: message }); } + /** + * @param {String} id + * @returns {Promise} + * @memberof IPC + */ async fetchUser(id) { process.send({ name: "fetchUser", id }); - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const callback = (user) => { this.removeListener(id, callback); resolve(user); @@ -43,10 +76,15 @@ class IPC extends EventEmitter { }); } + /** + * @param {String} id + * @returns {Promise} + * @memberof IPC + */ async fetchGuild(id) { process.send({ name: "fetchGuild", id }); - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const callback = (guild) => { this.removeListener(id, callback); resolve(guild); @@ -56,10 +94,15 @@ class IPC extends EventEmitter { }); } + /** + * @param {String} id + * @returns {Promise} + * @memberof IPC + */ async fetchChannel(id) { process.send({ name: "fetchChannel", id }); - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const callback = (channel) => { this.removeListener(id, callback); resolve(channel); @@ -69,10 +112,17 @@ class IPC extends EventEmitter { }); } + /** + * + * @param {String} guildID + * @param {String} memberID + * @returns {Promise} + * @memberof IPC + */ async fetchMember(guildID, memberID) { process.send({ name: "fetchMember", guildID, memberID }); - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const callback = (channel) => { this.removeListener(memberID, callback); resolve(channel); diff --git a/src/structures/SyncedRequestHandler.js b/src/structures/SyncedRequestHandler.js index 201b07e..abcec6b 100644 --- a/src/structures/SyncedRequestHandler.js +++ b/src/structures/SyncedRequestHandler.js @@ -1,11 +1,34 @@ const crypto = require('crypto'); +/** + * @class SyncedRequestHandler + */ class SyncedRequestHandler { + /** + * Creates an instance of SyncedRequestHandler. + * @param {import("./IPC")} ipc + * @param {Object} options + * @param {Number} options.timeout + * @memberof SyncedRequestHandler + */ constructor(ipc, options) { this.ipc = ipc; this.timeout = options.timeout + 1000; } + /** + * @param {String} method + * @param {String} url + * @param {Boolean} [auth] + * @param {Object} [body] + * @param {Object} [file] + * @param {ArrayBuffer | SharedArrayBuffer} file.file + * @param {String} file.name + * @param {String} _route + * @param {Boolean} short + * @returns {Promise} + * @memberof SyncedRequestHandler + */ request(method, url, auth, body, file, _route, short) { return new Promise((resolve, reject) => { let stackCapture = new Error().stack; diff --git a/src/utils/logger.js b/src/utils/logger.js index 6a2a4fa..2eef3cf 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -15,8 +15,6 @@ colors.setTheme({ var log = require('fancy-log'); /** - * - * * @class Logger */ class Logger { @@ -25,10 +23,8 @@ class Logger { } /** - * - * - * @param {any} source - * @param {any} msg + * @param {String} source + * @param {String} msg * @memberof Logger */ log(source, msg) { @@ -37,10 +33,8 @@ class Logger { } /** - * - * - * @param {any} source - * @param {any} msg + * @param {String} source + * @param {String} msg * @memberof Logger */ info(source, msg) { @@ -49,10 +43,8 @@ class Logger { } /** - * - * - * @param {any} source - * @param {any} msg + * @param {String} source + * @param {String} msg * @memberof Logger */ warn(source, msg) { @@ -61,10 +53,8 @@ class Logger { } /** - * - * - * @param {any} source - * @param {any} msg + * @param {String} source + * @param {String} msg * @memberof Logger */ error(source, msg) { @@ -73,10 +63,8 @@ class Logger { } /** - * - * - * @param {any} source - * @param {any} msg + * @param {String} source + * @param {String} msg * @memberof Logger */ data(source, msg) { @@ -85,10 +73,8 @@ class Logger { } /** - * - * - * @param {any} source - * @param {any} msg + * @param {String} source + * @param {String} msg * @memberof Logger */ debug(source, msg) { diff --git a/src/utils/queue.js b/src/utils/queue.js index 414da29..03b2571 100644 --- a/src/utils/queue.js +++ b/src/utils/queue.js @@ -1,9 +1,7 @@ let EventEmitter = require("events"); /** - * - * * @class Queue - * @extends {EventEmitter} + * @extends EventEmitter */ class Queue extends EventEmitter { /** @@ -15,6 +13,9 @@ class Queue extends EventEmitter { this.queue = []; } + /** + * @memberof Queue + */ executeQueue() { let item = this.queue[0]; @@ -23,9 +24,18 @@ class Queue extends EventEmitter { } /** - * - * - * @param {any} item + * @param {Object} item + * @param {Number} item.item + * @param {Object} item.value + * @param {Number} item.value.id + * @param {Number} item.value.clusterCount + * @param {String} item.value.name + * @param {Number} item.value.firstShardID + * @param {Number} item.value.lastShardID + * @param {String} item.value.maxShards + * @param {String} item.value.token + * @param {String} item.value.file + * @param {import("eris").ClientOptions} item.value.clientOptions * @memberof Queue */ queueItem(item) { From 5a48a5918a7e3f1f6816c55f365669dfce18175d Mon Sep 17 00:00:00 2001 From: Bsian Date: Wed, 7 Oct 2020 00:53:55 +0100 Subject: [PATCH 2/6] EOF --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index e739366..74a7cfa 100644 --- a/index.d.ts +++ b/index.d.ts @@ -165,4 +165,4 @@ declare module "eris-sharder" { restartCluster(clusterID: number): void; abstract launch(): any; } -} \ No newline at end of file +} From 11002761373b3f4f5cd9f2e0bd606858599e6be5 Mon Sep 17 00:00:00 2001 From: Bsian Date: Wed, 7 Oct 2020 08:57:24 +0100 Subject: [PATCH 3/6] Review pt1 --- index.d.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index 74a7cfa..8d92c44 100644 --- a/index.d.ts +++ b/index.d.ts @@ -48,6 +48,12 @@ interface ClusterData { } } +interface ClusterMap { + workerID: number; + firstShardID: number; + lastShardID: number; +} + interface Webhook { id: string; token: string; @@ -106,7 +112,7 @@ declare class Cluster { ipc: IPC; logOverride(message: unknown): string; spawn(): void; - connect(firstShardID: number, lastShardID: number, maxShards: number, token: string, type: unknown, clientOptions: Eris.ClientOptions): void; + connect(firstShardID: number, lastShardID: number, maxShards: number, token: string, type: "connect" | "reconnect", clientOptions: Eris.ClientOptions): void; loadCode(bot: C): void; startsStats(bot: C): void; } @@ -117,14 +123,14 @@ class Queue extends EventEmitter { queueItem(item: ClusterData): void; } -declare class ClusterManager extends EventEmitter { +declare class ClusterManager extends EventEmitter { shardCount: number | "auto"; firstShardID: number; lastShardID: number; clusterCount: number; clusterTimeout: number; token: string | false; - clusters: Map>; + clusters: Map; workers: Map; queue: Queue; callbacks: Map; From f30661bf51fbc59f24950031e418752a4832f9f4 Mon Sep 17 00:00:00 2001 From: Bsian Date: Wed, 7 Oct 2020 09:05:08 +0100 Subject: [PATCH 4/6] Remove duplicate identifier --- src/sharding/clustermanager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sharding/clustermanager.js b/src/sharding/clustermanager.js index c5fee89..057006c 100644 --- a/src/sharding/clustermanager.js +++ b/src/sharding/clustermanager.js @@ -6,7 +6,6 @@ const EventEmitter = require("events"); const Eris = require("eris"); const Queue = require("../utils/queue.js"); const pkg = require("../../package.json"); -const Eris = require("eris"); /** * @class ClusterManager From 692fd2587afcc86bd9fb5b3b8c991dfd0d14336b Mon Sep 17 00:00:00 2001 From: Bsian Date: Wed, 7 Oct 2020 09:23:29 +0100 Subject: [PATCH 5/6] Remove duplicate identifier --- src/sharding/cluster.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sharding/cluster.js b/src/sharding/cluster.js index 3ccb131..a325e1b 100644 --- a/src/sharding/cluster.js +++ b/src/sharding/cluster.js @@ -10,7 +10,6 @@ const Base = require("../structures/Base.js"); const SyncedRequestHandler = require('../structures/SyncedRequestHandler.js'); const { inspect } = require('util'); const IPC = require("../structures/IPC.js"); -const Eris = require("eris"); /** * @class Cluster From f0d6790ba1c62a2432b3db3180aad3a4f89af0be Mon Sep 17 00:00:00 2001 From: bsian03 Date: Tue, 9 Feb 2021 20:58:23 +0000 Subject: [PATCH 6/6] doc change --- src/utils/queue.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/utils/queue.js b/src/utils/queue.js index 03b2571..b6d2e0d 100644 --- a/src/utils/queue.js +++ b/src/utils/queue.js @@ -24,18 +24,7 @@ class Queue extends EventEmitter { } /** - * @param {Object} item - * @param {Number} item.item - * @param {Object} item.value - * @param {Number} item.value.id - * @param {Number} item.value.clusterCount - * @param {String} item.value.name - * @param {Number} item.value.firstShardID - * @param {Number} item.value.lastShardID - * @param {String} item.value.maxShards - * @param {String} item.value.token - * @param {String} item.value.file - * @param {import("eris").ClientOptions} item.value.clientOptions + * @param {Object} item * @memberof Queue */ queueItem(item) { @@ -48,4 +37,4 @@ class Queue extends EventEmitter { } } -module.exports = Queue; \ No newline at end of file +module.exports = Queue;