mrkeyoor.com_
Wed 23 Sept 00:34 UTC
npmCLI & Toolingupdated 22 Sept 2026

@hey-api/openapi-ts review

@hey-api/openapi-ts 0.99.0 is a Node code generator that turns an OpenAPI file, URL, registry identifier, or in-memory document into TypeScript. Plugins can emit request and response types, callable SDK functions, Fetch or Axios clients, runtime schemas, query helpers, mocks, and server adapters. The 0.99.0 release adds presets and merges repeated plugin configurations, while changing custom-plugin imports and several internal field names. It generates source files during development or CI; it is not the HTTP client that runs by itself in a browser.

Verdict

We measured an 8.3-second install for @hey-api/openapi-ts 0.99.0, followed by 42 MB on disk, 4 high audit findings, and two failed module-loading probes on Node 22.23.2. Use the pinned CLI when its SDK and schema plugins replace real hand-written code; wait or choose a narrower generator if stable programmatic loading and a clean audit are release requirements.

We installed it

Lab card: what happened when we installed @hey-api/openapi-tsScreenshot of @hey-api/openapi-ts documentation
Install✓ · 8.3s52 packages on disk · 42 MB
ImportESM import fails · require() fails · ESM package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns40 critical · 4 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @hey-api/openapi-ts install cleanly?

Yes. In a fresh container with an empty cache, npm install @hey-api/openapi-ts finished in 8 seconds, leaving 52 packages and 42 MB on disk. npm audit reported 4 known vulnerabilities.

Can @hey-api/openapi-ts run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does @hey-api/openapi-ts work with both ESM and CommonJS?

Neither plain import nor require succeeded in our sandbox, so it needs a bundler or extra setup.

Does @hey-api/openapi-ts include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@hey-api/openapi-ts or openapi-typescript: which should you use?

openapi-typescript: Choose it when the target is TypeScript types and you do not want generated request code. We measured an 8.3-second install for @hey-api/openapi-ts 0.99.0, followed by 42 MB on disk, 4 high audit findings, and two failed module-loading probes on Node 22.23.2.

When should you not use @hey-api/openapi-ts?

You require a stable 1.x generator contract: 0.99.0 is still initial-development software and its release contains four breaking changes

API stability2/5Release 0.99.0 contains four changes that the project labels breaking, despite being one step below 1.0: duplicate plugin definitions now merge, custom plugins use `.imports` instead of `.symbols`, `.external()` is gone, and one schema callback type widened. The README calls the package initial-development software and tells users to pin an exact version. Generated APIs also follow operation IDs and schemas from the input document, so teams must review both generator upgrades and contract diffs.
Docs5/5The official start page returned HTTP 200 and links into separate references for configuration, output ownership, migration, clients, plugins, Vite, and custom extensions. The package README gives CLI, Node, Vite, TypeScript config, CommonJS config, input, and output examples, then states that generated files may be erased. Release notes enumerate every 0.99.0 breaking change and name the affected plugin APIs. The remaining gap is diagnostic help for module-load failures such as the ones our smoke test hit.
Maintenance5/5Version 0.99.0 was published on 2026-06-22, and GitHub records a repository push on 2026-08-24. The monorepo is not archived, has 5,310 stars, and ships coordinated packages for parsing, code generation, clients, and framework plugins. GitHub reports 591 open issues and pull requests, which is a sizable queue rather than a true issue count. Frequent releases and repository activity are strong, but their pace also explains why exact pins and migration review are part of normal use.
Ecosystem5/5The npm downloads endpoint counted 4,416,207 downloads in the latest week. Official client choices cover Fetch, Angular, Axios, Ky, Next.js, Nuxt, and ofetch, while plugins target TypeScript, schemas, Zod, Valibot, several TanStack Query frameworks, MSW, Fastify, NestJS, and oRPC. That range can keep generated pieces on one contract. It also means the generator is only one dependency layer: selected output may require Axios, TanStack, validation, or server packages in the application.

Use it if

  • Your OpenAPI contract is authoritative and the team wants generated request functions beside generated TypeScript types
  • One generation job needs Zod or Valibot schemas plus framework-specific TanStack Query helpers
  • The project can pin 0.99.0 exactly, inspect generated diffs, and run on Node 22.18 or newer
  • You need a selectable transport such as Fetch, Axios, Angular, Next.js, Nuxt, Ky, or ofetch
Skip it if

Setup reality

In our sandbox, @hey-api/openapi-ts 0.99.0 installed in 8.3 seconds and left 52 packages using 42 MB. The package itself has 10 direct dependencies, one peer dependency, bundled TypeScript declarations, and a 3,048 KB unpacked size. npm audit found 4 high vulnerabilities and none at the other severities. It declares ESM and Node >=22.18.0, yet require() and ESM import both failed in our Node.js 22.23.2 probes.

Use an exact dev-dependency pin and run the openapi-ts executable from a package script. A normal config names the input, output directory, client, and plugin list. Inputs may be local JSON or YAML, remote URLs, or Hey API Registry identifiers. Private URL inputs need the server's authentication. The docs mention disabling TLS verification for a self-signed development endpoint; do not carry that process setting into CI or production.

