3.6 KiB
loader
(no submodules)
Purpose
loader.ts is the fetch → verify → unpack → Blob-URL pipeline for
packed resources. It is the only place in the package that issues a
network request, the only place that runs Unpacker.unpack, and the
only place that allocates a Blob URL. Splitting it out from
PackedResourceManager keeps every concern testable in isolation —
fetch retry, signature failure, abort propagation, and OTel histogram
emission can each be exercised without instantiating a cache.
Features
fetchrouted through@suaveplan/retry'swithRetrywith a single-attempt default policy; callers opt in to retry by passingretryConfig.AbortSignalhonoured at every yield point — pre-fetch, post-fetch, post-buffer, post-verify, and pre-unpack.- Optional Ed25519 signature verification when
verifyKeyis supplied and the response carries anX-Archive-Signatureheader. - OTel emission: increments
packed_resource_fetch_totalon every attempt; recordspacked_resource_decode_mson every successful pipeline run. - Typed error surface: every failure produces
PackerBrowserErrorwith aPACKER_BROWSER.*code and an i18n-resolved message. - Injectable
fetchfor tests — novi.mockrequired.
Usage: Basic
import {
createPackerBrowserObservability,
PackedResourceLoader,
resolveRuntime,
} from "@suaveplan/packer-browser";
const loader = new PackedResourceLoader({
runtime: resolveRuntime(),
observability: createPackerBrowserObservability(),
});
const { url, metadata } = await loader.load("/banner.packed");
img.src = url;
Usage: Advanced
import { createConstantBackoff } from "@suaveplan/retry";
import { PackedResourceLoader } from "@suaveplan/packer-browser";
const controller = new AbortController();
const loader = new PackedResourceLoader({
runtime: resolveRuntime(),
observability,
fetch: async (url) => recordedFetch(url),
});
const out = await loader.load("/banner.packed", {
verifyKey: trustAnchorPublicKey,
signal: controller.signal,
retryConfig: {
maxAttempts: 3,
delay: createConstantBackoff({ delay: 250 }),
},
});
API Reference
new PackedResourceLoader(opts: PackedResourceLoaderOptions).loader.load(url: string, opts?: PackedResourceLoadOptions): Promise<LoadedResource>.- Throws
RESOURCE_NOT_FOUNDfor non-2xx. - Throws
ARCHIVE_SIGNATURE_INVALIDfor a non-verifying signature whenverifyKeyis supplied. - Throws
LOAD_FAILEDwhenUnpacker.unpackrejects. - Throws
ABORTEDwhen the supplied signal fires.
- Throws
PackedResourceLoadOptions:verifyChecksum?: boolean— defaultfalse.verifyKey?: Uint8Array— optional Ed25519 public key.signal?: AbortSignal— checked at every yield.retryConfig?: RetryConfig— default: single attempt.messageResolver?: MessageResolver— overrides the constructor's resolver for this call.
Implementation Notes
Cluster A's loader treats every fetched payload as a raw PackedData
whose metadata is reconstructed from the bytes; signature verification
covers the archive transport layer, while integrity verification
is delegated to the Unpacker and currently skipped
(verifyIntegrity: false) because Cluster A archives do not carry the
BLAKE3 integrity bundle. Cluster B introduces the formal manifest
decoder and re-enables integrity. The X-Archive-Signature header
contract is unchanged across clusters — switching to a separate
signature manifest is a Cluster B concern only.