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-api template must be installed:
dotnet new install Trax.Samples

Installation

Install as a global .NET tool:

dotnet tool install --global Trax.Cli

Usage

trax generate --schema <path> --output <dir> --name <project-name> [--type graphql|openapi] [--force]

Options

OptionRequiredDescription
--schemaYesPath to the schema file (.graphql, .gql, .json, .yaml, .yml)
--outputYesOutput directory for the generated project
--nameYesProject name (used for namespace and .csproj)
--typeNoForce schema type: graphql or openapi. Auto-detected from file extension if omitted.
--forceNoOverwrite 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 --force

Schema-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-api template, with its Program.cs patched to scan the trains library assembly and a ProjectReference to the trains library.
  • Trains library — a class library containing all the domain code:
    • ManifestNames.cs — centralized const string identifiers for each operation (kebab-case), matching the pattern used in the DistributedWorkers sample.
    • Trains are grouped into folders by noun (e.g., createPlayer and getPlayer both go under Players/).
    • 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.

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#

GraphQLC#
Stringstring
IDstring
Intint
Floatdouble
Booleanbool
DateTimeDateTime
Long, BigIntlong
Decimaldecimal
[T]List<T>
T!required T
T (nullable)T?
Custom scalarsstring (with TODO)

OpenAPI to C#

OpenAPIC#
stringstring
string + date-timeDateTime
string + dateDateOnly
string + uuidGuid
string + uriUri
string + binarybyte[]
integerint
integer + int64long
numberdouble
number + floatfloat
booleanbool
arrayList<T>
object + additionalPropertiesDictionary<string, T>
$refNamed C# record
enum (string)C# enum

After Generating

  1. cd into the API project directory (MyProject/MyProject.Api)
  2. Run dotnet restore
  3. Search for TODO in the junction files under MyProject.Trains/ and implement your business logic
  4. Start PostgreSQL (docker compose up -d or similar)
  5. Update the connection string in appsettings.json if needed
  6. Run dotnet run to start the API
  7. Open http://localhost:5002/trax/graphql in a browser for the GraphQL playground