Files
2026-06-09 21:06:27 +01:00
..
2026-06-09 21:06:27 +01:00

@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 — Defines the stable GRAPHQL.* error-code registry for @suaveplan/api-plugin-graphql and the GraphQLError class con…
    • error-codes — Defines the stable GRAPHQL.* error-code registry for @suaveplan/api-plugin-graphql and the GraphQLError class con…
  • otel — Defines the OpenTelemetry instruments emitted from createQueryExecutedMiddleware. The middleware is the only producti…
    • instruments — Defines the OpenTelemetry instruments emitted from createQueryExecutedMiddleware. The middleware is the only producti…
  • plugin — Declares defineGraphQLPlugin(options), the factory that produces a GraphQLPluginDefinition consumable by the Suavep…
    • plugin — Declares defineGraphQLPlugin(options), the factory that produces a GraphQLPluginDefinition consumable by the Suavep…
  • resolver — Implements ResolverComposer (the fluent builder for resolver maps), the two built-in middleware factories `requireRol…
    • resolver — Implements ResolverComposer (the fluent builder for resolver maps), the two built-in middleware factories `requireRol…
  • schema-builder — Declares SchemaBuilder, the fluent builder for GraphQL schema definitions. Consumers describe types, queries, mutatio…
    • schema-builder — Declares SchemaBuilder, the fluent builder for GraphQL schema definitions. Consumers describe types, queries, mutatio…
  • schemas — Defines DefineGraphQLPluginOptionsSchema, the Zod schema wired at the package boundary inside defineGraphQLPlugin.…
    • options — Defines DefineGraphQLPluginOptionsSchema, the Zod schema wired at the package boundary inside defineGraphQLPlugin.…
  • type-builder — Declares the TypeBuilder class — the inner builder SchemaBuilder hands to user-supplied callbacks when declaring ob…
    • type-builder — 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<GraphQLEventMap> 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

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

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.