Spaces:
Running
Running
Download src/lib/imageCache.ts from lrigamai/browser: direct link, hf CLI and curl.
- Browser
- Download file 2.39 kB
-
https://huggingface.co/spaces/lrigamai/browser/resolve/main/src/lib/imageCache.ts
- Command line
-
hf download hf://spaces/lrigamai/browser/src/lib/imageCache.ts
-
curl -L -o imageCache.ts https://huggingface.co/spaces/lrigamai/browser/resolve/main/src/lib/imageCache.ts
2.39 kB
| // Persistent image cache for preview images. | |
| // | |
| // Hub `resolve/` URLs answer `Cache-Control: no-store` and redirect to a freshly signed CDN | |
| // URL on every request, so the browser's HTTP cache never reuses them. Instead we keep the | |
| // bytes in Cache Storage, keyed by the file's content hash from the dataset listing: a hit | |
| // skips the network entirely, and a changed image gets a new hash (so a new entry). | |
| const CACHE_NAME = "lora-previews-v1"; | |
| /** Synthetic request URL per content hash; never fetched, only used as a cache key. */ | |
| const keyUrl = (hash: string) => `https://preview-cache.invalid/${hash}`; | |
| // One in-flight load per hash, shared by every <LoraPreview> showing that image. | |
| const loads = new Map<string, Promise<string>>(); | |
| // Finished loads, readable synchronously so a remounted preview can render the image in its | |
| // first frame instead of flashing the placeholder while a promise settles. | |
| const ready = new Map<string, string>(); | |
| /** Object URL for an image that has already finished loading, if any. */ | |
| export const loadedImage = (hash: string) => ready.get(hash); | |
| /** Object URL for the image (from cache, or fetched then cached). Falls back to `url` itself. */ | |
| export function cachedImage(url: string, hash: string): Promise<string> { | |
| let p = loads.get(hash); | |
| if (!p) { | |
| p = load(url, hash); | |
| loads.set(hash, p); | |
| p.then((src) => loads.get(hash) === p && ready.set(hash, src)); | |
| } | |
| return p; | |
| } | |
| async function load(url: string, hash: string): Promise<string> { | |
| try { | |
| const cache = await caches.open(CACHE_NAME); | |
| let res = await cache.match(keyUrl(hash)); | |
| if (!res) { | |
| const net = await fetch(url, { mode: "cors" }); | |
| if (!net.ok) throw new Error(`${net.status}`); | |
| await cache.put(keyUrl(hash), net.clone()); | |
| res = net; | |
| } | |
| return URL.createObjectURL(await res.blob()); | |
| } catch { | |
| // Cache Storage unavailable (private mode, blocked storage) or fetch failed: | |
| // let the <img> load the URL directly. | |
| loads.delete(hash); | |
| return url; | |
| } | |
| } | |
| /** Drop cached images that are no longer in the dataset (replaced or removed). */ | |
| export async function pruneImageCache(keep: Iterable<string>): Promise<void> { | |
| try { | |
| const wanted = new Set([...keep].map(keyUrl)); | |
| const cache = await caches.open(CACHE_NAME); | |
| for (const req of await cache.keys()) if (!wanted.has(req.url)) await cache.delete(req); | |
| } catch { | |
| // best effort | |
| } | |
| } | |