first commit
This commit is contained in:
97
docs/api-stack/api/api-graphql-ui-altair/README.md
Normal file
97
docs/api-stack/api/api-graphql-ui-altair/README.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# @suaveplan/api-graphql-ui-altair — Altair GraphQL UI plugin for the Suaveplan API plugin system. Mounts the Altair shell at GET /graphql/ui via createAltairUi(opts), serves bundled (no-CDN) assets from a hashed static map, embeds graphqlEndpoint / subscriptionEndpoint / initialQuery / initialHeaders / initialEnvironments into the shell, attaches a strict CSP (no script 'unsafe-inline'), increments graphql.ui.requests_total{ ui: "altair" } via an injectable MeterProvider, and refuses endpoint collisions with the GRAPHQL_UI_ALTAIR_ENDPOINT_COLLISION code. Structural sibling of api-graphql-ui-graphiql.
|
||||
|
||||
Altair GraphQL UI plugin for the Suaveplan API plugin
|
||||
system. Structural sibling of `@suaveplan/api-graphql-ui-graphiql`.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [assets](./src/assets/assets.md) — `assets` ships the Altair shell as a static-asset map keyed by logical filename. Every entry carries a content-type, th…
|
||||
- [assets](./src/assets/assets.md) — `assets` ships the Altair shell as a static-asset map keyed by logical filename. Every entry carries a content-type, th…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — `error-codes` is the package's single source of truth for the two stable error codes the Altair UI plugin emits. Centra…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — `error-codes` is the package's single source of truth for the two stable error codes the Altair UI plugin emits. Centra…
|
||||
- [factory](./src/factory/create-altair-ui.md) — `factory/create-altair-ui` is the package's public entry point. `createAltairUi(opts)` validates the caller's options a…
|
||||
- [create-altair-ui](./src/factory/create-altair-ui.md) — `factory/create-altair-ui` is the package's public entry point. `createAltairUi(opts)` validates the caller's options a…
|
||||
- [headers](./src/headers/csp.md) — `headers/csp` produces the Content-Security-Policy and the two ancillary security headers (`X-Content-Type-Options`, `R…
|
||||
- [csp](./src/headers/csp.md) — `headers/csp` produces the Content-Security-Policy and the two ancillary security headers (`X-Content-Type-Options`, `R…
|
||||
- [html](./src/html/render-shell.md) — `html/render-shell` produces the single HTML document the Altair UI plugin serves at `<uiEndpoint>`. The shell mounts a…
|
||||
- [render-shell](./src/html/render-shell.md) — `html/render-shell` produces the single HTML document the Altair UI plugin serves at `<uiEndpoint>`. The shell mounts a…
|
||||
- [instruments](./src/instruments/instruments.md) — `instruments` owns the package's single OpenTelemetry counter, `graphql.ui.requests_total`, labelled with the constant…
|
||||
- [instruments](./src/instruments/instruments.md) — `instruments` owns the package's single OpenTelemetry counter, `graphql.ui.requests_total`, labelled with the constant…
|
||||
- [options](./src/options/options.md) — `options` owns the Zod-validated configuration surface every consumer of the Altair UI plugin passes through. The schem…
|
||||
- [options](./src/options/options.md) — `options` owns the Zod-validated configuration surface every consumer of the Altair UI plugin passes through. The schem…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## What this package is
|
||||
|
||||
- **Opt-in.** The host serves nothing at `/graphql/ui` unless this
|
||||
plugin (or its GraphiQL sibling) is wired against the router.
|
||||
- **Bundled assets only — no CDN.** Every asset the HTML shell loads
|
||||
ships inside this package's `dist/` output. The plugin works in
|
||||
air-gapped, offline-first environments.
|
||||
- **Alternative to GraphiQL, not co-existing.** Operators wire one or
|
||||
the other against `/graphql/ui`. Both at once is refused by host
|
||||
config (the engine adapters return 404 there when neither is wired).
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import { createAltairUi } from "@suaveplan/api-graphql-ui-altair";
|
||||
import { Router } from "@suaveplan/api-router";
|
||||
|
||||
const router = new Router();
|
||||
const altair = createAltairUi();
|
||||
altair.mount(router);
|
||||
|
||||
// router.match("GET", "/graphql/ui") resolves to the Altair HTML handler.
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```ts
|
||||
createAltairUi({
|
||||
uiEndpoint: "/graphql/ui", // default
|
||||
graphqlEndpoint: "/graphql", // default
|
||||
subscriptionEndpoint: "/graphql/ws", // default
|
||||
theme: "system", // "light" | "dark" | "system"
|
||||
initialQuery: "",
|
||||
initialHeaders: { "x-tenant": "acme" },
|
||||
initialEnvironments: {
|
||||
production: {
|
||||
url: "https://api.example.com/graphql",
|
||||
subscriptionsEndpoint: "wss://api.example.com/graphql",
|
||||
headers: { "x-env": "prod" },
|
||||
variables: { region: "us-east-1" },
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Security posture
|
||||
|
||||
- Strict Content-Security-Policy on every HTML response.
|
||||
- `script-src 'self'` — no inline scripts.
|
||||
- `style-src 'self' 'unsafe-inline'` — required for the Altair shell.
|
||||
- `frame-ancestors 'none'` — clickjacking defence.
|
||||
- `X-Content-Type-Options: nosniff`, `Referrer-Policy: no-referrer`.
|
||||
- Static assets carry `Cache-Control: public, max-age=31536000, immutable`.
|
||||
|
||||
## Observability
|
||||
|
||||
Emits one OTel counter: `graphql.ui.requests_total` with label
|
||||
`ui="altair"`. The metric name is deliberately identical to the
|
||||
GraphiQL sibling so dashboards can sum across both UIs by dropping
|
||||
the `ui` label.
|
||||
|
||||
## Error codes
|
||||
|
||||
- `GRAPHQL_UI_ALTAIR.ASSET_MISSING` — request for a static asset the
|
||||
bundled registry doesn't recognise (404).
|
||||
- `GRAPHQL_UI_ALTAIR.ENDPOINT_COLLISION` — `mount()` called against a
|
||||
router that already serves `GET <uiEndpoint>` (typically the
|
||||
GraphiQL sibling is wired against the same path).
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user