# `assets` — Bundled asset registry, resolver, CDN-clean check _(no submodules)_ ## Purpose `assets` ships the Altair shell as a static-asset map keyed by logical filename. Every entry carries a content-type, the payload bytes, and a short SHA-256 hash derived once at module init so cache-bust URLs are stable across deploys with unchanged payloads. The shell is shipped inline (no FS reads at request time, no CDN fetches) which preserves the Altair plugin's hermetic-bundle guarantee — the package can boot in air-gapped, offline-first environments and still serve a usable UI. ## Features - Default registry: `altair.js` + `altair.css`. - `defineAsset(name, contentType, body)` returns a frozen `BundledAsset`. - `resolveAsset(registry, uiEndpointBase, name)` produces a `ResolvedAsset` with a hash-busted URL. - Missing names throw `GraphqlUiAltairError` (`ASSET_MISSING`). - `findExternalHostReferences` is the CDN-clean conformance check. - Hash derivation is SHA-256, truncated to 16 hex chars — same cardinality as a `git rev-parse --short=16`. ## Usage: Basic ```ts import { buildDefaultAssetRegistry, resolveAsset, } from "@suaveplan/api-graphql-ui-altair/assets"; const registry = buildDefaultAssetRegistry(); const jsAsset = resolveAsset(registry, "/graphql/ui", "altair.js"); console.log(jsAsset.url); // /graphql/ui/assets//altair.js ``` ## Usage: Advanced ```ts import { buildDefaultAssetRegistry, defineAsset, findExternalHostReferences, } from "@suaveplan/api-graphql-ui-altair/assets"; // Extend the registry with an operator-specific asset. const registry = new Map(buildDefaultAssetRegistry()); registry.set( "logo.svg", defineAsset( "logo.svg", "image/svg+xml", '' ) ); const offenders = findExternalHostReferences(registry); if (offenders.length > 0) { throw new Error("CDN leak: " + offenders.join(", ")); } ``` ## API Reference - `BundledAsset` — `{ name, contentType, body, hash }`. - `ResolvedAsset extends BundledAsset` — adds `url`. - `defineAsset(name, contentType, body): BundledAsset`. - `buildDefaultAssetRegistry(): ReadonlyMap`. - `resolveAsset(registry, uiEndpointBase, name): ResolvedAsset` — throws `GraphqlUiAltairError` (`ASSET_MISSING`) on misses. - `findExternalHostReferences(registry): readonly string[]`. ## Implementation Notes The asset bodies are held as JavaScript template literals so the build emits them as plain string constants — no FS access at boot, no `process.cwd()` dependence. The hash is computed via `node:crypto` to match the same hashing the rest of the project's static-asset pipeline uses; the truncation to 16 hex chars is intentional — a collision in a single deploy's asset set is vanishingly unlikely and the shorter URL is easier on the eyes in production logs.