UNPKG

openapi-ts-json-schema

Version:

OpenAPI to JSON schema generator with TypeScript in mind

172 lines (127 loc) 11.5 kB
# openapi-ts-json-schema [![Build Status][ci-badge]][ci] [![Npm version][npm-version-badge]][npm] [![Coveralls][coveralls-badge]][coveralls] Generate **TypeScript JSON schema** files (`.ts` modules with `as const` assertions) from **OpenAPI** definitions. **TypeScript JSON schemas** are 100% valid JSON schemas which serve as the single source of truth for runtime validation and data type inference. TypeScript JSON schemas serve various purposes, including: - Validate data and infer validated data TS types with the same JSON schema (with any JSON schema validator like [Ajv](https://ajv.js.org/)) - Infer TS type definitions from JSON schemas (with [`json-schema-to-ts`](https://github.com/ThomasAribart/json-schema-to-ts)) - Fastify integration: infer route handlers input types from their schema (with [`@fastify/type-provider-json-schema-to-ts`](https://github.com/fastify/fastify-type-provider-json-schema-to-ts)) Given an OpenAPI definition file, `openapi-ts-json-schema` will: - Resolve external/remote `$ref`s and dereference them with [`@apidevtools/json-schema-ref-parser`](https://github.com/APIDevTools/json-schema-ref-parser) - Optionally inline, import or retain local `$ref`s - Convert to JSON schema with [`@openapi-contrib/openapi-schema-to-json-schema`](https://github.com/openapi-contrib/openapi-schema-to-json-schema) and [`openapi-jsonschema-parameters`](https://www.npmjs.com/package/openapi-jsonschema-parameters) - Generate a TypeScript JSON schema file for each definition (`.ts` files with `as const` assertion) - Organizing schemas in a folder structure mirroring the original OpenAPI definition layout. `openapi-ts-json-schema` is currently in v0, which means it's still in its testing phase. I'm actively collecting feedback from users to improve its functionality and usability. **Please don't hesitate to open an issue if you encounter any problems or issues while using it.** ## Installation ``` npm i openapi-ts-json-schema -D ``` ## Usage Generate your TypeScript JSON schemas: ```ts import { openapiToTsJsonSchema } from 'openapi-ts-json-schema'; const { outputPath } = await openapiToTsJsonSchema({ openApiSchema: 'path/to/open-api-specs.yaml', definitionPathsToGenerateFrom: ['paths', 'components.schemas'], }); ``` ...and use them in your TS project: ```ts import Ajv from 'ajv'; import type { FromSchema } from 'json-schema-to-ts'; import mySchema from 'path/to/generated/schemas/MyModel.ts'; const ajv = new Ajv(); // Perform data validation and type inference using the same schema const validate = ajv.compile<FromSchema<typeof mySchema>>(mySchema); const data: unknown = {}; if (validate(data)) { // data gets type inference console.log(data.foo); } else { console.log(validate.errors); } ``` ## Options | Property | Type | Description | Default | | ---------------------------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | **openApiSchema** _(required)_ | `string` | Path to the OpenApi file (supports yaml and json). | - | | **definitionPathsToGenerateFrom** _(required)_ | `string[]` | OpenApi definition object paths to generate the JSON schemas from. Only matching paths will be generated. Supports dot notation: `["components.schemas"]`. | - | | **refHandling** | `"import" \| "inline" \| "keep"` | `"import"`: generate and import `$ref` schemas.<br/>`"inline"`: inline `$ref` schemas.<br/>`"keep"`: keep `$ref` values. | `"import"` | | **$idMapper** | `(params: { id: string }) => string` | Customize generated schemas `$id`s and `$ref`s | - | | **schemaPatcher** | `(params: { schema: JSONSchema }) => void` | Dynamically patch generated JSON schemas. The provided function will be invoked against every single JSON schema node. | - | | **outputPath** | `string` | Path where the generated schemas will be saved. Defaults to `/schemas-autogenerated` in the same directory of `openApiSchema`. | - | | **plugins** | `ReturnType<Plugin>[]` | A set of optional plugins to generate extra custom output. See [plugins docs](./docs/plugins.md). | - | | **silent** | `boolean` | Don't log user messages. | `false` | ## Notes Take a look at the [Developer's notes](./docs/developer-notes.md) for a few more in-depth explanations. ### `$ref`s handling `openapi-ts-json-schema` provides 3 `refHandling` strategies for OpenAPI `$ref` properties: | `refHandling` option | | | -------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `inline` | Replaces `$ref`s with inline copies of the target definition, creating self-contained schemas with potential redundancy | | `import` | Replaces `$ref`s with a local variable pointing to the module of the target `$ref` definition | | `keep` | Retains `$ref`s values without modification | `inline` and `import` are the more straightforward options, producing outputs that can be readily interpreted and resolved by both JavaScript engines and TypeScript type checkers. Nevertheless, a downside of these approaches is the absence of `$ref` references, causing entities initially designed as shareable (`$ref`-able) components (e.g. `components/schemas/Foo`) to lose their recognizability. A significant limitation arises from consumer applications being unable to automatically expose an OpenAPI schema with proper shared `components/schemas` definitions, as everything becomes inlined. One potential solution involves preserving `$ref`s using the `keep` option and crafting a plugin (as discussed in the [Plugins](#plugins) section) to facilitate the interpretation of `$ref` information by JavaScript and TypeScript. The implementation logic of this plugin hinges on the framework through which the generated schemas will be consumed. `openapi-ts-json-schema` ships with a [`fastify` plugin](/docs/plugins.md) available out of the box, enabling seamless integration of schema types through [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts). #### Circular `$ref`s Circular `$ref`s references are supported, too: | `refHandling` option | | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `inline` | Nested circular references are replaced with `{}` | | `import` | Completely resolves the JSON schema tree. However, the TypeScript engine will halt type recursion and assign the schema type as `any`, resulting in error `ts(7022)` | | `keep` | Does not resolve circular references by definition | For further details, refer to the [relevant tests](https://github.com/toomuchdesign/openapi-ts-json-schema/blob/master/test/circularReference.test.ts). ## Return values Beside generating the expected schema files under `outputPath`, `openapiToTsJsonSchema` returns the following meta data: ```ts { // 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"` originalSchema: JSONSchema | string; // Original dereferenced JSON schema isRef: boolean; // True if schemas is used as a `$ref` 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 are intended as a way to generate extra artifacts based on the same internal metadata created to generate the JSON schema output. `openapi-ts-json-schema` currently ships with one plugin specifically designed to better integrate with [Fastify](https://fastify.dev/), but you can write your own! Read [plugins documentation 📖](./docs/plugins.md). ## Todo - Consider removing required `definitionPathsToGenerateFrom` option in favour of exporting the whole OpenAPI definitions based on the structure defined in specs - Improve external `#ref`s 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 - Handle `$ref` parameters according to `refHandler` options [ci-badge]: https://github.com/toomuchdesign/openapi-ts-json-schema/actions/workflows/ci.yml/badge.svg [ci]: https://github.com/toomuchdesign/openapi-ts-json-schema/actions/workflows/ci.yml [coveralls-badge]: https://coveralls.io/repos/github/toomuchdesign/openapi-ts-json-schema/badge.svg?branch=master [coveralls]: https://coveralls.io/github/toomuchdesign/openapi-ts-json-schema?branch=master [npm]: https://www.npmjs.com/package/openapi-ts-json-schema [npm-version-badge]: https://img.shields.io/npm/v/openapi-ts-json-schema.svg