Download local-docker/packages/runtime/src/fetch.ts from ti3x-m/web-decisions-webgpu-quickstart: direct link, hf CLI and curl.
- Browser
- Download file 2.12 kB
-
https://huggingface.co/spaces/ti3x-m/web-decisions-webgpu-quickstart/resolve/main/local-docker/packages/runtime/src/fetch.ts
- Command line
-
hf download hf://spaces/ti3x-m/web-decisions-webgpu-quickstart/local-docker/packages/runtime/src/fetch.ts
-
curl -L -o fetch.ts https://huggingface.co/spaces/ti3x-m/web-decisions-webgpu-quickstart/resolve/main/local-docker/packages/runtime/src/fetch.ts
2.12 kB
| import type { LoadProgress } from "./shared/types"; | |
| const CACHE = "laya-webgpu-v1"; | |
| async function sha256(bytes: ArrayBuffer): Promise<string> { | |
| const hash = await crypto.subtle.digest("SHA-256", bytes); | |
| return [...new Uint8Array(hash)].map((part) => part.toString(16).padStart(2, "0")).join(""); | |
| } | |
| export async function fetchVerified( | |
| url: string, | |
| expectedHash?: string, | |
| onProgress?: (progress: LoadProgress) => void, | |
| signal?: AbortSignal, | |
| ): Promise<ArrayBuffer> { | |
| const cache = "caches" in globalThis ? await caches.open(CACHE).catch(() => undefined) : undefined; | |
| const cached = await cache?.match(url).catch(() => undefined); | |
| if (cached) { | |
| const bytes = await cached.arrayBuffer(); | |
| if (!expectedHash || await sha256(bytes) === expectedHash.toLowerCase()) return bytes; | |
| await cache?.delete(url).catch(() => false); | |
| } | |
| const response = await fetch(url, { signal }); | |
| if (!response.ok) throw new Error(`Download failed (${response.status}) for ${url}`); | |
| const total = Number(response.headers.get("content-length")) || undefined; | |
| if (!response.body) { | |
| const bytes = await response.arrayBuffer(); | |
| if (expectedHash && await sha256(bytes) !== expectedHash.toLowerCase()) throw new Error(`SHA-256 mismatch for ${url}`); | |
| return bytes; | |
| } | |
| const reader = response.body.getReader(); | |
| const chunks: Uint8Array[] = []; | |
| let loaded = 0; | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| chunks.push(value); | |
| loaded += value.byteLength; | |
| onProgress?.({ phase: "model", loaded, total, detail: url }); | |
| } | |
| const joined = new Uint8Array(loaded); | |
| let offset = 0; | |
| for (const chunk of chunks) { joined.set(chunk, offset); offset += chunk.length; } | |
| if (expectedHash && await sha256(joined.buffer) !== expectedHash.toLowerCase()) throw new Error(`SHA-256 mismatch for ${url}`); | |
| await cache?.put(url, new Response(joined, { headers: response.headers })).catch(() => undefined); | |
| return joined.buffer; | |
| } | |
| export async function clearModelCache(): Promise<void> { | |
| if ("caches" in globalThis) await caches.delete(CACHE); | |
| } | |