New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

indomitable

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

indomitable - npm Package Compare versions

Comparing version
4.0.3
to
4.1.0
+743
dist/index.d.mts
import { ClientOptions, Client } from 'discord.js';
import { Worker, ClusterSettings } from 'node:cluster';
import EventEmitter from 'node:events';
import { Serializable } from 'node:child_process';
import { RequestOptions } from 'node:https';
import { WebSocketShardEvents, FetchingStrategyOptions, IShardingStrategy, WebSocketManager, WebSocketShardDestroyOptions, WebSocketShardStatus, WebSocketShard, IContextFetchingStrategy, SessionInfo } from '@discordjs/ws';
import { Worker as Worker$1, ResourceLimits } from 'node:worker_threads';
import { Collection } from '@discordjs/collection';
/**
* A wrapper for @discordjs/ws to work exclusively with Indomitable's dynamic concurrency with support for abort controller
*/
declare class ConcurrencyManager {
private readonly throttler;
private readonly signals;
constructor(concurrency: number);
/**
* Method to try and acquire a lock for identify
*/
waitForIdentify(shardId: number): Promise<void>;
/**
* Aborts an acquire lock request
*/
abortIdentify(shardId: number): void;
}
/**
* Hoisted Environmental Variable for ease of fetching
*/
declare const EnvProcessData: {
clusterId: number;
clusterCount: number;
shardIds: number[];
shardCount: number;
};
/**
* Internal operation codes for the cluster -> thread
*/
declare enum MainStrategyOps {
CONNECT = "connect",
DESTROY = "destroy",
SEND = "send",
STATUS = "status",
RECONNECT = "reconnect"
}
/**
* Internal operation codes for the thread <- cluster
*/
declare enum ThreadStrategyOps {
REQUEST_IDENTIFY = "requestIdentify",
CANCEL_IDENTIFY = "cancelIdentify",
SHARD_EVENT = "shardEvent",
RETRIEVE_SESSION = "retrieveSession",
UPDATE_SESSION = "updateSession"
}
/**
* Internal operation codes
*/
declare enum InternalOps {
EVAL = "eval",
RESTART = "restart",
RESTART_ALL = "restartAll",
DESTROY_CLIENT = "destroyClient",
REQUEST_IDENTIFY = "requestIdentify",
CANCEL_IDENTIFY = "cancelIdentify",
SESSION_INFO = "sessionInfo",
PING = "ping"
}
/**
* Events for internal use
*/
declare enum ClientEvents {
READY = "ready",
SHARD_READY = "shardReady",
SHARD_RECONNECT = "shardReconnect",
SHARD_RESUME = "shardResume",
SHARD_DISCONNECT = "shardDisconnect",
ERROR = "ERROR"
}
/**
* Events emitted by Indomitable
*/
declare enum LibraryEvents {
DEBUG = "debug",
MESSAGE = "message",
ERROR = "error",
WORKER_FORK = "workerFork",
WORKER_READY = "workerReady",
WORKER_EXIT = "workerExit",
SHARD_READY = "shardReady",
SHARD_RECONNECT = "shardReconnect",
SHARD_RESUME = "shardResume",
SHARD_DISCONNECT = "shardDisconnect",
CLIENT_READY = "clientReady",
RAW = "raw"
}
/**
* Type for raw ipc message
*/
declare enum RawIpcMessageType {
MESSAGE = "message",
RESPONSE = "response",
ERROR = "error"
}
/**
* Type for raw ipc messages of cluster -> thread
*/
interface MainStrategyData {
op: MainStrategyOps;
data: any;
internal: true;
}
/**
* Type for raw ipc messages of cluster <- thread
*/
interface ThreadStrategyData {
op: ThreadStrategyOps;
event: WebSocketShardEvents;
data: any;
shardId: number;
internal: true;
}
/**
* Data structure representing an internal event
*/
interface InternalOpsData {
op: InternalOps;
data: any;
internal: true;
}
/**
* Data structure representing an internal discord.js event
*/
interface ClientEventData {
op: ClientEvents;
data: any;
internal: true;
}
/**
* Data structure representing an internal error
*/
interface IpcErrorData {
name: string;
reason: string;
stack: string;
}
/**
* Data structure representing IPC data
*/
interface Transportable {
content: any;
repliable?: boolean;
signal?: AbortSignal;
}
/**
* Data structure representing an internal abort data
*/
interface InternalAbortSignal {
listener: () => void;
signal: AbortSignal;
}
interface SavePromiseOptions {
id: string;
resolve: (data: unknown) => void;
reject: (reason: unknown) => void;
signal?: AbortSignal | undefined;
}
/**
* Data structure representing a generated abort controller instance
*/
interface AbortableData {
controller: AbortController;
timeout: NodeJS.Timeout;
}
/**
* Internal promise data tracking
*/
interface InternalPromise {
resolve: Function;
reject: Function;
controller?: InternalAbortSignal;
}
/**
* Data structure representing internal IPC data
*/
interface RawIpcMessage {
id: string | null;
content: any;
internal: true;
type: RawIpcMessageType;
}
/**
* Data structure representing an IPC message
*/
interface Message {
reply: (data: any) => void;
content: any;
repliable: boolean;
}
/**
* Data structure representing a Discord session
*/
interface SessionObject {
url: string;
shards: number;
session_start_limit: {
total: number;
remaining: number;
reset_after: number;
max_concurrency: number;
};
}
/**
* Wrapper function for fetching data using HTTP
* @param url URL of resource to fetch
* @param options RequestOptions to modify behavior
* @returns A promise containing data fetched, or an error
*/
declare function Fetch(url: string | URL, options: RequestOptions): Promise<any>;
/**
* Fetch sessions from discord
* @param token Bot token
* @returns A promise containing a session object
*/
declare function FetchSessions(token: string): Promise<SessionObject>;
/**
* Modify an array to contain the specified amount of chunks
* @param original An array of data
* @param chunks The amount of chunks to transform into
* @returns A modified array
*/
declare function Chunk(original: any[], chunks: number): any[];
/**
* Wait for a specific amount of time (timeout)
* @param ms Time to wait in milliseconds
* @returns A promise that resolves in x seconds
*/
declare function Delay(ms: number): Promise<void>;
/**
* Creates an abortable request with controller and timeout
* @param delay Time before an abort error throws
* @returns An abortable data with controller and timeout
*/
declare function MakeAbortableRequest(delay: number): AbortableData;
type Util_AbortableData = AbortableData;
declare const Util_Chunk: typeof Chunk;
type Util_ClientEventData = ClientEventData;
type Util_ClientEvents = ClientEvents;
declare const Util_ClientEvents: typeof ClientEvents;
declare const Util_Delay: typeof Delay;
declare const Util_EnvProcessData: typeof EnvProcessData;
declare const Util_Fetch: typeof Fetch;
declare const Util_FetchSessions: typeof FetchSessions;
type Util_InternalAbortSignal = InternalAbortSignal;
type Util_InternalOps = InternalOps;
declare const Util_InternalOps: typeof InternalOps;
type Util_InternalOpsData = InternalOpsData;
type Util_InternalPromise = InternalPromise;
type Util_IpcErrorData = IpcErrorData;
type Util_LibraryEvents = LibraryEvents;
declare const Util_LibraryEvents: typeof LibraryEvents;
type Util_MainStrategyData = MainStrategyData;
type Util_MainStrategyOps = MainStrategyOps;
declare const Util_MainStrategyOps: typeof MainStrategyOps;
declare const Util_MakeAbortableRequest: typeof MakeAbortableRequest;
type Util_Message = Message;
type Util_RawIpcMessage = RawIpcMessage;
type Util_RawIpcMessageType = RawIpcMessageType;
declare const Util_RawIpcMessageType: typeof RawIpcMessageType;
type Util_SavePromiseOptions = SavePromiseOptions;
type Util_SessionObject = SessionObject;
type Util_ThreadStrategyData = ThreadStrategyData;
type Util_ThreadStrategyOps = ThreadStrategyOps;
declare const Util_ThreadStrategyOps: typeof ThreadStrategyOps;
type Util_Transportable = Transportable;
declare namespace Util {
export { type Util_AbortableData as AbortableData, Util_Chunk as Chunk, type Util_ClientEventData as ClientEventData, Util_ClientEvents as ClientEvents, Util_Delay as Delay, Util_EnvProcessData as EnvProcessData, Util_Fetch as Fetch, Util_FetchSessions as FetchSessions, type Util_InternalAbortSignal as InternalAbortSignal, Util_InternalOps as InternalOps, type Util_InternalOpsData as InternalOpsData, type Util_InternalPromise as InternalPromise, type Util_IpcErrorData as IpcErrorData, Util_LibraryEvents as LibraryEvents, type Util_MainStrategyData as MainStrategyData, Util_MainStrategyOps as MainStrategyOps, Util_MakeAbortableRequest as MakeAbortableRequest, type Util_Message as Message, type Util_RawIpcMessage as RawIpcMessage, Util_RawIpcMessageType as RawIpcMessageType, type Util_SavePromiseOptions as SavePromiseOptions, type Util_SessionObject as SessionObject, type Util_ThreadStrategyData as ThreadStrategyData, Util_ThreadStrategyOps as ThreadStrategyOps, type Util_Transportable as Transportable };
}
/**
* Base class where primary and worker ipc inherits
*/
declare abstract class BaseIpc {
readonly manager: Indomitable | EventEmitter;
protected readonly promises: Map<string, InternalPromise>;
protected constructor(manager: Indomitable | EventEmitter);
/**
* Number of promises pending to be resolved
*/
get pendingPromises(): number;
/**
* Rejects all the pending promises
*/
flushPromises(reason: string): void;
/**
* Raw send method without abort controller handling
* @param transportable Data to send
*/
send(transportable: Transportable): Promise<unknown | undefined>;
/**
* Taps into message event of worker or primary process to handle ipc communication
* @internal
*/
handleRawResponse(data: Serializable, errorCallback: (error: unknown) => any): Promise<boolean | void>;
protected waitForPromise(options: SavePromiseOptions): void;
private handlePromise;
private handleUnparsedMessage;
protected emitMessage(message: Message): void;
protected abstract available(): boolean;
protected abstract sendData(data: RawIpcMessage): void;
protected abstract handleMessage(message: Message): Promise<void>;
}
/**
* Primary ipc class. Only initialized at main process
*/
declare class MainWorker extends BaseIpc {
readonly cluster: ClusterManager;
constructor(cluster: ClusterManager);
protected available(): boolean;
protected sendData(data: RawIpcMessage): void;
protected handleMessage(message: Message): Promise<void>;
}
/**
* Options for child processes
*/
interface ClusterManagerOptions {
id: number;
shards: number[];
manager: Indomitable;
}
/**
* A class to manage a cluster
*/
declare class ClusterManager {
readonly manager: Indomitable;
readonly id: number;
readonly ipc: MainWorker;
shards: number[];
started: boolean;
ready: boolean;
readyAt: number;
worker?: Worker;
/**
* @param options.id ClusterId of this Cluster Manager being created
* @param options.shards An array of numbers representing the shards that this cluster controls
* @param options.manager Indomitable instance that spawned this cluster
*/
constructor(options: ClusterManagerOptions);
/**
* Destroy associated worker process
* @param signal Process exit signal
*/
destroy(signal?: string): void;
/**
* Respawn associated worker process
* @param delay Time to wait before restarting worker process
*/
respawn(delay?: number): Promise<void>;
/**
* Spawn a worker process
*/
spawn(): Promise<void>;
/**
* Remove all listeners on attached worker process and free from memory
*/
private cleanup;
/**
* Waits for this cluster to be ready
* @returns A promise that resolves to void
* @internal
*/
private wait;
}
/**
* Options to control Indomitable behavior
*/
interface IndomitableOptions {
clusterCount?: number | 'auto';
shardCount?: number | 'auto';
clientOptions?: ClientOptions;
clusterSettings?: ClusterSettings;
ipcTimeout?: number;
spawnTimeout?: number;
spawnDelay?: number;
autoRestart?: boolean;
waitForReady?: boolean;
handleConcurrency?: boolean;
client: typeof Client;
token: string;
}
interface ReconfigureOptions {
clusters?: number;
shards?: number;
}
interface ShardEventData {
clusterId: number;
shardId?: number;
replayed?: number;
event?: CloseEvent;
}
declare interface Indomitable {
/**
* Emitted when data useful for debugging is produced
* @eventProperty
*/
on(event: 'debug', listener: (message: string) => void): this;
/**
* Emitted when an IPC message is received
* @eventProperty
*/
on(event: 'message', listener: (message: Message | unknown) => void): this;
/**
* Emitted when an error occurs
* @eventProperty
*/
on(event: 'error', listener: (error: unknown) => void): this;
/**
* Emitted when a new worker process is forked
* @eventProperty
*/
on(event: 'workerFork', listener: (cluster: ClusterManager) => void): this;
/**
* Emitted when a worker process is ready
* @eventProperty
*/
on(event: 'workerReady', listener: (cluster: ClusterManager) => void): this;
/**
* Emitted when a worker process exits
* @eventProperty
*/
on(event: 'workerExit', listener: (code: number | null, signal: string | null, cluster: ClusterManager) => void): this;
/**
* Emitted when a Discord.js shard is ready
* @eventProperty
*/
on(event: 'shardReady', listener: (event: ShardEventData) => void): this;
/**
* Emitted when a Discord.js shard is reconnecting
* @eventProperty
*/
on(event: 'shardReconnect', listener: (event: ShardEventData) => void): this;
/**
* Emitted when a Discord.js shard resumes
* @eventProperty
*/
on(event: 'shardResume', listener: (event: ShardEventData) => void): this;
/**
* Emitted when a Discord.js shard disconnects
* @eventProperty
*/
on(event: 'shardDisconnect', listener: (event: ShardEventData) => void): this;
/**
* Emitted when a Discord.js client is ready
* @eventProperty
*/
on(event: 'clientReady', listener: (event: ShardEventData) => void): this;
/**
* Emitted on every ipc message the handler receives
* @eventProperty
*/
on(event: 'raw', listener: (event: unknown) => void): this;
once(event: 'debug', listener: (message: string) => void): this;
once(event: 'message', listener: (message: Message | unknown) => void): this;
once(event: 'error', listener: (error: unknown) => void): this;
once(event: 'workerFork', listener: (cluster: ClusterManager) => void): this;
once(event: 'workerReady', listener: (cluster: ClusterManager) => void): this;
once(event: 'workerExit', listener: (code: number | null, signal: string | null, cluster: ClusterManager) => void): this;
once(event: 'shardReady', listener: (event: ShardEventData) => void): this;
once(event: 'shardReconnect', listener: (event: ShardEventData) => void): this;
once(event: 'shardResume', listener: (event: ShardEventData) => void): this;
once(event: 'shardDisconnect', listener: (event: ShardEventData) => void): this;
once(event: 'clientReady', listener: (event: ShardEventData) => void): this;
once(event: 'raw', listener: (event: unknown) => void): this;
off(event: 'debug', listener: (message: string) => void): this;
off(event: 'message', listener: (message: Message | unknown) => void): this;
off(event: 'error', listener: (error: unknown) => void): this;
off(event: 'workerFork', listener: (cluster: ClusterManager) => void): this;
off(event: 'workerReady', listener: (cluster: ClusterManager) => void): this;
off(event: 'workerExit', listener: (code: number | null, signal: string | null, cluster: ClusterManager) => void): this;
off(event: 'shardReady', listener: (event: ShardEventData) => void): this;
off(event: 'shardReconnect', listener: (event: ShardEventData) => void): this;
off(event: 'shardResume', listener: (event: ShardEventData) => void): this;
off(event: 'shardDisconnect', listener: (event: ShardEventData) => void): this;
off(event: 'clientReady', listener: (event: ShardEventData) => void): this;
off(event: 'raw', listener: (event: unknown) => void): this;
}
/**
* The main Indomitable class, exposing all functionality.
*/
declare class Indomitable extends EventEmitter {
clusterCount: number | 'auto';
shardCount: number | 'auto';
cachedSession?: SessionObject;
concurrencyManager?: ConcurrencyManager;
readonly clientOptions: ClientOptions;
readonly clusterSettings: ClusterSettings;
readonly ipcTimeout: number;
readonly spawnTimeout: number;
readonly spawnDelay: number;
readonly autoRestart: boolean;
readonly waitForReady: boolean;
readonly handleConcurrency: boolean;
readonly client: typeof Client;
readonly clusters: Map<number, ClusterManager>;
private readonly spawnQueue;
private readonly token;
private busy;
/**
* @param [options.clusterCount=auto] The amount of clusters to spawn. Expects a number or 'auto'
* @param [options.shardCount=auto] The number of shards to create. Expects a number or 'auto'
* @param [options.clientOptions] Options for the Discord.js client
* @param [options.clusterSettings] Options for the forked process
* @param [options.ipcTimeout] Time to wait before an ipc request aborts
* @param [options.spawnTimeout] Time to wait before reporting a failed child process spawn
* @param [options.spawnDelay] Time to wait before spawning another child process
* @param [options.autoRestart] Whether to automatically restart shards that have been killed unintentionally
* @param [options.waitForReady] Whether to wait for clusters to be ready before spawning a new one
* @param [options.handleConcurrency] Whether you want to handle concurrency properly. Enabling this may result into more stable connection
* @param [options.client] A Discord.js client class or a modified Discord.js client class
* @param options.token Discord bot token
*/
constructor(options: IndomitableOptions);
/**
* Checks the internal private flag if Indomitable is busy
* @returns Number of clusters in queue
*/
get isBusy(): boolean;
/**
* Gets how many clusters are waiting to be spawned
* @returns Number of clusters in queue
*/
get inSpawnQueueCount(): number;
/**
* Gets the current session info of the bot token Indomitable currently handles
* @returns Session Info
*/
fetchSessions(force?: boolean): Promise<SessionObject>;
/**
* Spawn a new ShardClient if this instance is a child process, or start a new cluster and IPC server if this instance is the primary process
* @returns A promise that resolves to void
*/
spawn(): Promise<void>;
/**
* Restart specified cluster if this instance is the primary process
* @param clusterId Id of cluster to restart
* @returns A promise that resolves to void
*/
restart(clusterId: number): Promise<void>;
/**
* Restart all clusters if this instance is the primary process
* @returns A promise that resolves to void
*/
restartAll(): Promise<void>;
/**
* Sends a message to a specific cluster
* @returns A promise that resolves to undefined or an unknown value depending on how you reply to it
*/
send(id: number, transportable: Transportable): Promise<unknown | undefined>;
/**
* Sends a message on all clusters
* @returns An array of promise that resolves to undefined or an unknown value depending on how you reply to it
*/
broadcast(transportable: Transportable): Promise<unknown[] | undefined>;
/**
* Reconfigures to launch more shards / clusters without killing the existing processes if possible to avoid big downtimes
* @remarks Never execute restart() or restartAll() during this process or else you will double restart that cluster / all clusters
* @returns A promise that resolves to void
*/
reconfigure(options?: ReconfigureOptions): Promise<void>;
/**
* Adds a cluster to spawn queue
* @internal
*/
addToSpawnQueue(...clusters: ClusterManager[]): Promise<void>;
/**
* Destroys the client on a cluster
* @internal
*/
private destroyClusterClient;
/**
* Processes the cluster queue
* @internal
*/
private processQueue;
}
interface PartialInternalEvents {
op: ClientEvents;
data: {
clusterId: number;
shardId?: number;
replayed?: number;
event?: CloseEvent;
ipcId?: string;
};
}
declare class ShardClient {
readonly manager: Indomitable;
readonly client: Client;
readonly clusterId: number;
constructor(manager: Indomitable);
start(token: string): Promise<void>;
private send;
}
/**
* Basic worker ipc class, basic child process ipc handler
*/
declare class BaseWorker extends BaseIpc {
constructor(manager?: Indomitable | EventEmitter);
protected available(): boolean;
protected sendData(data: RawIpcMessage): void;
protected handleMessage(message: Message): Promise<void>;
}
/**
* Extended worker ipc class, shard client util ipc class
*/
declare class ClientWorker extends BaseWorker {
readonly shard: ShardClientUtil;
constructor(shard: ShardClientUtil, manager: Indomitable);
protected emitMessage(message: Message): void;
protected handleMessage(message: Message): Promise<void>;
}
declare interface ShardClientUtil {
/**
* Emitted when an IPC message from parent process is received
* @eventProperty
*/
on(event: 'message', listener: (message: Message | unknown) => void): this;
once(event: 'message', listener: (message: Message | unknown) => void): this;
off(event: 'message', listener: (message: Message | unknown) => void): this;
}
/**
* A class that replaces d.js stock shard client util. The class is built similar to it with minor changes
*/
declare class ShardClientUtil extends EventEmitter {
client: Client;
readonly ipc: ClientWorker;
readonly clusterId: number;
readonly clusterCount: number;
readonly shardIds: number[];
readonly shardCount: number;
constructor(client: Client, manager: Indomitable);
/**
* Gets the current ipc delay
* @returns A promise that resolves to delay in nanoseconds
*/
ping(): Promise<number>;
/**
* Evaluates a script or function on all clusters in the context of the client
* @returns A promise that resolves to an array of code results
*/
broadcastEval(script: Function, context?: any): Promise<unknown[]>;
/**
* Fetches a client property value on all clusters
* @returns A promise that resolves to an array of code results
*/
fetchClientValues(prop: string): Promise<unknown[]>;
/**
* Gets the cached session info or fetches an updated session info
* @param update If you want to fetch and update the cached session info
* @returns A session object
*/
fetchSessions(update?: boolean): Promise<SessionObject>;
/**
* Restarts the given cluster from the clusterId given
* @returns A promise that resolves to void
*/
restart(clusterId: number): Promise<undefined>;
/**
* Restarts all the clusters Indomitable handles sequentially
* @returns A promise that resolves to void
*/
restartAll(): Promise<undefined>;
/**
* Sends a message to primary process
* @returns A promise that resolves to void or a repliable object
*/
send(transportable: Transportable): Promise<unknown | undefined>;
}
interface WorkerData extends FetchingStrategyOptions {
shardId: number;
}
interface IndomitableWorker {
thread: Worker$1;
ipc: MainStrategyWorker;
}
interface IndomitableStrategyOptions {
path?: string;
resourceLimits?: ResourceLimits;
}
declare class IndomitableStrategy implements IShardingStrategy {
readonly manager: WebSocketManager;
readonly ipc: BaseWorker;
readonly workers: Collection<number, IndomitableWorker>;
private readonly options;
constructor(manager: WebSocketManager, ipc: BaseWorker, options?: IndomitableStrategyOptions);
spawn(shardIds: number[]): Promise<void>;
connect(): Promise<void>;
destroy(data?: Omit<WebSocketShardDestroyOptions, 'recover'>): Promise<void>;
reconnect(shardId: number): Promise<void>;
send(shardId: number, data: any): Promise<void>;
fetchStatus(): Promise<Collection<number, WebSocketShardStatus>>;
private createWorker;
}
declare class MainStrategyWorker extends BaseIpc {
readonly id: number;
readonly thread: Worker$1;
readonly strategy: IndomitableStrategy;
constructor(id: number, thread: Worker$1, strategy: IndomitableStrategy);
protected available(): boolean;
protected sendData(data: RawIpcMessage): void;
protected handleMessage(message: Message): Promise<void>;
}
declare class ThreadStrategyWorker extends BaseIpc {
private shard;
constructor();
build(shard: WebSocketShard): void;
protected available(): boolean;
protected sendData(data: RawIpcMessage): void;
protected handleMessage(message: Message): Promise<void>;
}
declare class IndomitableFetchingStrategy implements IContextFetchingStrategy {
private readonly ipc;
readonly options: FetchingStrategyOptions;
constructor(ipc: ThreadStrategyWorker, options: FetchingStrategyOptions);
retrieveSessionInfo(shardId: number): Promise<SessionInfo | null>;
updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Promise<void>;
waitForIdentify(shardId: number, signal: AbortSignal): Promise<void>;
private abortIdentify;
}
export { BaseIpc, BaseWorker, ClientWorker, ClusterManager, type ClusterManagerOptions, ConcurrencyManager, Indomitable, IndomitableFetchingStrategy, type IndomitableOptions, IndomitableStrategy, type IndomitableStrategyOptions, type IndomitableWorker, MainStrategyWorker, MainWorker, type PartialInternalEvents, type ReconfigureOptions, ShardClient, ShardClientUtil, type ShardEventData, ThreadStrategyWorker, Util as Utils, type WorkerData };
+4
-29

