npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

openapi-ts-json-schema

v2.3.0

Published

Generate TypeScript-first JSON schemas from OpenAPI definitions

Readme

openapi-ts-json-schema

Build Status Npm version Coveralls

Generate TypeScript JSON Schema modules (.ts files with as const) directly from your OpenAPI spec — one source of truth for runtime validation and static type inference.

Why?

Your OpenAPI spec, runtime schemas, and TypeScript types tend to drift when maintained separately. This library generates them all from the spec — one source of truth.

The output is plain JSON Schema as const TypeScript modules, so they work with any JSON Schema-aware tool (Ajv, TypeBox, Hyperjump, Fastify, …) and can be passed directly to json-schema-to-ts for static type inference.

These schemas:

  • ✅ are 100% JSON Schema–compatible (usable with Ajv, Fastify, etc.)
  • ✅ are TypeScript-native (as const objects you can import)
  • ✅ can be used for type inference via json-schema-to-ts
  • ✅ are generated automatically from your OpenAPI spec

In short: OpenAPI spec becomes the single source of truth for both runtime validation and TypeScript typing.

Example

From this OpenAPI definition:

components:
  schemas:
    User:
      type: object
      properties:
        id: { type: string }
        name: { type: string }
      required: [id, name]

openapi-ts-json-schema generates:

// components/schemas/User.ts
export default {
  type: 'object',
  properties: {
    id: { type: 'string' },
    name: { type: 'string' },
  },
  required: ['id', 'name'],
} as const;

Now you can use it for both runtime validation and type inference:

import Ajv from 'ajv';
import type { FromSchema } from 'json-schema-to-ts';

import userSchema from './components/schemas/User';

const ajv = new Ajv();
const validate = ajv.compile<FromSchema<typeof userSchema>>(userSchema);

const data: unknown = {};
if (validate(data)) {
  // data is now typed as { id: string; name: string }
}

How this fits with openapi-typescript

Different tools for different jobs — not competitors:

  • Types only, no runtimeopenapi-typescript
  • Runtime schemas + types from one specopenapi-ts-json-schema + json-schema-to-ts (works with any JSON Schema-compatible tool)
  • Both togetheropenapi-ts-json-schema handles runtime; fall back to openapi-typescript types where json-schema-to-ts inference breaks down

Installation

npm i openapi-ts-json-schema -D

Usage

import { openapiToTsJsonSchema } from 'openapi-ts-json-schema';

const { outputPath } = await openapiToTsJsonSchema({
  openApiDocument: 'path/to/open-api-specs.yaml',
  targets: {
    collections: ['components.schemas', 'paths'],
  },
});

Schemas are generated in a folder mirroring your OpenAPI layout (default: schemas-autogenerated).

CommonJS

Since openapi-ts-json-schema is distributed as an ESM-only package, it must be imported using a dynamic import() when used from a CommonJS project:

async function run() {
  const { openapiToTsJsonSchema } = await import('openapi-ts-json-schema');

  const { outputPath } = await openapiToTsJsonSchema({
    openApiDocument: 'path/to/open-api-specs.yaml',
    targets: {
      collections: ['components.schemas', 'paths'],
    },
    importExtension: 'none',
  });
}

run();

Options

Core options

| Property | Type                                              | Description | Default | | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | openApiDocument (required) | string | Path to an OpenAPI document (JSON or YAML). | - | | targets (required) | { collections?: string[]; single?: string[];} | OpenAPI definition paths to generate JSON Schemas from (dot notation).collections: paths pointing to objects/records of definitions, where each entry will be generated (eg: ["components.schemas"]).single: paths pointing to individual definitions to generate (eg: ["paths./users/{id}"]). | - | | outputPath | string | Directory where generated schemas will be written. Defaults to /schemas-autogenerated in the same directory of openApiDocument. | - | | refHandling | "import" \| "inline" \| "keep" | "import": generate and import $ref schemas."inline": inline $ref schemas."keep": keep $ref values. | "import" | | importExtension | "js" \| "ts" \| "none" | File extension appended to relative import specifiers in generated artifacts. | "js" | | moduleSystem (deprecated) | "cjs" \| "esm" | Deprecated — use importExtension instead. Kept for backwards compatibility: "esm" maps to importExtension: "js", "cjs" maps to importExtension: "none". Ignored when importExtension is also provided. | - | | silent | boolean | Don't log user messages. | false |

Advanced options

