export async function fetchWithTimeout(url: string, timeoutMs: number, signal?: AbortSignal): Promise { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeoutMs); const combinedSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal; try { return await fetch(url, { signal: combinedSignal }); } catch (error) { if (error instanceof Error && error.name === "AbortError") { if (signal?.aborted) { throw error; } throw new Error(`Request timed out after ${Math.ceil(timeoutMs / 1000)}s`); } throw error; } finally { clearTimeout(timer); } }