Skip to content

OpenAPI 3.x → TypeScript & React code generator. Zero-dependency clients, SWR hooks, and SSE streaming.

License

Notifications You must be signed in to change notification settings

urmzd/openapi-generator

Repository files navigation

oag

OpenAPI 3.x code generator with a plugin-style architecture supporting TypeScript, React, and Python FastAPI.

demo

Why oag?

OpenAPI 3.2 shipped but most generators haven't caught up. When you need to glue a frontend to a backend during a POC, you don't want to fight a generator that produces bloated code requiring heavy post-processing.

oag focuses on simplicity: one config file, one command, clean output.

  • Parses OpenAPI 3.x specs with full $ref resolution
  • Plugin-style architecture: enable only the generators you need
  • TypeScript/Node client with zero runtime dependencies
  • React/SWR hooks for queries, mutations, and SSE streaming
  • Python FastAPI server with Pydantic v2 models
  • First-class Server-Sent Events support via AsyncGenerator (TS) and StreamingResponse (Python)
  • Test generation — pytest tests for FastAPI, vitest tests for TypeScript/React (opt-out via scaffold.test_runner: false)
  • Scaffolds Biome + tsdown configuration for TypeScript projects, Ruff for Python
  • Configurable naming strategies and operation aliases
  • Three layout modes per generator: bundled, modular, or split

Quick start

Install from crates.io:

cargo install oag-cli

Or build from source:

git clone https://github.com/urmzd/openapi-generator.git
cd openapi-generator
cargo install --path crates/oag-cli

Initialize a config file:

oag init

This creates .urmzd.oag.yaml in the current directory:

# oag configuration — https://github.com/urmzd/openapi-generator
input: openapi.yaml

naming:
  strategy: use_operation_id  # use_operation_id | use_route_based
  aliases: {}
    # createChatCompletion: chat     # operationId → custom name
    # listModels: models

generators:
  node-client:
    output: src/generated/node
    layout: modular           # bundled | modular | split
    # split_by: tag           # operation | tag | route (only for split layout)
    # base_url: https://api.example.com
    # no_jsdoc: false
    # source_dir: src         # subdirectory for source files ("src", "lib", or "" for root)
    scaffold:
      # package_name: my-api-client
      # repository: https://github.com/you/your-repo
      # existing_repo: false   # set to true to skip all scaffold files (package.json, tsconfig, etc.)
      formatter: biome        # biome | false
      test_runner: vitest     # vitest | false
      bundler: tsdown         # tsdown | false

  # react-swr-client:
  #   output: src/generated/react
  #   layout: modular
  #   scaffold:
  #     formatter: biome
  #     test_runner: vitest
  #     bundler: tsdown

  # fastapi-server:
  #   output: src/generated/server
  #   layout: modular
  #   scaffold:
  #     formatter: ruff       # ruff | false
  #     test_runner: pytest   # pytest | false

Generate code:

oag generate

This will generate code for all configured generators. You can override the input spec:

oag generate -i other-spec.yaml

Note: The old config format (with target, output, output_options, and client fields) is still supported for backward compatibility and automatically converted.

CLI reference

Command Description
generate Generate code from an OpenAPI spec
validate Validate an OpenAPI spec and report errors
inspect Dump the parsed intermediate representation (YAML or JSON)
init Create a .urmzd.oag.yaml config file
completions Generate shell completions (bash, zsh, fish, etc.)

Run oag <command> --help for detailed usage.

Configuration

All options are set in .urmzd.oag.yaml. The CLI supports -i/--input to override the input spec path.

Global options

Key Type Default Description
input string openapi.yaml Path to the OpenAPI spec (YAML or JSON)
naming.strategy string use_operation_id How to derive function names: use_operation_id or use_route_based
naming.aliases map {} Map of operationId to custom name overrides

Generators

The generators map configures which generators to run and their options. Each generator has its own output directory and settings.

Available generators:

  • node-client — TypeScript/Node API client (zero dependencies)
  • react-swr-client — React/SWR hooks (extends node-client)
  • fastapi-server — Python FastAPI server stubs with Pydantic v2 models

Generator options (node-client, react-swr-client, fastapi-server)

Key Type Default Description
output string required Output directory for this generator
layout string modular Layout mode: bundled (single file), modular (separate files per concern), or split (separate files per operation group)
split_by string tag Only for split layout: operation, tag, or route
base_url string (from spec servers) Override the API base URL (TypeScript generators only)
no_jsdoc bool false Disable JSDoc comments (TypeScript generators only)
source_dir string "src" Subdirectory for generated source files — set to "" to place files at the output root (TypeScript generators only)
scaffold.package_name string (from spec title) Custom package name (TypeScript: npm, Python: pyproject.toml)
scaffold.repository string Repository URL for package metadata
scaffold.formatter string or false biome (TS) / ruff (Python) Code formatter — set to false to disable
scaffold.test_runner string or false vitest (TS) / pytest (Python) Test runner — set to false to disable test generation
scaffold.bundler string or false tsdown Bundler config (TypeScript only) — set to false to disable
scaffold.existing_repo bool false Set to true to skip all scaffold files (package.json, tsconfig, biome, tsdown) and only emit a root index.ts re-export

Layout modes

  • bundled — Everything in a single file (e.g., src/index.ts or main.py)
  • modular — Separate files per concern (e.g., src/types.ts, src/client.ts, src/sse.ts, src/index.ts)
  • split — Separate files per operation group (e.g., src/pets.ts, src/users.ts, src/orders.ts)

For TypeScript generators, source files are placed in a src/ subdirectory by default (configurable via source_dir). This matches the scaffold's tsconfig.json (rootDir, include) and tsdown.config.ts (entry) — all of which adapt automatically to the configured source_dir. Set source_dir: "" to place files directly at the output root. Scaffold files (package.json, tsconfig.json, biome.json, tsdown.config.ts) always remain at the output root.

When using split layout, specify split_by:

  • operation — One file per operation
  • tag — One file per OpenAPI tag (default)
  • route — One file per route prefix

Backward compatibility

The old config format (with target, output, output_options, and client fields) is still supported and automatically converted to the new format.

Architecture

oag-cli  -->  [oag-node-client, oag-react-swr-client, oag-fastapi-server]  -->  oag-core

The workspace uses a plugin-style architecture with five crates:

Crate Role
oag-core OpenAPI parser, intermediate representation, transform pipeline, and CodeGenerator trait
oag-node-client TypeScript/Node API client generator (zero dependencies)
oag-react-swr-client React/SWR hooks generator (extends node-client)
oag-fastapi-server Python FastAPI server generator with Pydantic v2 models
oag-cli Command-line interface that orchestrates all generators

oag-core defines the CodeGenerator trait:

pub trait CodeGenerator {
    fn id(&self) -> config::GeneratorId;
    fn generate(
        &self,
        ir: &ir::IrSpec,
        config: &config::GeneratorConfig,
    ) -> Result<Vec<GeneratedFile>, GeneratorError>;
}

Each generator implements this trait with a unique ID (node-client, react-swr-client, or fastapi-server). The CLI loops over the configured generators in .urmzd.oag.yaml and invokes each one.

Examples

Working examples with generated output are in the examples/ directory:

  • petstore — Node client and React client generated from the Petstore 3.2 spec
  • sse-chat — Node client and React hooks with SSE streaming for a chat API

Each example has its own .urmzd.oag.yaml configuring generators with separate output directories (e.g. generated/node and generated/react).

Regenerate them with:

just examples

License

Apache-2.0

About

OpenAPI 3.x → TypeScript & React code generator. Zero-dependency clients, SWR hooks, and SSE streaming.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages