Contributor-facing documentation for the Graphitron generator: how the pipeline classifies a GraphQL schema, what code it emits, and the design principles that govern both. For end-user documentation (writing schemas, wiring up Maven, running the generator), see the user manual.
You came here because…
You want to extend the runtime, wire per-request values into Graphitron.newExecutionInput(…), register custom scalars, hook in jOOQ listeners. → Runtime Extension Points.
You’re integrating with Apollo Federation, the @link opt-in, the <schemaInput tag> flag, providing a custom entity fetcher. → Getting started → Federation.
You want to understand rejections, what AUTHOR_ERROR / INVALID_SCHEMA / DEFERRED actually mean in the builder, why rejection is a typed variant rather than a string, how Levenshtein candidate hints get attached. → Typed rejection.
You’re integrating an editor or agent with the dev loop, what the dev Mojo wires up, what the LSP / schema watcher / classpath watcher each watch, why idempotent writes matter. → Getting started → Dev loop.
You want to read the classification taxonomy, every variant the schema builder produces, every generator’s input. → Code Generation Triggers.
You’re looking for a deeper reference, the architectural principles that govern both classifier and emitter, the test-tier rubric, the unified argument-resolution lift, the dispatch-axis model behind DataLoader-backed source-side fields. → see Rewrite Design Principles, Test-tier guide, Argument Resolution, Dispatch axes. The ongoing-work view lives at Rewrite Roadmap.
Pipeline at a glance
flowchart LR
A[".graphqls files"] --> B["RewriteSchemaLoader<br/>(parse + auto-inject<br/>directives.graphqls)"]
B --> C["GraphitronSchemaBuilder<br/>(classify into<br/>GraphitronSchema)"]
C --> D["GraphitronSchemaValidator<br/>(reject Unclassified*,<br/>surface diagnostics)"]
D --> E["Generators<br/>(TypeFetcher / TypeClass /<br/>TypeConditions /<br/>QueryConditions / ...)"]
E --> F["JavaFile.writeToPath<br/>(idempotent writes,<br/>orphan sweep)"]
F --> G["consumer compile<br/>(graphitron-sakila-example<br/>verifies type + behaviour)"]
Three things to know about this pipeline that the diagram doesn’t show:
-
The loader auto-injects
directives.graphqlsfrom thegraphitronjar before parse, so consumer schemas never re-declare the canonical directives. This is what lets the classifier treat directive presence as ground truth one stage later: the schema loader has already fed every directive declaration into the parsed schema, regardless of whether the consumer’s.graphqlsfiles mentioned them. -
Classification is the only place directives are read.
GraphitronSchemaBuilderreads each directive once and resolves everything the generator needs into typed model values: table names, column references, method names, extraction strategies, batch keys. Generators downstream see the classified model and never touch directive syntax. The boundary keeps the model "what to emit," never "what to interpret." -
The writer’s idempotency contract is unconditional. On every run,
JavaFile.writeToPathwrites only files whose rendered content differs from disk (SHA-256 comparison) and deletes orphans in rewrite-owned sub-packages. Both halves run on every emit, not just full builds; this is what keeps the dev-loop’s IDE-recompile times proportional and what stops a delete-a-type cycle from leaving stale files behind. Pinned byIdempotentWriterTestandGeneratorDeterminismTest.
The Code Generation Triggers page is a zoomed-in view of the middle three stages (schema → classified model → generators). This index page names the loader, the validator, the writer’s idempotency contract, and the consumer compile that closes the loop.
Modules
graphitron-rewrite/ is a nested monorepo with its own parent pom (graphitron-rewrite-parent, 10-SNAPSHOT). Nine modules cover the generator, its inputs, its consumers, and the tooling that wraps both ends:
| Module | Purpose |
|---|---|
|
Internal fork of Square JavaPoet; the emit-time API every generator builds through. |
|
The generator core: schema loader, classifier, validator, and every generator. |
|
Builds the test database and runs jOOQ codegen against it. |
|
Packages those generated jOOQ classes (Sakila-inspired catalog plus the |
|
|
|
Maven plugin: |
|
End-to-end consumer: compiles emitted Java against a real jOOQ catalog, executes it against Postgres, and serves a runnable Quarkus + JAX-RS reference application from the same module. |
|
Editor LSP server for |
|
Regenerates |
Per-module READMEs are deliberately not maintained; this table is the orientation surface, and lives next to the architecture pages so it stays in sync with the pipeline they describe.
Publishing
Trunk runs at 10-SNAPSHOT; releases are cut from tag-driven GitHub Releases. The .github/workflows/maven-publish.yml workflow accepts v<MAJOR>.<MINOR>.<PATCH> and v<MAJOR>.<MINOR>.<PATCH>-RC<n>, sets the version across the rewrite reactor, signs (sources + javadoc + GPG), and pushes to Maven Central via the central-publishing-maven-plugin with autoPublish=true. Maven version ordering treats 10.0.0-RC1 as strictly less than 10.0.0, so consumers asking for [10.0.0,) won’t pick up RCs by accident. Snapshots aren’t published; the rewrite parent declares no <snapshotRepository>, so an accidental mvn deploy on 10-SNAPSHOT fails fast.
Publishable surface: graphitron-javapoet, graphitron, graphitron-lsp, graphitron-maven-plugin. Test fixtures and example consumers (graphitron-fixtures-codegen, graphitron-sakila-db, graphitron-sakila-service, graphitron-sakila-example, roadmap-tool, docs) carry <maven.deploy.skip>true</maven.deploy.skip>.