Files
webrequest/ts/cache/cache.manager.ts
Juergen Kunz 54afcc46e2 feat: Implement comprehensive web request handling with caching, retry, and interceptors
- 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.
2025-10-20 09:59:24 +00:00

157 lines
3.6 KiB
TypeScript

/**
* Cache manager - orchestrates caching logic
*/
import type {
ICacheOptions,
TCacheStrategy,
TStandardCacheMode,
} from '../webrequest.types.js';
import { CacheStore } from './cache.store.js';
import {
getStrategyHandler,
type IStrategyContext,
type IStrategyResult,
} from './cache.strategies.js';
import { extractCacheMetadata } from './cache.headers.js';
export class CacheManager {
private cacheStore: CacheStore;
constructor(dbName?: string, storeName?: string) {
this.cacheStore = new CacheStore(dbName, storeName);
}
/**
* Execute a request with caching
*/
public async execute(
request: Request,
options: ICacheOptions & { logging?: boolean },
fetchFn: (request: Request) => Promise<Response>,
): Promise<IStrategyResult> {
// Determine the cache strategy
const strategy = this.determineStrategy(request, options);
// If no caching (no-store or network-only), bypass cache
if (strategy === 'network-only') {
const response = await fetchFn(request);
return {
response,
fromCache: false,
revalidated: false,
};
}
// Generate cache key
const cacheKey = this.generateCacheKey(request, options);
// Get strategy handler
const handler = getStrategyHandler(strategy);
// Execute strategy
const context: IStrategyContext = {
request,
cacheKey,
cacheStore: this.cacheStore,
fetchFn,
logging: options.logging,
};
return await handler.execute(context);
}
/**
* Determine the caching strategy based on options and request
*/
private determineStrategy(
request: Request,
options: ICacheOptions,
): TCacheStrategy {
// If explicit strategy provided, use it
if (options.cacheStrategy) {
return options.cacheStrategy;
}
// Map standard cache modes to strategies
if (options.cache) {
return this.mapCacheModeToStrategy(options.cache);
}
// Check request cache mode
if (request.cache) {
return this.mapCacheModeToStrategy(request.cache as TStandardCacheMode);
}
// Default strategy
return 'network-first';
}
/**
* Map standard fetch cache modes to our strategies
*/
private mapCacheModeToStrategy(
cacheMode: TStandardCacheMode,
): TCacheStrategy {
switch (cacheMode) {
case 'default':
return 'network-first';
case 'no-store':
case 'reload':
return 'network-only';
case 'no-cache':
return 'network-first'; // Will use revalidation
case 'force-cache':
return 'cache-first';
case 'only-if-cached':
return 'cache-only';
default:
return 'network-first';
}
}
/**
* Generate cache key
*/
private generateCacheKey(request: Request, options: ICacheOptions): string {
// If custom cache key provided
if (options.cacheKey) {
if (typeof options.cacheKey === 'function') {
return options.cacheKey(request);
}
return options.cacheKey;
}
// Default cache key generation
return this.cacheStore.generateCacheKey(request);
}
/**
* Clear the cache
*/
public async clear(): Promise<void> {
await this.cacheStore.clear();
}
/**
* Delete a specific cache entry
*/
public async delete(cacheKey: string): Promise<void> {
await this.cacheStore.delete(cacheKey);
}
/**
* Check if a cache entry exists
*/
public async has(cacheKey: string): Promise<boolean> {
return await this.cacheStore.has(cacheKey);
}
/**
* Get the underlying cache store
*/
public getStore(): CacheStore {
return this.cacheStore;
}
}