first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# `assets` — Bundled asset registry, resolver, CDN-clean check
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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/<hash>/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",
'<svg xmlns="http://www.w3.org/2000/svg" />'
)
);
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<string, BundledAsset>`.
- `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.