Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

workos/oagen

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

445 Commits
445 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oagen

oagen (oʊweɪdd͡ʒɛn) is a framework for building custom SDK generators from OpenAPI 3.x specifications.

Its core job is narrow:

  • parse an OpenAPI spec into a typed intermediate representation (IR)
  • let language emitters turn that IR into files
  • regenerate the SDK when the spec changes

More advanced workflows, such as preserving the public API of an existing SDK during a migration to generation, is also supported.

Who This Is For

oagen is a fit if you:

  • need more control than off-the-shelf generators give you
  • want to build or maintain a custom emitter for one or more languages
  • care about generated output being idiomatic for a specific SDK style

oagen is probably not a fit if you:

  • just want a turnkey SDK generator with batteries included
  • do not want to maintain emitter code
  • do not need a reusable IR or generation framework

Core Concept

oagen has a small core:

  • Parser: OpenAPI 3.x -> ApiSpec IR
  • Emitter runtime: ApiSpec -> GeneratedFile[]
  • Diffing: compare spec versions and map changes to generated output

Advanced features such as API-surface extraction, compatibility overlays, smoke verification, and live-SDK integration are available, but they are optional. You can ignore them until you need them.

Quickstart

Install the package:

npm install @workos/oagen

Inspect a spec:

oagen parse --spec openapi.yml

Create an emitter project:

oagen init --lang ruby --project ./my-emitter
cd ./my-emitter

Generate files with your emitter:

npm run sdk:generate -- --spec ../openapi.yml --namespace MyService

For the shortest end-to-end setup, see Minimal Quickstart.

The Core API

The default @workos/oagen entrypoint is intentionally focused on the framework core:

import {
  defaultSdkBehavior,
  mergeSdkBehavior,
  diffSpecs,
  generate,
  generateFiles,
  getEmitter,
  parseSpec,
  planOperation,
  registerEmitter,
  toCamelCase,
  toPascalCase,
  toSnakeCase,
} from "@workos/oagen";
import type {
  ApiSpec,
  SdkBehavior,
  Emitter,
  EmitterContext,
  GeneratedFile,
  Model,
  Enum,
  Service,
  OperationPlan,
} from "@workos/oagen";

Advanced compat and verification APIs are available through explicit subpaths:

import {
  buildOverlayLookup,
  patchOverlay,
  registerExtractor,
} from "@workos/oagen/compat";
import { runCompatCheck, runOverlayRetryLoop } from "@workos/oagen/verify";

Building an Emitter

Emitters are pure functions over the IR. They receive typed IR nodes and return GeneratedFile[].

import type { Emitter } from "@workos/oagen";

const myEmitter: Emitter = {
  language: "go",
  generateModels: (models, ctx) => [
    /* ... */
  ],
  generateEnums: (enums, ctx) => [
    /* ... */
  ],
  generateResources: (services, ctx) => [
    /* ... */
  ],
  generateClient: (spec, ctx) => [
    /* ... */
  ],
  generateErrors: () => [],
  generateTests: () => [],
  fileHeader: () => "// Auto-generated by oagen. Do not edit.",
};

Start with:

SDK Behavior

ApiSpec.sdk contains language-agnostic runtime policies — retry logic, error mapping, telemetry, pagination delays, User-Agent construction, and more. It is always populated (via defaultSdkBehavior() during parsing).

Emitters read policy from ctx.spec.sdk instead of hardcoding values:

function generateHttpClient(ctx: EmitterContext) {
  const sdk = ctx.spec.sdk;
  const retryCodes = sdk.retry.retryableStatusCodes; // [429, 500, 502, 503, 504]
  const maxRetries = sdk.retry.maxRetries; // 3
  const backoff = sdk.retry.backoff; // { initialDelay: 1, multiplier: 2, maxDelay: 30, jitterFactor: 0.5 }
  // ...generate code using these values
}

Override defaults per-SDK via oagen.config.ts:

// oagen.config.ts — Python SDK overrides
export default {
  sdkBehavior: {
    retry: { backoff: { initialDelay: 0.5, maxDelay: 8.0 } },
    timeout: {
      defaultTimeoutSeconds: 30,
      timeoutEnvVar: "SDK_REQUEST_TIMEOUT",
    },
    pagination: { autoPageDelayMs: 0 },
  },
};

See src/ir/sdk-behavior.ts for all interfaces and default values.

Operation Resolution

resolveOperations(spec, hints?, mountRules?) derives method names and mount targets for every operation in the spec. The algorithm produces a snake_case name from the HTTP method and path, then applies optional overrides from a hint map.

Emitters consume ctx.resolvedOperations instead of computing names independently, ensuring all SDKs use the same method names (converted to each language's convention).

Configure hints and mount rules in oagen.config.ts:

export default {
  operationHints: {
    'GET /sso/authorize': { name: 'get_authorization_url' },
    'POST /user_management/authenticate': {
      split: [
        { name: 'authenticate_with_password', targetVariant: 'PasswordRequest', ... },
      ],
    },
  },
  mountRules: {
    Connections: 'SSO',           // All Connections ops mount on SSO
    DirectoryGroups: 'DirectorySync',
  },
  modelHints: {
    // Pin a model's placement when "first service to reference it wins"
    // would otherwise drift as the spec evolves.
    User: 'UserManagementUsers',
  },
};

Review resolved names with oagen resolve:

oagen resolve --spec openapi.yml --format table   # Markdown review table
oagen resolve --spec openapi.yml --format json     # JSON for programmatic use

See src/ir/operation-hints.ts for types and docs/architecture/ir-types.md for the full reference.

Commands

Command Purpose
oagen parse Parse a spec and print IR JSON
oagen init Scaffold an emitter project
oagen generate Run a registered emitter
oagen resolve Review resolved operation names (table or JSON)
oagen diff Compare two specs and output a diff report
oagen extract Advanced: extract an SDK API surface for compat use
oagen verify Advanced: smoke-test output and run compat checks

See CLI Reference.

Documentation

Advanced Workflows

oagen also includes tooling for a more opinionated migration workflow:

  • extract the public API of an existing SDK
  • generate a replacement while preserving names and exports
  • verify the generated SDK against smoke tests and compatibility checks
  • integrate generated files into a live SDK tree

Those workflows are documented separately because they are not required to use the core framework:

AI / Plugin Tooling

This repo ships with Claude Code plugin assets and skills for scaffold-and-verify workflows. The framework is usable without any agent tooling.

If you need them, start here:

Development

npm install
npm run build
npm test
npm run typecheck

About

A framework for building custom SDK generators from OpenAPI

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.