Search by

linkfast / exengine-graphql

gchiappe

GraphQL for the ExEngine microframework: schema-first, precompiled schema, persisted queries.

Package info

gitlab.com/linkfast/oss/exengine-extensions/exengine-graphql

Issues

Type:exengine-extension

pkg:composer/linkfast/exengine-graphql

Statistics

Installs: 34

Dependents: 1

Suggesters: 0

Stars: 0

1.0.0-a1 2026-10-13 00:59 UTC

This package is not auto-updated.

Last update: 2026-10-14 05:53:40 UTC


README

GraphQL for the ExEngine microframework, built on webonyx/graphql-php. The schema comes first and is precompiled during development. For production there are persisted queries and query limits.

© LinkFast S.A. (https://linkfast.io) · MIT License

In development (pre-releases 1.0.0-aN).

Requirements

  • PHP 8.1 or higher
  • ExEngine 1.3.0-a3 or higher (needed for explicit routes)
  • Optional: ext-apcu, so that PHP-FPM processes share automatic persisted queries

Installation

exen extension:add linkfast/exengine-graphql:^1.0.0-a1

You can also run composer require linkfast/exengine-graphql:^1.0.0-a1. ExEngine activates the extension at boot.

Then generate the code of your schema with exen (1.0.0-a6 or higher), which reads it with this package's webonyx/graphql-php:

exen contract:add schema.graphql --name shop                       # or: exen new shop --api schema.graphql
exen contract:add schema.graphql --name shop --operations contracts/shop   # with trusted documents

exen writes the models, one interface per type you resolve (QueryApi, MutationApi, ...), the SchemaDefinition with the precompiled schema, the Extension that registers it, and your resolvers (src/Shop/QueryResolver.php), once. Run exen generate after editing the schema. See the exen README for the details and for generated GraphQL clients.

How it works

The extension serves the application's schema at graphql.path (default /graphql):

  • GET accepts queries only.
  • POST accepts any operation, sent either as a JSON body (query, variables, operationName, extensions) or as the operation text with Content-Type: application/graphql.

The application registers its schema as a SchemaDefinition, which exen generate writes:

  • ast() returns the SDL already parsed into an array during development, so nothing is parsed at runtime. Each process builds the schema once, and a RoadRunner worker reuses it for every request.
  • resolvers() lists, for each GraphQL type, the application class that resolves it and the fields that class handles: every field of the root types, and the fields with arguments or marked @resolve. That class is created through dependency injection once per request. Any other field is read from the parent value, as a public property or an array key.
  • enums() maps GraphQL enums to PHP backed enums. Resolvers receive and return those enums.
  • types() maps GraphQL object types to their PHP classes, which is how interfaces and unions are resolved.
  • documents() lists the trusted documents as sha256 => operation (from the operation documents exen validated).

To report an error the client should see, a resolver throws ExEngine\GraphQL\UserError, optionally with a code that appears in extensions.code. Any other exception is reported only as "Internal server error".

Configuration

KeyDefaultDescription
graphql.path/graphqlPath of the endpoint
graphql.introspectiontrueAllow introspection (turn it off in production)
graphql.max-depth15Maximum query depth; 0 for no limit
graphql.max-complexity0Maximum query complexity; 0 for no limit
graphql.trusted-documentsfalseRun only the trusted documents, sent by their sha256 (documentId)
graphql.apqoffAutomatic persisted queries: off, memory (per process) or apcu
graphql.debugfalseInclude exception messages and traces in errors (development only)

Development

composer install
vendor/bin/phpunit

License

MIT, see LICENSE.