/** * Enhanced fetch wrapper with proxy support and automatic debug logging * Drop-in replacement for native fetch with additional features */ export interface BunRequestInit extends RequestInit { proxy?: string; } export interface FetchOptions extends RequestInit { logger?: any; proxy?: string | null; timeout?: number; } export async function fetch(input: RequestInfo | URL, options?: FetchOptions): Promise { const logger = options?.logger || console; const url = typeof input === 'string' ? input : input instanceof URL ? input.href : (input as Request).url; // Build request options const requestOptions: RequestInit = { method: options?.method || 'GET', headers: options?.headers || {}, body: options?.body, signal: options?.signal, credentials: options?.credentials, cache: options?.cache, redirect: options?.redirect, referrer: options?.referrer, referrerPolicy: options?.referrerPolicy, integrity: options?.integrity, keepalive: options?.keepalive, mode: options?.mode, }; // Handle proxy for Bun if (options?.proxy) { // Bun supports proxy via fetch options (requestOptions as BunRequestInit).proxy = options.proxy; } // Handle timeout if (options?.timeout) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), options.timeout); requestOptions.signal = controller.signal; try { const response = await performFetch(input, requestOptions, logger, url); clearTimeout(timeoutId); return response; } catch (error) { clearTimeout(timeoutId); throw error; } } return performFetch(input, requestOptions, logger, url); } async function performFetch( input: RequestInfo | URL, requestOptions: RequestInit, logger: any, url: string ): Promise { logger.debug('HTTP request', { method: requestOptions.method, url, headers: requestOptions.headers, proxy: (requestOptions as BunRequestInit).proxy || null, }); try { const response = await globalThis.fetch(input, requestOptions); logger.debug('HTTP response', { url, status: response.status, statusText: response.statusText, ok: response.ok, headers: Object.fromEntries(response.headers.entries()), }); return response; } catch (error) { logger.debug('HTTP error', { url, error: error instanceof Error ? error.message : String(error), name: error instanceof Error ? error.name : 'Unknown', }); throw error; } }