New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

openapi-typescript

Package Overview
Dependencies
Maintainers
1
Versions
145
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

openapi-typescript - npm Package Compare versions

Comparing version 6.2.4 to 6.2.5

./dist/index.js

3

bin/cli.js

@@ -30,2 +30,3 @@ #!/usr/bin/env node

--alphabetize (optional) Sort types alphabetically
--exclude-deprecated (optional) Exclude deprecated fields from types
`;

@@ -58,2 +59,3 @@

"alphabetize",
"excludeDeprecated",
],

@@ -109,2 +111,3 @@ string: ["auth", "header", "headersObject", "httpMethod"],

alphabetize: flags.alphabetize,
excludeDeprecated: flags.excludeDeprecated,
});

@@ -111,0 +114,0 @@

3

dist/index.js

@@ -36,2 +36,3 @@ import { URL } from "node:url";

supportArrayLength: options.supportArrayLength ?? false,
excludeDeprecated: options.excludeDeprecated ?? false,
};

@@ -104,3 +105,3 @@ const isInlineSchema = typeof schema !== "string" && schema instanceof URL === false;

indentLv++;
for (const [k, v] of getEntries(subschemaTypes, options.alphabetize)) {
for (const [k, v] of getEntries(subschemaTypes, options.alphabetize, options.excludeDeprecated)) {
if (EMPTY_OBJECT_RE.test(v))

@@ -107,0 +108,0 @@ output.push(indent(`${escObjKey(k)}: Record<string, never>;`, indentLv));

@@ -29,5 +29,3 @@ import fs from "node:fs";

return new URL(filename.startsWith("//") ? `https:${filename}` : filename);
const localPath = path.isAbsolute(filename)
? new URL(`file://${filename}`)
: new URL(filename, `file://${process.cwd()}/`);
const localPath = path.isAbsolute(filename) ? new URL(`file://${filename}`) : new URL(filename, `file://${process.cwd()}/`);
if (!fs.existsSync(localPath)) {

@@ -230,4 +228,3 @@ error(`Could not locate ${filename}`);

return;
options.discriminators[schemaID === "." ? makeTSIndex(nodePath) : makeTSIndex(["external", k, ...nodePath])] =
node.discriminator;
options.discriminators[schemaID === "." ? makeTSIndex(nodePath) : makeTSIndex(["external", k, ...nodePath])] = node.discriminator;
});

@@ -234,0 +231,0 @@ }

@@ -15,3 +15,3 @@ import { escObjKey, getEntries, getSchemaObjectComment, indent, tsOptionalProperty, tsReadonly } from "../utils.js";

