Skip to content

Migrating from hey-api or orval

This guide is for developers who already have a TypeScript project with an OpenAPI generator set up and want to switch to @codewithagents/openapi-gen. It covers the mental model shift, the step-by-step switch, and what to watch for.

Many OpenAPI generators follow a pattern where the generated code depends on a runtime client library that the generator itself publishes. Your code calls into that runtime, and the generated types describe its API. The generator ships a package to dependencies, not just devDependencies.

This toolchain works differently:

  • Generated files are owned code. models.ts, client.ts, client-config.ts, and (optionally) schemas.ts live in your repository. They are plain TypeScript you can read, extend, and commit like any other file.
  • Zero runtime footprint. The generator (@codewithagents/openapi-gen) is a devDependency. The generated client.ts uses only native fetch. Nothing is added to your production bundle that your project did not already have.
  • Runtime validation is opt-in and user-owned. If you add input_schema to your config, the generator bootstraps a Zod schemas.ts file once, then never overwrites it. You add error messages and business rules. The generator warns on drift but your schema stays yours.
  • Requests and responses are validated at runtime when Zod integration is enabled: the client calls Schema.parse(body) before sending and Schema.parse(await res.json()) after receiving.
  1. Remove the old generator.

    Uninstall the previous generator and any runtime packages it required:

    Terminal window
    # example: remove hey-api packages
    npm uninstall @hey-api/client-fetch @hey-api/openapi-ts
    # example: remove orval
    npm uninstall orval

    Delete the old generated output directory and any existing generator config files (orval.config.ts, openapi-ts.config.ts, etc.).

  2. Install @codewithagents/openapi-gen.

    Terminal window
    npm install -D @codewithagents/openapi-gen

    If you also want React Query hooks, add the hooks package:

    Terminal window
    npm install -D @codewithagents/openapi-react-query
  3. Create the config file.

    Create openapi-gen.config.json in your project root:

    {
    "input_openapi": "./openapi.json",
    "output": "./src/api"
    }

    Optional fields for a fuller setup:

    {
    "input_openapi": "./openapi.json",
    "output": "./src/api",
    "input_schema": "./src/api/schemas.ts",
    "baseUrl": "https://api.example.com",
    "server_client": true
    }
    FieldRequiredDescription
    input_openapiYesPath to your OpenAPI spec (JSON or YAML)
    outputYesDirectory to write the generated files
    input_schemaNoPath to a user-owned Zod schema file. Bootstrapped on first run, never overwritten after that.
    baseUrlNoDefault base URL embedded in client-config.ts
    server_clientNoWhen true, also generates server.ts with a createServerClient() factory
  4. Run the generator.

    Terminal window
    npx openapi-gen

    This writes the following files to your output directory:

    FileContents
    models.tsTypeScript interfaces for every schema
    client.tsOne typed async function per API operation
    client-config.tsconfigureClient() and getConfig()
    index.tsBarrel re-export of all three files above
  5. Update your imports.

    Replace imports from the old generator’s runtime with imports from your generated barrel:

    // Before: importing from a runtime package
    import { createClient } from '@hey-api/client-fetch'
    // After: importing from your own generated code
    import { configureClient, listTasks, ApiError } from './src/api'

    Call configureClient once at app startup:

    import { configureClient } from './src/api'
    configureClient({
    baseUrl: 'https://api.example.com',
    token: () => getAccessToken(), // sync or async, called per request
    })
  6. Add a generate script to package.json.

    {
    "scripts": {
    "generate": "openapi-gen"
    }
    }
// orval.config.ts (illustrative, your config may differ)
import { defineConfig } from 'orval'
export default defineConfig({
myApi: {
input: './openapi.json',
output: {
target: './src/api/client.ts',
client: 'react-query',
},
},
})
// package.json dependencies (illustrative)
{
"devDependencies": {
"orval": "^7.x"
},
"dependencies": {
"axios": "^1.x"
}
}

Types and fetch client

Complete configuration reference, generated file details, and advanced usage.

openapi-gen guide