Initial Commit
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# `@suaveplan/api-graphql-ui-graphiql` — GraphiQL UI mount at `/graphql/ui`
|
||||
|
||||
**Package**: `@suaveplan/api-graphql-ui-graphiql`
|
||||
**Status**: PROPOSED
|
||||
**Type**: new-package
|
||||
**Stage**: 7 (GraphQL + WebSocket / SSE engines) — see umbrella `openspec/changes/api-plugin-foundation/`
|
||||
|
||||
## Why
|
||||
|
||||
Per design doc §10.6 the foundation reserves `GET /graphql/ui` for an interactive query explorer but does not bundle one by default — UI choice is opt-in via a separate package so the host's runtime image stays minimal for production deployments that don't need it. GraphiQL is the default option called out in §10.6 ("`GET /graphql/ui` — GraphiQL (or Altair via `api-graphql-ui-altair`)"). Operators wire this package when they want the canonical GraphQL UI; they wire `api-graphql-ui-altair` instead when they prefer Altair.
|
||||
|
||||
The GraphQL engine adapters (`api-graphql-yoga`, `api-graphql-apollo`) intentionally return 404 at `/graphql/ui` when no UI plugin is wired — so this package is the standard way to give developers an in-browser explorer.
|
||||
|
||||
## What changes
|
||||
|
||||
Net-new package depending on `@suaveplan/api-types`, `@suaveplan/api-router`, `@suaveplan/api-graphql`, `@suaveplan/error`, `@suaveplan/logger`, and `graphiql` (peer; static assets served from this package, not fetched from a CDN).
|
||||
|
||||
- ADDED: `createGraphiqlUi(opts)` — factory returning a `RouterPlugin` value that registers a `GET <uiEndpoint>` handler serving the GraphiQL HTML shell + assets.
|
||||
- ADDED: `GraphiqlUiOptions` — Zod-validated config: `uiEndpoint` (default `/graphql/ui`), `graphqlEndpoint` (default `/graphql`), `subscriptionEndpoint` (default `/graphql/ws`), `theme` (`"light"` | `"dark"` | `"system"`, default `"system"`), `defaultQuery`, `defaultVariableEditorOpen`, `editorOptions` (codemirror passthroughs).
|
||||
- ADDED: Static-asset serving — GraphiQL's bundle is served from the package's own `dist/assets/` (no CDN dependency). The HTML shell embeds versioned hashes for cache-busting.
|
||||
- ADDED: CSP/security headers — `Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'` (GraphiQL needs inline styles) emitted on the HTML response.
|
||||
- ADDED: `GRAPHQL_UI_GRAPHIQL_*` error codes: `GRAPHQL_UI_GRAPHIQL_ASSET_MISSING`, `GRAPHQL_UI_GRAPHIQL_ENDPOINT_COLLISION`.
|
||||
- ADDED: OTel instruments: `graphql.ui.requests_total { ui: "graphiql" }` counter.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- A CDN-fetched GraphiQL variant — bundled assets only, per the foundation's "no runtime CDN fetches" rule (security + offline-dev posture).
|
||||
- The Altair alternative — separate package `api-graphql-ui-altair`.
|
||||
- Schema introspection — that's the engine adapter's job (Yoga / Apollo configure introspection on `/graphql`). This package just renders an explorer that calls into whatever the engine exposes.
|
||||
- Authentication on the UI route — host config decides whether `/graphql/ui` is behind auth; this package surfaces a `RouterPlugin` whose route options can be configured by the operator.
|
||||
|
||||
## Source mapping
|
||||
|
||||
Genesis-original. Source of design intent: `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`.
|
||||
|
||||
| Requirement | Design doc section |
|
||||
|---|---|
|
||||
| `GET /graphql/ui` default to GraphiQL | §10.6 |
|
||||
| UI as opt-in via separate package | §10.6 + cross-ref to engine adapters returning 404 when not wired |
|
||||
| Theme / config passthroughs | §10.6 (implied — interactive explorer) |
|
||||
|
||||
## Verification approach
|
||||
|
||||
- `src/factory/create-graphiql-ui.test.ts` — factory returns a valid `RouterPlugin`; HTML response shape; CSP header presence; asset 200s.
|
||||
- `src/factory/create-graphiql-ui.spec-conformance.test.ts` — pins that the mounted endpoint serves at `uiEndpoint` and that the response embeds the configured `graphqlEndpoint` + `subscriptionEndpoint`.
|
||||
- `src/assets/assets.test.ts` — every bundled asset reachable; missing-asset path raises `GRAPHQL_UI_GRAPHIQL_ASSET_MISSING`.
|
||||
- `tests/integration/graphiql-end-to-end.test.ts` (30000ms) — boots `api-graphql-yoga` + this UI plugin, opens a Playwright browser at `/graphql/ui`, runs a query through the live editor, asserts results render.
|
||||
|
||||
## Migration impact
|
||||
|
||||
None — additive only.
|
||||
Reference in New Issue
Block a user