indentLv++;
for (const [name, schemaObject] of getEntries(components.schemas, ctx.alphabetize)) {
for (const [name, schemaObject] of getEntries(components.schemas, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(schemaObject, indentLv);

@@ -38,3 +38,3 @@ if (c)

indentLv++;
for (const [name, responseObject] of getEntries(components.responses, ctx.alphabetize)) {
for (const [name, responseObject] of getEntries(components.responses, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(responseObject, indentLv);

@@ -66,3 +66,3 @@ if (c)

indentLv++;
for (const [name, parameterObject] of getEntries(components.parameters, ctx.alphabetize)) {
for (const [name, parameterObject] of getEntries(components.parameters, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(parameterObject, indentLv);

@@ -97,3 +97,3 @@ if (c)

indentLv++;
for (const [name, requestBodyObject] of getEntries(components.requestBodies, ctx.alphabetize)) {
for (const [name, requestBodyObject] of getEntries(components.requestBodies, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(requestBodyObject, indentLv);

@@ -132,3 +132,3 @@ if (c)

indentLv++;
for (const [name, headerObject] of getEntries(components.headers, ctx.alphabetize)) {
for (const [name, headerObject] of getEntries(components.headers, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(headerObject, indentLv);

@@ -160,3 +160,3 @@ if (c)

indentLv++;
for (const [name, pathItemObject] of getEntries(components.pathItems, ctx.alphabetize)) {
for (const [name, pathItemObject] of getEntries(components.pathItems, ctx.alphabetize, ctx.excludeDeprecated)) {
let key = escObjKey(name);

@@ -163,0 +163,0 @@ if (ctx.immutableTypes)

@@ -11,3 +11,3 @@ import { escStr, getEntries, getSchemaObjectComment, indent, tsReadonly } from "../utils.js";

indentLv++;
for (const [contentType, mediaTypeObject] of getEntries(headerObject.content, ctx.alphabetize)) {
for (const [contentType, mediaTypeObject] of getEntries(headerObject.content, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(mediaTypeObject, indentLv);

@@ -14,0 +14,0 @@ if (c)

@@ -17,2 +17,3 @@ import { escObjKey, getEntries, getSchemaObjectComment, indent, tsOptionalProperty, tsReadonly } from "../utils.js";

indentLv++;
let allOptional = true;
for (const param of operationObject.parameters ?? []) {

@@ -23,4 +24,8 @@ const node = "$ref" in param ? ctx.parameters[param.$ref] : param;

let key = escObjKey(node.name);
if (paramIn !== "path" && !node.required)
if (paramIn !== "path" && !node.required) {
key = tsOptionalProperty(key);
}
else {
allOptional = false;
}
const c = getSchemaObjectComment(param, indentLv);

@@ -39,3 +44,4 @@ if (c)

if (paramInternalOutput.length) {
parameterOutput.push(indent(`${paramIn}: {`, indentLv));
const key = allOptional ? tsOptionalProperty(paramIn) : paramIn;
parameterOutput.push(indent(`${key}: {`, indentLv));
parameterOutput.push(...paramInternalOutput);

@@ -79,3 +85,3 @@ parameterOutput.push(indent(`};`, indentLv));

indentLv++;
for (const [responseCode, responseObject] of getEntries(operationObject.responses, ctx.alphabetize)) {
for (const [responseCode, responseObject] of getEntries(operationObject.responses, ctx.alphabetize, ctx.excludeDeprecated)) {
const key = escObjKey(responseCode);

@@ -82,0 +88,0 @@ const c = getSchemaObjectComment(responseObject, indentLv);

@@ -5,5 +5,3 @@ import { escObjKey, indent, tsOptionalProperty, tsReadonly } from "../utils.js";

const output = [];
const parameters = Array.isArray(parameterObjectArray)
? parameterObjectArray.map((p) => [p.name, p])
: Object.entries(parameterObjectArray);
const parameters = Array.isArray(parameterObjectArray) ? parameterObjectArray.map((p) => [p.name, p]) : Object.entries(parameterObjectArray);
for (const [id, param] of parameters) {

@@ -10,0 +8,0 @@ let key = escObjKey(id);

import { escStr, getEntries, indent } from "../utils.js";
import transformParameterObject from "./parameter-object.js";
import transformPathItemObject from "./path-item-object.js";
const OPERATIONS = ["get", "post", "put", "delete", "options", "head", "patch", "trace"];
function extractPathParams(obj) {
const params = new Map();
if (obj && "parameters" in obj) {
for (const p of obj.parameters ?? []) {
if ("in" in p && p.in === "path")
params.set(p.name, p);
}
}
return params;
}
export default function transformPathsObject(pathsObject, ctx) {

@@ -8,10 +19,9 @@ let { indentLv } = ctx;

indentLv++;
for (const [url, pathItemObject] of getEntries(pathsObject, ctx.alphabetize)) {
for (const [url, pathItemObject] of getEntries(pathsObject, ctx.alphabetize, ctx.excludeDeprecated)) {
let path = url;
if (ctx.pathParamsAsTypes && pathItemObject.parameters) {
for (const p of pathItemObject.parameters) {
if ("in" in p && p.in === "path") {
const paramType = transformParameterObject(p, { path: `#/paths/${url}/parameters/${p.name}`, ctx });
path = path.replace(`{${p.name}}`, `\${${paramType}}`);
}
const pathParams = new Map([...extractPathParams(pathItemObject), ...OPERATIONS.flatMap((op) => Array.from(extractPathParams(pathItemObject[op])))]);
if (ctx.pathParamsAsTypes && pathParams) {
for (const p of pathParams.values()) {
const paramType = transformParameterObject(p, { path: `#/paths/${url}/parameters/${p.name}`, ctx });
path = path.replace(`{${p.name}}`, `\${${paramType}}`);
}

@@ -18,0 +28,0 @@ path = `[path: \`${path}\`]`;

@@ -12,3 +12,3 @@ import { escStr, getEntries, getSchemaObjectComment, indent, tsReadonly } from "../utils.js";

indentLv++;
for (const [contentType, mediaTypeObject] of getEntries(requestBodyObject.content, ctx.alphabetize)) {
for (const [contentType, mediaTypeObject] of getEntries(requestBodyObject.content, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(mediaTypeObject, indentLv);

@@ -15,0 +15,0 @@ if (c)

@@ -1,2 +0,2 @@

import { escObjKey, escStr, getEntries, getSchemaObjectComment, indent, tsOptionalProperty, tsReadonly, } from "../utils.js";
import { escObjKey, escStr, getEntries, getSchemaObjectComment, indent, tsOptionalProperty, tsReadonly } from "../utils.js";
import transformHeaderObject from "./header-object.js";

@@ -14,3 +14,3 @@ import transformMediaTypeObject from "./media-type-object.js";

indentLv++;
for (const [name, headerObject] of getEntries(responseObject.headers, ctx.alphabetize)) {
for (const [name, headerObject] of getEntries(responseObject.headers, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(headerObject, indentLv);

@@ -42,3 +42,3 @@ if (c)

indentLv++;
for (const [contentType, mediaTypeObject] of getEntries(responseObject.content, ctx.alphabetize)) {
for (const [contentType, mediaTypeObject] of getEntries(responseObject.content, ctx.alphabetize, ctx.excludeDeprecated)) {
let key = escStr(contentType);

@@ -45,0 +45,0 @@ if (ctx.immutableTypes)

@@ -1,2 +0,2 @@

import { escObjKey, escStr, getEntries, getSchemaObjectComment, indent, parseRef, tsArrayOf, tsIntersectionOf, tsOmit, tsOneOf, tsOptionalProperty, tsReadonly, tsTupleOf, tsUnionOf, tsWithRequired, } from "../utils.js";
import { escObjKey, escStr, getEntries, getSchemaObjectComment, indent, parseRef, tsArrayOf, tsIntersectionOf, tsOmit, tsOneOf, tsOptionalProperty, tsReadonly, tsTupleOf, tsUnionOf, tsWithRequired } from "../utils.js";
export default function transformSchemaObject(schemaObject, options) {

@@ -48,6 +48,3 @@ const result = defaultSchemaObjectTransform(schemaObject, options);

}
return tsUnionOf(...items, ...(schemaObject.nullable ||
("type" in schemaObject && Array.isArray(schemaObject.type) && schemaObject.type.includes("null"))
? ["null"]
: []));
return tsUnionOf(...items, ...(schemaObject.nullable || ("type" in schemaObject && Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) ? ["null"] : []));
}

@@ -90,5 +87,3 @@ if ("oneOf" in schemaObject && !schemaObject.oneOf.some((t) => "$ref" in t && ctx.discriminators[t.$ref])) {

const minItems = typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0;
const maxItems = typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && minItems <= schemaObject.maxItems
? schemaObject.maxItems
: undefined;
const maxItems = typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && minItems <= schemaObject.maxItems ? schemaObject.maxItems : undefined;
const estimateCodeSize = typeof maxItems !== "number" ? minItems : (maxItems * (maxItems + 1) - minItems * (minItems - 1)) / 2;

@@ -117,6 +112,5 @@ if (ctx.supportArrayLength && (minItems !== 0 || maxItems !== undefined) && estimateCodeSize < 30) {

const coreType = [];
if (("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length) ||
("additionalProperties" in schemaObject && schemaObject.additionalProperties)) {
if (("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length) || ("additionalProperties" in schemaObject && schemaObject.additionalProperties)) {
indentLv++;
for (const [k, v] of getEntries(schemaObject.properties ?? {}, ctx.alphabetize)) {
for (const [k, v] of getEntries(schemaObject.properties ?? {}, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(v, indentLv);

@@ -123,0 +117,0 @@ if (c)

@@ -7,3 +7,3 @@ import { escStr, getEntries, indent } from "../utils.js";

indentLv++;
for (const [name, pathItemObject] of getEntries(webhooksObject, ctx.alphabetize)) {
for (const [name, pathItemObject] of getEntries(webhooksObject, ctx.alphabetize, ctx.excludeDeprecated)) {
output.push(indent(`${escStr(name)}: ${transformPathItemObject(pathItemObject, {

@@ -10,0 +10,0 @@ path: `#/webhooks/${name}`,

@@ -316,2 +316,3 @@ /// <reference types="node" resolution-mode="require"/>

fetch?: Fetch;
excludeDeprecated?: boolean;
}

@@ -369,3 +370,4 @@ export type Subschema = {

supportArrayLength: boolean;
excludeDeprecated: boolean;
}
export type Fetch = (input: RequestInfo, init?: RequestInit) => Promise<Response>;

@@ -45,3 +45,3 @@ import c from "ansi-colors";

export declare function indent(input: string, level: number): string;
export declare function getEntries<T>(obj: ArrayLike<T> | Record<string, T>, alphabetize?: boolean): [string, T][];
export declare function getEntries<T>(obj: ArrayLike<T> | Record<string, T>, alphabetize?: boolean, excludeDeprecated?: boolean): [string, T][];
export declare function error(msg: string): void;

@@ -48,0 +48,0 @@ export declare function isRemoteURL(url: string): boolean;

@@ -187,6 +187,8 @@ import c from "ansi-colors";

}
export function getEntries(obj, alphabetize) {
const entries = Object.entries(obj);
export function getEntries(obj, alphabetize, excludeDeprecated) {
let entries = Object.entries(obj);
if (alphabetize)
entries.sort(([a], [b]) => a.localeCompare(b, "en", { numeric: true }));
if (excludeDeprecated)
entries = entries.filter(([, v]) => !(v && typeof v === "object" && "deprecated" in v && v.deprecated));
return entries;

@@ -193,0 +195,0 @@ }

{
"name": "openapi-typescript",
"description": "Generate TypeScript types from Swagger OpenAPI specs",
"version": "6.2.4",
"author": "drew@pow.rs",
"version": "6.2.5",
"author": {
"name": "Drew Powers",
"email": "drew@pow.rs"
},
"license": "MIT",

@@ -10,5 +13,4 @@ "bin": {

},
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"type": "module",
"files": [

@@ -19,5 +21,7 @@ "bin",

],
"homepage": "https://openapi-ts.pages.dev",
"repository": {
"type": "git",
"url": "https://github.com/drwpow/openapi-typescript"
"url": "https://github.com/drwpow/openapi-typescript",
"directory": "packages/openapi-typescript"
},

@@ -38,16 +42,2 @@ "keywords": [

},
"homepage": "https://github.com/drwpow/openapi-typescript#readme",
"scripts": {
"build": "del dist && tsc -p tsconfig.build.json",
"dev": "tsc -p tsconfig.build.json --watch",
"download:schemas": "vite-node ./scripts/download-schemas.ts",
"format": "npm run prettier -w .",
"lint": "eslint \"src/**/*.{js,ts}\"",
"prepare": "npm run build",
"test": "npm run test:ts && vitest run",
"test:ts": "tsc --noEmit",
"test:coverage": "npm run test:ts && vitest run --coverage",
"update:examples": "vite-node ./scripts/update-examples.ts",
"version": "npm run build"
},
"dependencies": {

@@ -58,3 +48,3 @@ "ansi-colors": "^4.1.3",

"supports-color": "^9.3.1",
"undici": "^5.22.0",
"undici": "^5.22.1",
"yargs-parser": "^21.1.1"

@@ -65,18 +55,27 @@ },

"@types/js-yaml": "^4.0.5",
"@types/node": "^18.16.1",
"@typescript-eslint/eslint-plugin": "^5.59.1",
"@typescript-eslint/parser": "^5.59.1",
"@vitest/coverage-c8": "^0.29.8",
"@types/node": "^20.2.3",
"@typescript-eslint/eslint-plugin": "^5.59.7",
"@typescript-eslint/parser": "^5.59.7",
"degit": "^2.8.4",
"del-cli": "^5.0.0",
"eslint": "^8.39.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"execa": "^6.1.0",
"prettier": "^2.8.8",
"typescript": "^5.0.4",
"vite": "^4.3.3",
"vite-node": "^0.29.8",
"vitest": "^0.29.8"
"vite": "^4.3.8",
"vite-node": "^0.31.1",
"vitest": "^0.31.1"
},
"scripts": {
"build": "del dist && tsc -p tsconfig.build.json",
"dev": "tsc -p tsconfig.build.json --watch",
"download:schemas": "vite-node ./scripts/download-schemas.ts",
"format": "pnpm run prettier -w .",
"lint": "run-p -s lint:*",
"lint:js": "eslint \"src/**/*.{js,ts}\"",
"lint:prettier": "prettier --check \"src/**/*\"",
"test": "run-p -s test:*",
"test:js": "vitest run",
"test:ts": "tsc --noEmit",
"update:examples": "vite-node ./scripts/update-examples.ts",
"prepublish": "pnpm run build",
"version": "pnpm run build"
}
}
}

@@ -1,20 +0,13 @@

[![version(scoped)](https://img.shields.io/npm/v/openapi-typescript.svg)](https://www.npmjs.com/package/openapi-typescript)
[![npm downloads (weekly)](https://img.shields.io/npm/dw/openapi-typescript)](https://www.npmjs.com/package/openapi-typescript)
[![codecov](https://codecov.io/gh/drwpow/openapi-typescript/branch/main/graph/badge.svg)](https://codecov.io/gh/drwpow/openapi-typescript)
<img src="../../docs/public/assets/openapi-ts.svg" alt="openapi-typescript" width="200" height="40" />
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-70-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
openapi-typescript generates TypeScript types from static <a href="https://spec.openapis.org/oas/latest.html" target="_blank" rel="noopener noreferrer">OpenAPI</a> schemas quickly using only Node.js. It is fast, lightweight, (almost) dependency-free, and no Java/node-gyp/running OpenAPI servers necessary.
# 📘️ openapi-typescript
The code is [MIT-licensed](./LICENSE) and free for use.
🚀 Convert static [OpenAPI](https://spec.openapis.org/oas/latest.html) schemas to TypeScript types quickly using pure Node.js. Fast, lightweight, (almost) dependency-free, and no Java/node-gyp/running OpenAPI servers necessary.
**Features**
- ✅ Supports YAML and JSON formats
- ✅ Supports advanced OpenAPI 3.1 features like [discriminators](https://spec.openapis.org/oas/v3.1.0#discriminator-object)
- ✅ Supports loading via remote URL (simple authentication supported with the `--auth` flag)
- ✅ Supports remote references: `$ref: "external.yaml#components/schemas/User"`
- ✅ Fetches remote schemas quickly using [undici](https://www.npmjs.com/package/undici)
- ✅ Supports OpenAPI 3.0 and 3.1 (including advanced features like <a href="https://spec.openapis.org/oas/v3.1.0#discriminator-object" target="_blank" rel="noopener noreferrer">discriminators</a>)
- ✅ Generate **runtime-free types** that outperform old-school codegen
- ✅ Load schemas from YAML or JSON, locally or remotely
- ✅ Native Node.js code is fast and generates types within milliseconds

@@ -27,16 +20,33 @@ **Examples**

Note:️ openapiTS requires **VALID** OpenAPI 3.x schemas to work, and this library does not handle validation. There are several quality tools that handle this like [@apidevtools/swagger-parser](https://www.npmjs.com/package/@apidevtools/swagger-parser). Make sure to validate your schemas first!
First, generate a local type file by running `npx openapi-typescript`:
### 🖥️ CLI
```bash
# Local schema
npx openapi-typescript ./path/to/my/schema.yaml -o ./path/to/my/schema.d.ts
# 🚀 ./path/to/my/schema.yaml -> ./path/to/my/schema.d.ts [7ms]
#### 🗄️ Reading a local schema
# Remote schema
npx openapi-typescript https://myapi.dev/api/v1/openapi.yaml -o ./path/to/my/schema.d.ts
# 🚀 https://myapi.dev/api/v1/openapi.yaml -> ./path/to/my/schema.d.ts [250ms]
```
```bash
npx openapi-typescript schema.yaml --output schema.ts
> ⚠️ Be sure to <a href="https://redocly.com/docs/cli/commands/lint/" target="_blank" rel="noopener noreferrer">validate your schemas</a>! openapi-typescript will err on invalid schemas.
# 🔭 Loading spec from schema.yaml…
# 🚀 schema.yaml -> schema.ts [250ms]
Then, import schemas from the generated file like so:
```ts
import { paths, components } from "./path/to/my/schema"; // <- generated by openapi-typescript
// Schema Obj
type MyType = components["schemas"]["MyType"];
// Path params
type EndpointParams = paths["/my/endpoint"]["parameters"];
// Response obj
type SuccessResponse = paths["/my/endpoint"]["get"]["responses"][200]["content"]["application/json"]["schema"];
type ErrorResponse = paths["/my/endpoint"]["get"]["responses"][500]["content"]["application/json"]["schema"];
```
##### 🦠 Globbing local schemas
#### 🦠 Globbing local schemas

@@ -46,8 +56,5 @@ ```bash

# 🔭 Loading spec from specs/one.yaml…
# 🔭 Loading spec from specs/two.yaml…
# 🔭 Loading spec from specs/three.yaml…
# 🚀 specs/one.yaml -> schemas/specs/one.ts [250ms]
# 🚀 specs/two.yaml -> schemas/specs/two.ts [250ms]
# 🚀 specs/three.yaml -> schemas/specs/three.ts [250ms]
# 🚀 specs/one.yaml -> schemas/specs/one.ts [7ms]
# 🚀 specs/two.yaml -> schemas/specs/two.ts [7ms]
# 🚀 specs/three.yaml -> schemas/specs/three.ts [7ms]
```

@@ -57,3 +64,3 @@

#### ☁️ Reading remote schemas
#### ☁️ Remote schemas

@@ -63,4 +70,3 @@ ```bash

# 🔭 Loading spec from https://petstore3.swagger.io/api/v3/openapi.yaml…
# 🚀 https://petstore3.swagger.io/api/v3/openapi.yaml -> petstore.d.ts [650ms]
# 🚀 https://petstore3.swagger.io/api/v3/openapi.yaml -> petstore.d.ts [250ms]
```

@@ -70,26 +76,2 @@

#### 🟦 Using in TypeScript
Import any top-level item from the generated spec to use it. It works best if you also alias types to save on typing:
```ts
import { components } from "./generated-schema.ts";
type APIResponse = components["schemas"]["APIResponse"];
```
Because OpenAPI schemas may have invalid TypeScript characters as names, the square brackets are a safe way to access every property.
##### 🏗️ Operations
Operations can be imported directly by their [operationId](https://spec.openapis.org/oas/latest.html#operation-object):
```ts
import { operations } from "./generated-schema.ts";
type getUsersById = operations["getUsersById"];
```
_Thanks, [@gr2m](https://github.com/gr2m)!_
#### ⚾ Fetching data

@@ -118,3 +100,5 @@

✨ **Tip**: Automatically-typed fetch wrappers are better to use than manually-assigned generics. The latter is not only more work, but it can be error-prone (which makes your OpenAPI typing worthless if it can’t catch all your errors!).
> ✨ **Tip**
>
> A good fetch wrapper should **never use generics.** Generics require more typing and can hide errors!

@@ -142,2 +126,3 @@ ### 📖 Options

| `--alphabetize` | | `false` | Sort types alphabetically |
| `--exclude-deprecated` | | `false` | Exclude deprecated fields from types |

@@ -232,3 +217,3 @@ #### 🚩 `--path-params-as-types`

The Node API may be useful if dealing with dynamically-created schemas, or you’re using within context of a larger application. Pass in either a JSON-friendly object to load a schema from memory, or a string to load a schema from a local file or remote URL (it will load the file quickly using built-in Node methods). Note that a YAML string isn’t supported in the Node.js API; either use the CLI or convert to JSON using [js-yaml](https://www.npmjs.com/package/js-yaml) first.
> ⚠️ Note that unlike the CLI, YAML isn’t supported in the Node.js API. You’ll need to convert it to JSON yourself using <a href="https://www.npmjs.com/package/js-yaml" target="_blank" rel="noopener noreferrer">js-yaml</a> first.

@@ -248,4 +233,7 @@ #### 📖 Node options

If using the Node.js API, you can override the normal Schema Object transformer with your own. This is useful for providing enhanced functionality for specific parts of your schema.
Use the `transform()` and `postTransform()` options to override the default Schema Object transformer with your own. This is useful for providing non-standard modifications for specific parts of your schema.
- `transform()` runs **BEFORE** the conversion to TypeScript (you’re working with the original OpenAPI nodes)
- `postTransform()` runs **AFTER** the conversion to TypeScript (you’re working with TypeScript types)
For example, say your schema has the following property:

@@ -283,8 +271,7 @@

✨ Don’t forget about `postTransform()` as well! It works the same way, but runs _after_ the TypeScript transformation so you can extend/modify types as-needed.
## 🏅 Project Goals
1. Support converting any valid OpenAPI schema to TypeScript types, no matter how complicated.
1. This library does **NOT** validate your schema, there are other libraries for that.
1. Generate **runtime-free types** for maximum performance.
1. This library does **NOT** validate your schema, there existing libraries for that (like [`redocly lint`](https://redocly.com/docs/cli/commands/lint/)).
1. The generated TypeScript types **must** match your schema as closely as possible (e.g. no renaming to `PascalCase`)

@@ -297,111 +284,1 @@ 1. This library should never require Java, node-gyp, or some other complex environment to work. This should require Node.js and nothing else.

PRs are welcome! Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) guide.
### Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://pow.rs"><img src="https://avatars3.githubusercontent.com/u/1369770?v=4?s=100" width="100px;" alt="Drew Powers"/><br /><sub><b>Drew Powers</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=dangodev" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=dangodev" title="Documentation">📖</a> <a href="#infra-dangodev" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=dangodev" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://smyrdek.com"><img src="https://avatars1.githubusercontent.com/u/6187417?v=4?s=100" width="100px;" alt="Przemek Smyrdek"/><br /><sub><b>Przemek Smyrdek</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=psmyrdek" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=psmyrdek" title="Documentation">📖</a> <a href="#ideas-psmyrdek" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=psmyrdek" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://danielenman.com"><img src="https://avatars3.githubusercontent.com/u/432487?v=4?s=100" width="100px;" alt="Dan Enman"/><br /><sub><b>Dan Enman</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aenmand" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=enmand" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://atlefren.net"><img src="https://avatars2.githubusercontent.com/u/1829927?v=4?s=100" width="100px;" alt="Atle Frenvik Sveen"/><br /><sub><b>Atle Frenvik Sveen</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=atlefren" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=atlefren" title="Documentation">📖</a> <a href="#ideas-atlefren" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=atlefren" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.timdewolf.com"><img src="https://avatars0.githubusercontent.com/u/4455209?v=4?s=100" width="100px;" alt="Tim de Wolf"/><br /><sub><b>Tim de Wolf</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=tpdewolf" title="Code">💻</a> <a href="#ideas-tpdewolf" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tombarton"><img src="https://avatars1.githubusercontent.com/u/6222711?v=4?s=100" width="100px;" alt="Tom Barton"/><br /><sub><b>Tom Barton</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=tombarton" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=tombarton" title="Documentation">📖</a> <a href="#ideas-tombarton" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=tombarton" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.viig.no"><img src="https://avatars0.githubusercontent.com/u/1080888?v=4?s=100" width="100px;" alt="Sven Nicolai Viig"/><br /><sub><b>Sven Nicolai Viig</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Asvnv" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=svnv" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=svnv" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://toot.cafe/@sorin"><img src="https://avatars1.githubusercontent.com/u/2109702?v=4?s=100" width="100px;" alt="Sorin Davidoi"/><br /><sub><b>Sorin Davidoi</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Asorin-davidoi" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=sorin-davidoi" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=sorin-davidoi" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/scvnathan"><img src="https://avatars3.githubusercontent.com/u/73474?v=4?s=100" width="100px;" alt="Nathan Schneirov"/><br /><sub><b>Nathan Schneirov</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=scvnathan" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=scvnathan" title="Documentation">📖</a> <a href="#ideas-scvnathan" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=scvnathan" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://lbenie.xyz/"><img src="https://avatars1.githubusercontent.com/u/7316046?v=4?s=100" width="100px;" alt="Lucien Bénié"/><br /><sub><b>Lucien Bénié</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=lbenie" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=lbenie" title="Documentation">📖</a> <a href="#ideas-lbenie" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=lbenie" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://boris.sh"><img src="https://avatars1.githubusercontent.com/u/17952318?v=4?s=100" width="100px;" alt="Boris K"/><br /><sub><b>Boris K</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=bokub" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://twitter.com/antonk52"><img src="https://avatars1.githubusercontent.com/u/5817809?v=4?s=100" width="100px;" alt="Anton"/><br /><sub><b>Anton</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aantonk52" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=antonk52" title="Code">💻</a> <a href="#ideas-antonk52" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=antonk52" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tshelburne"><img src="https://avatars3.githubusercontent.com/u/1202267?v=4?s=100" width="100px;" alt="Tim Shelburne"/><br /><sub><b>Tim Shelburne</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=tshelburne" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=tshelburne" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://typeofweb.com"><img src="https://avatars0.githubusercontent.com/u/1338731?v=4?s=100" width="100px;" alt="Michał Miszczyszyn"/><br /><sub><b>Michał Miszczyszyn</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=mmiszy" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/skh-"><img src="https://avatars1.githubusercontent.com/u/1292598?v=4?s=100" width="100px;" alt="Sam K Hall"/><br /><sub><b>Sam K Hall</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=skh-" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=skh-" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BlooJeans"><img src="https://avatars2.githubusercontent.com/u/1751182?v=4?s=100" width="100px;" alt="Matt Jeanes"/><br /><sub><b>Matt Jeanes</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=BlooJeans" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.selbekk.io"><img src="https://avatars1.githubusercontent.com/u/1307267?v=4?s=100" width="100px;" alt="Kristofer Giltvedt Selbekk"/><br /><sub><b>Kristofer Giltvedt Selbekk</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=selbekk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://mause.me"><img src="https://avatars2.githubusercontent.com/u/1405026?v=4?s=100" width="100px;" alt="Elliana May"/><br /><sub><b>Elliana May</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=Mause" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=Mause" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/henhal"><img src="https://avatars3.githubusercontent.com/u/9608258?v=4?s=100" width="100px;" alt="Henrik Hall"/><br /><sub><b>Henrik Hall</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=henhal" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=henhal" title="Documentation">📖</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=henhal" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dev.to/gr2m"><img src="https://avatars3.githubusercontent.com/u/39992?v=4?s=100" width="100px;" alt="Gregor Martynus"/><br /><sub><b>Gregor Martynus</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=gr2m" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=gr2m" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Agr2m" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://samn.co.uk"><img src="https://avatars2.githubusercontent.com/u/408983?v=4?s=100" width="100px;" alt="Sam Mesterton-Gibbons"/><br /><sub><b>Sam Mesterton-Gibbons</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=samdbmg" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Asamdbmg" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=samdbmg" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://rendall.dev"><img src="https://avatars2.githubusercontent.com/u/293263?v=4?s=100" width="100px;" alt="Rendall"/><br /><sub><b>Rendall</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=rendall" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Arendall" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=rendall" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://massaioli.wordpress.com"><img src="https://avatars3.githubusercontent.com/u/149178?v=4?s=100" width="100px;" alt="Robert Massaioli"/><br /><sub><b>Robert Massaioli</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=robertmassaioli" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Arobertmassaioli" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://jankuca.com"><img src="https://avatars3.githubusercontent.com/u/367262?v=4?s=100" width="100px;" alt="Jan Kuča"/><br /><sub><b>Jan Kuča</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=jankuca" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=jankuca" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/th-m"><img src="https://avatars3.githubusercontent.com/u/13792029?v=4?s=100" width="100px;" alt="Thomas Valadez"/><br /><sub><b>Thomas Valadez</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=th-m" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://asithadesilva.com"><img src="https://avatars1.githubusercontent.com/u/3814354?v=4?s=100" width="100px;" alt="Asitha de Silva"/><br /><sub><b>Asitha de Silva</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=asithade" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aasithade" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MikeYermolayev"><img src="https://avatars2.githubusercontent.com/u/8783498?v=4?s=100" width="100px;" alt="Mikhail Yermolayev"/><br /><sub><b>Mikhail Yermolayev</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3AMikeYermolayev" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/radist2s"><img src="https://avatars.githubusercontent.com/u/725645?v=4?s=100" width="100px;" alt="Alex Batalov"/><br /><sub><b>Alex Batalov</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=radist2s" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=radist2s" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FedeBev"><img src="https://avatars.githubusercontent.com/u/22151395?v=4?s=100" width="100px;" alt="Federico Bevione"/><br /><sub><b>Federico Bevione</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3AFedeBev" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=FedeBev" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=FedeBev" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yamacent"><img src="https://avatars.githubusercontent.com/u/8544439?v=4?s=100" width="100px;" alt="Daisuke Yamamoto"/><br /><sub><b>Daisuke Yamamoto</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=yamacent" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Ayamacent" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=yamacent" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dnalborczyk"><img src="https://avatars.githubusercontent.com/u/2903325?v=4?s=100" width="100px;" alt="dnalborczyk"/><br /><sub><b>dnalborczyk</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=dnalborczyk" title="Documentation">📖</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=dnalborczyk" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=dnalborczyk" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FabioWanner"><img src="https://avatars.githubusercontent.com/u/46821078?v=4?s=100" width="100px;" alt="FabioWanner"/><br /><sub><b>FabioWanner</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3AFabioWanner" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=FabioWanner" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=FabioWanner" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.ashsmith.io"><img src="https://avatars.githubusercontent.com/u/1086841?v=4?s=100" width="100px;" alt="Ash Smith"/><br /><sub><b>Ash Smith</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=ashsmith" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aashsmith" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=ashsmith" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://mehalter.com"><img src="https://avatars.githubusercontent.com/u/1591837?v=4?s=100" width="100px;" alt="Micah Halter"/><br /><sub><b>Micah Halter</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=mehalter" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=mehalter" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Amehalter" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Chrg1001"><img src="https://avatars.githubusercontent.com/u/40189653?v=4?s=100" width="100px;" alt="Yuto Yoshihara"/><br /><sub><b>Yuto Yoshihara</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=Chrg1001" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3AChrg1001" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=Chrg1001" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sharmarajdaksh"><img src="https://avatars.githubusercontent.com/u/33689528?v=4?s=100" width="100px;" alt="Dakshraj Sharma"/><br /><sub><b>Dakshraj Sharma</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=sharmarajdaksh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shuluster"><img src="https://avatars.githubusercontent.com/u/1707910?v=4?s=100" width="100px;" alt="Shaosu Liu"/><br /><sub><b>Shaosu Liu</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=shuluster" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://vytenis.kuciauskas.lt"><img src="https://avatars.githubusercontent.com/u/468006?v=4?s=100" width="100px;" alt="Vytenis"/><br /><sub><b>Vytenis</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=FDiskas" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.zornwebdev.com"><img src="https://avatars.githubusercontent.com/u/22532542?v=4?s=100" width="100px;" alt="Eric Zorn"/><br /><sub><b>Eric Zorn</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=ericzorn93" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=ericzorn93" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=ericzorn93" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.mbelsky.com/"><img src="https://avatars.githubusercontent.com/u/3923527?v=4?s=100" width="100px;" alt="Max Belsky"/><br /><sub><b>Max Belsky</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=mbelsky" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Ambelsky" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Peteck"><img src="https://avatars.githubusercontent.com/u/1520592?v=4?s=100" width="100px;" alt="Peter Bech"/><br /><sub><b>Peter Bech</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=Peteck" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3APeteck" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://rusty.today"><img src="https://avatars.githubusercontent.com/u/731941?v=4?s=100" width="100px;" alt="Rusty Conover"/><br /><sub><b>Rusty Conover</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=rustyconover" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bunkscene"><img src="https://avatars.githubusercontent.com/u/2693678?v=4?s=100" width="100px;" alt="Dave Carlson"/><br /><sub><b>Dave Carlson</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=bunkscene" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ottomated.net"><img src="https://avatars.githubusercontent.com/u/31470743?v=4?s=100" width="100px;" alt="ottomated"/><br /><sub><b>ottomated</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=ottomated" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aottomated" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://karanarqq.dev"><img src="https://avatars.githubusercontent.com/u/28733669?v=4?s=100" width="100px;" alt="Artem Shuvaev"/><br /><sub><b>Artem Shuvaev</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=sadfsdfdsa" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Asadfsdfdsa" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ajaishankar"><img src="https://avatars.githubusercontent.com/u/328008?v=4?s=100" width="100px;" alt="ajaishankar"/><br /><sub><b>ajaishankar</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=ajaishankar" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.dominikdosoudil.cz"><img src="https://avatars.githubusercontent.com/u/15929942?v=4?s=100" width="100px;" alt="Dominik Dosoudil"/><br /><sub><b>Dominik Dosoudil</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=dominikdosoudil" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=dominikdosoudil" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://kgtkr.net/"><img src="https://avatars.githubusercontent.com/u/17868838?v=4?s=100" width="100px;" alt="tkr"/><br /><sub><b>tkr</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=kgtkr" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=kgtkr" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/berzi"><img src="https://avatars.githubusercontent.com/u/32619123?v=4?s=100" width="100px;" alt="berzi"/><br /><sub><b>berzi</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=berzi" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=berzi" title="Documentation">📖</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=berzi" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://philip-trauner.me"><img src="https://avatars.githubusercontent.com/u/9287847?v=4?s=100" width="100px;" alt="Philip Trauner"/><br /><sub><b>Philip Trauner</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=PhilipTrauner" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=PhilipTrauner" title="Documentation">📖</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=PhilipTrauner" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://powell-v2.github.io/"><img src="https://avatars.githubusercontent.com/u/25308326?v=4?s=100" width="100px;" alt="Pavel Yermolin"/><br /><sub><b>Pavel Yermolin</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=Powell-v2" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=Powell-v2" title="Documentation">📖</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=Powell-v2" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.duncanbeevers.com"><img src="https://avatars.githubusercontent.com/u/7367?v=4?s=100" width="100px;" alt="Duncan Beevers"/><br /><sub><b>Duncan Beevers</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=duncanbeevers" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aduncanbeevers" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=duncanbeevers" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=duncanbeevers" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://t.me/tkukushkin"><img src="https://avatars.githubusercontent.com/u/1482516?v=4?s=100" width="100px;" alt="Timofey Kukushkin"/><br /><sub><b>Timofey Kukushkin</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=tkukushkin" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=tkukushkin" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Atkukushkin" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://semigradsky.dev/"><img src="https://avatars.githubusercontent.com/u/1198848?v=4?s=100" width="100px;" alt="Dmitry Semigradsky"/><br /><sub><b>Dmitry Semigradsky</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3ASemigradsky" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=Semigradsky" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=Semigradsky" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://jeremyliberman.com/"><img src="https://avatars.githubusercontent.com/u/2754163?v=4?s=100" width="100px;" alt="Jeremy Liberman"/><br /><sub><b>Jeremy Liberman</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=MrLeebo" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=MrLeebo" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://axelhzf.com"><img src="https://avatars.githubusercontent.com/u/175627?v=4?s=100" width="100px;" alt="Axel Hernández Ferrera"/><br /><sub><b>Axel Hernández Ferrera</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=axelhzf" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aaxelhzf" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=axelhzf" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/imagoiq"><img src="https://avatars.githubusercontent.com/u/12294151?v=4?s=100" width="100px;" alt="Loïc Fürhoff"/><br /><sub><b>Loïc Fürhoff</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=imagoiq" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=imagoiq" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aimagoiq" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BTMPL"><img src="https://avatars.githubusercontent.com/u/247153?v=4?s=100" width="100px;" alt="Bartosz Szczeciński"/><br /><sub><b>Bartosz Szczeciński</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=BTMPL" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3ABTMPL" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=BTMPL" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/HiiiiD"><img src="https://avatars.githubusercontent.com/u/61231210?v=4?s=100" width="100px;" alt="Marco Salomone"/><br /><sub><b>Marco Salomone</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=HiiiiD" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=HiiiiD" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3AHiiiiD" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yacinehmito"><img src="https://avatars.githubusercontent.com/u/6893840?v=4?s=100" width="100px;" alt="Yacine Hmito"/><br /><sub><b>Yacine Hmito</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=yacinehmito" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=yacinehmito" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Ayacinehmito" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://sajadtorkamani.com"><img src="https://avatars.githubusercontent.com/u/9380313?v=4?s=100" width="100px;" alt="Sajad Torkamani"/><br /><sub><b>Sajad Torkamani</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=sajadtorkamani" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sci-scale.net/"><img src="https://avatars.githubusercontent.com/u/6804901?v=4?s=100" width="100px;" alt="Marius van den Beek"/><br /><sub><b>Marius van den Beek</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=mvdbeek" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Amvdbeek" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=mvdbeek" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sgrimm"><img src="https://avatars.githubusercontent.com/u/1248649?v=4?s=100" width="100px;" alt="Steven Grimm"/><br /><sub><b>Steven Grimm</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=sgrimm" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Asgrimm" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=sgrimm" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://trutoo.com/people/erik-hughes"><img src="https://avatars.githubusercontent.com/u/455178?v=4?s=100" width="100px;" alt="Erik Hughes"/><br /><sub><b>Erik Hughes</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=Swiftwork" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3ASwiftwork" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=Swiftwork" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mtth"><img src="https://avatars.githubusercontent.com/u/1216372?v=4?s=100" width="100px;" alt="Matthieu Monsch"/><br /><sub><b>Matthieu Monsch</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=mtth" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Amtth" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=mtth" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mitchell-merry"><img src="https://avatars.githubusercontent.com/u/8567231?v=4?s=100" width="100px;" alt="Mitchell Merry"/><br /><sub><b>Mitchell Merry</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=mitchell-merry" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=mitchell-merry" title="Tests">⚠️</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Amitchell-merry" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.francoisrisoud.com"><img src="https://avatars.githubusercontent.com/u/6012554?v=4?s=100" width="100px;" alt="François Risoud"/><br /><sub><b>François Risoud</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=qnp" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aqnp" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=qnp" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shoffmeister"><img src="https://avatars.githubusercontent.com/u/3868036?v=4?s=100" width="100px;" alt="shoffmeister"/><br /><sub><b>shoffmeister</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=shoffmeister" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/liangskyli"><img src="https://avatars.githubusercontent.com/u/31531283?v=4?s=100" width="100px;" alt="liangsky"/><br /><sub><b>liangsky</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=liangskyli" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Aliangskyli" title="Bug reports">🐛</a> <a href="https://github.com/drwpow/openapi-typescript/commits?author=liangskyli" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://happycollision.com"><img src="https://avatars.githubusercontent.com/u/3663628?v=4?s=100" width="100px;" alt="Don Denton"/><br /><sub><b>Don Denton</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=happycollision" title="Code">💻</a> <a href="https://github.com/drwpow/openapi-typescript/issues?q=author%3Ahappycollision" title="Bug reports">🐛</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
Contributions of any kind welcome!

@@ -38,6 +38,3 @@ import type { GlobalContext, OpenAPI3, OpenAPITSOptions, Subschema } from "./types.js";

*/
async function openapiTS(
schema: string | URL | OpenAPI3 | Readable,
options: OpenAPITSOptions = {} as Partial<OpenAPITSOptions>
): Promise<string> {
async function openapiTS(schema: string | URL | OpenAPI3 | Readable, options: OpenAPITSOptions = {} as Partial<OpenAPITSOptions>): Promise<string> {
const ctx: GlobalContext = {

@@ -58,2 +55,3 @@ additionalProperties: options.additionalProperties ?? false,

supportArrayLength: options.supportArrayLength ?? false,
excludeDeprecated: options.excludeDeprecated ?? false,
};

@@ -110,6 +108,3 @@

if (rootTypes[k] && !EMPTY_OBJECT_RE.test(rootTypes[k])) {
output.push(
options.exportType ? `export type ${k} = ${rootTypes[k]};` : `export interface ${k} ${rootTypes[k]}`,
""
);
output.push(options.exportType ? `export type ${k} = ${rootTypes[k]};` : `export interface ${k} ${rootTypes[k]}`, "");
} else {

@@ -141,3 +136,3 @@ output.push(`export type ${k} = Record<string, never>;`, "");

indentLv++;
for (const [k, v] of getEntries(subschemaTypes, options.alphabetize)) {
for (const [k, v] of getEntries(subschemaTypes, options.alphabetize, options.excludeDeprecated)) {
if (EMPTY_OBJECT_RE.test(v)) output.push(indent(`${escObjKey(k)}: Record<string, never>;`, indentLv));

@@ -234,9 +229,3 @@ else output.push(indent(`${escObjKey(k)}: ${v};`, indentLv));

if (output.join("\n").includes("WithRequired")) {
output.splice(
1,
0,
"/** WithRequired type helpers */",
"type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };",
""
);
output.splice(1, 0, "/** WithRequired type helpers */", "type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };", "");
}

@@ -243,0 +232,0 @@

@@ -1,15 +0,2 @@

import type {
ComponentsObject,
Fetch,
GlobalContext,
OpenAPI3,
OperationObject,
ParameterObject,
PathItemObject,
ReferenceObject,
RequestBodyObject,
ResponseObject,
SchemaObject,
Subschema,
} from "./types.js";
import type { ComponentsObject, Fetch, GlobalContext, OpenAPI3, OperationObject, ParameterObject, PathItemObject, ReferenceObject, RequestBodyObject, ResponseObject, SchemaObject, Subschema } from "./types.js";
import fs from "node:fs";

@@ -52,5 +39,3 @@ import path from "node:path";

// option 2: local
const localPath = path.isAbsolute(filename)
? new URL(`file://${filename}`)
: new URL(filename, `file://${process.cwd()}/`);
const localPath = path.isAbsolute(filename) ? new URL(`file://${filename}`) : new URL(filename, `file://${process.cwd()}/`);

@@ -109,6 +94,3 @@ if (!fs.existsSync(localPath)) {

/** Load a schema from local path or remote URL */
export default async function load(
schema: URL | Subschema | Readable,
options: LoadOptions
): Promise<{ [url: string]: Subschema }> {
export default async function load(schema: URL | Subschema | Readable, options: LoadOptions): Promise<{ [url: string]: Subschema }> {
let schemaID = ".";

@@ -210,4 +192,3 @@ // 1. load contents

if (options.schemas[schemaID].hint === "OpenAPI3") {
if ("components" in currentSchema && currentSchema.components && "examples" in currentSchema.components)
delete currentSchema.components.examples;
if ("components" in currentSchema && currentSchema.components && "examples" in currentSchema.components) delete currentSchema.components.examples;
}

@@ -221,4 +202,3 @@

rawNode[k] = (rawNode as any)[k].filter((o: SchemaObject | ReferenceObject) => {
if (!o || typeof o !== "object" || Array.isArray(o))
throw new Error(`${nodePath}.${k}: Expected array of objects. Is your schema valid?`);
if (!o || typeof o !== "object" || Array.isArray(o)) throw new Error(`${nodePath}.${k}: Expected array of objects. Is your schema valid?`);
if (!("$ref" in o) || typeof o.$ref !== "string") return true;

@@ -230,6 +210,3 @@ const ref = parseRef(o.$ref);

}
if (!rawNode || typeof rawNode !== "object" || Array.isArray(rawNode))
throw new Error(
`${nodePath}: Expected object, got ${Array.isArray(rawNode) ? "array" : typeof rawNode}. Is your schema valid?`
);
if (!rawNode || typeof rawNode !== "object" || Array.isArray(rawNode)) throw new Error(`${nodePath}: Expected object, got ${Array.isArray(rawNode) ? "array" : typeof rawNode}. Is your schema valid?`);
if (!("$ref" in rawNode) || typeof rawNode.$ref !== "string") return;

@@ -319,4 +296,3 @@ const node = rawNode as unknown as ReferenceObject;

if (!node.discriminator) return;
options.discriminators[schemaID === "." ? makeTSIndex(nodePath) : makeTSIndex(["external", k, ...nodePath])] =
node.discriminator;
options.discriminators[schemaID === "." ? makeTSIndex(nodePath) : makeTSIndex(["external", k, ...nodePath])] = node.discriminator;
});

@@ -331,4 +307,3 @@ }

function relativePath(src: URL, dest: URL): string {
const isSameOrigin =
dest.protocol.startsWith("http") && src.protocol.startsWith("http") && dest.origin === src.origin;
const isSameOrigin = dest.protocol.startsWith("http") && src.protocol.startsWith("http") && dest.origin === src.origin;
const isSameDisk = dest.protocol === "file:" && src.protocol === "file:";

@@ -335,0 +310,0 @@ if (isSameOrigin || isSameDisk) {

@@ -19,3 +19,3 @@ import type { ComponentsObject, GlobalContext } from "../types.js";

indentLv++;
for (const [name, schemaObject] of getEntries(components.schemas, ctx.alphabetize)) {
for (const [name, schemaObject] of getEntries(components.schemas, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(schemaObject, indentLv);

@@ -41,3 +41,3 @@ if (c) output.push(indent(c, indentLv));

indentLv++;
for (const [name, responseObject] of getEntries(components.responses, ctx.alphabetize)) {
for (const [name, responseObject] of getEntries(components.responses, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(responseObject, indentLv);

@@ -48,8 +48,3 @@ if (c) output.push(indent(c, indentLv));

if ("$ref" in responseObject) {
output.push(
indent(
`${key}": ${transformSchemaObject(responseObject, { path: `#/components/responses/${name}`, ctx })};`,
indentLv
)
);
output.push(indent(`${key}": ${transformSchemaObject(responseObject, { path: `#/components/responses/${name}`, ctx })};`, indentLv));
} else {

@@ -73,3 +68,3 @@ const responseType = transformResponseObject(responseObject, {

indentLv++;
for (const [name, parameterObject] of getEntries(components.parameters, ctx.alphabetize)) {
for (const [name, parameterObject] of getEntries(components.parameters, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(parameterObject, indentLv);

@@ -80,8 +75,3 @@ if (c) output.push(indent(c, indentLv));

if ("$ref" in parameterObject) {
output.push(
indent(
`${key}: ${transformSchemaObject(parameterObject, { path: `#/components/parameters/${name}`, ctx })};`,
indentLv
)
);
output.push(indent(`${key}: ${transformSchemaObject(parameterObject, { path: `#/components/parameters/${name}`, ctx })};`, indentLv));
} else {

@@ -108,3 +98,3 @@ if (parameterObject.in !== "path" && !parameterObject.required) {

indentLv++;
for (const [name, requestBodyObject] of getEntries(components.requestBodies, ctx.alphabetize)) {
for (const [name, requestBodyObject] of getEntries(components.requestBodies, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(requestBodyObject, indentLv);

@@ -144,3 +134,3 @@ if (c) output.push(indent(c, indentLv));

indentLv++;
for (const [name, headerObject] of getEntries(components.headers, ctx.alphabetize)) {
for (const [name, headerObject] of getEntries(components.headers, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(headerObject, indentLv);

@@ -151,8 +141,3 @@ if (c) output.push(indent(c, indentLv));

if ("$ref" in headerObject) {
output.push(
indent(
`${key}: ${transformSchemaObject(headerObject, { path: `#/components/headers/${name}`, ctx })};`,
indentLv
)
);
output.push(indent(`${key}: ${transformSchemaObject(headerObject, { path: `#/components/headers/${name}`, ctx })};`, indentLv));
} else {

@@ -176,3 +161,3 @@ const headerType = transformHeaderObject(headerObject, {

indentLv++;
for (const [name, pathItemObject] of getEntries(components.pathItems, ctx.alphabetize)) {
for (const [name, pathItemObject] of getEntries(components.pathItems, ctx.alphabetize, ctx.excludeDeprecated)) {
let key = escObjKey(name);

@@ -183,8 +168,3 @@ if (ctx.immutableTypes) key = tsReadonly(key);

if (c) output.push(indent(c, indentLv));
output.push(
indent(
`${key}: ${transformSchemaObject(pathItemObject, { path: `#/components/pathItems/${name}`, ctx })};`,
indentLv
)
);
output.push(indent(`${key}: ${transformSchemaObject(pathItemObject, { path: `#/components/pathItems/${name}`, ctx })};`, indentLv));
} else {

@@ -191,0 +171,0 @@ output.push(

@@ -11,6 +11,3 @@ import type { GlobalContext, HeaderObject } from "../types.js";

export default function transformHeaderObject(
headerObject: HeaderObject,
{ path, ctx }: TransformHeaderObjectOptions
): string {
export default function transformHeaderObject(headerObject: HeaderObject, { path, ctx }: TransformHeaderObjectOptions): string {
if (headerObject.schema) return transformSchemaObject(headerObject.schema, { path, ctx });

@@ -21,3 +18,3 @@ if (headerObject.content) {

indentLv++;
for (const [contentType, mediaTypeObject] of getEntries(headerObject.content, ctx.alphabetize)) {
for (const [contentType, mediaTypeObject] of getEntries(headerObject.content, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(mediaTypeObject, indentLv);

@@ -28,8 +25,3 @@ if (c) output.push(indent(c, indentLv));

if ("$ref" in mediaTypeObject) {
output.push(
indent(
`${key}: ${transformSchemaObject(mediaTypeObject, { path: `${path}/${contentType}`, ctx })};`,
indentLv
)
);
output.push(indent(`${key}: ${transformSchemaObject(mediaTypeObject, { path: `${path}/${contentType}`, ctx })};`, indentLv));
} else {

@@ -36,0 +28,0 @@ const mediaType = transformMediaTypeObject(mediaTypeObject, { path: `${path}/${contentType}`, ctx });

@@ -9,8 +9,5 @@ import type { GlobalContext, MediaTypeObject } from "../types.js";

export default function transformMediaTypeObject(
mediaTypeObject: MediaTypeObject,
{ path, ctx }: TransformMediaTypeObjectOptions
): string {
export default function transformMediaTypeObject(mediaTypeObject: MediaTypeObject, { path, ctx }: TransformMediaTypeObjectOptions): string {
if (!mediaTypeObject.schema) return "unknown";
return transformSchemaObject(mediaTypeObject.schema, { path, ctx });
}

@@ -14,6 +14,3 @@ import type { GlobalContext, OperationObject, ParameterObject } from "../types.js";

export default function transformOperationObject(
operationObject: OperationObject,
{ path, ctx, wrapObject = true }: TransformOperationObjectOptions
): string {
export default function transformOperationObject(operationObject: OperationObject, { path, ctx, wrapObject = true }: TransformOperationObjectOptions): string {
let { indentLv } = ctx;

@@ -31,2 +28,3 @@ const output: string[] = wrapObject ? ["{"] : [];

indentLv++;
let allOptional = true;
for (const param of operationObject.parameters ?? []) {

@@ -36,3 +34,7 @@ const node: ParameterObject | undefined = "$ref" in param ? ctx.parameters[param.$ref] : param;

let key = escObjKey(node.name);
if (paramIn !== "path" && !node.required) key = tsOptionalProperty(key);
if (paramIn !== "path" && !node.required) {
key = tsOptionalProperty(key);
} else {
allOptional = false;
}
const c = getSchemaObjectComment(param, indentLv);

@@ -51,3 +53,4 @@ if (c) paramInternalOutput.push(indent(c, indentLv));

if (paramInternalOutput.length) {
parameterOutput.push(indent(`${paramIn}: {`, indentLv));
const key = allOptional ? tsOptionalProperty(paramIn) : paramIn;
parameterOutput.push(indent(`${key}: {`, indentLv));
parameterOutput.push(...paramInternalOutput);

@@ -92,3 +95,3 @@ parameterOutput.push(indent(`};`, indentLv));

indentLv++;
for (const [responseCode, responseObject] of getEntries(operationObject.responses, ctx.alphabetize)) {
for (const [responseCode, responseObject] of getEntries(operationObject.responses, ctx.alphabetize, ctx.excludeDeprecated)) {
const key = escObjKey(responseCode);

@@ -95,0 +98,0 @@ const c = getSchemaObjectComment(responseObject, indentLv);

@@ -10,10 +10,5 @@ import type { GlobalContext, ParameterObject, ReferenceObject } from "../types.js";

export default function transformParameterObjectArray(
parameterObjectArray: (ParameterObject | ReferenceObject)[] | Record<string, ParameterObject | ReferenceObject>,
{ path, ctx }: TransformParameterArrayOptions
): string {
export default function transformParameterObjectArray(parameterObjectArray: (ParameterObject | ReferenceObject)[] | Record<string, ParameterObject | ReferenceObject>, { path, ctx }: TransformParameterArrayOptions): string {
const output: string[] = [];
const parameters: [string, ParameterObject | ReferenceObject][] = Array.isArray(parameterObjectArray)
? parameterObjectArray.map((p) => [(p as ParameterObject).name!, p])
: Object.entries(parameterObjectArray);
const parameters: [string, ParameterObject | ReferenceObject][] = Array.isArray(parameterObjectArray) ? parameterObjectArray.map((p) => [(p as ParameterObject).name!, p]) : Object.entries(parameterObjectArray);

@@ -20,0 +15,0 @@ for (const [id, param] of parameters) {

@@ -9,7 +9,4 @@ import type { GlobalContext, ParameterObject } from "../types.js";

export default function transformParameterObject(
parameterObject: ParameterObject,
{ path, ctx }: TransformParameterObjectOptions
): string {
export default function transformParameterObject(parameterObject: ParameterObject, { path, ctx }: TransformParameterObjectOptions): string {
return parameterObject.schema ? transformSchemaObject(parameterObject.schema, { path, ctx }) : "string"; // assume a parameter is a string by default rather than "unknown"
}

@@ -12,6 +12,3 @@ import type { GlobalContext, ParameterObject, PathItemObject, ReferenceObject } from "../types.js";

export default function transformPathItemObject(
pathItem: PathItemObject,
{ path, ctx }: TransformPathItemObjectOptions
): string {
export default function transformPathItemObject(pathItem: PathItemObject, { path, ctx }: TransformPathItemObjectOptions): string {
let { indentLv } = ctx;

@@ -44,6 +41,3 @@ const output: string[] = [];

else if (operationObject.operationId) {
const operationType = transformOperationObject(
{ ...operationObject, parameters: Object.values(keyedParameters) },
{ path, ctx: { ...ctx, indentLv: 1 } }
);
const operationType = transformOperationObject({ ...operationObject, parameters: Object.values(keyedParameters) }, { path, ctx: { ...ctx, indentLv: 1 } });
ctx.operations[operationObject.operationId] = {

@@ -55,6 +49,3 @@ operationType,

} else {
const operationType = transformOperationObject(
{ ...operationObject, parameters: Object.values(keyedParameters) },
{ path, ctx: { ...ctx, indentLv } }
);
const operationType = transformOperationObject({ ...operationObject, parameters: Object.values(keyedParameters) }, { path, ctx: { ...ctx, indentLv } });
output.push(indent(`${method}: ${operationType};`, indentLv));

@@ -66,8 +57,3 @@ }

if (pathItem.parameters?.length) {
output.push(
indent(
transformOperationObject({ parameters: pathItem.parameters }, { path, ctx, wrapObject: false }).trim(),
indentLv
)
);
output.push(indent(transformOperationObject({ parameters: pathItem.parameters }, { path, ctx, wrapObject: false }).trim(), indentLv));
}

@@ -74,0 +60,0 @@

@@ -1,2 +0,2 @@

import type { GlobalContext, PathsObject } from "../types.js";
import type { GlobalContext, PathsObject, PathItemObject, ParameterObject, ReferenceObject, OperationObject } from "../types.js";
import { escStr, getEntries, indent } from "../utils.js";

@@ -6,2 +6,14 @@ import transformParameterObject from "./parameter-object.js";

const OPERATIONS = ["get", "post", "put", "delete", "options", "head", "patch", "trace"];
function extractPathParams(obj?: ReferenceObject | PathItemObject | OperationObject | undefined): Map<string, ParameterObject> {
const params = new Map<string, ParameterObject>();
if (obj && "parameters" in obj) {
for (const p of obj.parameters ?? []) {
if ("in" in p && p.in === "path") params.set(p.name, p);
}
}
return params;
}
export default function transformPathsObject(pathsObject: PathsObject, ctx: GlobalContext): string {

@@ -11,12 +23,12 @@ let { indentLv } = ctx;

indentLv++;
for (const [url, pathItemObject] of getEntries(pathsObject, ctx.alphabetize)) {
for (const [url, pathItemObject] of getEntries(pathsObject, ctx.alphabetize, ctx.excludeDeprecated)) {
let path = url;
const pathParams = new Map([...extractPathParams(pathItemObject), ...OPERATIONS.flatMap((op) => Array.from(extractPathParams(pathItemObject[op as keyof PathItemObject])))]);
// build dynamic string template literal index
if (ctx.pathParamsAsTypes && pathItemObject.parameters) {
for (const p of pathItemObject.parameters) {
if ("in" in p && p.in === "path") {
const paramType = transformParameterObject(p, { path: `#/paths/${url}/parameters/${p.name}`, ctx });
path = path.replace(`{${p.name}}`, `\${${paramType}}`);
}
if (ctx.pathParamsAsTypes && pathParams) {
for (const p of pathParams.values()) {
const paramType = transformParameterObject(p, { path: `#/paths/${url}/parameters/${p.name}`, ctx });
path = path.replace(`{${p.name}}`, `\${${paramType}}`);
}

@@ -23,0 +35,0 @@ path = `[path: \`${path}\`]`;

@@ -11,6 +11,3 @@ import type { GlobalContext, RequestBodyObject } from "../types.js";

export default function transformRequestBodyObject(
requestBodyObject: RequestBodyObject,
{ path, ctx }: TransformRequestBodyObjectOptions
): string {
export default function transformRequestBodyObject(requestBodyObject: RequestBodyObject, { path, ctx }: TransformRequestBodyObjectOptions): string {
let { indentLv } = ctx;

@@ -22,3 +19,3 @@ const output: string[] = ["{"];

indentLv++;
for (const [contentType, mediaTypeObject] of getEntries(requestBodyObject.content, ctx.alphabetize)) {
for (const [contentType, mediaTypeObject] of getEntries(requestBodyObject.content, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(mediaTypeObject, indentLv);

@@ -25,0 +22,0 @@ if (c) output.push(indent(c, indentLv));

import type { GlobalContext, ResponseObject } from "../types.js";
import {
escObjKey,
escStr,
getEntries,
getSchemaObjectComment,
indent,
tsOptionalProperty,
tsReadonly,
} from "../utils.js";
import { escObjKey, escStr, getEntries, getSchemaObjectComment, indent, tsOptionalProperty, tsReadonly } from "../utils.js";
import transformHeaderObject from "./header-object.js";

@@ -19,6 +11,3 @@ import transformMediaTypeObject from "./media-type-object.js";

export default function transformResponseObject(
responseObject: ResponseObject,
{ path, ctx }: TransformResponseObjectOptions
): string {
export default function transformResponseObject(responseObject: ResponseObject, { path, ctx }: TransformResponseObjectOptions): string {
// never

@@ -37,3 +26,3 @@ if (!responseObject.content) {

indentLv++;
for (const [name, headerObject] of getEntries(responseObject.headers, ctx.alphabetize)) {
for (const [name, headerObject] of getEntries(responseObject.headers, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(headerObject, indentLv);

@@ -68,3 +57,3 @@ if (c) output.push(indent(c, indentLv));

indentLv++;
for (const [contentType, mediaTypeObject] of getEntries(responseObject.content, ctx.alphabetize)) {
for (const [contentType, mediaTypeObject] of getEntries(responseObject.content, ctx.alphabetize, ctx.excludeDeprecated)) {
let key = escStr(contentType);

@@ -71,0 +60,0 @@ if (ctx.immutableTypes) key = tsReadonly(key);

import type { GlobalContext, ReferenceObject, SchemaObject } from "../types.js";
import {
escObjKey,
escStr,
getEntries,
getSchemaObjectComment,
indent,
parseRef,
tsArrayOf,
tsIntersectionOf,
tsOmit,
tsOneOf,
tsOptionalProperty,
tsReadonly,
tsTupleOf,
tsUnionOf,
tsWithRequired,
} from "../utils.js";
import { escObjKey, escStr, getEntries, getSchemaObjectComment, indent, parseRef, tsArrayOf, tsIntersectionOf, tsOmit, tsOneOf, tsOptionalProperty, tsReadonly, tsTupleOf, tsUnionOf, tsWithRequired } from "../utils.js";

@@ -27,6 +11,3 @@ export interface TransformSchemaObjectOptions {

export default function transformSchemaObject(
schemaObject: SchemaObject | ReferenceObject,
options: TransformSchemaObjectOptions
): string {
export default function transformSchemaObject(schemaObject: SchemaObject | ReferenceObject, options: TransformSchemaObjectOptions): string {
const result = defaultSchemaObjectTransform(schemaObject, options);

@@ -40,6 +21,3 @@ if (typeof options.ctx.postTransform === "function") {

export function defaultSchemaObjectTransform(
schemaObject: SchemaObject | ReferenceObject,
{ path, ctx }: TransformSchemaObjectOptions
): string {
export function defaultSchemaObjectTransform(schemaObject: SchemaObject | ReferenceObject, { path, ctx }: TransformSchemaObjectOptions): string {
let { indentLv } = ctx;

@@ -84,4 +62,3 @@

if ("type" in schemaObject) {
if (schemaObject.type === "string" || (Array.isArray(schemaObject.type) && schemaObject.type.includes("string")))
items = items.map((t) => escStr(t || "")); // empty/missing values are empty strings
if (schemaObject.type === "string" || (Array.isArray(schemaObject.type) && schemaObject.type.includes("string"))) items = items.map((t) => escStr(t || "")); // empty/missing values are empty strings
}

@@ -92,9 +69,3 @@ // if no type, assume "string"

}
return tsUnionOf(
...items,
...(schemaObject.nullable ||
("type" in schemaObject && Array.isArray(schemaObject.type) && schemaObject.type.includes("null"))
? ["null"]
: [])
);
return tsUnionOf(...items, ...(schemaObject.nullable || ("type" in schemaObject && Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) ? ["null"] : []));
}

@@ -112,5 +83,3 @@

if (Array.isArray(schemaObject.type)) {
return tsOneOf(
...schemaObject.type.map((t) => transformSchemaObject({ ...schemaObject, type: t }, { path, ctx }))
);
return tsOneOf(...schemaObject.type.map((t) => transformSchemaObject({ ...schemaObject, type: t }, { path, ctx })));
}

@@ -149,10 +118,5 @@

}
const minItems: number =
typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0;
const maxItems: number | undefined =
typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && minItems <= schemaObject.maxItems
? schemaObject.maxItems
: undefined;
const estimateCodeSize =
typeof maxItems !== "number" ? minItems : (maxItems * (maxItems + 1) - minItems * (minItems - 1)) / 2;
const minItems: number = typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0;
const maxItems: number | undefined = typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && minItems <= schemaObject.maxItems ? schemaObject.maxItems : undefined;
const estimateCodeSize = typeof maxItems !== "number" ? minItems : (maxItems * (maxItems + 1) - minItems * (minItems - 1)) / 2;
// export types

@@ -188,8 +152,5 @@ if (ctx.supportArrayLength && (minItems !== 0 || maxItems !== undefined) && estimateCodeSize < 30) {

const coreType: string[] = [];
if (
("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length) ||
("additionalProperties" in schemaObject && schemaObject.additionalProperties)
) {
if (("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length) || ("additionalProperties" in schemaObject && schemaObject.additionalProperties)) {
indentLv++;
for (const [k, v] of getEntries(schemaObject.properties ?? {}, ctx.alphabetize)) {
for (const [k, v] of getEntries(schemaObject.properties ?? {}, ctx.alphabetize, ctx.excludeDeprecated)) {
const c = getSchemaObjectComment(v, indentLv);

@@ -224,5 +185,3 @@ if (c) coreType.push(indent(c, indentLv));

if (!(k in schemaObject)) continue;
const discriminatorRef: ReferenceObject | undefined = (schemaObject as any)[k].find(
(t: SchemaObject | ReferenceObject) => "$ref" in t && ctx.discriminators[t.$ref]
);
const discriminatorRef: ReferenceObject | undefined = (schemaObject as any)[k].find((t: SchemaObject | ReferenceObject) => "$ref" in t && ctx.discriminators[t.$ref]);
if (discriminatorRef) {

@@ -233,5 +192,3 @@ const discriminator = ctx.discriminators[discriminatorRef.$ref];

// Mapping value can either be a fully-qualified ref (#/components/schemas/XYZ) or a schema name (XYZ)
const matchedValue = Object.entries(discriminator.mapping).find(
([_, v]) => (!v.startsWith("#") && v === value) || (v.startsWith("#") && parseRef(v).path.pop() === value)
);
const matchedValue = Object.entries(discriminator.mapping).find(([_, v]) => (!v.startsWith("#") && v === value) || (v.startsWith("#") && parseRef(v).path.pop() === value));
if (matchedValue) value = matchedValue[0]; // why was this designed backwards!?

@@ -238,0 +195,0 @@ }

@@ -9,3 +9,3 @@ import type { GlobalContext, WebhooksObject } from "../types.js";

indentLv++;
for (const [name, pathItemObject] of getEntries(webhooksObject, ctx.alphabetize)) {
for (const [name, pathItemObject] of getEntries(webhooksObject, ctx.alphabetize, ctx.excludeDeprecated)) {
output.push(

@@ -12,0 +12,0 @@ indent(

@@ -624,2 +624,4 @@ import type { URL } from "node:url";

fetch?: Fetch;
/** Exclude deprecated fields from types? (default: false) */
excludeDeprecated?: boolean;
}

@@ -665,2 +667,3 @@

supportArrayLength: boolean;
excludeDeprecated: boolean;
}

@@ -667,0 +670,0 @@

@@ -38,7 +38,3 @@ import c from "ansi-colors";

/** Walk through any JSON-serializable object */
export function walk(
obj: unknown,
cb: (value: Record<string, unknown>, path: (string | number)[]) => void,
path: (string | number)[] = []
): void {
export function walk(obj: unknown, cb: (value: Record<string, unknown>, path: (string | number)[]) => void, path: (string | number)[] = []): void {
if (!obj || typeof obj !== "object") return;

@@ -268,5 +264,6 @@ if (Array.isArray(obj)) {

/** call Object.entries() and optionally sort */
export function getEntries<T>(obj: ArrayLike<T> | Record<string, T>, alphabetize?: boolean) {
const entries = Object.entries(obj);
export function getEntries<T>(obj: ArrayLike<T> | Record<string, T>, alphabetize?: boolean, excludeDeprecated?: boolean) {
let entries = Object.entries(obj);
if (alphabetize) entries.sort(([a], [b]) => a.localeCompare(b, "en", { numeric: true }));
if (excludeDeprecated) entries = entries.filter(([, v]) => !(v && typeof v === "object" && "deprecated" in v && v.deprecated));
return entries;

@@ -273,0 +270,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc