galactic.ts 1.0.1

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.
@@ -0,0 +1,327 @@
1
+ import { Connection, Server } from 'net-ipc';
2
+ import { GatewayIntentsString, Client } from 'discord.js';
3
+ import { ChildProcess } from 'child_process';
4
+
5
+ type EventPayload = {
6
+ id: string;
7
+ type: 'message' | 'request' | 'response' | 'response_error';
8
+ data: unknown;
9
+ };
10
+
11
+ declare class EventManager {
12
+ private pendingPayloads;
13
+ private pendingTimeouts;
14
+ private readonly _send;
15
+ private readonly _on;
16
+ private readonly _request;
17
+ constructor(send: (payload: EventPayload) => Promise<void>, on: (message: unknown) => void, request: (message: unknown) => unknown);
18
+ send(data: unknown): Promise<void>;
19
+ request<T>(payload: unknown, timeout: number): Promise<T>;
20
+ receive(possiblePayload: unknown): void;
21
+ close(reason?: string): void;
22
+ }
23
+
24
+ declare enum BridgeClientConnectionStatus {
25
+ READY = "ready",
26
+ PENDING_STOP = "pending_stop"
27
+ }
28
+ declare class BridgeClientConnection {
29
+ readonly instanceID: number;
30
+ readonly eventManager: EventManager;
31
+ readonly connection: Connection;
32
+ readonly data: unknown;
33
+ connectionStatus: BridgeClientConnectionStatus;
34
+ readonly dev: boolean;
35
+ private _onMessage?;
36
+ private _onRequest?;
37
+ constructor(instanceID: number, connection: Connection, data: unknown, dev: boolean);
38
+ messageReceive(message: any): void;
39
+ onRequest(callback: (message: unknown) => unknown): void;
40
+ onMessage(callback: (message: unknown) => void): void;
41
+ }
42
+
43
+ declare enum BridgeClientClusterConnectionStatus {
44
+ REQUESTING = "requesting",
45
+ STARTING = "starting",
46
+ CONNECTED = "connected",
47
+ RECLUSTERING = "reclustering",
48
+ DISCONNECTED = "disconnected"
49
+ }
50
+ declare class BridgeClientCluster {
51
+ readonly clusterID: number;
52
+ readonly shardList: number[];
53
+ connectionStatus: BridgeClientClusterConnectionStatus;
54
+ connection?: BridgeClientConnection;
55
+ oldConnection?: BridgeClientConnection;
56
+ missedHeartbeats: number;
57
+ heartbeatResponse?: HeartbeatResponse;
58
+ heartbeatPending: boolean;
59
+ startedAt?: number;
60
+ constructor(clusterID: number, shardList: number[]);
61
+ setConnection(connection?: BridgeClientConnection): void;
62
+ setOldConnection(connection?: BridgeClientConnection): void;
63
+ isUsed(): boolean;
64
+ reclustering(connection: BridgeClientConnection): void;
65
+ addMissedHeartbeat(): void;
66
+ removeMissedHeartbeat(): void;
67
+ resetMissedHeartbeats(): void;
68
+ }
69
+ type HeartbeatResponse = {
70
+ cpu: {
71
+ raw: {
72
+ user: number;
73
+ system: number;
74
+ };
75
+ cpuPercent: string;
76
+ };
77
+ memory: {
78
+ raw: {
79
+ rss: number;
80
+ heapTotal: number;
81
+ heapUsed: number;
82
+ external: number;
83
+ arrayBuffers: number;
84
+ };
85
+ memoryPercent: string;
86
+ usage: number;
87
+ };
88
+ ping: number;
89
+ shardPings: {
90
+ id: number;
91
+ ping: number;
92
+ status: number;
93
+ guilds: number;
94
+ members: number;
95
+ }[];
96
+ };
97
+
98
+ declare class Bridge {
99
+ readonly port: number;
100
+ readonly server: Server;
101
+ readonly connectedClients: Map<string, BridgeClientConnection>;
102
+ private readonly token;
103
+ private readonly intents;
104
+ private readonly shardsPerCluster;
105
+ private readonly clusterToStart;
106
+ private readonly clusterCalculator;
107
+ private readonly eventMap;
108
+ constructor(port: number, token: string, intents: GatewayIntentsString[], shardsPerCluster: number, clusterToStart: number);
109
+ start(): void;
110
+ private interval;
111
+ private checkRecluster;
112
+ private heartbeat;
113
+ private checkCreate;
114
+ private createCluster;
115
+ startListening(): void;
116
+ sendMessageToClient(clientId: string, message: unknown): void;
117
+ private getTotalShards;
118
+ on<K extends keyof BridgeEventListeners>(event: K, listener: BridgeEventListeners[K]): void;
119
+ getClusters(): BridgeClientCluster[];
120
+ stopAllInstances(): Promise<void>;
121
+ stopAllInstancesWithRestart(): Promise<void>;
122
+ moveCluster(instance: BridgeClientConnection, cluster: BridgeClientCluster): Promise<void>;
123
+ stopInstance(instance: BridgeClientConnection, recluster?: boolean): Promise<void>;
124
+ }
125
+ type BridgeEventListeners = {
126
+ 'CLUSTER_READY': ((cluster: BridgeClientCluster, guilds: number, members: number) => void) | undefined;
127
+ 'CLUSTER_STOPPED': ((cluster: BridgeClientCluster) => void) | undefined;
128
+ 'CLUSTER_SPAWNED': ((cluster: BridgeClientCluster, connection: BridgeClientConnection) => void) | undefined;
129
+ 'CLUSTER_RECLUSTER': ((cluster: BridgeClientCluster, newConnection: BridgeClientConnection, oldConnection: BridgeClientConnection) => void) | undefined;
130
+ 'CLUSTER_HEARTBEAT_FAILED': ((cluster: BridgeClientCluster, error: unknown) => void) | undefined;
131
+ 'CLIENT_CONNECTED': ((client: BridgeClientConnection) => void) | undefined;
132
+ 'CLIENT_DISCONNECTED': ((client: BridgeClientConnection, reason: string) => void) | undefined;
133
+ 'ERROR': ((error: string) => void) | undefined;
134
+ 'CLIENT_STOP': ((instance: BridgeClientConnection) => void) | undefined;
135
+ };
136
+
137
+ /**
138
+ * Manages the calculation and distribution of clusters for a Discord bot sharding system.
139
+ * This class is responsible for creating clusters with their assigned shards,
140
+ * tracking which clusters are in use, and providing methods to retrieve available clusters.
141
+ */
142
+ declare class ClusterCalculator {
143
+ /** The total number of clusters to initialize */
144
+ private readonly clusterToStart;
145
+ /** The number of shards that each cluster will manage */
146
+ private readonly shardsPerCluster;
147
+ /** List of all clusters managed by this calculator */
148
+ readonly clusterList: BridgeClientCluster[];
149
+ /**
150
+ * Creates a new ClusterCalculator and initializes the clusters.
151
+ *
152
+ * @param clusterToStart - The number of clusters to create
153
+ * @param shardsPerCluster - The number of shards each cluster will manage
154
+ */
155
+ constructor(clusterToStart: number, shardsPerCluster: number);
156
+ /**
157
+ * Calculates and initializes all clusters with their assigned shards.
158
+ * Each cluster is assigned a sequential range of shard IDs based on its cluster index.
159
+ */
160
+ private calculateClusters;
161
+ /**
162
+ * Retrieves the next available (unused) cluster and marks it as used.
163
+ *
164
+ * @returns The next available cluster, or undefined if all clusters are in use
165
+ */
166
+ getNextCluster(): BridgeClientCluster | undefined;
167
+ /**
168
+ * Retrieves multiple available clusters up to the specified count.
169
+ * Each returned cluster is marked as used.
170
+ *
171
+ * @param count - The maximum number of clusters to retrieve
172
+ * @returns An array of available clusters (may be fewer than requested if not enough are available)
173
+ */
174
+ getNextClusters(count: number): BridgeClientCluster[];
175
+ /**
176
+ * Sets the used status of a specific cluster by its ID.
177
+ *
178
+ * @param clusterID - The ID of the cluster to update
179
+ * @param connection - The connection to associate with the cluster
180
+ */
181
+ clearClusterConnection(clusterID: number): void;
182
+ getClusterForConnection(connection: BridgeClientConnection): BridgeClientCluster[];
183
+ getOldClusterForConnection(connection: BridgeClientConnection): BridgeClientCluster[];
184
+ checkAllClustersConnected(): boolean;
185
+ findMostAndLeastClustersForConnections(connectedClients: BridgeClientConnection[]): {
186
+ most: BridgeClientConnection | undefined;
187
+ least: BridgeClientConnection | undefined;
188
+ };
189
+ getClusterWithLowestLoad(connectedClients: Map<string, BridgeClientConnection>): BridgeClientConnection | undefined;
190
+ getClusterOfShard(shardID: number): BridgeClientCluster | undefined;
191
+ }
192
+
193
+ declare class Cluster<T extends Client> {
194
+ readonly instanceID: number;
195
+ readonly clusterID: number;
196
+ readonly shardList: number[];
197
+ readonly totalShards: number;
198
+ readonly token: string;
199
+ readonly intents: GatewayIntentsString[];
200
+ eventManager: EventManager;
201
+ client: T;
202
+ private readonly eventMap;
203
+ constructor(instanceID: number, clusterID: number, shardList: number[], totalShards: number, token: string, intents: GatewayIntentsString[]);
204
+ static initial<T extends Client>(): Cluster<T>;
205
+ triggerReady(guilds: number, members: number): void;
206
+ triggerError(e: any): void;
207
+ private wait;
208
+ private _onMessage;
209
+ private _onRequest;
210
+ on<K extends keyof ClusterEventListeners>(event: K, listener: ClusterEventListeners[K]): void;
211
+ sendMessage(data: unknown): void;
212
+ sendRequest(data: unknown, timeout?: number): Promise<unknown>;
213
+ broadcastEval<Result>(fn: (cluster: T) => Result, timeout?: number): Promise<Result[]>;
214
+ sendMessageToClusterOfGuild(guildID: string, message: unknown): void;
215
+ sendRequestToClusterOfGuild(guildID: string, message: unknown, timeout?: number): Promise<unknown>;
216
+ }
217
+ type ClusterEventListeners = {
218
+ message: (message: unknown) => void;
219
+ request: (message: unknown, resolve: (data: unknown) => void, reject: (error: any) => void) => void;
220
+ CLUSTER_READY: () => void;
221
+ };
222
+
223
+ type ClusterProcessState = 'starting' | 'running' | 'stopped';
224
+ declare class ClusterProcess {
225
+ readonly child: ChildProcess;
226
+ readonly eventManager: EventManager;
227
+ readonly id: number;
228
+ readonly shardList: number[];
229
+ readonly totalShards: number;
230
+ status: ClusterProcessState;
231
+ readonly createdAt: number;
232
+ private _onMessage?;
233
+ private _onRequest?;
234
+ constructor(id: number, child: ChildProcess, shardList: number[], totalShards: number);
235
+ onMessage(callback: (message: unknown) => void): void;
236
+ onRequest(callback: (message: unknown) => unknown): void;
237
+ sendMessage(data: unknown): void;
238
+ sendRequest(data: unknown, timeout?: number): Promise<unknown>;
239
+ }
240
+
241
+ declare class ShardingUtil {
242
+ static getShardIDForGuild(guildID: string, totalShards: number): number;
243
+ }
244
+
245
+ declare abstract class BotInstance {
246
+ private readonly entryPoint;
247
+ private readonly execArgv;
248
+ readonly clients: Map<number, ClusterProcess>;
249
+ protected constructor(entryPoint: string, execArgv?: string[]);
250
+ protected readonly eventMap: BotInstanceEventListeners;
251
+ protected startProcess(instanceID: number, clusterID: number, shardList: number[], totalShards: number, token: string, intents: GatewayIntentsString[]): void;
252
+ protected killProcess(client: ClusterProcess, reason: string): void;
253
+ protected abstract setClusterStopped(client: ClusterProcess, reason: string): void;
254
+ protected abstract setClusterReady(client: ClusterProcess, guilds: number, members: number): void;
255
+ protected abstract setClusterSpawned(client: ClusterProcess): void;
256
+ abstract start(): void;
257
+ private onMessage;
258
+ protected abstract onRequest(client: ClusterProcess, message: any): Promise<unknown>;
259
+ on<K extends keyof BotInstanceEventListeners>(event: K, listener: BotInstanceEventListeners[K]): void;
260
+ sendRequestToClusterOfGuild(guildID: string, message: unknown, timeout?: number): Promise<unknown>;
261
+ sendRequestToCluster(cluster: ClusterProcess, message: unknown, timeout?: number): Promise<unknown>;
262
+ }
263
+ type BotInstanceEventListeners = {
264
+ 'message': ((client: ClusterProcess, message: unknown) => void) | undefined;
265
+ 'request': ((client: ClusterProcess, message: unknown, resolve: (data: unknown) => void, reject: (error: any) => void) => void) | undefined;
266
+ 'PROCESS_KILLED': ((client: ClusterProcess, reason: string, processKilled: boolean) => void) | undefined;
267
+ 'PROCESS_SPAWNED': ((client: ClusterProcess) => void) | undefined;
268
+ 'PROCESS_ERROR': ((client: ClusterProcess, error: unknown) => void) | undefined;
269
+ 'CLUSTER_READY': ((client: ClusterProcess) => void) | undefined;
270
+ 'CLUSTER_ERROR': ((client: ClusterProcess, error: unknown) => void) | undefined;
271
+ 'CLUSTER_RECLUSTER': ((client: ClusterProcess) => void) | undefined;
272
+ 'ERROR': ((error: string) => void) | undefined;
273
+ 'BRIDGE_CONNECTION_ESTABLISHED': (() => void) | undefined;
274
+ 'BRIDGE_CONNECTION_CLOSED': ((reason: string) => void) | undefined;
275
+ 'BRIDGE_CONNECTION_STATUS_CHANGE': ((status: number) => void) | undefined;
276
+ 'INSTANCE_STOP': (() => void) | undefined;
277
+ 'INSTANCE_STOPPED': (() => void) | undefined;
278
+ 'SELF_CHECK_SUCCESS': (() => void) | undefined;
279
+ 'SELF_CHECK_ERROR': ((error: string) => void) | undefined;
280
+ 'SELF_CHECK_RECEIVED': ((data: {
281
+ clusterList: number[];
282
+ }) => void) | undefined;
283
+ };
284
+
285
+ declare enum BridgeConnectionStatus {
286
+ CONNECTED = 0,
287
+ DISCONNECTED = 1
288
+ }
289
+ declare class ManagedInstance extends BotInstance {
290
+ private readonly host;
291
+ private readonly port;
292
+ private readonly instanceID;
293
+ private eventManager;
294
+ private connectionStatus;
295
+ private data;
296
+ private dev;
297
+ constructor(entryPoint: string, host: string, port: number, instanceID: number, data: unknown, execArgv?: string[], dev?: boolean);
298
+ start(): void;
299
+ private selfCheck;
300
+ protected setClusterStopped(client: ClusterProcess, reason: string): void;
301
+ protected setClusterReady(client: ClusterProcess, guilds: number, members: number): void;
302
+ protected setClusterSpawned(client: ClusterProcess): void;
303
+ private onClusterCreate;
304
+ private onClusterStop;
305
+ private onClusterRecluster;
306
+ protected onRequest(client: ClusterProcess, message: any): Promise<unknown>;
307
+ private onBridgeRequest;
308
+ stopInstance(): void;
309
+ }
310
+
311
+ declare class StandaloneInstance extends BotInstance {
312
+ private readonly totalClusters;
313
+ private readonly shardsPerCluster;
314
+ readonly token: string;
315
+ readonly intents: GatewayIntentsString[];
316
+ constructor(entryPoint: string, shardsPerCluster: number, totalClusters: number, token: string, intents: GatewayIntentsString[], execArgv?: string[]);
317
+ get totalShards(): number;
318
+ private calculateClusters;
319
+ start(): void;
320
+ protected setClusterStopped(client: ClusterProcess, reason: string): void;
321
+ protected setClusterReady(client: ClusterProcess): void;
322
+ protected setClusterSpawned(client: ClusterProcess): void;
323
+ private restartProcess;
324
+ protected onRequest(client: ClusterProcess, message: any): Promise<unknown>;
325
+ }
326
+
327
+ export { BotInstance, type BotInstanceEventListeners, Bridge, BridgeClientCluster, BridgeClientClusterConnectionStatus, BridgeClientConnection, BridgeClientConnectionStatus, BridgeConnectionStatus, type BridgeEventListeners, Cluster, ClusterCalculator, type ClusterEventListeners, ClusterProcess, type ClusterProcessState, EventManager, type EventPayload, type HeartbeatResponse, ManagedInstance, ShardingUtil, StandaloneInstance };