How It Works
Rivet is a CLI tool — not a source generator — that uses Roslyn to analyse your C# project and emit TypeScript files.
Why a CLI tool, not a source generator?
Source generators run inside the compiler and are limited to emitting C# code into the current compilation. Rivet needs to:
- Emit
.tsfiles to an arbitrary output directory - Optionally emit Zod validators
- Optionally emit
openapi.json - Work across project boundaries
A CLI tool (like dotnet-ef or dotnet-format) can do all of this. You run it when you want, and it produces files where you want them.
Architecture
Forward pipeline: C# → TypeScript
.csproj
→ MSBuildWorkspace (Roslyn)
→ Compilation
→ Walkers (ContractWalker, EndpointWalker, TypeWalker)
→ Model (TsEndpointDefinition, TsTypeDefinition)
→ Emitters (TypeEmitter, ClientEmitter, ZodValidatorEmitter, OpenApiEmitter)
→ .ts files + openapi.json- Opens your
.csprojvia Roslyn'sMSBuildWorkspace - Discovers all types transitively from endpoint/contract signatures (plus any explicitly marked
[RivetType]) - Finds
[RivetClient]classes and[RivetEndpoint]methods — reads[HttpGet],[Route],[ProducesResponseType],[FromBody], etc. - Finds
[RivetContract]classes and reads theirRouteDefinition<T>chains via Roslyn's semantic model - Merges controller-sourced and contract-sourced endpoints (contract wins on collision)
- Groups types by C# namespace, promotes cross-referenced types to
common.ts - Emits per-controller client files and optionally
validators.tsandopenapi.json - With
--compile, emits JSON Schema + Zod validators and re-emits clients with assertion wiring
Reverse pipeline: OpenAPI → C#
openapi.json
→ OpenApiImporter (parser)
→ SchemaMapper (JSON Schema → C# types)
→ ContractBuilder (operations → RouteDefinition chains)
→ CSharpWriter
→ .cs files- Parses an OpenAPI 3.x JSON spec
- Maps
#/components/schemasto C# types (sealed records, enums, branded VOs) - Groups
#/pathsoperations by tag into[RivetContract]static classes - Emits
.csfiles that feed directly into the forward pipeline
Multi-SDK discovery
Roslyn's MSBuildWorkspace needs to find the .NET SDK. Rivet handles the common cases:
- System install (
/usr/local/share/dotnet,C:\Program Files\dotnet) - Homebrew on macOS (
/opt/homebrew/share/dotnet) - Linux package manager installs
The SDK path is resolved at startup. If Rivet can't find it, you'll get a clear error message.
