export const sleep = (ms: number, signal?: AbortSignal): Promise => new Promise((resolve, reject) => { if (signal?.aborted) { reject(signal.reason ?? new Error("aborted")); return; } const onAbort = (): void => { clearTimeout(timer); reject(signal?.reason ?? new Error("aborted")); }; const timer = setTimeout(() => { signal?.removeEventListener("abort", onAbort); resolve(); }, ms); signal?.addEventListener("abort", onAbort, { once: true }); }); export type Deadline = { readonly remainingMs: () => number; readonly expired: () => boolean; }; export const deadline = (totalMs: number): Deadline => { const end = Date.now() + totalMs; return { remainingMs: () => Math.max(0, end - Date.now()), expired: () => Date.now() >= end, }; };