first commit
This commit is contained in:
90
docs/api-stack/api/api-graphql-yoga/README.md
Normal file
90
docs/api-stack/api/api-graphql-yoga/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# @suaveplan/api-graphql-yoga — GraphQL Yoga engine adapter for @suaveplan/api-graphql. Default GraphQL engine per design doc §10.5. Implements the abstract GraphqlEngine contract from @suaveplan/api-graphql via createYogaGraphqlEngine(opts) — Zod-validated YogaGraphqlOptions, federation through @graphql-tools/schema makeExecutableSchema, schema-collision detection delegated to the canonical GRAPHQL.SCHEMA_COLLISION code, per-request DataLoader scoping bound to RequestContext, depth + complexity guards, masked errors / introspection toggles, graphql-ws subscription transport over an injected api-ws broker, OTel instruments (requests counter, request duration histogram, resolver duration histogram, subscriptions_active gauge, schema_rebuilds counter), 10 GRAPHQL_YOGA_* error codes, and a ./testing subpath re-exporting runGraphqlEngineConformance bound to the Yoga factory.
|
||||
|
||||
Stage-7 GraphQL Yoga engine adapter. **Default GraphQL engine** for the
|
||||
Suaveplan API plugin system per design doc §10.5 — Bun-friendly,
|
||||
fastest for our usage pattern, and simpler to operate than Apollo
|
||||
Server. Implements the abstract `GraphqlEngine` contract from
|
||||
`@suaveplan/api-graphql` so the same conformance suite
|
||||
(`runGraphqlEngineConformance`) passes against this adapter and any
|
||||
future engine; swapping engines is host-config-only.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [execute-helpers](./src/engine/execute-helpers.md) — Houses the smaller execution helpers the Yoga engine uses on every request, kept out of `yoga-engine.ts` so the orchest…
|
||||
- [yoga-engine](./src/engine/yoga-engine.md) — Implements the abstract `GraphqlEngine` contract from `@suaveplan/api-graphql` over the Yoga / `graphql-js` stack. The…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — Defines the frozen `GRAPHQL_YOGA.*` error-code registry and the `GraphqlYogaError` subclass of `SuaveplanError` used th…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — Defines the frozen `GRAPHQL_YOGA.*` error-code registry and the `GraphqlYogaError` subclass of `SuaveplanError` used th…
|
||||
- [federation](./src/federation/federation.md) — Aggregates plugin-side `GraphqlRegistry` contributions into a single `(MergedSchema, ResolverMap)` pair that the Yoga e…
|
||||
- [federation](./src/federation/federation.md) — Aggregates plugin-side `GraphqlRegistry` contributions into a single `(MergedSchema, ResolverMap)` pair that the Yoga e…
|
||||
- [guards](./src/guards/depth-and-complexity.md) — Implements the static depth + complexity guard that the Yoga engine runs after parsing each query and before execution.…
|
||||
- [depth-and-complexity](./src/guards/depth-and-complexity.md) — Implements the static depth + complexity guard that the Yoga engine runs after parsing each query and before execution.…
|
||||
- [instruments](./src/instruments/instruments.md) — Builds and caches the OpenTelemetry instrument bundle the Yoga GraphQL engine emits per request. The bundle covers a co…
|
||||
- [instruments](./src/instruments/instruments.md) — Builds and caches the OpenTelemetry instrument bundle the Yoga GraphQL engine emits per request. The bundle covers a co…
|
||||
- [loaders](./src/loaders/loaders.md) — Defines the per-request loader bag the Yoga engine constructs at pipeline step 7 and disposes at step 11. Two concurren…
|
||||
- [loaders](./src/loaders/loaders.md) — Defines the per-request loader bag the Yoga engine constructs at pipeline step 7 and disposes at step 11. Two concurren…
|
||||
- [options](./src/options/options.md) — Defines `YogaGraphqlOptions`, the Zod-validated configuration boundary that hosts use to wire `createYogaGraphqlEngine`…
|
||||
- [options](./src/options/options.md) — Defines `YogaGraphqlOptions`, the Zod-validated configuration boundary that hosts use to wire `createYogaGraphqlEngine`…
|
||||
- [subscriptions](./src/subscriptions/subscriptions.md) — Bridges the `WsBroker` contract from `@suaveplan/api-ws` to GraphQL `Subscription` resolvers via `AsyncIterable<Payload…
|
||||
- [subscriptions](./src/subscriptions/subscriptions.md) — Bridges the `WsBroker` contract from `@suaveplan/api-ws` to GraphQL `Subscription` resolvers via `AsyncIterable<Payload…
|
||||
- [testing](./src/testing/testing.md) — Binds the abstract `runGraphqlEngineConformance` from `@suaveplan/api-graphql/testing` to the Yoga engine factory so co…
|
||||
- [testing](./src/testing/testing.md) — Binds the abstract `runGraphqlEngineConformance` from `@suaveplan/api-graphql/testing` to the Yoga engine factory so co…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Modules
|
||||
|
||||
- **engine** — `createYogaGraphqlEngine(config)` + helpers
|
||||
(`maskOrPassthrough`, `withTimeout`, `assertIntrospectionAllowed`,
|
||||
`wrapSubscription`).
|
||||
- **federation** — `federatePlugins(entries)` aggregating multiple
|
||||
plugin contributions into one `(MergedSchema, ResolverMap)` pair via
|
||||
`mergeSdl` from `@suaveplan/api-graphql`.
|
||||
- **options** — Zod-validated `YogaGraphqlOptions` +
|
||||
`resolveYogaGraphqlOptions` with safe defaults
|
||||
(`endpoint: "/graphql"`, `maxQueryDepth: 10`,
|
||||
`maxQueryComplexity: 1000`, `timeoutMs: 30000`, `maskedErrors: true`).
|
||||
- **guards** — `enforceGuards(doc, { maxDepth, maxComplexity })` static
|
||||
depth + complexity rejection.
|
||||
- **loaders** — `buildRequestLoaders(factories)` per-request DataLoader
|
||||
bag bound to `RequestContext`.
|
||||
- **subscriptions** — `subscribeBrokerTopic(broker, topic, tenant)`
|
||||
bridges `api-ws` to GraphQL `AsyncIterable`.
|
||||
- **instruments** — `getYogaInstruments()` OTel counter / histogram /
|
||||
gauge bundle.
|
||||
- **error-codes** — 10 `GRAPHQL_YOGA.*` codes + `GraphqlYogaError`.
|
||||
- **testing** — `runYogaConformance(label?, config?)` bound conformance
|
||||
harness.
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import { createGraphqlRegistry } from "@suaveplan/api-graphql";
|
||||
import { createYogaGraphqlEngine } from "@suaveplan/api-graphql-yoga";
|
||||
|
||||
const engine = createYogaGraphqlEngine();
|
||||
const reg = createGraphqlRegistry();
|
||||
reg.addTypes("type Query { ping: String! }");
|
||||
reg.addResolvers({ Query: { ping: () => "pong" } });
|
||||
engine.buildSchema(reg);
|
||||
const result = await engine.executeQuery({ query: "{ ping }" }, ctx);
|
||||
```
|
||||
|
||||
## Why this engine?
|
||||
|
||||
- **Bun runtime parity** — graphql-yoga is a thin layer over `graphql-js`
|
||||
and runs natively under Bun without polyfills.
|
||||
- **WebSocket subscriptions over `api-ws`** — `graphql-ws` protocol
|
||||
bridged to the WS broker via `subscribeBrokerTopic`.
|
||||
- **Per-request DataLoader scoping** — design doc §10.3 mandates
|
||||
per-request DataLoader instances; the `buildRequestLoaders` helper
|
||||
enforces this at the engine boundary.
|
||||
- **Depth + complexity guards** — denial-of-service rejection before
|
||||
resolvers run.
|
||||
- **Masked error mode** — flips production error messages to
|
||||
`"Unexpected error."` while preserving the `path` for log-side
|
||||
debugging.
|
||||
|
||||
## License
|
||||
|
||||
MIT — Suaveplan Team.
|
||||
|
||||
Reference in New Issue
Block a user