Generation owns its output folder and can erase hand edits. Commit the result if reviewed generated code is part of your release process, or regenerate in CI and fail when the diff changes. Operation IDs, component names, required fields, and nullability in the OpenAPI document determine exported names and signatures. A generator upgrade is only half the review; a contract edit can break callers while 0.99.0 stays pinned.

Plugins can add runtime obligations to the consuming app. Axios output needs Axios, and each TanStack plugin needs its matching framework package. The package has one TypeScript peer dependency. Our browser bundle could not be built by esbuild, which fits a Node-only code generator. Version 0.99.0 also merges duplicate plugin entries, adds presets, renames custom-plugin .symbols to .imports, and removes .external(), so custom plugins need the release notes before upgrading.

Patterns

Generate from a local contract run-cli-once

npx @hey-api/openapi-ts@0.99.0 -i ./openapi.yaml -o ./src/generated/api

The README asks users to pin an exact version because 0.99.0 is still in initial development.

Create a typed config file define-generator-config

import { defineConfig } from '@hey-api/openapi-ts'

export default defineConfig({
  input: './openapi.yaml',
  output: './src/generated/api',
  plugins: ['@hey-api/client-fetch', '@hey-api/sdk', '@hey-api/typescript'],
})

An explicit plugin array records the transport and artifacts in source control instead of relying on defaults.

Expose the pinned CLI through npm add-generate-script

{
  "scripts": {
    "generate:api": "openapi-ts"
  },
  "devDependencies": {
    "@hey-api/openapi-ts": "0.99.0"
  }
}

Run `npm run generate:api` from the project root so the loader can find `openapi-ts.config.ts`.

Call the generator from an ESM script generate-programmatically

import { createClient } from '@hey-api/openapi-ts'

await createClient({
  input: './openapi.yaml',
  output: './src/generated/api',
})

The package exports an ESM entry only, and both ESM `import` and `require()` failed in our Node 22.23.2 smoke tests. Verify this path in your exact runner before adopting it.

Emit Fetch calls and TypeScript types generate-fetch-client

export default defineConfig({
  input: './openapi.json',
  output: './src/generated/api',
  plugins: [
    '@hey-api/client-fetch',
    '@hey-api/sdk',
    '@hey-api/typescript',
  ],
})

The generated Fetch client handles requests; `@hey-api/openapi-ts` itself remains a Node generation tool.

Add Zod output beside the SDK generate-zod-schemas

export default defineConfig({
  input: './openapi.yaml',
  output: './src/generated/api',
  plugins: [
    '@hey-api/client-fetch',
    '@hey-api/sdk',
    '@hey-api/typescript',
    'zod',
  ],
})

Install the Zod runtime version required by the generated output; the generator package does not supply it for the application.

Produce React Query options generate-react-query

export default defineConfig({
  input: './openapi.yaml',
  output: './src/generated/api',
  plugins: [
    '@hey-api/client-fetch',
    '@hey-api/sdk',
    '@hey-api/typescript',
    '@tanstack/react-query',
  ],
})

Use the plugin matching the framework and install its TanStack runtime package in the consuming app.

Generate against Axios target-axios

export default defineConfig({
  input: './openapi.yaml',
  output: './src/generated/api',
  plugins: ['@hey-api/client-axios', '@hey-api/sdk', '@hey-api/typescript'],
})

Axios is a runtime dependency of the generated client and must be installed separately.

Run a formatter after generation format-output

export default defineConfig({
  input: './openapi.yaml',
  output: {
    path: './src/generated/api',
    postProcess: ['oxfmt'],
  },
})

The post-process command must exist on every developer and CI machine; pin it to prevent formatter-only diffs.

Set generated client defaults configure-runtime-client

import { client } from './generated/api/client.gen'

client.setConfig({
  baseUrl: 'https://api.example.com',
  headers: { Authorization: `Bearer ${token}` },
})

A shared mutable client can mix tenant credentials in a server process. Use an isolated client for request-scoped authentication.

Build a request-scoped client create-isolated-client

import { createClient } from './generated/api/client'

const apiClient = createClient({
  baseUrl: 'https://api.example.com',
  headers: { Authorization: `Bearer ${token}` },
})

Pass the returned instance to generated SDK calls when headers differ by user or tenant.

Invoke one generated SDK function call-generated-operation

import { getPetById } from './generated/api/sdk.gen'

const result = await getPetById({ path: { petId: 42 } })
if (result.error) throw new Error('pet request failed')
console.log(result.data)

The function name and `path` shape come from your OpenAPI operation, so inspect the generated file after every contract change.

Alternatives

PackageRegistryPick it when
openapi-typescriptnpmChoose it when the target is TypeScript types and you do not want generated request code.
orvalnpmChoose it when React Query clients and mock generation fit its established output model.
swagger-typescript-apinpmChoose it when editable templates are more important than a large plugin catalogue.
@openapitools/openapi-generator-clinpmChoose it for generators outside TypeScript and accept the larger OpenAPI Generator toolchain.

More cli & tooling guides

chalk · commander · typescript · esbuild · yargs · click · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.