| import type { EventEmitter } from "node:events"; |
|
|
| export type DiscordGatewayHandle = { |
| emitter?: Pick<EventEmitter, "on" | "removeListener">; |
| disconnect?: () => void; |
| }; |
|
|
| export type WaitForDiscordGatewayStopParams = { |
| gateway?: DiscordGatewayHandle; |
| abortSignal?: AbortSignal; |
| onGatewayError?: (err: unknown) => void; |
| shouldStopOnError?: (err: unknown) => boolean; |
| registerForceStop?: (forceStop: (err: unknown) => void) => void; |
| }; |
|
|
| export function getDiscordGatewayEmitter(gateway?: unknown): EventEmitter | undefined { |
| return (gateway as { emitter?: EventEmitter } | undefined)?.emitter; |
| } |
|
|
| export async function waitForDiscordGatewayStop( |
| params: WaitForDiscordGatewayStopParams, |
| ): Promise<void> { |
| const { gateway, abortSignal, onGatewayError, shouldStopOnError } = params; |
| const emitter = gateway?.emitter; |
| return await new Promise<void>((resolve, reject) => { |
| let settled = false; |
| const cleanup = () => { |
| abortSignal?.removeEventListener("abort", onAbort); |
| emitter?.removeListener("error", onGatewayErrorEvent); |
| }; |
| const finishResolve = () => { |
| if (settled) { |
| return; |
| } |
| settled = true; |
| cleanup(); |
| try { |
| gateway?.disconnect?.(); |
| } finally { |
| resolve(); |
| } |
| }; |
| const finishReject = (err: unknown) => { |
| if (settled) { |
| return; |
| } |
| settled = true; |
| cleanup(); |
| try { |
| gateway?.disconnect?.(); |
| } finally { |
| reject(err); |
| } |
| }; |
| const onAbort = () => { |
| finishResolve(); |
| }; |
| const onGatewayErrorEvent = (err: unknown) => { |
| onGatewayError?.(err); |
| const shouldStop = shouldStopOnError?.(err) ?? true; |
| if (shouldStop) { |
| finishReject(err); |
| } |
| }; |
| const onForceStop = (err: unknown) => { |
| finishReject(err); |
| }; |
|
|
| if (abortSignal?.aborted) { |
| onAbort(); |
| return; |
| } |
|
|
| abortSignal?.addEventListener("abort", onAbort, { once: true }); |
| emitter?.on("error", onGatewayErrorEvent); |
| params.registerForceStop?.(onForceStop); |
| }); |
| } |
|
|