Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# `endpoints/http` — `POST /graphql` + `GET /graphql/sdl`
|
||||
|
||||
## Purpose
|
||||
|
||||
`endpoints/http` mounts the two HTTP endpoints every GraphQL adapter
|
||||
must expose: `POST /graphql` for operation dispatch and
|
||||
`GET /graphql/sdl` for schema introspection by external tooling. The
|
||||
paths are driven by `ApolloGraphqlOptions` so operators can rename
|
||||
them — useful for shops that namespace internal APIs under `/internal/`.
|
||||
|
||||
The module is framework-agnostic in that it takes a `Router` from
|
||||
`@suaveplan/api-router` and registers handlers via the router's verb
|
||||
methods. Concrete router adapters (`api-router-hono`,
|
||||
`api-router-in-memory`) consume the same `Router` interface.
|
||||
|
||||
## Features
|
||||
|
||||
- Mount paths driven by `ApolloGraphqlOptions.endpoint` /
|
||||
`sdlEndpoint`.
|
||||
- `executeQuery` handler accepts a `{ body, headers, context }` envelope
|
||||
— the host's request pipeline decodes the HTTP frame into this shape
|
||||
before dispatch.
|
||||
- `sdl` handler returns the merged SDL synchronously.
|
||||
- Returns a teardown function (currently no-op; reserved for hot
|
||||
reload).
|
||||
- Empty `headers` default — handlers that the host invokes without an
|
||||
explicit map see `{}` rather than `undefined`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { Router } from "@suaveplan/api-router";
|
||||
import { mountGraphqlHttpEndpoints } from "@suaveplan/api-graphql-apollo/endpoints";
|
||||
import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options";
|
||||
|
||||
const router = new Router();
|
||||
mountGraphqlHttpEndpoints({
|
||||
router,
|
||||
options: parseApolloGraphqlOptions(),
|
||||
executeQuery: async (r) => ({ data: { ok: true } }),
|
||||
sdl: () => "type Query { ok: Boolean! }",
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Drive the executeQuery handler through the engine instead of a stub
|
||||
so the router calls into Apollo Server's lifecycle on every POST:
|
||||
|
||||
```ts
|
||||
import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo";
|
||||
|
||||
const engine = createApolloGraphqlEngine();
|
||||
engine.buildSchema(registry);
|
||||
mountGraphqlHttpEndpoints({
|
||||
router,
|
||||
options,
|
||||
executeQuery: async ({ body, context }) => {
|
||||
const req = body as { query: string; variables?: Record<string, unknown> };
|
||||
return await engine.executeQuery(req, context as RequestContext);
|
||||
},
|
||||
sdl: () => engine.sdl() ?? "",
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `GraphqlHttpHandler` — `(req: { body, headers, context }) → Promise<unknown>`.
|
||||
- `GraphqlSdlHandler` — `() → string`.
|
||||
- `MountHttpEndpointsArgs` — `{ router, options, executeQuery, sdl }`.
|
||||
- `mountGraphqlHttpEndpoints(args): () → void` — returns teardown.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The handler returns a free-form `Record<string, unknown>` because the
|
||||
host's transport adapter serialises the response to wire form. The
|
||||
SDL handler is synchronous on purpose; SDL is computed once at
|
||||
`buildSchema` time and held in memory thereafter. The teardown
|
||||
closure is a no-op today but exists so callers do not need to rewrite
|
||||
their host-wiring code when hot reload lands.
|
||||
@@ -0,0 +1,74 @@
|
||||
# `endpoints/ui-proxy` — `/graphql/ui` proxy
|
||||
|
||||
## Purpose
|
||||
|
||||
`endpoints/ui-proxy` mounts the `/graphql/ui` endpoint. The Apollo
|
||||
engine never embeds Apollo's landing page — UI is opt-in via a
|
||||
separate package (GraphiQL, Altair, …), identical to Yoga's stance.
|
||||
When no UI plugin is wired the endpoint returns `404` with a short
|
||||
text body explaining the policy; when a plugin is wired the endpoint
|
||||
forwards its `render()` output verbatim.
|
||||
|
||||
This module is deliberately framework-agnostic: it accepts a
|
||||
`@suaveplan/api-router` `Router` and a UI plugin descriptor with a
|
||||
`render()` method. The host wires whichever GraphiQL / Altair package
|
||||
it prefers without the engine becoming aware of the choice.
|
||||
|
||||
## Features
|
||||
|
||||
- 404 by default — no Apollo landing page leakage.
|
||||
- Custom mime type — UI plugins that ship binary (e.g. WASM) bodies
|
||||
can override the default `text/html`.
|
||||
- Driven by `ApolloGraphqlOptions.uiEndpoint` — operator can rename
|
||||
the path.
|
||||
- Returns a teardown handle reserved for future hot reload.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { Router } from "@suaveplan/api-router";
|
||||
import { mountGraphqlUiProxy } from "@suaveplan/api-graphql-apollo/endpoints";
|
||||
import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options";
|
||||
|
||||
const router = new Router();
|
||||
mountGraphqlUiProxy({
|
||||
router,
|
||||
options: parseApolloGraphqlOptions(),
|
||||
ui: null,
|
||||
});
|
||||
// GET /graphql/ui → 404
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Wire a GraphiQL-style UI plugin so the same router serves the
|
||||
playground at `/graphql/ui`:
|
||||
|
||||
```ts
|
||||
mountGraphqlUiProxy({
|
||||
router,
|
||||
options,
|
||||
ui: {
|
||||
render: () =>
|
||||
`<!doctype html>
|
||||
<html><body>
|
||||
<div id="root"></div>
|
||||
<script>/* GraphiQL bundle */</script>
|
||||
</body></html>`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `GraphqlUiPlugin` — `{ render(): string; contentType?: string }`.
|
||||
- `UiProxyResponse` — `{ status: 200 | 404; body: string; contentType: string }`.
|
||||
- `mountGraphqlUiProxy(args): () → void`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The UI plugin contract is intentionally minimal — `render()` returns
|
||||
a string and the proxy serves it. Future evolution (CSP nonces,
|
||||
per-tenant configuration) lives in the UI plugin itself, not in this
|
||||
module. The 404 response body is `text/plain` so curl users see a
|
||||
human-readable explanation rather than an empty page.
|
||||
Reference in New Issue
Block a user