published-bundle.ts (1323B)
1 import { decodeBundle, fetchBytes, sha256, type BundleHash } from './bundle.js'; 2 // Common authenticated package/source boundary, independent of the evaluator. 3 export async function publishedBundle(hash: BundleHash, localId?: string) { 4 const base = new URL('../', import.meta.url); 5 let source: string | null = null; 6 if (localId !== undefined) { 7 const catalogue: unknown = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(await fetchBytes(new URL('catalogue.json', base), 64000))); 8 if (!Array.isArray(catalogue)) throw new Error('Invalid catalogue'); 9 const entry = catalogue.find((item: unknown) => !!item && typeof item === 'object' && (item as Record<string, unknown>)['id'] === localId) as Record<string, unknown> | undefined; 10 if (!entry || entry['hash'] !== hash) throw new Error('Invalid catalogue pin'); 11 if (typeof entry['source'] !== 'string' || entry['source'].length > 32000 || await sha256(new TextEncoder().encode(entry['source'])) !== entry['sourceSha256']) throw new Error('Catalogue source integrity failure'); 12 source = entry['source']; 13 } 14 const bytes = await fetchBytes(new URL(`/_arboricx/bundle/hash/${hash}`, base)); 15 if (await sha256(bytes) !== hash) throw new Error('Bundle SHA-256 mismatch'); 16 return { hash, bytes, bundle: decodeBundle(bytes), source }; 17 }