- Added cache strategies: NetworkFirst, CacheFirst, StaleWhileRevalidate, NetworkOnly, and CacheOnly. - Introduced InterceptorManager for managing request, response, and error interceptors. - Developed RetryManager for handling request retries with customizable backoff strategies. - Implemented RequestDeduplicator to prevent simultaneous identical requests. - Created timeout utilities for handling request timeouts. - Enhanced WebrequestClient to support global interceptors, caching, and retry logic. - Added convenience methods for common HTTP methods (GET, POST, PUT, DELETE) with JSON handling. - Established a fetch-compatible webrequest function for seamless integration. - Defined core type structures for caching, retry options, interceptors, and web request configurations.
		
			
				
	
	
		
			67 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * Timeout handling utilities
 | |
|  */
 | |
| 
 | |
| import * as plugins from '../webrequest.plugins.js';
 | |
| 
 | |
| /**
 | |
|  * Create an AbortController with timeout
 | |
|  */
 | |
| export function createTimeoutController(timeoutMs: number): {
 | |
|   controller: AbortController;
 | |
|   cleanup: () => void;
 | |
| } {
 | |
|   const controller = new AbortController();
 | |
|   let timeoutId: any;
 | |
| 
 | |
|   // Set up timeout
 | |
|   plugins.smartdelay
 | |
|     .delayFor(timeoutMs)
 | |
|     .then(() => {
 | |
|       controller.abort();
 | |
|     })
 | |
|     .then((result) => {
 | |
|       timeoutId = result;
 | |
|     });
 | |
| 
 | |
|   // Cleanup function to clear timeout
 | |
|   const cleanup = () => {
 | |
|     if (timeoutId !== undefined) {
 | |
|       // smartdelay doesn't expose a cancel method, so we just ensure
 | |
|       // the controller won't abort if already completed
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   return { controller, cleanup };
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Execute a fetch with timeout
 | |
|  */
 | |
| export async function fetchWithTimeout(
 | |
|   url: string,
 | |
|   init: RequestInit,
 | |
|   timeoutMs: number,
 | |
| ): Promise<Response> {
 | |
|   const { controller, cleanup } = createTimeoutController(timeoutMs);
 | |
| 
 | |
|   try {
 | |
|     const response = await fetch(url, {
 | |
|       ...init,
 | |
|       signal: controller.signal,
 | |
|     });
 | |
| 
 | |
|     cleanup();
 | |
|     return response;
 | |
|   } catch (error) {
 | |
|     cleanup();
 | |
| 
 | |
|     // Re-throw with more informative error if it's a timeout
 | |
|     if (error instanceof Error && error.name === 'AbortError') {
 | |
|       throw new Error(`Request timeout after ${timeoutMs}ms: ${url}`);
 | |
|     }
 | |
| 
 | |
|     throw error;
 | |
|   }
 | |
| }
 |