# @suaveplan/api-plugin-graphql - GraphQL adapter plugin for @suaveplan/api — fluent SchemaBuilder / TypeBuilder for object/input/enum/interface/union types and queries/mutations/subscriptions, ResolverComposer with composable global + per-type middleware, requireRoles / validateArgs / createQueryExecutedMiddleware built-ins, typed graphqlEvents EventBus, defineGraphQLPlugin factory producing a GraphQLPluginDefinition compatible with the definePlugin pattern. 6 GRAPHQL.* error codes, Zod-validated boundary, OTel resolvers_executed_total + resolver_duration_ms instruments. GraphQL description + resolver-composition layer for `@suaveplan/api`. Server-tier — runs in Bun and Node. The package provides a typed, builder-driven way to declare GraphQL APIs without raw SDL. It does **not** ship a `graphql-js` executor — its output is a `GraphQLPluginDefinition` consumed by downstream tooling (a future `@suaveplan/api-plugin-graphql-executor`, or any third-party executor). ## Documentation tree - [error-codes](./src/error-codes/error-codes.md) — Defines the stable `GRAPHQL.*` error-code registry for `@suaveplan/api-plugin-graphql` and the `GraphQLError` class con… - [error-codes](./src/error-codes/error-codes.md) — Defines the stable `GRAPHQL.*` error-code registry for `@suaveplan/api-plugin-graphql` and the `GraphQLError` class con… - [otel](./src/otel/instruments.md) — Defines the OpenTelemetry instruments emitted from `createQueryExecutedMiddleware`. The middleware is the only producti… - [instruments](./src/otel/instruments.md) — Defines the OpenTelemetry instruments emitted from `createQueryExecutedMiddleware`. The middleware is the only producti… - [plugin](./src/plugin/plugin.md) — Declares `defineGraphQLPlugin(options)`, the factory that produces a `GraphQLPluginDefinition` consumable by the Suavep… - [plugin](./src/plugin/plugin.md) — Declares `defineGraphQLPlugin(options)`, the factory that produces a `GraphQLPluginDefinition` consumable by the Suavep… - [resolver](./src/resolver/resolver.md) — Implements `ResolverComposer` (the fluent builder for resolver maps), the two built-in middleware factories `requireRol… - [resolver](./src/resolver/resolver.md) — Implements `ResolverComposer` (the fluent builder for resolver maps), the two built-in middleware factories `requireRol… - [schema-builder](./src/schema-builder/schema-builder.md) — Declares `SchemaBuilder`, the fluent builder for GraphQL schema definitions. Consumers describe types, queries, mutatio… - [schema-builder](./src/schema-builder/schema-builder.md) — Declares `SchemaBuilder`, the fluent builder for GraphQL schema definitions. Consumers describe types, queries, mutatio… - [schemas](./src/schemas/options.md) — Defines `DefineGraphQLPluginOptionsSchema`, the Zod schema wired at the package boundary inside `defineGraphQLPlugin`.… - [options](./src/schemas/options.md) — Defines `DefineGraphQLPluginOptionsSchema`, the Zod schema wired at the package boundary inside `defineGraphQLPlugin`.… - [type-builder](./src/type-builder/type-builder.md) — Declares the `TypeBuilder` class — the inner builder `SchemaBuilder` hands to user-supplied callbacks when declaring ob… - [type-builder](./src/type-builder/type-builder.md) — Declares the `TypeBuilder` class — the inner builder `SchemaBuilder` hands to user-supplied callbacks when declaring ob… ## What you get - `defineGraphQLPlugin(options)` — typed factory producing a `GraphQLPluginDefinition` (name + merged config + lifecycle hooks + `getSchema()` / `getResolvers()`). - `SchemaBuilder` — fluent builder for object / input / enum / interface / union types and queries / mutations / subscriptions. - `TypeBuilder` — chainable field declarations consumed by `SchemaBuilder`. - `ResolverComposer` — `use` / `useForType` / `addResolver` / `addResolvers` / `build`, with right-to-left middleware composition. - `requireRoles(...roles)` — auth-check middleware. Throws `GraphQLError(UNAUTHENTICATED | INSUFFICIENT_ROLE)`. - `validateArgs(validator)` — arg-validation middleware. Throws `GraphQLError(VALIDATION_FAILED)`. - `graphqlEvents` — typed `EventBus` for `graphql:query:executed`. - `createQueryExecutedMiddleware(bus?)` — production observability middleware recording OTel instruments + emitting events. - `GRAPHQL_CODES` + `GraphQLError` — 6 stable codes (`UNAUTHENTICATED`, `INSUFFICIENT_ROLE`, `VALIDATION_FAILED`, `INVALID_INPUT`, `TYPE_NOT_FOUND`, `DUPLICATE_RESOLVER`). - OTel — `graphql.resolvers_executed_total{outcome}` counter and `graphql.resolver_duration_ms` histogram. ## Quick-start ```ts import { defineGraphQLPlugin, ResolverComposer, SchemaBuilder, requireRoles, validateArgs, createQueryExecutedMiddleware, graphqlEvents, } from "@suaveplan/api-plugin-graphql"; const schema = new SchemaBuilder() .addType("User", (t) => t.field("id", "ID", { required: true }) .field("email", "String", { required: true }) ) .addQuery("user", "User", { args: [{ name: "id", type: "ID", required: true, isList: false }], }) .addMutation("deleteUser", "Boolean", { required: true, args: [{ name: "id", type: "ID", required: true, isList: false }], }) .build(); const resolvers = new ResolverComposer() .useForType("Query", createQueryExecutedMiddleware()) .useForType("Mutation", createQueryExecutedMiddleware()) .useForType("Mutation", requireRoles("admin")) .useForType( "Mutation", validateArgs((a) => (typeof a.id === "string" ? null : "id required")) ) .addResolver("Query", "user", (_p, args) => ({ id: args.id, email: "x@y" })) .addResolver("Mutation", "deleteUser", () => true) .build(); graphqlEvents.on("graphql:query:executed", (e) => { console.log(`${e.operationType}.${e.operationName} ${e.durationMs}ms`); }); const definition = defineGraphQLPlugin({ name: "users-gql", version: "0.1.0", schema, resolvers, }); ``` ## Modules - [`error-codes/error-codes.md`](src/error-codes/error-codes.md) — `GRAPHQL_CODES`, `GraphQLError`. - [`otel/instruments.md`](src/otel/instruments.md) — OTel instruments. - [`plugin/plugin.md`](src/plugin/plugin.md) — `defineGraphQLPlugin`. - [`resolver/resolver.md`](src/resolver/resolver.md) — `ResolverComposer`, `requireRoles`, `validateArgs`, `createQueryExecutedMiddleware`, `graphqlEvents`. - [`schema-builder/schema-builder.md`](src/schema-builder/schema-builder.md) — `SchemaBuilder`. - [`schemas/options.md`](src/schemas/options.md) — `DefineGraphQLPluginOptionsSchema`. - [`type-builder/type-builder.md`](src/type-builder/type-builder.md) — `TypeBuilder`. - [`types/graphql.types.md`](src/types/graphql.types.md) — full type surface. ## Scope This package is functional-parity with upstream `@suaveplan/api-plugin-graphql` (suaveplan main, v1.0.4) plus hardening (typed errors, Zod boundary, OTel). Live execution (`graphql-js`), federation, persisted queries, subscriptions transport, SDL emission, and schema-registry publishing are **out of scope** for this release and are enumerated in `enterprise/api-plugin-graphql.md` §3 as future enterprise upgrades. ## License MIT.