- 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.
		
			
				
	
	
		
			150 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * Interceptor manager for request/response transformation
 | |
|  */
 | |
| 
 | |
| import type {
 | |
|   TRequestInterceptor,
 | |
|   TResponseInterceptor,
 | |
|   TErrorInterceptor,
 | |
| } from './interceptor.types.js';
 | |
| 
 | |
| export class InterceptorManager {
 | |
|   private requestInterceptors: TRequestInterceptor[] = [];
 | |
|   private responseInterceptors: TResponseInterceptor[] = [];
 | |
|   private errorInterceptors: TErrorInterceptor[] = [];
 | |
| 
 | |
|   /**
 | |
|    * Add a request interceptor
 | |
|    */
 | |
|   public addRequestInterceptor(interceptor: TRequestInterceptor): void {
 | |
|     this.requestInterceptors.push(interceptor);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Add a response interceptor
 | |
|    */
 | |
|   public addResponseInterceptor(interceptor: TResponseInterceptor): void {
 | |
|     this.responseInterceptors.push(interceptor);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Add an error interceptor
 | |
|    */
 | |
|   public addErrorInterceptor(interceptor: TErrorInterceptor): void {
 | |
|     this.errorInterceptors.push(interceptor);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Remove a request interceptor
 | |
|    */
 | |
|   public removeRequestInterceptor(interceptor: TRequestInterceptor): void {
 | |
|     const index = this.requestInterceptors.indexOf(interceptor);
 | |
|     if (index > -1) {
 | |
|       this.requestInterceptors.splice(index, 1);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Remove a response interceptor
 | |
|    */
 | |
|   public removeResponseInterceptor(interceptor: TResponseInterceptor): void {
 | |
|     const index = this.responseInterceptors.indexOf(interceptor);
 | |
|     if (index > -1) {
 | |
|       this.responseInterceptors.splice(index, 1);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Remove an error interceptor
 | |
|    */
 | |
|   public removeErrorInterceptor(interceptor: TErrorInterceptor): void {
 | |
|     const index = this.errorInterceptors.indexOf(interceptor);
 | |
|     if (index > -1) {
 | |
|       this.errorInterceptors.splice(index, 1);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Clear all interceptors
 | |
|    */
 | |
|   public clearAll(): void {
 | |
|     this.requestInterceptors = [];
 | |
|     this.responseInterceptors = [];
 | |
|     this.errorInterceptors = [];
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Process request through all request interceptors
 | |
|    */
 | |
|   public async processRequest(request: Request): Promise<Request> {
 | |
|     let processedRequest = request;
 | |
| 
 | |
|     for (const interceptor of this.requestInterceptors) {
 | |
|       try {
 | |
|         processedRequest = await interceptor(processedRequest);
 | |
|       } catch (error) {
 | |
|         // If interceptor throws, process through error interceptors
 | |
|         throw await this.processError(
 | |
|           error instanceof Error ? error : new Error(String(error)),
 | |
|         );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return processedRequest;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Process response through all response interceptors
 | |
|    */
 | |
|   public async processResponse(response: Response): Promise<Response> {
 | |
|     let processedResponse = response;
 | |
| 
 | |
|     for (const interceptor of this.responseInterceptors) {
 | |
|       try {
 | |
|         processedResponse = await interceptor(processedResponse);
 | |
|       } catch (error) {
 | |
|         // If interceptor throws, process through error interceptors
 | |
|         throw await this.processError(
 | |
|           error instanceof Error ? error : new Error(String(error)),
 | |
|         );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return processedResponse;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Process error through all error interceptors
 | |
|    */
 | |
|   public async processError(error: Error): Promise<Error> {
 | |
|     let processedError = error;
 | |
| 
 | |
|     for (const interceptor of this.errorInterceptors) {
 | |
|       try {
 | |
|         processedError = await interceptor(processedError);
 | |
|       } catch (newError) {
 | |
|         // If error interceptor throws, use the new error
 | |
|         processedError =
 | |
|           newError instanceof Error ? newError : new Error(String(newError));
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return processedError;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get count of registered interceptors
 | |
|    */
 | |
|   public getInterceptorCounts(): {
 | |
|     request: number;
 | |
|     response: number;
 | |
|     error: number;
 | |
|   } {
 | |
|     return {
 | |
|       request: this.requestInterceptors.length,
 | |
|       response: this.responseInterceptors.length,
 | |
|       error: this.errorInterceptors.length,
 | |
|     };
 | |
|   }
 | |
| }
 |