index.ts (2455B)
1 type CacheLike = { 2 match: (request: string) => Promise<Response | undefined>; 3 put: (request: string, response: Response) => Promise<void>; 4 }; 5 6 type CacheStorageLike = { 7 open: (cache_name: string) => Promise<CacheLike>; 8 }; 9 10 declare const caches: CacheStorageLike | undefined; 11 12 export const RADROOTS_ASSET_CACHE_NAME = "cache-app-assets-v1"; 13 export const RADROOTS_ASSET_CACHE_PREFIX = "cache-app-assets-v"; 14 15 export type AssetCacheMode = 16 | "default" 17 | "no-store" 18 | "reload" 19 | "no-cache" 20 | "force-cache" 21 | "only-if-cached"; 22 23 export type AssetCacheRequestInit = RequestInit & { 24 cache?: AssetCacheMode; 25 }; 26 27 export type AssetCacheFetchConfig = { 28 cache_name?: string; 29 request_init?: AssetCacheRequestInit; 30 }; 31 32 const cache_name_resolve = (config?: AssetCacheFetchConfig): string => 33 config?.cache_name ?? RADROOTS_ASSET_CACHE_NAME; 34 35 const cache_key_resolve = (url: string): string => { 36 const hash_index = url.indexOf("#"); 37 return hash_index >= 0 ? url.slice(0, hash_index) : url; 38 }; 39 40 const cache_read = async (cache_name: string, cache_key: string): Promise<Response | null> => { 41 if (typeof caches === "undefined") return null; 42 try { 43 const cache = await caches.open(cache_name); 44 const cached = await cache.match(cache_key); 45 return cached ?? null; 46 } catch { 47 return null; 48 } 49 }; 50 51 const cache_write = async (cache_name: string, cache_key: string, response: Response): Promise<void> => { 52 if (typeof caches === "undefined") return; 53 try { 54 const cache = await caches.open(cache_name); 55 await cache.put(cache_key, response); 56 } catch { } 57 }; 58 59 export const asset_cache_fetch = async (url: string, config?: AssetCacheFetchConfig): Promise<Response> => { 60 const cache_name = cache_name_resolve(config); 61 const cache_key = cache_key_resolve(url); 62 const cached = await cache_read(cache_name, cache_key); 63 if (cached) return cached; 64 const response = await fetch(url, config?.request_init); 65 if (response.ok || response.type === "opaque") await cache_write(cache_name, cache_key, response.clone()); 66 return response; 67 }; 68 69 export const asset_cache_fetch_bytes = async (url: string, config?: AssetCacheFetchConfig): Promise<Uint8Array | null> => { 70 const response = await asset_cache_fetch(url, config); 71 if (!response.ok) return null; 72 const buffer = await response.arrayBuffer(); 73 return new Uint8Array(buffer); 74 };