| Property | Type | Description | Default | | ----------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | ------- | | idMapper | (params: { id: string }) => string | Map internal schema ids to custom $id and $ref values in the generated output. See idMapper option below. | - | | schemaPatcher | (params: { schema: JSONSchema }) => void | Hook called for every generated schema node, allowing programmatic mutation before output. | - | | plugins | ReturnType<Plugin>[] | List of plugins to extend or customize the generation process. See plugins docs. | - |

Full configuration example

import {
  generateSchemaWith,
  openapiToTsJsonSchema,
} from 'openapi-ts-json-schema';

await openapiToTsJsonSchema({
  openApiDocument: './openapi.yaml',
  targets: {
    collections: ['components.schemas'],
    single: ['paths./users/{id}'],
  },
  outputPath: './generated',
  refHandling: 'import',
  importExtension: 'js',
  silent: false,

  idMapper: ({ id }) => id.toUpperCase(),
  schemaPatcher: ({ schema }) => {
    if (schema.properties && !schema.type) {
      schema.type = 'object';
    }
  },
  plugins: [generateSchemaWith$idPlugin()],
});

refHandling option

Three strategies for how $refs are resolved:

| refHandling option | description | | -------------------- | ---------------------------------------------------------------------------------------------- | | inline | Inlines $refss, creating self-contained schemas (no imports, but possible redundancy). | | import | Replaces$refs with imports of the target definition | | keep | Leaves $refs untouched — useful if you plan to interpret $refs dynamically or use a plugin |

Circular references are supported:

  • inline: circular refs are replaced with {}
  • import: resolves the JSON schema but TypeScript recursion halts (any type, TS error 7022)
  • keep: circular refs left unresolved

See tests for details.

idMapper option

Every schema gets an internal id derived from its path in the OpenAPI document (e.g. /components/schemas/Pet). idMapper lets you rewrite these ids before they are written as $id and $ref values in the generated output.

Strip the /components/schemas/ prefix so Fastify's addSchema / getSchema can look up schemas by a short name:

await openapiToTsJsonSchema({
  openApiDocument: './openapi.yaml',
  targets: { collections: ['components.schemas'] },
  refHandling: 'keep',
  idMapper: ({ id }) => {
    const prefix = '/components/schemas/';
    return id.startsWith(prefix) ? id.slice(prefix.length) : id;
    // '/components/schemas/Pet' → 'Pet'
  },
});

Map to a flat, namespaced identifier across multiple target collections:

idMapper: ({ id }) => id.replaceAll('/', '.').replace(/^\./, ''),
// '/components/schemas/Pet' → 'components.schemas.Pet'
// '/paths/~1users~1{id}/get' → 'paths.~1users~1{id}.get'

Return values

Along with generated schema files, openapi-ts-json-schema returns metadata:

{
  // The path where the schemas are generated
  outputPath: string;
  metaData: {
    // Meta data of the generated schemas
    schemas: Map<
      // Schema internal id. Eg: "/components/schemas/MySchema"
      string,
      {
        id: string;
        // Internal unique schema identifier. Eg `"/components/schemas/MySchema"`
        $id: string;
        // JSON schema Compound Schema Document `$id`. Eg: `"/components/schemas/MySchema"`
        uniqueName: string;
        // Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"`
        openApiDefinition: OpenApiObject;
        // Original dereferenced openAPI definition
        originalSchema: JSONSchema | string;
        // Original dereferenced JSON schema
        isRef: boolean;
        // True if schemas is used as a `$ref`
        shouldBeGenerated: boolean;
        // Text content of schema file
        fileContent?: string;

        absoluteDirName: string;
        // Absolute path pointing to schema folder (posix or win32). Eg: `"Users/username/output/path/components/schemas"`
        absolutePath: string;
        // Absolute path pointing to schema file (posix or win32). Eg: `"Users/username/output/path/components/schemas/MySchema.ts"`
        absoluteImportPath: string;
        // Absolute import path (posix or win32, without extension). Eg: `"Users/username/output/path/components/schemas/MySchema"`
      }
    >;
  }
}

Plugins

Plugins generate extra artifacts using the same internal metadata. Available plugins:

  • generateSchemaWith$idPlugin — adds a named export with the schema $id field set.
  • fastifyIntegrationPlugin — generates a fastify-integration.ts file with a schemas array for fastify.addSchema and a RefSchemas type for the json-schema-to-ts type provider.

See plugins documentation.

How it works

Given an OpenAPI definition file, openapi-ts-json-schema:

See developer's notes.

Todo

  • Improve external #refs handling (currently being inlined and duplicated)
  • Find a way to merge multiple different OpenApi definitions consistently
  • Consider implementing an option to inline circular $refs with a configurable nesting level