export const DEADLINE_EXPIRED_CODE = "ETIMEOUT"; export function createDeadline(budgetMs: number, now = Date.now()) { return now + Math.max(0, budgetMs); } export function remainingMs(deadline: number, now = Date.now()) { return Math.max(0, deadline - now); } export function timeoutError(message: string) { const error = new Error(message) as Error & { code: string }; error.code = DEADLINE_EXPIRED_CODE; return error; } export async function withDeadline( operation: Promise, deadline: number, onTimeout: () => void, message: string, ): Promise { const remaining = remainingMs(deadline); if (!remaining) { onTimeout(); throw timeoutError(message); } let timer: ReturnType | undefined; const timeout = new Promise((_, reject) => { timer = setTimeout(() => { onTimeout(); reject(timeoutError(message)); }, remaining); }); try { return await Promise.race([operation, timeout]); } finally { if (timer) clearTimeout(timer); } }