@@ -1,2 +0,2 @@

import { ClientOptions, Client, Collection } from 'discord.js';
import { ClientOptions, Client } from 'discord.js';
import { Worker, ClusterSettings } from 'node:cluster';

@@ -8,2 +8,3 @@ import EventEmitter from 'node:events';

import { Worker as Worker$1, ResourceLimits } from 'node:worker_threads';
import { Collection } from '@discordjs/collection';

@@ -278,29 +279,3 @@ /**

declare namespace Util {
export {
Util_AbortableData as AbortableData,
Util_Chunk as Chunk,
Util_ClientEventData as ClientEventData,
Util_ClientEvents as ClientEvents,
Util_Delay as Delay,
Util_EnvProcessData as EnvProcessData,
Util_Fetch as Fetch,
Util_FetchSessions as FetchSessions,
Util_InternalAbortSignal as InternalAbortSignal,
Util_InternalOps as InternalOps,
Util_InternalOpsData as InternalOpsData,
Util_InternalPromise as InternalPromise,
Util_IpcErrorData as IpcErrorData,
Util_LibraryEvents as LibraryEvents,
Util_MainStrategyData as MainStrategyData,
Util_MainStrategyOps as MainStrategyOps,
Util_MakeAbortableRequest as MakeAbortableRequest,
Util_Message as Message,
Util_RawIpcMessage as RawIpcMessage,
Util_RawIpcMessageType as RawIpcMessageType,
Util_SavePromiseOptions as SavePromiseOptions,
Util_SessionObject as SessionObject,
Util_ThreadStrategyData as ThreadStrategyData,
Util_ThreadStrategyOps as ThreadStrategyOps,
Util_Transportable as Transportable,
};
export { type Util_AbortableData as AbortableData, Util_Chunk as Chunk, type Util_ClientEventData as ClientEventData, Util_ClientEvents as ClientEvents, Util_Delay as Delay, Util_EnvProcessData as EnvProcessData, Util_Fetch as Fetch, Util_FetchSessions as FetchSessions, type Util_InternalAbortSignal as InternalAbortSignal, Util_InternalOps as InternalOps, type Util_InternalOpsData as InternalOpsData, type Util_InternalPromise as InternalPromise, type Util_IpcErrorData as IpcErrorData, Util_LibraryEvents as LibraryEvents, type Util_MainStrategyData as MainStrategyData, Util_MainStrategyOps as MainStrategyOps, Util_MakeAbortableRequest as MakeAbortableRequest, type Util_Message as Message, type Util_RawIpcMessage as RawIpcMessage, Util_RawIpcMessageType as RawIpcMessageType, type Util_SavePromiseOptions as SavePromiseOptions, type Util_SessionObject as SessionObject, type Util_ThreadStrategyData as ThreadStrategyData, Util_ThreadStrategyOps as ThreadStrategyOps, type Util_Transportable as Transportable };
}

@@ -770,2 +745,2 @@

export { BaseIpc, BaseWorker, ClientWorker, ClusterManager, ClusterManagerOptions, ConcurrencyManager, Indomitable, IndomitableFetchingStrategy, IndomitableOptions, IndomitableStrategy, IndomitableStrategyOptions, IndomitableWorker, MainStrategyWorker, MainWorker, PartialInternalEvents, ReconfigureOptions, ShardClient, ShardClientUtil, ShardEventData, ThreadStrategyWorker, Util as Utils, WorkerData };
export { BaseIpc, BaseWorker, ClientWorker, ClusterManager, type ClusterManagerOptions, ConcurrencyManager, Indomitable, IndomitableFetchingStrategy, type IndomitableOptions, IndomitableStrategy, type IndomitableStrategyOptions, type IndomitableWorker, MainStrategyWorker, MainWorker, type PartialInternalEvents, type ReconfigureOptions, ShardClient, ShardClientUtil, type ShardEventData, ThreadStrategyWorker, Util as Utils, type WorkerData };

@@ -181,3 +181,3 @@ "use strict";

var import_ws = require("@discordjs/ws");
var import_discord = require("discord.js");
var import_collection = require("@discordjs/collection");

@@ -390,3 +390,3 @@ // src/ipc/MainStrategyWorker.ts

this.ipc = ipc;
this.workers = new import_discord.Collection();
this.workers = new import_collection.Collection();
this.options = options;

@@ -446,3 +446,3 @@ }

async fetchStatus() {
const collection = new import_discord.Collection();
const collection = new import_collection.Collection();
const promises = this.workers.map(async (worker, id) => {

@@ -449,0 +449,0 @@ const content = {

@@ -148,3 +148,3 @@ var __defProp = Object.defineProperty;

} from "@discordjs/ws";
import { Collection } from "discord.js";
import { Collection } from "@discordjs/collection";

@@ -151,0 +151,0 @@ // src/ipc/MainStrategyWorker.ts

export { }
export { }

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../src/strategy/Thread.ts","../../../src/strategy/IndomitableFetchingStrategy.ts","../../../src/Util.ts","../../../src/ipc/ThreadStrategyWorker.ts","../../../src/ipc/BaseIpc.ts"],"sourcesContent":["import { WebSocketShard, WebSocketShardEvents } from '@discordjs/ws';\nimport { workerData } from 'worker_threads';\nimport { WorkerData } from './IndomitableStrategy';\nimport { IndomitableFetchingStrategy } from './IndomitableFetchingStrategy';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nconst options = workerData as WorkerData;\n\nconst ipc = new ThreadStrategyWorker();\nconst strategy = new IndomitableFetchingStrategy(ipc, options);\nconst shard = new WebSocketShard(strategy, options.shardId);\n\nipc.build(shard);\n\nfor (const event of Object.values(WebSocketShardEvents)) {\n // @ts-expect-error: unknown fix\n shard.on(event, data => {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.SHARD_EVENT,\n event,\n data,\n shardId: shard.id,\n internal: true\n };\n ipc.send({ content })\n .catch(() => null);\n });\n}\n\n\n\n\n\n","import { FetchingStrategyOptions, IContextFetchingStrategy, SessionInfo, WebSocketShardEvents } from '@discordjs/ws';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nexport class IndomitableFetchingStrategy implements IContextFetchingStrategy {\n private readonly ipc: ThreadStrategyWorker;\n public readonly options: FetchingStrategyOptions;\n constructor(ipc: ThreadStrategyWorker, options: FetchingStrategyOptions) {\n this.ipc = ipc;\n this.options = options;\n }\n\n public async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.RETRIEVE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n return await this.ipc.send({ content, repliable: true }) as SessionInfo;\n }\n\n public async updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.UPDATE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId, sessionInfo },\n shardId: shardId,\n internal: true\n };\n await this.ipc.send({ content });\n }\n\n public async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.REQUEST_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n const listener = () => this.abortIdentify(shardId);\n try {\n signal.addEventListener('abort', listener);\n await this.ipc.send({ content, repliable: true });\n } finally {\n signal.removeEventListener('abort', listener);\n }\n }\n\n private abortIdentify(shardId: number): void {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.CANCEL_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n this.ipc\n .send({ content, repliable: false })\n .catch(() => null);\n }\n}\n","import Https, { RequestOptions } from 'node:https';\nimport { WebSocketShardEvents } from '@discordjs/ws';\n\n/**\n * Hoisted Environmental Variable for ease of fetching\n */\nexport const EnvProcessData = {\n clusterId: Number(process.env.INDOMITABLE_CLUSTER || 0),\n clusterCount: Number(process.env.INDOMITABLE_CLUSTER_TOTAL || 0),\n shardIds: (process.env.INDOMITABLE_SHARDS || '').split(' ').map(Number),\n shardCount: Number(process.env.INDOMITABLE_SHARDS_TOTAL || 0)\n};\n\n/**\n * Internal operation codes for the cluster -> thread\n */\nexport enum MainStrategyOps {\n CONNECT = 'connect',\n DESTROY = 'destroy',\n SEND = 'send',\n STATUS = 'status',\n RECONNECT = 'reconnect'\n}\n\n/**\n * Internal operation codes for the thread <- cluster\n */\nexport enum ThreadStrategyOps {\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SHARD_EVENT = 'shardEvent',\n RETRIEVE_SESSION = 'retrieveSession',\n UPDATE_SESSION = 'updateSession'\n}\n\n/**\n * Internal operation codes\n */\nexport enum InternalOps {\n EVAL = 'eval',\n RESTART = 'restart',\n RESTART_ALL = 'restartAll',\n DESTROY_CLIENT = 'destroyClient',\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SESSION_INFO = 'sessionInfo',\n PING = 'ping'\n}\n\n/**\n * Events for internal use\n */\nexport enum ClientEvents {\n READY = 'ready',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n ERROR = 'ERROR'\n}\n\n/**\n * Events emitted by Indomitable\n */\nexport enum LibraryEvents {\n DEBUG = 'debug',\n MESSAGE = 'message',\n ERROR = 'error',\n WORKER_FORK = 'workerFork',\n WORKER_READY = 'workerReady',\n WORKER_EXIT = 'workerExit',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n CLIENT_READY = 'clientReady',\n RAW = 'raw'\n}\n\n/**\n * Type for raw ipc message\n */\nexport enum RawIpcMessageType {\n MESSAGE = 'message',\n RESPONSE = 'response',\n ERROR = 'error'\n}\n\n/**\n * Type for raw ipc messages of cluster -> thread\n */\nexport interface MainStrategyData {\n op: MainStrategyOps,\n data: any,\n internal: true\n}\n\n/**\n * Type for raw ipc messages of cluster <- thread\n */\nexport interface ThreadStrategyData {\n op: ThreadStrategyOps,\n event: WebSocketShardEvents,\n data: any,\n shardId: number,\n internal: true\n}\n\n/**\n * Data structure representing an internal event\n */\nexport interface InternalOpsData {\n op: InternalOps,\n data: any,\n internal: true\n}\n\n/**\n * Data structure representing an internal discord.js event\n */\nexport interface ClientEventData {\n op: ClientEvents,\n data: any,\n internal: true,\n}\n\n/**\n * Data structure representing an internal error\n */\nexport interface IpcErrorData {\n name: string;\n reason: string;\n stack: string;\n}\n\n/**\n * Data structure representing IPC data\n */\nexport interface Transportable {\n content: any;\n repliable?: boolean;\n signal?: AbortSignal\n}\n\n/**\n * Data structure representing an internal abort data\n */\nexport interface InternalAbortSignal {\n listener: () => void,\n signal: AbortSignal\n}\n\nexport interface SavePromiseOptions {\n id: string;\n resolve: (data: unknown) => void;\n reject: (reason: unknown) => void;\n signal?: AbortSignal | undefined;\n}\n\n/**\n * Data structure representing a generated abort controller instance\n */\nexport interface AbortableData {\n controller: AbortController;\n timeout: NodeJS.Timeout;\n}\n\n/**\n * Internal promise data tracking\n */\nexport interface InternalPromise {\n resolve: Function;\n reject: Function;\n controller?: InternalAbortSignal;\n}\n\n/**\n * Data structure representing internal IPC data\n */\nexport interface RawIpcMessage {\n id: string|null;\n content: any;\n internal: true;\n type: RawIpcMessageType\n}\n\n/**\n * Data structure representing an IPC message\n */\nexport interface Message {\n reply: (data: any) => void;\n content: any;\n repliable: boolean;\n}\n\n/**\n * Data structure representing a Discord session\n */\nexport interface SessionObject {\n\turl: string;\n\tshards: number;\n\tsession_start_limit: {\n\t\ttotal: number;\n\t\tremaining: number;\n\t\treset_after: number;\n max_concurrency: number;\n\t};\n}\n\n/**\n * Wrapper function for fetching data using HTTP\n * @param url URL of resource to fetch\n * @param options RequestOptions to modify behavior\n * @returns A promise containing data fetched, or an error\n */\nexport function Fetch(url: string|URL, options: RequestOptions): Promise<any> {\n return new Promise((resolve, reject) => {\n const request = Https.request(url, options, response => {\n const chunks: any[] = [];\n response.on('data', chunk => chunks.push(chunk));\n response.on('error', reject);\n response.on('end', () => {\n const code = response.statusCode ?? 500;\n const body = chunks.join('');\n if (code >= 200 && code <= 299)\n resolve(body);\n else\n reject(new Error(`Response received is not ok, Status Code: ${response.statusCode}, body: ${body}`));\n });\n });\n request.on('error', reject);\n request.end();\n });\n}\n\n/**\n * Fetch sessions from discord\n * @param token Bot token\n * @returns A promise containing a session object\n */\nexport async function FetchSessions(token: string): Promise<SessionObject> {\n const url = new URL('https://discord.com/api/v10/gateway/bot');\n const data = await Fetch(url, {\n method: 'GET',\n headers: { authorization: `Bot ${token}` }\n });\n return JSON.parse(data);\n}\n\n/**\n * Modify an array to contain the specified amount of chunks\n * @param original An array of data\n * @param chunks The amount of chunks to transform into\n * @returns A modified array\n */\nexport function Chunk(original: any[], chunks: number): any[] {\n const array = [];\n for (let i = 0; i < original.length; i += chunks)\n array.push(original.slice(i , i + chunks));\n return array;\n}\n\n/**\n * Wait for a specific amount of time (timeout)\n * @param ms Time to wait in milliseconds\n * @returns A promise that resolves in x seconds\n */\nexport function Delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(() => resolve(), ms));\n}\n\n/**\n * Creates an abortable request with controller and timeout\n * @param delay Time before an abort error throws\n * @returns An abortable data with controller and timeout\n */\nexport function MakeAbortableRequest(delay: number): AbortableData {\n const controller = new AbortController();\n const seconds = Math.round(delay / 1000);\n const timeout = setTimeout(\n () => controller.abort(new Error(`The request has been aborted in ${seconds} second(s)`)),\n delay\n );\n return { controller, timeout };\n}\n","import EventEmitter from 'node:events';\nimport { parentPort } from 'worker_threads';\nimport { WebSocketShard } from '@discordjs/ws';\nimport { BaseIpc } from './BaseIpc';\nimport {\n MainStrategyData,\n MainStrategyOps,\n Message,\n RawIpcMessage,\n} from '../Util';\n\nexport class ThreadStrategyWorker extends BaseIpc {\n private shard: WebSocketShard|undefined;\n constructor() {\n super(new EventEmitter());\n parentPort!.on('message', message => this.handleRawResponse(message, () => null));\n }\n\n public build(shard: WebSocketShard): void {\n if (!this.shard) this.shard = shard;\n }\n\n protected available(): boolean {\n return !!parentPort;\n }\n\n protected sendData(data: RawIpcMessage) {\n return parentPort!.postMessage(data);\n }\n\n protected async handleMessage(message: Message): Promise<void> {\n const content = message.content as MainStrategyData;\n if (!this.shard) throw new Error('Shard isn\\'t initialized yet');\n switch(content.op) {\n case MainStrategyOps.CONNECT:\n await this.shard.connect();\n message.reply(null);\n break;\n case MainStrategyOps.DESTROY:\n await this.shard.destroy(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.SEND:\n await this.shard.send(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.RECONNECT:\n await this.shard.destroy(content.data);\n message.reply(null);\n break;\n case MainStrategyOps.STATUS:\n message.reply(this.shard.status);\n break;\n }\n }\n}\n","import EventEmitter from 'node:events';\nimport { Serializable } from 'node:child_process';\nimport { randomUUID } from 'crypto';\nimport { Indomitable } from '../Indomitable.js';\nimport {\n InternalAbortSignal,\n InternalPromise,\n IpcErrorData,\n LibraryEvents,\n Message,\n RawIpcMessage,\n RawIpcMessageType,\n SavePromiseOptions,\n Transportable\n} from '../Util.js';\n\n/**\n * Base class where primary and worker ipc inherits\n */\nexport abstract class BaseIpc {\n public readonly manager: Indomitable|EventEmitter;\n protected readonly promises: Map<string, InternalPromise>;\n protected constructor(manager: Indomitable|EventEmitter) {\n this.manager = manager;\n this.promises = new Map();\n }\n\n /**\n * Number of promises pending to be resolved\n */\n public get pendingPromises(): number {\n return this.promises.size;\n }\n\n /**\n * Rejects all the pending promises\n */\n public flushPromises(reason: string): void {\n const error = new Error(reason);\n for (const promise of this.promises.values()) {\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n promise.reject(error);\n }\n this.promises.clear();\n }\n\n /**\n * Raw send method without abort controller handling\n * @param transportable Data to send\n */\n public send(transportable: Transportable): Promise<unknown|undefined> {\n return new Promise((resolve, reject) => {\n if (!this.available()) {\n this.manager.emit(LibraryEvents.DEBUG, 'IPC tried to send a message, but the ipc communication is not yet ready');\n return resolve(undefined);\n }\n const repliable = transportable.repliable || false;\n const id = repliable ? randomUUID() : null;\n const data: RawIpcMessage = {\n id,\n content: transportable.content,\n internal: true,\n type: RawIpcMessageType.MESSAGE\n };\n this.sendData(data);\n if (!id) return resolve(undefined);\n this.waitForPromise({ id, resolve, reject, signal: transportable.signal });\n });\n }\n\n /**\n * Taps into message event of worker or primary process to handle ipc communication\n * @internal\n */\n public async handleRawResponse(data: Serializable, errorCallback: (error: unknown) => any): Promise<boolean|void> {\n try {\n this.manager.emit(LibraryEvents.RAW, data);\n if (!(data as any).internal) return;\n switch((data as RawIpcMessage).type) {\n case RawIpcMessageType.MESSAGE:\n return await this.handleUnparsedMessage(data as RawIpcMessage);\n case RawIpcMessageType.RESPONSE:\n case RawIpcMessageType.ERROR:\n return this.handlePromise(data as RawIpcMessage);\n }\n } catch (error: unknown) {\n errorCallback(error);\n }\n }\n\n protected waitForPromise(options: SavePromiseOptions): void {\n let controller: InternalAbortSignal|undefined;\n if (options.signal) {\n const listener = () => {\n this.promises.delete(options.id);\n options.reject(new Error('This operation is aborted'));\n };\n controller = {\n listener,\n signal: options.signal\n };\n controller.signal.addEventListener('abort', listener);\n }\n this.promises.set(options.id, { resolve: options.resolve, reject: options.reject, controller } as InternalPromise);\n }\n\n private handlePromise(data: RawIpcMessage): void {\n const id = data.id as string;\n const promise = this.promises.get(id);\n if (!promise) return;\n this.promises.delete(id);\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n if (data.type === RawIpcMessageType.ERROR) {\n const content = data.content as IpcErrorData;\n const error = new Error(content.reason);\n error.stack = content.stack;\n error.name = content.name;\n promise.reject(error);\n return;\n }\n promise.resolve(data.content);\n }\n\n private async handleUnparsedMessage(data: RawIpcMessage): Promise<void> {\n const reply = (content: any) => {\n if (!data.id) return;\n const response: RawIpcMessage = {\n id: data.id,\n content,\n internal: true,\n type: RawIpcMessageType.RESPONSE\n };\n this.sendData(response);\n };\n const message: Message = {\n repliable: !!data.id,\n content: data.content,\n reply\n };\n if (!data.content.internal)\n return this.emitMessage(message);\n try {\n await this.handleMessage(message);\n } catch (error: any) {\n if (!message.repliable) return;\n const response: RawIpcMessage = {\n id: data.id,\n content: {\n name: error.name,\n reason: error.reason,\n stack: error.stack\n },\n internal: true,\n type: RawIpcMessageType.ERROR\n };\n this.sendData(response);\n }\n }\n\n protected emitMessage(message: Message): void {\n this.manager.emit(LibraryEvents.MESSAGE, message);\n }\n\n protected abstract available(): boolean;\n protected abstract sendData(data: RawIpcMessage): void;\n protected abstract handleMessage(message: Message): Promise<void>;\n}\n"],"mappings":"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","names":["import_ws","import_worker_threads","ipc","options","options","EventEmitter","shard"]}
{"version":3,"sources":["../../../src/strategy/Thread.ts","../../../src/strategy/IndomitableFetchingStrategy.ts","../../../src/Util.ts","../../../src/ipc/ThreadStrategyWorker.ts","../../../src/ipc/BaseIpc.ts"],"sourcesContent":["import { WebSocketShard, WebSocketShardEvents } from '@discordjs/ws';\nimport { workerData } from 'worker_threads';\nimport { WorkerData } from './IndomitableStrategy';\nimport { IndomitableFetchingStrategy } from './IndomitableFetchingStrategy';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nconst options = workerData as WorkerData;\n\nconst ipc = new ThreadStrategyWorker();\nconst strategy = new IndomitableFetchingStrategy(ipc, options);\nconst shard = new WebSocketShard(strategy, options.shardId);\n\nipc.build(shard);\n\nfor (const event of Object.values(WebSocketShardEvents)) {\n // @ts-expect-error: unknown fix\n shard.on(event, data => {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.SHARD_EVENT,\n event,\n data,\n shardId: shard.id,\n internal: true\n };\n ipc.send({ content })\n .catch(() => null);\n });\n}\n\n\n\n\n\n","import { FetchingStrategyOptions, IContextFetchingStrategy, SessionInfo, WebSocketShardEvents } from '@discordjs/ws';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nexport class IndomitableFetchingStrategy implements IContextFetchingStrategy {\n private readonly ipc: ThreadStrategyWorker;\n public readonly options: FetchingStrategyOptions;\n constructor(ipc: ThreadStrategyWorker, options: FetchingStrategyOptions) {\n this.ipc = ipc;\n this.options = options;\n }\n\n public async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.RETRIEVE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n return await this.ipc.send({ content, repliable: true }) as SessionInfo;\n }\n\n public async updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.UPDATE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId, sessionInfo },\n shardId: shardId,\n internal: true\n };\n await this.ipc.send({ content });\n }\n\n public async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.REQUEST_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n const listener = () => this.abortIdentify(shardId);\n try {\n signal.addEventListener('abort', listener);\n await this.ipc.send({ content, repliable: true });\n } finally {\n signal.removeEventListener('abort', listener);\n }\n }\n\n private abortIdentify(shardId: number): void {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.CANCEL_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n this.ipc\n .send({ content, repliable: false })\n .catch(() => null);\n }\n}\n","import Https, { RequestOptions } from 'node:https';\nimport { WebSocketShardEvents } from '@discordjs/ws';\n\n/**\n * Hoisted Environmental Variable for ease of fetching\n */\nexport const EnvProcessData = {\n clusterId: Number(process.env.INDOMITABLE_CLUSTER || 0),\n clusterCount: Number(process.env.INDOMITABLE_CLUSTER_TOTAL || 0),\n shardIds: (process.env.INDOMITABLE_SHARDS || '').split(' ').map(Number),\n shardCount: Number(process.env.INDOMITABLE_SHARDS_TOTAL || 0)\n};\n\n/**\n * Internal operation codes for the cluster -> thread\n */\nexport enum MainStrategyOps {\n CONNECT = 'connect',\n DESTROY = 'destroy',\n SEND = 'send',\n STATUS = 'status',\n RECONNECT = 'reconnect'\n}\n\n/**\n * Internal operation codes for the thread <- cluster\n */\nexport enum ThreadStrategyOps {\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SHARD_EVENT = 'shardEvent',\n RETRIEVE_SESSION = 'retrieveSession',\n UPDATE_SESSION = 'updateSession'\n}\n\n/**\n * Internal operation codes\n */\nexport enum InternalOps {\n EVAL = 'eval',\n RESTART = 'restart',\n RESTART_ALL = 'restartAll',\n DESTROY_CLIENT = 'destroyClient',\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SESSION_INFO = 'sessionInfo',\n PING = 'ping'\n}\n\n/**\n * Events for internal use\n */\nexport enum ClientEvents {\n READY = 'ready',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n ERROR = 'ERROR'\n}\n\n/**\n * Events emitted by Indomitable\n */\nexport enum LibraryEvents {\n DEBUG = 'debug',\n MESSAGE = 'message',\n ERROR = 'error',\n WORKER_FORK = 'workerFork',\n WORKER_READY = 'workerReady',\n WORKER_EXIT = 'workerExit',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n CLIENT_READY = 'clientReady',\n RAW = 'raw'\n}\n\n/**\n * Type for raw ipc message\n */\nexport enum RawIpcMessageType {\n MESSAGE = 'message',\n RESPONSE = 'response',\n ERROR = 'error'\n}\n\n/**\n * Type for raw ipc messages of cluster -> thread\n */\nexport interface MainStrategyData {\n op: MainStrategyOps,\n data: any,\n internal: true\n}\n\n/**\n * Type for raw ipc messages of cluster <- thread\n */\nexport interface ThreadStrategyData {\n op: ThreadStrategyOps,\n event: WebSocketShardEvents,\n data: any,\n shardId: number,\n internal: true\n}\n\n/**\n * Data structure representing an internal event\n */\nexport interface InternalOpsData {\n op: InternalOps,\n data: any,\n internal: true\n}\n\n/**\n * Data structure representing an internal discord.js event\n */\nexport interface ClientEventData {\n op: ClientEvents,\n data: any,\n internal: true,\n}\n\n/**\n * Data structure representing an internal error\n */\nexport interface IpcErrorData {\n name: string;\n reason: string;\n stack: string;\n}\n\n/**\n * Data structure representing IPC data\n */\nexport interface Transportable {\n content: any;\n repliable?: boolean;\n signal?: AbortSignal\n}\n\n/**\n * Data structure representing an internal abort data\n */\nexport interface InternalAbortSignal {\n listener: () => void,\n signal: AbortSignal\n}\n\nexport interface SavePromiseOptions {\n id: string;\n resolve: (data: unknown) => void;\n reject: (reason: unknown) => void;\n signal?: AbortSignal | undefined;\n}\n\n/**\n * Data structure representing a generated abort controller instance\n */\nexport interface AbortableData {\n controller: AbortController;\n timeout: NodeJS.Timeout;\n}\n\n/**\n * Internal promise data tracking\n */\nexport interface InternalPromise {\n resolve: Function;\n reject: Function;\n controller?: InternalAbortSignal;\n}\n\n/**\n * Data structure representing internal IPC data\n */\nexport interface RawIpcMessage {\n id: string|null;\n content: any;\n internal: true;\n type: RawIpcMessageType\n}\n\n/**\n * Data structure representing an IPC message\n */\nexport interface Message {\n reply: (data: any) => void;\n content: any;\n repliable: boolean;\n}\n\n/**\n * Data structure representing a Discord session\n */\nexport interface SessionObject {\n\turl: string;\n\tshards: number;\n\tsession_start_limit: {\n\t\ttotal: number;\n\t\tremaining: number;\n\t\treset_after: number;\n max_concurrency: number;\n\t};\n}\n\n/**\n * Wrapper function for fetching data using HTTP\n * @param url URL of resource to fetch\n * @param options RequestOptions to modify behavior\n * @returns A promise containing data fetched, or an error\n */\nexport function Fetch(url: string|URL, options: RequestOptions): Promise<any> {\n return new Promise((resolve, reject) => {\n const request = Https.request(url, options, response => {\n const chunks: any[] = [];\n response.on('data', chunk => chunks.push(chunk));\n response.on('error', reject);\n response.on('end', () => {\n const code = response.statusCode ?? 500;\n const body = chunks.join('');\n if (code >= 200 && code <= 299)\n resolve(body);\n else\n reject(new Error(`Response received is not ok, Status Code: ${response.statusCode}, body: ${body}`));\n });\n });\n request.on('error', reject);\n request.end();\n });\n}\n\n/**\n * Fetch sessions from discord\n * @param token Bot token\n * @returns A promise containing a session object\n */\nexport async function FetchSessions(token: string): Promise<SessionObject> {\n const url = new URL('https://discord.com/api/v10/gateway/bot');\n const data = await Fetch(url, {\n method: 'GET',\n headers: { authorization: `Bot ${token}` }\n });\n return JSON.parse(data);\n}\n\n/**\n * Modify an array to contain the specified amount of chunks\n * @param original An array of data\n * @param chunks The amount of chunks to transform into\n * @returns A modified array\n */\nexport function Chunk(original: any[], chunks: number): any[] {\n const array = [];\n for (let i = 0; i < original.length; i += chunks)\n array.push(original.slice(i , i + chunks));\n return array;\n}\n\n/**\n * Wait for a specific amount of time (timeout)\n * @param ms Time to wait in milliseconds\n * @returns A promise that resolves in x seconds\n */\nexport function Delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(() => resolve(), ms));\n}\n\n/**\n * Creates an abortable request with controller and timeout\n * @param delay Time before an abort error throws\n * @returns An abortable data with controller and timeout\n */\nexport function MakeAbortableRequest(delay: number): AbortableData {\n const controller = new AbortController();\n const seconds = Math.round(delay / 1000);\n const timeout = setTimeout(\n () => controller.abort(new Error(`The request has been aborted in ${seconds} second(s)`)),\n delay\n );\n return { controller, timeout };\n}\n","import EventEmitter from 'node:events';\nimport { parentPort } from 'worker_threads';\nimport { WebSocketShard } from '@discordjs/ws';\nimport { BaseIpc } from './BaseIpc';\nimport {\n MainStrategyData,\n MainStrategyOps,\n Message,\n RawIpcMessage,\n} from '../Util';\n\nexport class ThreadStrategyWorker extends BaseIpc {\n private shard: WebSocketShard|undefined;\n constructor() {\n super(new EventEmitter());\n parentPort!.on('message', message => this.handleRawResponse(message, () => null));\n }\n\n public build(shard: WebSocketShard): void {\n if (!this.shard) this.shard = shard;\n }\n\n protected available(): boolean {\n return !!parentPort;\n }\n\n protected sendData(data: RawIpcMessage) {\n return parentPort!.postMessage(data);\n }\n\n protected async handleMessage(message: Message): Promise<void> {\n const content = message.content as MainStrategyData;\n if (!this.shard) throw new Error('Shard isn\\'t initialized yet');\n switch(content.op) {\n case MainStrategyOps.CONNECT:\n await this.shard.connect();\n message.reply(null);\n break;\n case MainStrategyOps.DESTROY:\n await this.shard.destroy(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.SEND:\n await this.shard.send(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.RECONNECT:\n await this.shard.destroy(content.data);\n message.reply(null);\n break;\n case MainStrategyOps.STATUS:\n message.reply(this.shard.status);\n break;\n }\n }\n}\n","import EventEmitter from 'node:events';\nimport { Serializable } from 'node:child_process';\nimport { randomUUID } from 'crypto';\nimport { Indomitable } from '../Indomitable.js';\nimport {\n InternalAbortSignal,\n InternalPromise,\n IpcErrorData,\n LibraryEvents,\n Message,\n RawIpcMessage,\n RawIpcMessageType,\n SavePromiseOptions,\n Transportable\n} from '../Util.js';\n\n/**\n * Base class where primary and worker ipc inherits\n */\nexport abstract class BaseIpc {\n public readonly manager: Indomitable|EventEmitter;\n protected readonly promises: Map<string, InternalPromise>;\n protected constructor(manager: Indomitable|EventEmitter) {\n this.manager = manager;\n this.promises = new Map();\n }\n\n /**\n * Number of promises pending to be resolved\n */\n public get pendingPromises(): number {\n return this.promises.size;\n }\n\n /**\n * Rejects all the pending promises\n */\n public flushPromises(reason: string): void {\n const error = new Error(reason);\n for (const promise of this.promises.values()) {\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n promise.reject(error);\n }\n this.promises.clear();\n }\n\n /**\n * Raw send method without abort controller handling\n * @param transportable Data to send\n */\n public send(transportable: Transportable): Promise<unknown|undefined> {\n return new Promise((resolve, reject) => {\n if (!this.available()) {\n this.manager.emit(LibraryEvents.DEBUG, 'IPC tried to send a message, but the ipc communication is not yet ready');\n return resolve(undefined);\n }\n const repliable = transportable.repliable || false;\n const id = repliable ? randomUUID() : null;\n const data: RawIpcMessage = {\n id,\n content: transportable.content,\n internal: true,\n type: RawIpcMessageType.MESSAGE\n };\n this.sendData(data);\n if (!id) return resolve(undefined);\n this.waitForPromise({ id, resolve, reject, signal: transportable.signal });\n });\n }\n\n /**\n * Taps into message event of worker or primary process to handle ipc communication\n * @internal\n */\n public async handleRawResponse(data: Serializable, errorCallback: (error: unknown) => any): Promise<boolean|void> {\n try {\n this.manager.emit(LibraryEvents.RAW, data);\n if (!(data as any).internal) return;\n switch((data as RawIpcMessage).type) {\n case RawIpcMessageType.MESSAGE:\n return await this.handleUnparsedMessage(data as RawIpcMessage);\n case RawIpcMessageType.RESPONSE:\n case RawIpcMessageType.ERROR:\n return this.handlePromise(data as RawIpcMessage);\n }\n } catch (error: unknown) {\n errorCallback(error);\n }\n }\n\n protected waitForPromise(options: SavePromiseOptions): void {\n let controller: InternalAbortSignal|undefined;\n if (options.signal) {\n const listener = () => {\n this.promises.delete(options.id);\n options.reject(new Error('This operation is aborted'));\n };\n controller = {\n listener,\n signal: options.signal\n };\n controller.signal.addEventListener('abort', listener);\n }\n this.promises.set(options.id, { resolve: options.resolve, reject: options.reject, controller } as InternalPromise);\n }\n\n private handlePromise(data: RawIpcMessage): void {\n const id = data.id as string;\n const promise = this.promises.get(id);\n if (!promise) return;\n this.promises.delete(id);\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n if (data.type === RawIpcMessageType.ERROR) {\n const content = data.content as IpcErrorData;\n const error = new Error(content.reason);\n error.stack = content.stack;\n error.name = content.name;\n promise.reject(error);\n return;\n }\n promise.resolve(data.content);\n }\n\n private async handleUnparsedMessage(data: RawIpcMessage): Promise<void> {\n const reply = (content: any) => {\n if (!data.id) return;\n const response: RawIpcMessage = {\n id: data.id,\n content,\n internal: true,\n type: RawIpcMessageType.RESPONSE\n };\n this.sendData(response);\n };\n const message: Message = {\n repliable: !!data.id,\n content: data.content,\n reply\n };\n if (!data.content.internal)\n return this.emitMessage(message);\n try {\n await this.handleMessage(message);\n } catch (error: any) {\n if (!message.repliable) return;\n const response: RawIpcMessage = {\n id: data.id,\n content: {\n name: error.name,\n reason: error.reason,\n stack: error.stack\n },\n internal: true,\n type: RawIpcMessageType.ERROR\n };\n this.sendData(response);\n }\n }\n\n protected emitMessage(message: Message): void {\n this.manager.emit(LibraryEvents.MESSAGE, message);\n }\n\n protected abstract available(): boolean;\n protected abstract sendData(data: RawIpcMessage): void;\n protected abstract handleMessage(message: Message): Promise<void>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,aAAqD;AACrD,IAAAC,yBAA2B;;;ACD3B,gBAAqG;;;ACArG,wBAAsC;AAM/B,IAAM,iBAAiB;AAAA,EAC1B,WAAW,OAAO,QAAQ,IAAI,uBAAuB,CAAC;AAAA,EACtD,cAAc,OAAO,QAAQ,IAAI,6BAA6B,CAAC;AAAA,EAC/D,WAAW,QAAQ,IAAI,sBAAsB,IAAI,MAAM,GAAG,EAAE,IAAI,MAAM;AAAA,EACtE,YAAY,OAAO,QAAQ,IAAI,4BAA4B,CAAC;AAChE;;;ADPO,IAAM,8BAAN,MAAsE;AAAA,EAGzE,YAAYC,MAA2BC,UAAkC;AACrE,SAAK,MAAMD;AACX,SAAK,UAAUC;AAAA,EACnB;AAAA,EAEA,MAAa,oBAAoB,SAA8C;AAC3E,UAAM,UAA8B;AAAA,MAChC;AAAA,MACA,OAAO,+BAAqB;AAAA,MAC5B,MAAM,EAAE,QAAQ;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,IACd;AACA,WAAO,MAAM,KAAK,IAAI,KAAK,EAAE,SAAS,WAAW,KAAK,CAAC;AAAA,EAC3D;AAAA,EAEA,MAAa,kBAAkB,SAAiB,aAAgD;AAC5F,UAAM,UAA8B;AAAA,MAChC;AAAA,MACA,OAAO,+BAAqB;AAAA,MAC5B,MAAM,EAAE,SAAS,YAAY;AAAA,MAC7B;AAAA,MACA,UAAU;AAAA,IACd;AACA,UAAM,KAAK,IAAI,KAAK,EAAE,QAAQ,CAAC;AAAA,EACnC;AAAA,EAEA,MAAa,gBAAgB,SAAiB,QAAoC;AAC9E,UAAM,UAA8B;AAAA,MAChC;AAAA,MACA,OAAO,+BAAqB;AAAA,MAC5B,MAAM,EAAE,QAAQ;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,IACd;AACA,UAAM,WAAW,MAAM,KAAK,cAAc,OAAO;AACjD,QAAI;AACA,aAAO,iBAAiB,SAAS,QAAQ;AACzC,YAAM,KAAK,IAAI,KAAK,EAAE,SAAS,WAAW,KAAK,CAAC;AAAA,IACpD,UAAE;AACE,aAAO,oBAAoB,SAAS,QAAQ;AAAA,IAChD;AAAA,EACJ;AAAA,EAEQ,cAAc,SAAuB;AACzC,UAAM,UAA8B;AAAA,MAChC;AAAA,MACA,OAAO,+BAAqB;AAAA,MAC5B,MAAM,EAAE,QAAQ;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,IACd;AACA,SAAK,IACA,KAAK,EAAE,SAAS,WAAW,MAAM,CAAC,EAClC,MAAM,MAAM,IAAI;AAAA,EACzB;AACJ;;;AE/DA,yBAAyB;AACzB,4BAA2B;;;ACC3B,oBAA2B;AAiBpB,IAAe,UAAf,MAAuB;AAAA,EAGhB,YAAY,SAAmC;AACrD,SAAK,UAAU;AACf,SAAK,WAAW,oBAAI,IAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,kBAA0B;AACjC,WAAO,KAAK,SAAS;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKO,cAAc,QAAsB;AACvC,UAAM,QAAQ,IAAI,MAAM,MAAM;AAC9B,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC1C,UAAI,QAAQ,YAAY;AACpB,gBAAQ,WAAW,OAAO,oBAAoB,SAAS,QAAQ,WAAW,QAAQ;AAAA,MACtF;AACA,cAAQ,OAAO,KAAK;AAAA,IACxB;AACA,SAAK,SAAS,MAAM;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,KAAK,eAA0D;AAClE,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAI,CAAC,KAAK,UAAU,GAAG;AACnB,aAAK,QAAQ,0BAA0B,yEAAyE;AAChH,eAAO,QAAQ,MAAS;AAAA,MAC5B;AACA,YAAM,YAAY,cAAc,aAAa;AAC7C,YAAM,KAAK,gBAAY,0BAAW,IAAI;AACtC,YAAM,OAAsB;AAAA,QACxB;AAAA,QACA,SAAS,cAAc;AAAA,QACvB,UAAU;AAAA,QACV;AAAA,MACJ;AACA,WAAK,SAAS,IAAI;AAClB,UAAI,CAAC;AAAI,eAAO,QAAQ,MAAS;AACjC,WAAK,eAAe,EAAE,IAAI,SAAS,QAAQ,QAAQ,cAAc,OAAO,CAAC;AAAA,IAC7E,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,kBAAkB,MAAoB,eAA+D;AAC9G,QAAI;AACA,WAAK,QAAQ,sBAAwB,IAAI;AACzC,UAAI,CAAE,KAAa;AAAU;AAC7B,cAAQ,KAAuB,MAAM;AAAA,QACjC;AACI,iBAAO,MAAM,KAAK,sBAAsB,IAAqB;AAAA,QACjE;AAAA,QACA;AACI,iBAAO,KAAK,cAAc,IAAqB;AAAA,MACvD;AAAA,IACJ,SAAS,OAAgB;AACrB,oBAAc,KAAK;AAAA,IACvB;AAAA,EACJ;AAAA,EAEU,eAAeC,UAAmC;AACxD,QAAI;AACJ,QAAIA,SAAQ,QAAQ;AAChB,YAAM,WAAW,MAAM;AACnB,aAAK,SAAS,OAAOA,SAAQ,EAAE;AAC/B,QAAAA,SAAQ,OAAO,IAAI,MAAM,2BAA2B,CAAC;AAAA,MACzD;AACA,mBAAa;AAAA,QACT;AAAA,QACA,QAAQA,SAAQ;AAAA,MACpB;AACA,iBAAW,OAAO,iBAAiB,SAAS,QAAQ;AAAA,IACxD;AACA,SAAK,SAAS,IAAIA,SAAQ,IAAI,EAAE,SAASA,SAAQ,SAAS,QAAQA,SAAQ,QAAQ,WAAW,CAAoB;AAAA,EACrH;AAAA,EAEQ,cAAc,MAA2B;AAC7C,UAAM,KAAK,KAAK;AAChB,UAAM,UAAU,KAAK,SAAS,IAAI,EAAE;AACpC,QAAI,CAAC;AAAS;AACd,SAAK,SAAS,OAAO,EAAE;AACvB,QAAI,QAAQ,YAAY;AACpB,cAAQ,WAAW,OAAO,oBAAoB,SAAS,QAAQ,WAAW,QAAQ;AAAA,IACtF;AACA,QAAI,KAAK,8BAAkC;AACvC,YAAM,UAAU,KAAK;AACrB,YAAM,QAAQ,IAAI,MAAM,QAAQ,MAAM;AACtC,YAAM,QAAQ,QAAQ;AACtB,YAAM,OAAO,QAAQ;AACrB,cAAQ,OAAO,KAAK;AACpB;AAAA,IACJ;AACA,YAAQ,QAAQ,KAAK,OAAO;AAAA,EAChC;AAAA,EAEA,MAAc,sBAAsB,MAAoC;AACpE,UAAM,QAAQ,CAAC,YAAiB;AAC5B,UAAI,CAAC,KAAK;AAAI;AACd,YAAM,WAA0B;AAAA,QAC5B,IAAI,KAAK;AAAA,QACT;AAAA,QACA,UAAU;AAAA,QACV;AAAA,MACJ;AACA,WAAK,SAAS,QAAQ;AAAA,IAC1B;AACA,UAAM,UAAmB;AAAA,MACrB,WAAW,CAAC,CAAC,KAAK;AAAA,MAClB,SAAS,KAAK;AAAA,MACd;AAAA,IACJ;AACA,QAAI,CAAC,KAAK,QAAQ;AACd,aAAO,KAAK,YAAY,OAAO;AACnC,QAAI;AACA,YAAM,KAAK,cAAc,OAAO;AAAA,IACpC,SAAS,OAAY;AACjB,UAAI,CAAC,QAAQ;AAAW;AACxB,YAAM,WAA0B;AAAA,QAC5B,IAAI,KAAK;AAAA,QACT,SAAS;AAAA,UACL,MAAM,MAAM;AAAA,UACZ,QAAQ,MAAM;AAAA,UACd,OAAO,MAAM;AAAA,QACjB;AAAA,QACA,UAAU;AAAA,QACV;AAAA,MACJ;AACA,WAAK,SAAS,QAAQ;AAAA,IAC1B;AAAA,EACJ;AAAA,EAEU,YAAY,SAAwB;AAC1C,SAAK,QAAQ,8BAA4B,OAAO;AAAA,EACpD;AAKJ;;;AD/JO,IAAM,uBAAN,cAAmC,QAAQ;AAAA,EAE9C,cAAc;AACV,UAAM,IAAI,mBAAAC,QAAa,CAAC;AACxB,qCAAY,GAAG,WAAW,aAAW,KAAK,kBAAkB,SAAS,MAAM,IAAI,CAAC;AAAA,EACpF;AAAA,EAEO,MAAMC,QAA6B;AACtC,QAAI,CAAC,KAAK;AAAO,WAAK,QAAQA;AAAA,EAClC;AAAA,EAEU,YAAqB;AAC3B,WAAO,CAAC,CAAC;AAAA,EACb;AAAA,EAEU,SAAS,MAAqB;AACpC,WAAO,iCAAY,YAAY,IAAI;AAAA,EACvC;AAAA,EAEA,MAAgB,cAAc,SAAiC;AAC3D,UAAM,UAAU,QAAQ;AACxB,QAAI,CAAC,KAAK;AAAO,YAAM,IAAI,MAAM,6BAA8B;AAC/D,YAAO,QAAQ,IAAI;AAAA,MACf;AACI,cAAM,KAAK,MAAM,QAAQ;AACzB,gBAAQ,MAAM,IAAI;AAClB;AAAA,MACJ;AACI,cAAM,KAAK,MAAM,QAAQ,QAAQ,QAAQ,CAAC,CAAC;AAC3C,gBAAQ,MAAM,IAAI;AAClB;AAAA,MACJ;AACI,cAAM,KAAK,MAAM,KAAK,QAAQ,QAAQ,CAAC,CAAC;AACxC,gBAAQ,MAAM,IAAI;AAClB;AAAA,MACJ;AACI,cAAM,KAAK,MAAM,QAAQ,QAAQ,IAAI;AACrC,gBAAQ,MAAM,IAAI;AAClB;AAAA,MACJ;AACI,gBAAQ,MAAM,KAAK,MAAM,MAAM;AAC/B;AAAA,IACR;AAAA,EACJ;AACJ;;;AHhDA,IAAM,UAAU;AAEhB,IAAM,MAAM,IAAI,qBAAqB;AACrC,IAAM,WAAW,IAAI,4BAA4B,KAAK,OAAO;AAC7D,IAAM,QAAQ,IAAI,0BAAe,UAAU,QAAQ,OAAO;AAE1D,IAAI,MAAM,KAAK;AAEf,WAAW,SAAS,OAAO,OAAO,+BAAoB,GAAG;AAErD,QAAM,GAAG,OAAO,UAAQ;AACpB,UAAM,UAA8B;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,MAAM;AAAA,MACf,UAAU;AAAA,IACd;AACA,QAAI,KAAK,EAAE,QAAQ,CAAC,EACf,MAAM,MAAM,IAAI;AAAA,EACzB,CAAC;AACL;","names":["import_ws","import_worker_threads","ipc","options","options","EventEmitter","shard"]}

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../src/strategy/Thread.ts","../../../src/strategy/IndomitableFetchingStrategy.ts","../../../src/Util.ts","../../../src/ipc/ThreadStrategyWorker.ts","../../../src/ipc/BaseIpc.ts"],"sourcesContent":["import { WebSocketShard, WebSocketShardEvents } from '@discordjs/ws';\nimport { workerData } from 'worker_threads';\nimport { WorkerData } from './IndomitableStrategy';\nimport { IndomitableFetchingStrategy } from './IndomitableFetchingStrategy';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nconst options = workerData as WorkerData;\n\nconst ipc = new ThreadStrategyWorker();\nconst strategy = new IndomitableFetchingStrategy(ipc, options);\nconst shard = new WebSocketShard(strategy, options.shardId);\n\nipc.build(shard);\n\nfor (const event of Object.values(WebSocketShardEvents)) {\n // @ts-expect-error: unknown fix\n shard.on(event, data => {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.SHARD_EVENT,\n event,\n data,\n shardId: shard.id,\n internal: true\n };\n ipc.send({ content })\n .catch(() => null);\n });\n}\n\n\n\n\n\n","import { FetchingStrategyOptions, IContextFetchingStrategy, SessionInfo, WebSocketShardEvents } from '@discordjs/ws';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nexport class IndomitableFetchingStrategy implements IContextFetchingStrategy {\n private readonly ipc: ThreadStrategyWorker;\n public readonly options: FetchingStrategyOptions;\n constructor(ipc: ThreadStrategyWorker, options: FetchingStrategyOptions) {\n this.ipc = ipc;\n this.options = options;\n }\n\n public async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.RETRIEVE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n return await this.ipc.send({ content, repliable: true }) as SessionInfo;\n }\n\n public async updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.UPDATE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId, sessionInfo },\n shardId: shardId,\n internal: true\n };\n await this.ipc.send({ content });\n }\n\n public async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.REQUEST_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n const listener = () => this.abortIdentify(shardId);\n try {\n signal.addEventListener('abort', listener);\n await this.ipc.send({ content, repliable: true });\n } finally {\n signal.removeEventListener('abort', listener);\n }\n }\n\n private abortIdentify(shardId: number): void {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.CANCEL_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n this.ipc\n .send({ content, repliable: false })\n .catch(() => null);\n }\n}\n","import Https, { RequestOptions } from 'node:https';\nimport { WebSocketShardEvents } from '@discordjs/ws';\n\n/**\n * Hoisted Environmental Variable for ease of fetching\n */\nexport const EnvProcessData = {\n clusterId: Number(process.env.INDOMITABLE_CLUSTER || 0),\n clusterCount: Number(process.env.INDOMITABLE_CLUSTER_TOTAL || 0),\n shardIds: (process.env.INDOMITABLE_SHARDS || '').split(' ').map(Number),\n shardCount: Number(process.env.INDOMITABLE_SHARDS_TOTAL || 0)\n};\n\n/**\n * Internal operation codes for the cluster -> thread\n */\nexport enum MainStrategyOps {\n CONNECT = 'connect',\n DESTROY = 'destroy',\n SEND = 'send',\n STATUS = 'status',\n RECONNECT = 'reconnect'\n}\n\n/**\n * Internal operation codes for the thread <- cluster\n */\nexport enum ThreadStrategyOps {\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SHARD_EVENT = 'shardEvent',\n RETRIEVE_SESSION = 'retrieveSession',\n UPDATE_SESSION = 'updateSession'\n}\n\n/**\n * Internal operation codes\n */\nexport enum InternalOps {\n EVAL = 'eval',\n RESTART = 'restart',\n RESTART_ALL = 'restartAll',\n DESTROY_CLIENT = 'destroyClient',\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SESSION_INFO = 'sessionInfo',\n PING = 'ping'\n}\n\n/**\n * Events for internal use\n */\nexport enum ClientEvents {\n READY = 'ready',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n ERROR = 'ERROR'\n}\n\n/**\n * Events emitted by Indomitable\n */\nexport enum LibraryEvents {\n DEBUG = 'debug',\n MESSAGE = 'message',\n ERROR = 'error',\n WORKER_FORK = 'workerFork',\n WORKER_READY = 'workerReady',\n WORKER_EXIT = 'workerExit',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n CLIENT_READY = 'clientReady',\n RAW = 'raw'\n}\n\n/**\n * Type for raw ipc message\n */\nexport enum RawIpcMessageType {\n MESSAGE = 'message',\n RESPONSE = 'response',\n ERROR = 'error'\n}\n\n/**\n * Type for raw ipc messages of cluster -> thread\n */\nexport interface MainStrategyData {\n op: MainStrategyOps,\n data: any,\n internal: true\n}\n\n/**\n * Type for raw ipc messages of cluster <- thread\n */\nexport interface ThreadStrategyData {\n op: ThreadStrategyOps,\n event: WebSocketShardEvents,\n data: any,\n shardId: number,\n internal: true\n}\n\n/**\n * Data structure representing an internal event\n */\nexport interface InternalOpsData {\n op: InternalOps,\n data: any,\n internal: true\n}\n\n/**\n * Data structure representing an internal discord.js event\n */\nexport interface ClientEventData {\n op: ClientEvents,\n data: any,\n internal: true,\n}\n\n/**\n * Data structure representing an internal error\n */\nexport interface IpcErrorData {\n name: string;\n reason: string;\n stack: string;\n}\n\n/**\n * Data structure representing IPC data\n */\nexport interface Transportable {\n content: any;\n repliable?: boolean;\n signal?: AbortSignal\n}\n\n/**\n * Data structure representing an internal abort data\n */\nexport interface InternalAbortSignal {\n listener: () => void,\n signal: AbortSignal\n}\n\nexport interface SavePromiseOptions {\n id: string;\n resolve: (data: unknown) => void;\n reject: (reason: unknown) => void;\n signal?: AbortSignal | undefined;\n}\n\n/**\n * Data structure representing a generated abort controller instance\n */\nexport interface AbortableData {\n controller: AbortController;\n timeout: NodeJS.Timeout;\n}\n\n/**\n * Internal promise data tracking\n */\nexport interface InternalPromise {\n resolve: Function;\n reject: Function;\n controller?: InternalAbortSignal;\n}\n\n/**\n * Data structure representing internal IPC data\n */\nexport interface RawIpcMessage {\n id: string|null;\n content: any;\n internal: true;\n type: RawIpcMessageType\n}\n\n/**\n * Data structure representing an IPC message\n */\nexport interface Message {\n reply: (data: any) => void;\n content: any;\n repliable: boolean;\n}\n\n/**\n * Data structure representing a Discord session\n */\nexport interface SessionObject {\n\turl: string;\n\tshards: number;\n\tsession_start_limit: {\n\t\ttotal: number;\n\t\tremaining: number;\n\t\treset_after: number;\n max_concurrency: number;\n\t};\n}\n\n/**\n * Wrapper function for fetching data using HTTP\n * @param url URL of resource to fetch\n * @param options RequestOptions to modify behavior\n * @returns A promise containing data fetched, or an error\n */\nexport function Fetch(url: string|URL, options: RequestOptions): Promise<any> {\n return new Promise((resolve, reject) => {\n const request = Https.request(url, options, response => {\n const chunks: any[] = [];\n response.on('data', chunk => chunks.push(chunk));\n response.on('error', reject);\n response.on('end', () => {\n const code = response.statusCode ?? 500;\n const body = chunks.join('');\n if (code >= 200 && code <= 299)\n resolve(body);\n else\n reject(new Error(`Response received is not ok, Status Code: ${response.statusCode}, body: ${body}`));\n });\n });\n request.on('error', reject);\n request.end();\n });\n}\n\n/**\n * Fetch sessions from discord\n * @param token Bot token\n * @returns A promise containing a session object\n */\nexport async function FetchSessions(token: string): Promise<SessionObject> {\n const url = new URL('https://discord.com/api/v10/gateway/bot');\n const data = await Fetch(url, {\n method: 'GET',\n headers: { authorization: `Bot ${token}` }\n });\n return JSON.parse(data);\n}\n\n/**\n * Modify an array to contain the specified amount of chunks\n * @param original An array of data\n * @param chunks The amount of chunks to transform into\n * @returns A modified array\n */\nexport function Chunk(original: any[], chunks: number): any[] {\n const array = [];\n for (let i = 0; i < original.length; i += chunks)\n array.push(original.slice(i , i + chunks));\n return array;\n}\n\n/**\n * Wait for a specific amount of time (timeout)\n * @param ms Time to wait in milliseconds\n * @returns A promise that resolves in x seconds\n */\nexport function Delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(() => resolve(), ms));\n}\n\n/**\n * Creates an abortable request with controller and timeout\n * @param delay Time before an abort error throws\n * @returns An abortable data with controller and timeout\n */\nexport function MakeAbortableRequest(delay: number): AbortableData {\n const controller = new AbortController();\n const seconds = Math.round(delay / 1000);\n const timeout = setTimeout(\n () => controller.abort(new Error(`The request has been aborted in ${seconds} second(s)`)),\n delay\n );\n return { controller, timeout };\n}\n","import EventEmitter from 'node:events';\nimport { parentPort } from 'worker_threads';\nimport { WebSocketShard } from '@discordjs/ws';\nimport { BaseIpc } from './BaseIpc';\nimport {\n MainStrategyData,\n MainStrategyOps,\n Message,\n RawIpcMessage,\n} from '../Util';\n\nexport class ThreadStrategyWorker extends BaseIpc {\n private shard: WebSocketShard|undefined;\n constructor() {\n super(new EventEmitter());\n parentPort!.on('message', message => this.handleRawResponse(message, () => null));\n }\n\n public build(shard: WebSocketShard): void {\n if (!this.shard) this.shard = shard;\n }\n\n protected available(): boolean {\n return !!parentPort;\n }\n\n protected sendData(data: RawIpcMessage) {\n return parentPort!.postMessage(data);\n }\n\n protected async handleMessage(message: Message): Promise<void> {\n const content = message.content as MainStrategyData;\n if (!this.shard) throw new Error('Shard isn\\'t initialized yet');\n switch(content.op) {\n case MainStrategyOps.CONNECT:\n await this.shard.connect();\n message.reply(null);\n break;\n case MainStrategyOps.DESTROY:\n await this.shard.destroy(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.SEND:\n await this.shard.send(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.RECONNECT:\n await this.shard.destroy(content.data);\n message.reply(null);\n break;\n case MainStrategyOps.STATUS:\n message.reply(this.shard.status);\n break;\n }\n }\n}\n","import EventEmitter from 'node:events';\nimport { Serializable } from 'node:child_process';\nimport { randomUUID } from 'crypto';\nimport { Indomitable } from '../Indomitable.js';\nimport {\n InternalAbortSignal,\n InternalPromise,\n IpcErrorData,\n LibraryEvents,\n Message,\n RawIpcMessage,\n RawIpcMessageType,\n SavePromiseOptions,\n Transportable\n} from '../Util.js';\n\n/**\n * Base class where primary and worker ipc inherits\n */\nexport abstract class BaseIpc {\n public readonly manager: Indomitable|EventEmitter;\n protected readonly promises: Map<string, InternalPromise>;\n protected constructor(manager: Indomitable|EventEmitter) {\n this.manager = manager;\n this.promises = new Map();\n }\n\n /**\n * Number of promises pending to be resolved\n */\n public get pendingPromises(): number {\n return this.promises.size;\n }\n\n /**\n * Rejects all the pending promises\n */\n public flushPromises(reason: string): void {\n const error = new Error(reason);\n for (const promise of this.promises.values()) {\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n promise.reject(error);\n }\n this.promises.clear();\n }\n\n /**\n * Raw send method without abort controller handling\n * @param transportable Data to send\n */\n public send(transportable: Transportable): Promise<unknown|undefined> {\n return new Promise((resolve, reject) => {\n if (!this.available()) {\n this.manager.emit(LibraryEvents.DEBUG, 'IPC tried to send a message, but the ipc communication is not yet ready');\n return resolve(undefined);\n }\n const repliable = transportable.repliable || false;\n const id = repliable ? randomUUID() : null;\n const data: RawIpcMessage = {\n id,\n content: transportable.content,\n internal: true,\n type: RawIpcMessageType.MESSAGE\n };\n this.sendData(data);\n if (!id) return resolve(undefined);\n this.waitForPromise({ id, resolve, reject, signal: transportable.signal });\n });\n }\n\n /**\n * Taps into message event of worker or primary process to handle ipc communication\n * @internal\n */\n public async handleRawResponse(data: Serializable, errorCallback: (error: unknown) => any): Promise<boolean|void> {\n try {\n this.manager.emit(LibraryEvents.RAW, data);\n if (!(data as any).internal) return;\n switch((data as RawIpcMessage).type) {\n case RawIpcMessageType.MESSAGE:\n return await this.handleUnparsedMessage(data as RawIpcMessage);\n case RawIpcMessageType.RESPONSE:\n case RawIpcMessageType.ERROR:\n return this.handlePromise(data as RawIpcMessage);\n }\n } catch (error: unknown) {\n errorCallback(error);\n }\n }\n\n protected waitForPromise(options: SavePromiseOptions): void {\n let controller: InternalAbortSignal|undefined;\n if (options.signal) {\n const listener = () => {\n this.promises.delete(options.id);\n options.reject(new Error('This operation is aborted'));\n };\n controller = {\n listener,\n signal: options.signal\n };\n controller.signal.addEventListener('abort', listener);\n }\n this.promises.set(options.id, { resolve: options.resolve, reject: options.reject, controller } as InternalPromise);\n }\n\n private handlePromise(data: RawIpcMessage): void {\n const id = data.id as string;\n const promise = this.promises.get(id);\n if (!promise) return;\n this.promises.delete(id);\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n if (data.type === RawIpcMessageType.ERROR) {\n const content = data.content as IpcErrorData;\n const error = new Error(content.reason);\n error.stack = content.stack;\n error.name = content.name;\n promise.reject(error);\n return;\n }\n promise.resolve(data.content);\n }\n\n private async handleUnparsedMessage(data: RawIpcMessage): Promise<void> {\n const reply = (content: any) => {\n if (!data.id) return;\n const response: RawIpcMessage = {\n id: data.id,\n content,\n internal: true,\n type: RawIpcMessageType.RESPONSE\n };\n this.sendData(response);\n };\n const message: Message = {\n repliable: !!data.id,\n content: data.content,\n reply\n };\n if (!data.content.internal)\n return this.emitMessage(message);\n try {\n await this.handleMessage(message);\n } catch (error: any) {\n if (!message.repliable) return;\n const response: RawIpcMessage = {\n id: data.id,\n content: {\n name: error.name,\n reason: error.reason,\n stack: error.stack\n },\n internal: true,\n type: RawIpcMessageType.ERROR\n };\n this.sendData(response);\n }\n }\n\n protected emitMessage(message: Message): void {\n this.manager.emit(LibraryEvents.MESSAGE, message);\n }\n\n protected abstract available(): boolean;\n protected abstract sendData(data: RawIpcMessage): void;\n protected abstract handleMessage(message: Message): Promise<void>;\n}\n"],"mappings":"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","names":["WebSocketShardEvents","ipc","options","options","shard","WebSocketShardEvents"]}
{"version":3,"sources":["../../../src/strategy/Thread.ts","../../../src/strategy/IndomitableFetchingStrategy.ts","../../../src/Util.ts","../../../src/ipc/ThreadStrategyWorker.ts","../../../src/ipc/BaseIpc.ts"],"sourcesContent":["import { WebSocketShard, WebSocketShardEvents } from '@discordjs/ws';\nimport { workerData } from 'worker_threads';\nimport { WorkerData } from './IndomitableStrategy';\nimport { IndomitableFetchingStrategy } from './IndomitableFetchingStrategy';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nconst options = workerData as WorkerData;\n\nconst ipc = new ThreadStrategyWorker();\nconst strategy = new IndomitableFetchingStrategy(ipc, options);\nconst shard = new WebSocketShard(strategy, options.shardId);\n\nipc.build(shard);\n\nfor (const event of Object.values(WebSocketShardEvents)) {\n // @ts-expect-error: unknown fix\n shard.on(event, data => {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.SHARD_EVENT,\n event,\n data,\n shardId: shard.id,\n internal: true\n };\n ipc.send({ content })\n .catch(() => null);\n });\n}\n\n\n\n\n\n","import { FetchingStrategyOptions, IContextFetchingStrategy, SessionInfo, WebSocketShardEvents } from '@discordjs/ws';\nimport { ThreadStrategyWorker } from '../ipc/ThreadStrategyWorker';\nimport { ThreadStrategyData, ThreadStrategyOps } from '../Util';\n\nexport class IndomitableFetchingStrategy implements IContextFetchingStrategy {\n private readonly ipc: ThreadStrategyWorker;\n public readonly options: FetchingStrategyOptions;\n constructor(ipc: ThreadStrategyWorker, options: FetchingStrategyOptions) {\n this.ipc = ipc;\n this.options = options;\n }\n\n public async retrieveSessionInfo(shardId: number): Promise<SessionInfo | null> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.RETRIEVE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n return await this.ipc.send({ content, repliable: true }) as SessionInfo;\n }\n\n public async updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.UPDATE_SESSION,\n event: WebSocketShardEvents.Ready,\n data: { shardId, sessionInfo },\n shardId: shardId,\n internal: true\n };\n await this.ipc.send({ content });\n }\n\n public async waitForIdentify(shardId: number, signal: AbortSignal): Promise<void> {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.REQUEST_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n const listener = () => this.abortIdentify(shardId);\n try {\n signal.addEventListener('abort', listener);\n await this.ipc.send({ content, repliable: true });\n } finally {\n signal.removeEventListener('abort', listener);\n }\n }\n\n private abortIdentify(shardId: number): void {\n const content: ThreadStrategyData = {\n op: ThreadStrategyOps.CANCEL_IDENTIFY,\n event: WebSocketShardEvents.Ready,\n data: { shardId },\n shardId: shardId,\n internal: true\n };\n this.ipc\n .send({ content, repliable: false })\n .catch(() => null);\n }\n}\n","import Https, { RequestOptions } from 'node:https';\nimport { WebSocketShardEvents } from '@discordjs/ws';\n\n/**\n * Hoisted Environmental Variable for ease of fetching\n */\nexport const EnvProcessData = {\n clusterId: Number(process.env.INDOMITABLE_CLUSTER || 0),\n clusterCount: Number(process.env.INDOMITABLE_CLUSTER_TOTAL || 0),\n shardIds: (process.env.INDOMITABLE_SHARDS || '').split(' ').map(Number),\n shardCount: Number(process.env.INDOMITABLE_SHARDS_TOTAL || 0)\n};\n\n/**\n * Internal operation codes for the cluster -> thread\n */\nexport enum MainStrategyOps {\n CONNECT = 'connect',\n DESTROY = 'destroy',\n SEND = 'send',\n STATUS = 'status',\n RECONNECT = 'reconnect'\n}\n\n/**\n * Internal operation codes for the thread <- cluster\n */\nexport enum ThreadStrategyOps {\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SHARD_EVENT = 'shardEvent',\n RETRIEVE_SESSION = 'retrieveSession',\n UPDATE_SESSION = 'updateSession'\n}\n\n/**\n * Internal operation codes\n */\nexport enum InternalOps {\n EVAL = 'eval',\n RESTART = 'restart',\n RESTART_ALL = 'restartAll',\n DESTROY_CLIENT = 'destroyClient',\n REQUEST_IDENTIFY = 'requestIdentify',\n CANCEL_IDENTIFY = 'cancelIdentify',\n SESSION_INFO = 'sessionInfo',\n PING = 'ping'\n}\n\n/**\n * Events for internal use\n */\nexport enum ClientEvents {\n READY = 'ready',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n ERROR = 'ERROR'\n}\n\n/**\n * Events emitted by Indomitable\n */\nexport enum LibraryEvents {\n DEBUG = 'debug',\n MESSAGE = 'message',\n ERROR = 'error',\n WORKER_FORK = 'workerFork',\n WORKER_READY = 'workerReady',\n WORKER_EXIT = 'workerExit',\n SHARD_READY = 'shardReady',\n SHARD_RECONNECT = 'shardReconnect',\n SHARD_RESUME = 'shardResume',\n SHARD_DISCONNECT = 'shardDisconnect',\n CLIENT_READY = 'clientReady',\n RAW = 'raw'\n}\n\n/**\n * Type for raw ipc message\n */\nexport enum RawIpcMessageType {\n MESSAGE = 'message',\n RESPONSE = 'response',\n ERROR = 'error'\n}\n\n/**\n * Type for raw ipc messages of cluster -> thread\n */\nexport interface MainStrategyData {\n op: MainStrategyOps,\n data: any,\n internal: true\n}\n\n/**\n * Type for raw ipc messages of cluster <- thread\n */\nexport interface ThreadStrategyData {\n op: ThreadStrategyOps,\n event: WebSocketShardEvents,\n data: any,\n shardId: number,\n internal: true\n}\n\n/**\n * Data structure representing an internal event\n */\nexport interface InternalOpsData {\n op: InternalOps,\n data: any,\n internal: true\n}\n\n/**\n * Data structure representing an internal discord.js event\n */\nexport interface ClientEventData {\n op: ClientEvents,\n data: any,\n internal: true,\n}\n\n/**\n * Data structure representing an internal error\n */\nexport interface IpcErrorData {\n name: string;\n reason: string;\n stack: string;\n}\n\n/**\n * Data structure representing IPC data\n */\nexport interface Transportable {\n content: any;\n repliable?: boolean;\n signal?: AbortSignal\n}\n\n/**\n * Data structure representing an internal abort data\n */\nexport interface InternalAbortSignal {\n listener: () => void,\n signal: AbortSignal\n}\n\nexport interface SavePromiseOptions {\n id: string;\n resolve: (data: unknown) => void;\n reject: (reason: unknown) => void;\n signal?: AbortSignal | undefined;\n}\n\n/**\n * Data structure representing a generated abort controller instance\n */\nexport interface AbortableData {\n controller: AbortController;\n timeout: NodeJS.Timeout;\n}\n\n/**\n * Internal promise data tracking\n */\nexport interface InternalPromise {\n resolve: Function;\n reject: Function;\n controller?: InternalAbortSignal;\n}\n\n/**\n * Data structure representing internal IPC data\n */\nexport interface RawIpcMessage {\n id: string|null;\n content: any;\n internal: true;\n type: RawIpcMessageType\n}\n\n/**\n * Data structure representing an IPC message\n */\nexport interface Message {\n reply: (data: any) => void;\n content: any;\n repliable: boolean;\n}\n\n/**\n * Data structure representing a Discord session\n */\nexport interface SessionObject {\n\turl: string;\n\tshards: number;\n\tsession_start_limit: {\n\t\ttotal: number;\n\t\tremaining: number;\n\t\treset_after: number;\n max_concurrency: number;\n\t};\n}\n\n/**\n * Wrapper function for fetching data using HTTP\n * @param url URL of resource to fetch\n * @param options RequestOptions to modify behavior\n * @returns A promise containing data fetched, or an error\n */\nexport function Fetch(url: string|URL, options: RequestOptions): Promise<any> {\n return new Promise((resolve, reject) => {\n const request = Https.request(url, options, response => {\n const chunks: any[] = [];\n response.on('data', chunk => chunks.push(chunk));\n response.on('error', reject);\n response.on('end', () => {\n const code = response.statusCode ?? 500;\n const body = chunks.join('');\n if (code >= 200 && code <= 299)\n resolve(body);\n else\n reject(new Error(`Response received is not ok, Status Code: ${response.statusCode}, body: ${body}`));\n });\n });\n request.on('error', reject);\n request.end();\n });\n}\n\n/**\n * Fetch sessions from discord\n * @param token Bot token\n * @returns A promise containing a session object\n */\nexport async function FetchSessions(token: string): Promise<SessionObject> {\n const url = new URL('https://discord.com/api/v10/gateway/bot');\n const data = await Fetch(url, {\n method: 'GET',\n headers: { authorization: `Bot ${token}` }\n });\n return JSON.parse(data);\n}\n\n/**\n * Modify an array to contain the specified amount of chunks\n * @param original An array of data\n * @param chunks The amount of chunks to transform into\n * @returns A modified array\n */\nexport function Chunk(original: any[], chunks: number): any[] {\n const array = [];\n for (let i = 0; i < original.length; i += chunks)\n array.push(original.slice(i , i + chunks));\n return array;\n}\n\n/**\n * Wait for a specific amount of time (timeout)\n * @param ms Time to wait in milliseconds\n * @returns A promise that resolves in x seconds\n */\nexport function Delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(() => resolve(), ms));\n}\n\n/**\n * Creates an abortable request with controller and timeout\n * @param delay Time before an abort error throws\n * @returns An abortable data with controller and timeout\n */\nexport function MakeAbortableRequest(delay: number): AbortableData {\n const controller = new AbortController();\n const seconds = Math.round(delay / 1000);\n const timeout = setTimeout(\n () => controller.abort(new Error(`The request has been aborted in ${seconds} second(s)`)),\n delay\n );\n return { controller, timeout };\n}\n","import EventEmitter from 'node:events';\nimport { parentPort } from 'worker_threads';\nimport { WebSocketShard } from '@discordjs/ws';\nimport { BaseIpc } from './BaseIpc';\nimport {\n MainStrategyData,\n MainStrategyOps,\n Message,\n RawIpcMessage,\n} from '../Util';\n\nexport class ThreadStrategyWorker extends BaseIpc {\n private shard: WebSocketShard|undefined;\n constructor() {\n super(new EventEmitter());\n parentPort!.on('message', message => this.handleRawResponse(message, () => null));\n }\n\n public build(shard: WebSocketShard): void {\n if (!this.shard) this.shard = shard;\n }\n\n protected available(): boolean {\n return !!parentPort;\n }\n\n protected sendData(data: RawIpcMessage) {\n return parentPort!.postMessage(data);\n }\n\n protected async handleMessage(message: Message): Promise<void> {\n const content = message.content as MainStrategyData;\n if (!this.shard) throw new Error('Shard isn\\'t initialized yet');\n switch(content.op) {\n case MainStrategyOps.CONNECT:\n await this.shard.connect();\n message.reply(null);\n break;\n case MainStrategyOps.DESTROY:\n await this.shard.destroy(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.SEND:\n await this.shard.send(content.data || {});\n message.reply(null);\n break;\n case MainStrategyOps.RECONNECT:\n await this.shard.destroy(content.data);\n message.reply(null);\n break;\n case MainStrategyOps.STATUS:\n message.reply(this.shard.status);\n break;\n }\n }\n}\n","import EventEmitter from 'node:events';\nimport { Serializable } from 'node:child_process';\nimport { randomUUID } from 'crypto';\nimport { Indomitable } from '../Indomitable.js';\nimport {\n InternalAbortSignal,\n InternalPromise,\n IpcErrorData,\n LibraryEvents,\n Message,\n RawIpcMessage,\n RawIpcMessageType,\n SavePromiseOptions,\n Transportable\n} from '../Util.js';\n\n/**\n * Base class where primary and worker ipc inherits\n */\nexport abstract class BaseIpc {\n public readonly manager: Indomitable|EventEmitter;\n protected readonly promises: Map<string, InternalPromise>;\n protected constructor(manager: Indomitable|EventEmitter) {\n this.manager = manager;\n this.promises = new Map();\n }\n\n /**\n * Number of promises pending to be resolved\n */\n public get pendingPromises(): number {\n return this.promises.size;\n }\n\n /**\n * Rejects all the pending promises\n */\n public flushPromises(reason: string): void {\n const error = new Error(reason);\n for (const promise of this.promises.values()) {\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n promise.reject(error);\n }\n this.promises.clear();\n }\n\n /**\n * Raw send method without abort controller handling\n * @param transportable Data to send\n */\n public send(transportable: Transportable): Promise<unknown|undefined> {\n return new Promise((resolve, reject) => {\n if (!this.available()) {\n this.manager.emit(LibraryEvents.DEBUG, 'IPC tried to send a message, but the ipc communication is not yet ready');\n return resolve(undefined);\n }\n const repliable = transportable.repliable || false;\n const id = repliable ? randomUUID() : null;\n const data: RawIpcMessage = {\n id,\n content: transportable.content,\n internal: true,\n type: RawIpcMessageType.MESSAGE\n };\n this.sendData(data);\n if (!id) return resolve(undefined);\n this.waitForPromise({ id, resolve, reject, signal: transportable.signal });\n });\n }\n\n /**\n * Taps into message event of worker or primary process to handle ipc communication\n * @internal\n */\n public async handleRawResponse(data: Serializable, errorCallback: (error: unknown) => any): Promise<boolean|void> {\n try {\n this.manager.emit(LibraryEvents.RAW, data);\n if (!(data as any).internal) return;\n switch((data as RawIpcMessage).type) {\n case RawIpcMessageType.MESSAGE:\n return await this.handleUnparsedMessage(data as RawIpcMessage);\n case RawIpcMessageType.RESPONSE:\n case RawIpcMessageType.ERROR:\n return this.handlePromise(data as RawIpcMessage);\n }\n } catch (error: unknown) {\n errorCallback(error);\n }\n }\n\n protected waitForPromise(options: SavePromiseOptions): void {\n let controller: InternalAbortSignal|undefined;\n if (options.signal) {\n const listener = () => {\n this.promises.delete(options.id);\n options.reject(new Error('This operation is aborted'));\n };\n controller = {\n listener,\n signal: options.signal\n };\n controller.signal.addEventListener('abort', listener);\n }\n this.promises.set(options.id, { resolve: options.resolve, reject: options.reject, controller } as InternalPromise);\n }\n\n private handlePromise(data: RawIpcMessage): void {\n const id = data.id as string;\n const promise = this.promises.get(id);\n if (!promise) return;\n this.promises.delete(id);\n if (promise.controller) {\n promise.controller.signal.removeEventListener('abort', promise.controller.listener);\n }\n if (data.type === RawIpcMessageType.ERROR) {\n const content = data.content as IpcErrorData;\n const error = new Error(content.reason);\n error.stack = content.stack;\n error.name = content.name;\n promise.reject(error);\n return;\n }\n promise.resolve(data.content);\n }\n\n private async handleUnparsedMessage(data: RawIpcMessage): Promise<void> {\n const reply = (content: any) => {\n if (!data.id) return;\n const response: RawIpcMessage = {\n id: data.id,\n content,\n internal: true,\n type: RawIpcMessageType.RESPONSE\n };\n this.sendData(response);\n };\n const message: Message = {\n repliable: !!data.id,\n content: data.content,\n reply\n };\n if (!data.content.internal)\n return this.emitMessage(message);\n try {\n await this.handleMessage(message);\n } catch (error: any) {\n if (!message.repliable) return;\n const response: RawIpcMessage = {\n id: data.id,\n content: {\n name: error.name,\n reason: error.reason,\n stack: error.stack\n },\n internal: true,\n type: RawIpcMessageType.ERROR\n };\n this.sendData(response);\n }\n }\n\n protected emitMessage(message: Message): void {\n this.manager.emit(LibraryEvents.MESSAGE, message);\n }\n\n protected abstract available(): boolean;\n protected abstract sendData(data: RawIpcMessage): void;\n protected abstract handleMessage(message: Message): Promise<void>;\n}\n"],"mappings":"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","names":["WebSocketShardEvents","ipc","options","options","shard","WebSocketShardEvents"]}
{
"name": "indomitable",
"version": "4.0.3",
"description": "A lightweight (the actual ship is heavy though), performant, powerful & no dependency sharder for Discord.JS",
"version": "4.1.0",
"description": "A lightweight (the actual ship is heavy though), performant, and powerful sharder for Discord.JS",
"main": "dist/index.js",

@@ -47,16 +47,19 @@ "module": "dist/index.mjs",

"peerDependencies": {
"discord.js": ">=14.10.x",
"@discordjs/ws": ">=1.0.0"
"@discordjs/ws": ">=1.0.x",
"discord.js": ">=14.14.x"
},
"devDependencies": {
"@augu/eslint-config": "^4.0.1",
"@types/node": "^20.3.1",
"@types/ws": "^8.5.5",
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/parser": "^5.60.0",
"eslint": "^8.43.0",
"tsup": "^7.0.0",
"typedoc": "^0.24.8",
"typescript": "^5.1.3"
"@augu/eslint-config": "^5.0.0",
"@types/node": "^20.10.5",
"@types/ws": "^8.5.10",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
"eslint": "^8.56.0",
"tsup": "^8.0.1",
"typedoc": "^0.25.4",
"typescript": "^5.3.3"
},
"dependencies": {
"@discordjs/collection": "^2.0.0"
}
}
+144
-132
## Indomitable
> A lightweight (the actual ship is heavy though), performant, powerful & no dependency sharder for Discord.JS
> A lightweight (the actual ship is heavy though), performant, and powerful sharder for Discord.JS
<p align="center">

@@ -10,21 +11,19 @@ <img src="https://cdn.donmai.us/original/9b/cf/__indomitable_azur_lane_drawn_by_kincora__9bcf19b2f822ce75ea707e5047882d6a.png">

* Supports Discord.JS `v13` and `v14`
## Features
* Fast
- Fast
* Lightweight
- Lightweight
* Reliable
- Reliable
* ESM & CommonJS supported
- ESM & CommonJS supported
* Shard Concurrency Support
- Shard Concurrency Support
* Easy to use promised based IPC
- Easy to use promised based IPC
* No dependencies
- No dependencies
* Very cute (and lazy)
- Very cute (and lazy)

@@ -35,3 +34,3 @@ ## Used in prod by the ff:

> Kashima (https://kashima.saya.moe/)
> Kashima (https://kashima.saya.moe/)

@@ -42,7 +41,7 @@ > Or add your own!

* Stable
- Stable
> `npm install indomitable`
* Dev
- Dev

@@ -53,3 +52,3 @@ > `npm install https://github.com/Deivu/Indomitable.git#master`

🔗 https://deivu.github.io/Indomitable/index.html
🔗 https://indomitable.shipgirl.moe/

@@ -61,9 +60,12 @@ > Don't forget to read my "Notes" below!

> Basic usage
```js
const { Indomitable } = require('indomitable');
const { Client } = require('discord.js');
const token = 'your_token';
const { Indomitable } = require("indomitable");
const { Client } = require("discord.js");
const token = "your_token";
const manager = new Indomitable({ client: Client, token })
.on('error', console.error);
const manager = new Indomitable({ client: Client, token }).on(
"error",
console.error
);

@@ -74,26 +76,27 @@ manager.spawn();

> Basic usage with more Indomitable Options
```js
const { Indomitable } = require('indomitable');
const { Client } = require('discord.js');
const token = 'your_token';
const { Indomitable } = require("indomitable");
const { Client } = require("discord.js");
const token = "your_token";
const options = {
// Processes to run
clusterCount: 2,
// Websocket shards to run
shardCount: 8,
// Discord.JS options
clientOptions: {
intents: [1 << 0] // Bitwise for GUILD intent only
},
// Auto restart processes that have been killed
autoRestart: true, // This defaults to false by default unless you specify it
// Your Discord.JS client
client: Client,
// Your bot token
token
}
// Processes to run
clusterCount: 2,
// Websocket shards to run
shardCount: 8,
// Discord.js options
clientOptions: {
intents: [1 << 0], // Bitwise for GUILD intent only
},
// Auto restart processes that have been killed
// This defaults to false by default unless you specify it
autoRestart: true,
// Discord.js client
client: Client,
// Your bot token
token,
};
const manager = new Indomitable(options)
.on('error', console.error);
const manager = new Indomitable(options).on("error", console.error);

@@ -104,2 +107,3 @@ manager.spawn();

> Broadcasteval as one way to get data across shards
```js

@@ -110,81 +114,88 @@ // Saya's note:

client.shard
.broadcastEval(client => client.guilds.cache.size)
.then(console.log);
.broadcastEval((client) => client.guilds.cache.size)
.then(console.log);
```
> Example of a very basic ipc communication (non repliable)
```js
// Primary Process
indomitable.on('message', message => {
if (message.content.op === 'something') {
doSomething();
}
indomitable.on("message", (message) => {
if (message.content.op === "something") {
doSomething();
}
});
// ClientWorker Process (your client most likely)
client.shard.send({ content: { op: 'something' } })
.catch(console.error);
client.shard.send({ content: { op: "something" } }).catch(console.error);
```
> Example of a very basic ipc communication (repliable)
```js
// Primary Process
indomitable.on('message', message => {
if (message.content.op === 'something') {
if (!message.repliable) return; // check if the message is repliable just incase, though it won't error even it is not
const someValue = doSomething();
message.reply(someValue);
}
indomitable.on("message", (message) => {
if (message.content.op === "something") {
if (!message.repliable) return; // check if the message is repliable just incase, though it won't error even it is not
const someValue = doSomething();
message.reply(someValue);
}
});
// ClientWorker Process (your client most likely)
client.shard.send({ content: { op: 'something' }, repliable: true })
.then(console.log)
.catch(console.error);
client.shard
.send({ content: { op: "something" }, repliable: true })
.then(console.log)
.catch(console.error);
```
> You could also do it reversely (main process asking data from clusters instead of clusters asking main process)
```js
// Primary Process
// send to specific cluster
indomitable.send(0, { content: { op: 'nya' } })
.catch(console.error);
// send to specific cluster
indomitable.send(0, { content: { op: "nya" } }).catch(console.error);
// send to specific cluster with repliable
indomitable.send(0, { content: { op: 'something' }, repliable: true })
.then(console.log)
.catch(console.error);
indomitable
.send(0, { content: { op: "something" }, repliable: true })
.then(console.log)
.catch(console.error);
// broadcast to all clusters
indomitable.broadcast({ content: { op: 'meow' } })
.catch(console.error);
indomitable.broadcast({ content: { op: "meow" } }).catch(console.error);
// broadcast to all clusters with repliable is possible as well
indomitable.broadcast({ content: { op: 'meow' }, repliable: true })
.then(console.log)
.catch(console.error);
indomitable
.broadcast({ content: { op: "meow" }, repliable: true })
.then(console.log)
.catch(console.error);
// ClientWorker Process (your client most likely)
client.shard.on('message', message => {
if (message.content.op === 'something') {
if (!message.repliable) return;
const someValue = doSomething();
message.reply(someValue);
}
if (message.content.op === 'nya') {
doSomething();
}
if (message.content.op === 'meow') {
if (!message.repliable) return;
message.reply('nya');
}
})
client.shard.on("message", (message) => {
if (message.content.op === "something") {
if (!message.repliable) return;
const someValue = doSomething();
message.reply(someValue);
}
if (message.content.op === "nya") {
doSomething();
}
if (message.content.op === "meow") {
if (!message.repliable) return;
message.reply("nya");
}
});
```
> Reconfiguring Indomitable on the go, to launch more clusters or more shard, or more on both
```js
// Reconfigure to launch more shards based on Discord Recommendation without spawning more clusters
indomitable.reconfigure()
.then(() => console.log('Done, Indomitable is reconfigured'));
indomitable
.reconfigure()
.then(() => console.log("Done, Indomitable is reconfigured"));
// Reconfigure to launch more clusters based on your value, but leave the shards based on Discord's recommendation
indomitable.reconfigure({ clusters: 8 })
.then(() => console.log('Done, Indomitable is reconfigured'));
indomitable
.reconfigure({ clusters: 8 })
.then(() => console.log("Done, Indomitable is reconfigured"));
// Reconfigure to launch more clusters or shards based on your values
indomitable.reconfigure({ clusters: 8, shards: 8 })
.then(() => console.log('Done, Indomitable is reconfigured'));
indomitable
.reconfigure({ clusters: 8, shards: 8 })
.then(() => console.log("Done, Indomitable is reconfigured"));
// Do not run restart() or restartAll() while this is running. It will cause your cluster / clusters to restart twice.

@@ -197,29 +208,29 @@ if (!indomitable.isBusy) indomitable.restartAll();

> Enabling concurrency handling (across all your shards) (Read Notes Below)
```js
const { Indomitable } = require('indomitable');
const { Client } = require('discord.js');
const token = 'your_token';
const { Indomitable } = require("indomitable");
const { Client } = require("discord.js");
const token = "your_token";
const options = {
// Processes to run
clusterCount: 2,
// Websocket shards to run
shardCount: 8,
// Discord.JS options
clientOptions: {
intents: [1 << 0] // Bitwise for GUILD intent only
},
// Auto restart processes that have been killed
// This defaults to false by default unless you specify it
autoRestart: true,
// Enable max concurrency handling
handleConcurrency: true,
// Your Discord.JS client
client: Client,
// Your bot token
token
}
// Processes to run
clusterCount: 2,
// Websocket shards to run
shardCount: 8,
// Discord.js options
clientOptions: {
intents: [1 << 0], // Bitwise for GUILD intent only
},
// Auto restart processes that have been killed
// This defaults to false by default unless you specify it
autoRestart: true,
// Enable max concurrency handling
handleConcurrency: true,
// Your Discord.js client
client: Client,
// Your bot token
token,
};
const manager = new Indomitable(options)
.on('error', console.error);
const manager = new Indomitable(options).on("error", console.error);

@@ -229,15 +240,15 @@ manager.spawn();

* Indomitable's concurrency handling will work in **any shard # and cluster #** regardless
- Indomitable's concurrency handling will work in **any shard # and cluster #** regardless
* Pair this with **waitForReady** disabled, and you will get amazingly fast boot times, specially for those who have access to big bot sharding.
- Pair this with **waitForReady** disabled, and you will get amazingly fast boot times, specially for those who have access to big bot sharding.
* Reduces your identify calls by following global max_concurrency identifies resulting into better connection quality
- Reduces your identify calls by following global max_concurrency identifies resulting into better connection quality
### Notes
* You don't need to call `client.login('token');` yourself, Indomitable will call it for you.
- You don't need to call `client.login('token');` yourself, Indomitable will call it for you.
* Extended clients that extend from discord.js client will work, as long as you use `client.login('token');` to get your bot running
- Extended clients that extend from discord.js client will work, as long as you use `client.login('token');` to get your bot running
* Your Discord.JS Client ShardClientUtil is replaced with Indomitable's ShardClientUtil. Refer to our docs for documentation 🔗 https://deivu.github.io/Indomitable/classes/client_ShardClientUtil.ShardClientUtil.html
- Your Discord.JS Client ShardClientUtil is replaced with Indomitable's ShardClientUtil. Refer to our docs for documentation 🔗 https://deivu.github.io/Indomitable/classes/client_ShardClientUtil.ShardClientUtil.html

@@ -249,17 +260,18 @@ ### Other Links

### Indomitable Options
| Option | Type | Description | Required | Default |
|--------------------|------------------|------------------------------------------------------------------------------|----------|----------------------------------------------------|
| clusterCount | number or 'auto' | How many clusters we should spawn | No | 'auto' |
| shardCount | number or 'auto' | How many websocket shards we should make | No | 'auto' |
| clientOptions | Object | Discord.JS Client Options | No | {} |
| clusterSettings | Object | Options for the forked process | No | {} |
| ipcTimeout | number | Timeout before we fail a request | No | 30000 |
| spawnTimeout | number | Timeout before we fail a cluster spawn | No | 60000 (multiplied by clusterShardCount internally) |
| spawnDelay | number | Time to wait before spawning a new cluster | No | 5000 |
| autoRestart | boolean | If you want to auto restart the shards that have been killed unintentionally | No | false |
| waitForReady | boolean | If you want to wait for cluster ready before spawning another cluster | No | true |
| handleConcurrency | boolean | Whether you want to handle shard concurrency properly | No | false |
| client | Client | Your Discord.JS non modified OR modified client | Yes | None |
| token | string | The token of your bot | Yes | None |
### Made with ❤ by `@sayanyan` (https://github.com/Deivu/)
| Option | Type | Description | Required | Default |
| ----------------- | ---------------- | ---------------------------------------------------------------------------- | -------- | -------------------------------------------------- |
| clusterCount | number or 'auto' | How many clusters we should spawn | No | 'auto' |
| shardCount | number or 'auto' | How many websocket shards we should make | No | 'auto' |
| clientOptions | Object | Discord.JS Client Options | No | {} |
| clusterSettings | Object | Options for the forked process | No | {} |
| ipcTimeout | number | Timeout before we fail a request | No | 30000 |
| spawnTimeout | number | Timeout before we fail a cluster spawn | No | 60000 (multiplied by clusterShardCount internally) |
| spawnDelay | number | Time to wait before spawning a new cluster | No | 5000 |
| autoRestart | boolean | If you want to auto restart the shards that have been killed unintentionally | No | false |
| waitForReady | boolean | If you want to wait for cluster ready before spawning another cluster | No | true |
| handleConcurrency | boolean | Whether you want to handle shard concurrency properly | No | false |
| client | Client | Your Discord.JS non modified OR modified client | Yes | None |
| token | string | The token of your bot | Yes | None |
### Made with ❤ by `@ichimakase` (https://github.com/Deivu/)

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display