Trax CLI
The Trax CLI generates Trax API projects from existing API schemas. Point it at a GraphQL SDL file or an OpenAPI spec and it scaffolds an API project (via dotnet new trax-api) alongside a shared trains library with trains, junctions, input/output records, and wiring — following the same structure as the DistributedWorkers sample.
Prerequisites
- The
trax-apitemplate must be installed:
dotnet new install Trax.SamplesInstallation
Install as a global .NET tool:
dotnet tool install --global Trax.CliUsage
trax generate --schema <path> --output <dir> --name <project-name> [--type graphql|openapi] [--force]Options
| Option | Required | Description |
|---|---|---|
--schema | Yes | Path to the schema file (.graphql, .gql, .json, .yaml, .yml) |
--output | Yes | Output directory for the generated project |
--name | Yes | Project name (used for namespace and .csproj) |
--type | No | Force schema type: graphql or openapi. Auto-detected from file extension if omitted. |
--force | No | Overwrite the output directory if it already exists |
Examples
# Generate from a GraphQL schema
trax generate --schema ./schema.graphql --output ./MyProject --name MyProject
# Generate from an OpenAPI spec
trax generate --schema ./openapi.json --output ./MyProject --name MyProject
# Force schema type detection
trax generate --schema ./spec.yaml --output ./MyProject --name MyProject --type openapi
# Overwrite existing output
trax generate --schema ./schema.graphql --output ./MyProject --name MyProject --forceSchema-to-Train Mapping
GraphQL
Each field on the Query type becomes a [TraxQuery] train. Each field on the Mutation type becomes a [TraxMutation] train. Subscription fields are skipped.
Field arguments become properties on the train's input record. The return type maps to the output record or a shared model type.
OpenAPI / REST
Each endpoint becomes a train. GET endpoints become [TraxQuery] trains; POST, PUT, DELETE, and PATCH endpoints become [TraxMutation] trains.
Path parameters, query parameters, and request body fields are merged into a single input record. The response schema becomes the output type.
Generated Project Structure
The CLI produces two projects: an API project (from the trax-api template) and a shared trains library (generated from the schema). This follows the same pattern as the DistributedWorkers sample.
Given a schema with a createPlayer mutation and getPlayer query:
MyProject/
├── MyProject.Api/ # From dotnet new trax-api
│ ├── MyProject.Api.csproj # + ProjectReference to trains library
│ ├── Program.cs # Patched: AddMediator scans trains assembly
│ ├── appsettings.json
│ └── Trains/ # Template sample trains (HelloWorld, Lookup)
│ └── ...
├── MyProject.Trains/ # Generated from schema
│ ├── MyProject.Trains.csproj # Class library (not web SDK)
│ ├── ManifestNames.cs # Centralized manifest external IDs
│ ├── Models/
│ │ └── Player.cs
│ └── Trains/
│ └── Players/
│ ├── CreatePlayer/
│ │ ├── ICreatePlayerTrain.cs
│ │ ├── CreatePlayerTrain.cs
│ │ ├── CreatePlayerInput.cs
│ │ └── Junctions/
│ │ └── CreatePlayerJunction.cs
│ └── GetPlayer/
│ ├── IGetPlayerTrain.cs
│ ├── GetPlayerTrain.cs
│ ├── GetPlayerInput.cs
│ └── Junctions/
│ └── GetPlayerJunction.cs
What gets generated
- API project — a fully wired Trax API from the
trax-apitemplate, with itsProgram.cspatched to scan the trains library assembly and aProjectReferenceto the trains library. - Trains library — a class library containing all the domain code:
- ManifestNames.cs — centralized
const stringidentifiers for each operation (kebab-case), matching the pattern used in the DistributedWorkers sample. - Trains are grouped into folders by noun (e.g.,
createPlayerandgetPlayerboth go underPlayers/). - Shared types referenced by multiple operations are placed in
Models/. - Enums are also placed in
Models/. - Junctions contain a
throw new NotImplementedException()with a TODO comment — this is where you add your business logic. - For OpenAPI endpoints, the junction includes the original HTTP method and path as a comment.
- ManifestNames.cs — centralized
Why two projects?
This structure separates infrastructure from domain logic. The trains library can be referenced by multiple projects — an API, a scheduler, standalone workers — without duplicating train definitions. This is the same pattern demonstrated in the DistributedWorkers sample with Trax.Samples.EnergyHub.
Type Mapping
GraphQL to C#
| GraphQL | C# |
|---|---|
String | string |
ID | string |
Int | int |
Float | double |
Boolean | bool |
DateTime | DateTime |
Long, BigInt | long |
Decimal | decimal |
[T] | List<T> |
T! | required T |
T (nullable) | T? |
| Custom scalars | string (with TODO) |
OpenAPI to C#
| OpenAPI | C# |
|---|---|
string | string |
string + date-time | DateTime |
string + date | DateOnly |
string + uuid | Guid |
string + uri | Uri |
string + binary | byte[] |
integer | int |
integer + int64 | long |
number | double |
number + float | float |
boolean | bool |
array | List<T> |
object + additionalProperties | Dictionary<string, T> |
$ref | Named C# record |
enum (string) | C# enum |
After Generating
cdinto the API project directory (MyProject/MyProject.Api)- Run
dotnet restore - Search for
TODOin the junction files underMyProject.Trains/and implement your business logic - Start PostgreSQL (
docker compose up -dor similar) - Update the connection string in
appsettings.jsonif needed - Run
dotnet runto start the API - Open
http://localhost:5002/trax/graphqlin a browser for the GraphQL playground