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,88 @@
# `factory/create-altair-ui` — Altair UI plugin factory
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`factory/create-altair-ui` is the package's public entry point.
`createAltairUi(opts)` validates the caller's options against the Zod
schema, builds the asset registry and OTel instruments, and returns a
`RouterPlugin` whose `mount(router)` method registers `GET <uiEndpoint>`
plus the hashed-asset routes against any `Router` instance. Endpoint
collisions are detected up-front via `router.collidesWith` and reject
the mount with a typed `GRAPHQL_UI_ALTAIR.ENDPOINT_COLLISION` error
before any route is written — partial mounts are impossible.
## Features
- Zero-config call: `createAltairUi()` works out of the box.
- Returns a frozen `RouterPlugin` with `name`, `options`, `mount`,
`renderHtml`, and `renderAsset` members.
- HTML response always carries the strict CSP + ancillary security
headers.
- Asset response carries `Cache-Control: public, max-age=31536000, immutable`.
- Asset misses (wrong hash, wrong name) throw `GraphqlUiAltairError`
with code `ASSET_MISSING`.
- Endpoint collisions throw `GraphqlUiAltairError` with code
`ENDPOINT_COLLISION` before any route is registered.
- Injectable internals (`assetRegistry`, `instruments`) for integration
tests and operators wanting custom asset bundles.
## Usage: Basic
```ts
import { createAltairUi } from "@suaveplan/api-graphql-ui-altair/factory";
import { Router } from "@suaveplan/api-router";
const router = new Router();
const altair = createAltairUi();
altair.mount(router);
// router.match("GET", "/graphql/ui") now resolves to the HTML handler.
```
## Usage: Advanced
```ts
import { createAltairUi } from "@suaveplan/api-graphql-ui-altair/factory";
import { createAltairInstruments } from "@suaveplan/api-graphql-ui-altair/instruments";
import { MeterProvider } from "@opentelemetry/sdk-metrics";
import { Router } from "@suaveplan/api-router";
const meterProvider = new MeterProvider();
const instruments = createAltairInstruments({ meterProvider });
const router = new Router();
const altair = createAltairUi(
{
uiEndpoint: "/dev/altair",
graphqlEndpoint: "/api/graphql",
theme: "dark",
initialEnvironments: {
production: {
url: "https://api.example.com/graphql",
headers: { "x-tenant": "acme" },
},
},
},
{ instruments }
);
altair.mount(router);
```
## API Reference
- `createAltairUi(input?: AltairUiOptionsInput, internals?: CreateAltairUiInternals): RouterPlugin`.
- `RouterPlugin` — `{ name, options, mount(router), renderHtml(), renderAsset(hash, name) }`.
- `CreateAltairUiInternals` — `{ assetRegistry?, instruments? }`.
## Implementation Notes
The factory composes five lower-level modules — options, assets, html,
headers, instruments — and exposes their behaviour behind one
ergonomic entry point. The `RouterPlugin.options` field is the parsed,
defaulted bundle (not the caller's raw input) so downstream code reads
the same value the renderer wrote. Frozen-everything posture means
operators cannot accidentally mutate the plugin between `mount` calls.