Progenitor
Generates opinionated, fully typed Rust API clients from OpenAPI 3.0.x specifications
Repository Health
Technical Analysis
Progenitor is a Rust code generator that turns an OpenAPI 3.0.x document into an idiomatic, fully typed async client crate, complete with request/response types, error handling, and optional pagination support via Rust Streams. It can be used as a generate_api! procedural macro embedded directly in a source file, wired into a build.rs script for visible generated code, or run as a standalone cargo progenitor binary that emits a self-contained, publishable client crate.
Beyond client generation, Progenitor can also emit a CLI for interacting with an OpenAPI service and typed httpmock helpers for testing against a mocked version of the API. It supports two generated interface styles — positional arguments or fluent builders — and is primarily built around OpenAPI documents produced by Oxide’s Dropshot framework, though it aims to support the broader OpenAPI ecosystem. Because OpenAPI covers such a wide surface area, Progenitor may not handle every document perfectly, and the project actively takes issue reports with sample specs that fail to generate.
What You Get
- A
generate_api!procedural macro for embedding client generation directly inmain.rs/lib.rs - A
build.rs-friendlyGeneratorAPI that produces visible, inspectable generated code - A standalone
cargo progenitorCLI that emits a self-contained, publishable client crate - Choice of positional or fluent-builder generated call styles
- Optional CLI generation and
httpmock-based typed test helpers for the target API - Support for pagination via Rust
Streams, plus chrono/uuid/regex-aware type generation
Common Use Cases
- Generating a maintained-in-sync Rust SDK for an internal or third-party OpenAPI service
- Producing typed clients for Dropshot-based APIs (Progenitor’s primary target ecosystem)
- Building a CLI tool to interact with an OpenAPI service without hand-writing HTTP plumbing
- Creating strongly typed httpmock-based test doubles for an OpenAPI-described dependency
Under The Hood
Architecture - The workspace splits code generation into a shared core (progenitor-impl), which parses the OpenAPI document, maps schemas to Rust types (to_schema.rs), and emits token streams for client methods (method.rs), a CLI (cli.rs), and httpmock helpers (httpmock.rs). Three consumer-facing crates sit on top: progenitor-macro implements the generate_api! procedural macro, progenitor is the primary crate re-exporting the macro (feature-gated) plus a Generator type for build.rs use, and progenitor-client provides the runtime support types (ResponseValue, Error, byte-stream helpers) that generated code depends on at runtime. A separate cargo-progenitor binary wraps the same progenitor-impl core to emit a fully standalone, publishable crate directly to disk.
Tech Stack - Rust workspace (edition 2024, MSRV 1.88) using syn/quote/proc-macro2 for code generation, openapiv3 for spec parsing, and prettyplease for formatting emitted code. Generated clients depend on reqwest for HTTP, serde/serde_json for (de)serialization, and optionally chrono, uuid, regress, base64, and rand depending on which OpenAPI format keywords appear in the source spec. The workspace also ships example-macro, example-build, example-out-dir, and example-wasm crates demonstrating each integration style, including WASM target support.
Code Quality - The generation core is centralized in progenitor-impl rather than duplicated across the macro/build.rs/CLI entry points, which keeps the three usage modes behaviorally consistent. The repo includes sample_openapi/ fixture documents (e.g. keeper.json) used across the example crates and, per the README, the project explicitly asks users to file issues with failing OpenAPI documents, indicating an issue-driven compatibility-hardening process rather than a claim of full spec coverage.
API Design - Progenitor optimizes for three distinct entry points depending on how much visibility into generated code a consumer wants: a one-line generate_api! macro for the simplest case, a build.rs + Generator combination when visible generated code matters, and a cargo progenitor CLI for a fully standalone crate. The generated client itself offers a choice between positional-argument methods (simple, but parameter types must match exactly) and builder-style methods (more verbose internally, but ergonomic call sites with TryInto conversions and per-field defaults) — letting API consumers pick their preferred trade-off between generation complexity and call-site ergonomics.