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.2
to
4.0.3
+1
-1
dist/index.js

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

signal.addEventListener("abort", listener);
await this.ipc.send({ content, repliable: true }).catch(() => null);
await this.ipc.send({ content, repliable: true });
} finally {

@@ -954,0 +954,0 @@ signal.removeEventListener("abort", listener);

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

signal.addEventListener("abort", listener);
await this.ipc.send({ content, repliable: true }).catch(() => null);
await this.ipc.send({ content, repliable: true });
} finally {

@@ -921,0 +921,0 @@ signal.removeEventListener("abort", listener);

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

signal.addEventListener("abort", listener);
await this.ipc.send({ content, repliable: true }).catch(() => null);
await this.ipc.send({ content, repliable: true });
} finally {

@@ -81,0 +81,0 @@ signal.removeEventListener("abort", listener);

@@ -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\n .send({ content, repliable: true })\n .catch(() => null);\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":"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","names":["import_ws","import_worker_threads","ipc","options","options","EventEmitter","shard"]}

@@ -53,3 +53,3 @@ // src/strategy/Thread.ts

signal.addEventListener("abort", listener);
await this.ipc.send({ content, repliable: true }).catch(() => null);
await this.ipc.send({ content, repliable: true });
} finally {

@@ -56,0 +56,0 @@ signal.removeEventListener("abort", listener);

@@ -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\n .send({ content, repliable: true })\n .catch(() => null);\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.2",
"version": "4.0.3",
"description": "A lightweight (the actual ship is heavy though), performant, powerful & no dependency sharder for Discord.JS",

@@ -48,3 +48,3 @@ "main": "dist/index.js",

"discord.js": ">=14.10.x",
"@discordjs/ws": ">=0.8.3"
"@discordjs/ws": ">=1.0.0"
},

@@ -51,0 +51,0 @@ "devDependencies": {

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

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