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 2.4.2 to 3.0.0-alpha.0

dist-src/transform/index.js

54

bin/cli.js
#!/usr/bin/env node
const fs = require("fs");
const chalk = require("chalk");
const { bold, green, red } = require("kleur");
const path = require("path");

@@ -16,3 +16,3 @@ const meow = require("meow");

--help display this
--output, -o specify output file
--output, -o (optional) specify output file (default: stdout)
--prettier-config (optional) specify path to Prettier config file

@@ -41,18 +41,26 @@ --raw-schema (optional) Read from raw schema instead of document

console.info(
chalk.bold(`✨ openapi-typescript ${require("../package.json").version}`)
);
const pathToSpec = cli.input[0];
const timeStart = process.hrtime();
(async () => {
let spec = "";
async function main() {
let output = "FILE"; // FILE or STDOUT
const pathToSpec = cli.input[0];
// 0. setup
if (!cli.flags.output) {
output = "STDOUT"; // if --output not specified, fall back to stdout
}
if (output === "FILE") {
console.info(bold(`✨ openapi-typescript ${require("../package.json").version}`)); // only log if we’re NOT writing to stdout
}
// 1. input
let spec = undefined;
try {
spec = await loadSpec(pathToSpec);
} catch (e) {
console.error(chalk.red(`❌ "${e}"`));
return;
spec = await loadSpec(pathToSpec, { log: output !== "STDOUT" });
} catch (err) {
process.exitCode = 1; // needed for async functions
throw new Error(red(`❌ ${err}`));
}
// 2. generate schema (the main part!)
const result = swaggerToTS(spec, {

@@ -64,4 +72,5 @@ prettierConfig: cli.flags.prettierConfig,

// Write to file if specifying output
if (cli.flags.output) {
// 3. output
if (output === "FILE") {
// output option 1: file
const outputFile = path.resolve(process.cwd(), cli.flags.output);

@@ -82,12 +91,11 @@

const time = timeEnd[0] + Math.round(timeEnd[1] / 1e6);
console.log(
chalk.green(
`🚀 ${cli.input[0]} -> ${chalk.bold(cli.flags.output)} [${time}ms]`
)
);
return;
console.log(green(`🚀 ${pathToSpec} -> ${bold(cli.flags.output)} [${time}ms]`));
} else {
// output option 2: stdout
process.stdout.write(result);
}
// Otherwise, return result
return result;
})();
}
main();
const yaml = require("js-yaml");
const chalk = require("chalk");
const { bold, yellow } = require("kleur");

@@ -8,16 +8,19 @@ const loadFromFs = require("./loadFromFs");

async function load(pathToSpec) {
let rawSpec;
// option 1: remote URL
if (/^https?:\/\//.test(pathToSpec)) {
try {
rawSpec = await loadFromHttp(pathToSpec);
const rawSpec = await loadFromHttp(pathToSpec);
return rawSpec;
} catch (e) {
if (e.code === 'ENOTFOUND') {
throw new Error(`The URL ${pathToSpec} could not be reached. Ensure the URL is correct, that you're connected to the internet and that the URL is reachable via a browser.`)
if (e.code === "ENOTFOUND") {
throw new Error(
`The URL ${pathToSpec} could not be reached. Ensure the URL is correct, that you're connected to the internet and that the URL is reachable via a browser.`
);
}
throw e;
}
} else {
rawSpec = await loadFromFs(pathToSpec);
}
return rawSpec;
// option 2: local file
return loadFromFs(pathToSpec);
}

@@ -29,4 +32,6 @@

module.exports.loadSpec = async (pathToSpec) => {
console.log(chalk.yellow(`🤞 Loading spec from ${chalk.bold(pathToSpec)}…`));
module.exports.loadSpec = async (pathToSpec, { log = true }) => {
if (log === true) {
console.log(yellow(`🤞 Loading spec from ${bold(pathToSpec)}…`)); // only log if not writing to stdout
}
const rawSpec = await load(pathToSpec);

@@ -36,3 +41,3 @@

if (isYamlSpec(rawSpec, pathToSpec)) {
return yaml.safeLoad(rawSpec);
return yaml.load(rawSpec);
}

@@ -52,6 +57,4 @@ } catch (err) {

} catch {
throw new Error(
`The spec under ${pathToSpec} couldn’t be parsed neither as YAML nor JSON.`
);
throw new Error(`The spec under ${pathToSpec} couldn’t be parsed neither as YAML nor JSON.`);
}
};

@@ -8,14 +8,7 @@ const fs = require("fs");

return new Promise((resolve, reject) => {
if (pathExists) {
fs.readFile(pathname, "UTF-8", (err, data) => {
if (err) {
reject(err);
}
resolve(data);
});
} else {
reject(`Cannot find spec under the following path: ${pathname}`);
}
});
if (!pathExists) {
throw new Error(`Cannot find spec under the following path: ${pathname}`);
}
return fs.readFileSync(pathname, "utf8");
};

@@ -60,12 +60,13 @@ 'use strict';

function comment(text) {
const commentText = text.trim();
if (commentText.indexOf("\n") === -1) {
return `/** ${commentText} */\n`;
}
return `/**
* ${text.trim().replace("\n+$", "").replace(/\n/g, "\n * ")}
* ${commentText.replace(/\n/g, "\n * ")}
*/
`;
}
function fromEntries(entries) {
return entries.reduce((obj, [key, val]) => _objectSpread2(_objectSpread2({}, obj), {}, {
[key]: val
}), {});
}
function nodeType(obj) {

@@ -76,3 +77,3 @@ if (!obj || typeof obj !== "object") {

if (obj["$ref"]) {
if (obj.$ref) {
return "ref";

@@ -151,378 +152,288 @@ }

}
function unrefComponent(components, ref) {
const [type, object] = ref.match(/(?<=\[")([^"]+)/g);
return components[type][object];
function transformSchemaObjMap(obj, options) {
let output = "";
let required = (options === null || options === void 0 ? void 0 : options.required) || [];
Object.entries(obj).forEach(([key, value]) => {
if (value.description) output += comment(value.description);
output += `"${key}"${required.includes(key) ? "" : "?"}: `;
output += transformSchemaObj(value.schema || value);
output += `;\n`;
});
return output;
}
function transformAnyOf(anyOf) {
return tsIntersectionOf(anyOf.map(s => tsPartial(transformSchemaObj(s))));
}
function transformOneOf(oneOf) {
return tsUnionOf(oneOf.map(transformSchemaObj));
}
function transformSchemaObj(node) {
let output = "";
function propertyMapper(schema, transform) {
if (!transform) {
return schema;
if (node.nullable) {
output += "(";
}
return JSON.parse(JSON.stringify(schema), (_, node) => {
if (!node.properties) {
return node;
}
switch (nodeType(node)) {
case "ref":
{
output += transformRef(node.$ref);
break;
}
node.properties = fromEntries(Object.entries(node.properties).map(([key, val]) => {
if (val.$ref) {
return [key, val];
case "string":
case "number":
case "boolean":
{
output += nodeType(node) || "any";
break;
}
const schemaObject = val;
const property = transform(schemaObject, {
interfaceType: schemaObject.type,
optional: !Array.isArray(node.required) || node.required.includes(key),
description: schemaObject.description
});
if (property.optional) {
if (Array.isArray(node.required)) {
node.required = node.required.filter(r => r !== key);
}
} else {
node.required = [...(node.required || []), key];
case "enum":
{
output += tsUnionOf(node.enum.map(item => typeof item === "string" ? `'${item.replace(/'/g, "\\'")}'` : item));
break;
}
return [key, _objectSpread2(_objectSpread2({}, val), {}, {
type: property.interfaceType,
description: property.description
})];
}));
return node;
});
}
function generateTypesV2(input, options) {
const rawSchema = options && options.rawSchema;
let definitions;
if (rawSchema) {
definitions = input;
} else {
const document = input;
if (!document.definitions) {
throw new Error(`⛔️ 'definitions' missing from schema https://swagger.io/specification/v2/#definitions-object`);
}
definitions = document.definitions;
}
const propertyMapped = options ? propertyMapper(definitions, options.propertyMapper) : definitions;
function transform(node) {
switch (nodeType(node)) {
case "ref":
{
return transformRef(node.$ref, rawSchema ? "definitions/" : "");
case "object":
{
if ((!node.properties || !Object.keys(node.properties).length) && !node.allOf && !node.additionalProperties) {
output += `{ [key: string]: any }`;
break;
}
case "string":
case "number":
case "boolean":
{
return nodeType(node) || "any";
}
let properties = transformSchemaObjMap(node.properties || {}, {
required: node.required
});
let additionalProperties;
case "enum":
{
return tsUnionOf(node.enum.map(item => typeof item === "number" || typeof item === "boolean" ? item : `'${item}'`));
}
if (node.additionalProperties) {
if (node.additionalProperties === true) {
additionalProperties = `{ [key: string]: any }\n`;
} else if (typeof node.additionalProperties === "object") {
const oneOf = node.additionalProperties.oneOf || undefined;
const anyOf = node.additionalProperties.anyOf || undefined;
case "object":
{
if ((!node.properties || !Object.keys(node.properties).length) && !node.allOf && !node.additionalProperties) {
return `{ [key: string]: any }`;
if (oneOf) {
additionalProperties = `{ [key: string]: ${transformOneOf(oneOf)}; }\n`;
} else if (anyOf) {
additionalProperties = `{ [key: string]: ${transformAnyOf(anyOf)}; }\n`;
} else {
additionalProperties = `{ [key: string]: ${transformSchemaObj(node.additionalProperties) || "any"}; }\n`;
}
}
}
let properties = createKeys(node.properties || {}, node.required);
output += tsIntersectionOf([...(node.allOf ? node.allOf.map(transformSchemaObj) : []), ...(properties ? [`{ ${properties} }`] : []), ...(additionalProperties ? [additionalProperties] : [])]);
break;
}
if (node.additionalProperties) {
properties += `[key: string]: ${nodeType(node.additionalProperties) || "any"};\n`;
}
return tsIntersectionOf([...(node.allOf ? node.allOf.map(transform) : []), ...(properties ? [`{ ${properties} }`] : [])]);
case "array":
{
if (Array.isArray(node.items)) {
output += tsTupleOf(node.items.map(transformSchemaObj));
} else {
output += tsArrayOf(node.items ? transformSchemaObj(node.items) : "any");
}
case "array":
{
return tsArrayOf(transform(node.items));
}
}
break;
}
return "";
}
case "anyOf":
{
output += transformAnyOf(node.anyOf);
break;
}
function createKeys(obj, required = []) {
let output = "";
Object.entries(obj).forEach(([key, value]) => {
if (value.description) {
output += comment(value.description);
case "oneOf":
{
output += transformOneOf(node.oneOf);
break;
}
}
output += `"${key}"${!required || !required.includes(key) ? "?" : ""}: `;
output += transform(value);
output += ";\n";
});
return output;
if (node.nullable) {
output += ") | null";
}
return `export interface definitions {
${createKeys(propertyMapped, Object.keys(propertyMapped))}
}`;
return output;
}
function generateTypesV3(input, options) {
const {
rawSchema = false
} = options || {};
let {
paths = {},
components = {
schemas: {}
}
} = input;
function transformParametersArray(parameters, globalParameters) {
let output = "";
let mappedParams = {};
parameters.forEach(paramObj => {
if (paramObj.$ref && globalParameters) {
const paramName = paramObj.$ref.split("/").pop();
if (rawSchema) {
components = {
schemas: input
};
} else {
if (!input.components && !input.paths) {
throw new Error(`No components or paths found. Specify --raw-schema to load a raw schema.`);
if (globalParameters[paramName]) {
const reference = globalParameters[paramName];
if (!mappedParams[reference.in]) mappedParams[reference.in] = {};
mappedParams[reference.in][reference.name || paramName] = _objectSpread2(_objectSpread2({}, reference), {}, {
schema: {
$ref: paramObj.$ref
}
});
}
return;
}
}
const operations = {};
const propertyMapped = options ? propertyMapper(components.schemas, options.propertyMapper) : components.schemas;
if (!paramObj.in || !paramObj.name) return;
if (!mappedParams[paramObj.in]) mappedParams[paramObj.in] = {};
mappedParams[paramObj.in][paramObj.name] = paramObj;
});
Object.entries(mappedParams).forEach(([paramIn, paramGroup]) => {
output += ` ${paramIn}: {\n`;
Object.entries(paramGroup).forEach(([paramName, paramObj]) => {
if (!paramObj.schema) return;
let paramComment = "";
if (paramObj.deprecated) paramComment += `@deprecated `;
if (paramObj.description) paramComment += paramObj.description;
if (paramComment) output += comment(paramComment);
const required = paramObj.required ? `` : `?`;
output += ` "${paramName}"${required}: ${transformSchemaObj(paramObj.schema)};\n`;
});
output += ` }\n`;
});
return output;
}
function transform(node) {
switch (nodeType(node)) {
case "ref":
{
return transformRef(node.$ref, rawSchema ? "schemas/" : "");
}
function transformResponsesObj(responsesObj) {
let output = "";
Object.entries(responsesObj).forEach(([k, v]) => {
if (v.description) output += comment(v.description);
const resKey = parseInt(k, 10) ? k : `"${k}"`;
case "string":
case "number":
case "boolean":
{
return nodeType(node) || "any";
}
if (v.$ref) {
output += ` ${resKey}: ${transformRef(v.$ref)};\n`;
return;
}
case "enum":
{
return tsUnionOf(node.enum.map(item => typeof item === "number" || typeof item === "boolean" ? item : `'${item.replace(/'/g, "\\'")}'`));
}
case "oneOf":
{
return tsUnionOf(node.oneOf.map(transform));
}
case "anyOf":
{
return tsIntersectionOf(node.anyOf.map(anyOf => tsPartial(transform(anyOf))));
}
case "object":
{
if ((!node.properties || !Object.keys(node.properties).length) && !node.allOf && !node.additionalProperties) {
return `{ [key: string]: any }`;
}
let properties = createKeys(node.properties || {}, node.required);
const additionalProperties = node.additionalProperties ? [`{ [key: string]: ${node.additionalProperties === true ? "any" : transform(node.additionalProperties) || "any"};}\n`] : [];
return tsIntersectionOf([...(node.allOf ? node.allOf.map(transform) : []), ...(properties ? [`{ ${properties} }`] : []), ...additionalProperties]);
}
case "array":
{
if (Array.isArray(node.items)) {
return tsTupleOf(node.items.map(transform));
} else {
return tsArrayOf(node.items ? transform(node.items) : "any");
}
}
if (!v.content && !v.schema || v.content && !Object.keys(v.content).length) {
output += ` ${resKey}: unknown;\n`;
return;
}
return "";
}
output += ` ${resKey}: {\n`;
function createKeys(obj, required) {
let output = "";
Object.entries(obj).forEach(([key, value]) => {
if (value.description) {
output += comment(value.description);
if (v.headers) {
if (v.headers.$ref) {
output += ` headers: ${transformRef(v.headers.$ref)};\n`;
} else {
output += ` headers: {\n ${transformSchemaObjMap(v.headers)}\n }\n`;
}
}
output += `"${key}"${!required || !required.includes(key) ? "?" : ""}: `;
if (v.content) {
Object.entries(v.content).forEach(([contentType, contentResponse]) => {
output += ` "${contentType}": ${transformSchemaObj(contentResponse.schema)};\n`;
});
} else if (v.schema) {
output += ` schema: ${transformSchemaObj(v.schema)};\n`;
}
if (value.nullable) {
output += "(";
}
output += ` }\n`;
});
return output;
}
output += transform(value.schema ? value.schema : value);
function transformOperationObj(operation, globalParams) {
let output = "";
if (value.nullable) {
output += ") | null";
}
if (operation.parameters) {
output += ` parameters: {\n ${transformParametersArray(operation.parameters, globalParams)}\n }\n`;
}
output += ";\n";
});
return output;
if (operation.responses) {
output += ` responses: {\n ${transformResponsesObj(operation.responses)}\n }\n`;
}
function transformParameters(parameters) {
const allParameters = {};
let output = `parameters: {\n`;
parameters.forEach(p => {
if ("$ref" in p) {
const referencedValue = p.$ref.substr(2).split("/").reduce((value, property) => value[property], input);
if (!allParameters[referencedValue.in]) allParameters[referencedValue.in] = {};
allParameters[referencedValue.in][referencedValue.name] = transformRef(p.$ref);
return;
}
if (operation.requestBody && operation.requestBody.content) {
if (operation.requestBody.description) output += comment(operation.requestBody.description);
if (!allParameters[p.in]) allParameters[p.in] = {};
allParameters[p.in][p.name] = p;
});
Object.entries(allParameters).forEach(([loc, locParams]) => {
output += `"${loc}": {\n`;
Object.entries(locParams).forEach(([paramName, paramProps]) => {
if (typeof paramProps === "string") {
const {
required
} = unrefComponent(components, paramProps);
const key = required ? `"${paramName}"` : `"${paramName}"?`;
output += `${key}: ${paramProps}\n`;
return;
}
if (paramProps.description) output += comment(paramProps.description);
output += `"${paramName}"${paramProps.required === true ? "" : "?"}: ${transform(paramProps.schema)};\n`;
if (Object.keys(operation.requestBody.content).length) {
output += ` requestBody: {\n`;
Object.entries(operation.requestBody.content).forEach(([k, v]) => {
output += ` "${k}": ${transformSchemaObj(v.schema)};\n`;
});
output += `}\n`;
});
output += `}\n`;
return output;
output += ` }\n`;
} else {
output += ` requestBody: unknown;\n`;
}
}
function transformOperation(operation) {
let output = "";
output += `{\n`;
return output;
}
if (operation.parameters) {
output += transformParameters(operation.parameters);
}
function transformAll(schema, {
version,
rawSchema
}) {
let output = "";
let operations = {};
output += `export interface paths {\n`;
if (operation.requestBody) {
output += `requestBody: {\n`;
Object.entries(operation.requestBody.content || {}).forEach(([contentType, {
schema
}]) => {
output += `"${contentType}": ${transform(schema)};\n`;
});
output += `}\n`;
}
if (!rawSchema && schema.paths) {
Object.entries(schema.paths).forEach(([url, pathItem]) => {
if (pathItem.description) output += comment(pathItem.description);
output += `responses: {\n`;
Object.entries(operation.responses).forEach(([statusCode, response]) => {
if (response.description) output += comment(response.description);
if (!response.content || !Object.keys(response.content).length) {
const type = statusCode === "204" || Math.floor(+statusCode / 100) === 3 ? "never" : "unknown";
output += `"${statusCode}": ${type};\n`;
if (pathItem.$ref) {
output += ` "${url}": ${transformRef(pathItem.$ref)};\n`;
return;
}
output += `"${statusCode}": {\n`;
Object.entries(response.content).forEach(([contentType, encodedResponse]) => {
output += `"${contentType}": ${transform(encodedResponse.schema)};\n`;
});
output += `}\n`;
});
output += `}\n`;
output += `}\n`;
return output;
}
output += ` "${url}": {\n`;
Object.entries(pathItem).forEach(([method, operation]) => {
if (operation.description) output += comment(operation.description);
function transformPaths(paths) {
let output = "";
Object.entries(paths).forEach(([path, pathItem]) => {
output += `"${path}": {\n`;
Object.entries(pathItem).forEach(([field, operation]) => {
const isMethod = ["get", "put", "post", "delete", "options", "head", "patch", "trace"].includes(field);
if (operation.operationId) {
output += ` "${method}": operations["${operation.operationId}"];\n`;
operations[operation.operationId] = operation;
return;
}
if (isMethod) {
operation = operation;
if (operation.operationId) {
output += `"${field}": operations["${operation.operationId}"];\n`;
operations[operation.operationId] = operation;
} else {
if (operation.description) output += comment(operation.description);
output += `"${field}": ${transformOperation(operation)}`;
}
}
output += ` "${method}": {\n ${transformOperationObj(operation, schema.parameters)};\n }\n`;
});
if (pathItem.parameters) {
output += transformParameters(pathItem.parameters);
}
output += `}\n`;
output += ` }\n`;
});
return output;
}
if (rawSchema) {
return `export interface schemas {
${createKeys(propertyMapped, Object.keys(propertyMapped))}
}`;
}
output += `}\n\n`;
let finalOutput = "";
switch (version) {
case 2:
{
let schemaDefs = rawSchema ? schema : schema.definitions;
output += `export interface definitions { ${transformSchemaObjMap(schemaDefs || {}, {
required: Object.keys(schemaDefs)
})}\n}`;
}
if (Object.keys(paths).length) {
finalOutput += `export interface paths {
${transformPaths(paths)}
}
case 3:
{
var _schema$components;
`;
output += `export interface components {\n`;
let schemaDefs = rawSchema ? schema : (_schema$components = schema.components) === null || _schema$components === void 0 ? void 0 : _schema$components.schemas;
if (schemaDefs) output += ` schemas: {\n ${transformSchemaObjMap(schemaDefs, {
required: Object.keys(schemaDefs)
})}\n }\n`;
output += `}\n`;
}
}
finalOutput += "export interface operations {\n";
if (Object.keys(operations).length) {
output += `export interface operations {\n`;
Object.entries(operations).forEach(([operationId, operation]) => {
var _schema$components2;
for (const [operationId, operation] of Object.entries(operations)) {
if (operation.description) finalOutput += comment(operation.description);
finalOutput += `"${operationId}": ${transformOperation(operation)}`;
if (operation.description) output += comment(operation.description);
output += ` "${operationId}": {\n ${transformOperationObj(operation, (_schema$components2 = schema.components) === null || _schema$components2 === void 0 ? void 0 : _schema$components2.parameters)};\n }\n`;
});
output += `}\n`;
}
finalOutput += "\n}\n\n";
finalOutput += "export interface components {\n";
if (components.parameters && Object.keys(components.parameters).length) {
finalOutput += `
parameters: {
${createKeys(components.parameters, Object.keys(components.parameters))}
}\n`;
}
if (Object.keys(propertyMapped).length) {
finalOutput += `schemas: {
${createKeys(propertyMapped, Object.keys(propertyMapped))}
}`;
}
if (components.responses && Object.keys(components.responses).length) {
finalOutput += `
responses: {
${createKeys(components.responses, Object.keys(components.responses))}
}`;
}
finalOutput += "\n}";
return finalOutput;
return output;
}

@@ -539,18 +450,8 @@

const version = options && options.version || swaggerVersion(schema);
let output = `${WARNING_MESSAGE}`;
switch (version) {
case 2:
{
output = output.concat(generateTypesV2(schema, options));
break;
}
case 3:
{
output = output.concat(generateTypesV3(schema, options));
break;
}
}
let output = `${WARNING_MESSAGE}
${transformAll(schema, {
version,
rawSchema: options && options.rawSchema
})}
`;
let prettierOptions = {

@@ -557,0 +458,0 @@ parser: "typescript"

import path from "path";
import prettier from "prettier";
import { swaggerVersion } from "./utils";
import v2 from "./v2";
import v3 from "./v3";
import { transformAll } from "./transform/index";
export * from "./types/index";
export const WARNING_MESSAGE = `/**

@@ -14,15 +14,6 @@ * This file was auto-generated by openapi-typescript.

export default function swaggerToTS(schema, options) {
const version = (options && options.version) ||
swaggerVersion(schema);
let output = `${WARNING_MESSAGE}`;
switch (version) {
case 2: {
output = output.concat(v2(schema, options));
break;
}
case 3: {
output = output.concat(v3(schema, options));
break;
}
}
const version = (options && options.version) || swaggerVersion(schema);
let output = `${WARNING_MESSAGE}
${transformAll(schema, { version, rawSchema: options && options.rawSchema })}
`;
let prettierOptions = { parser: "typescript" };

@@ -29,0 +20,0 @@ if (options && options.prettierConfig) {

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

export * from "./OpenAPI2";
export * from "./OpenAPI3";
export {};
export function comment(text) {
const commentText = text.trim();
if (commentText.indexOf("\n") === -1) {
return `/** ${commentText} */\n`;
}
return `/**
* ${text.trim().replace("\n+$", "").replace(/\n/g, "\n * ")}
* ${commentText.replace(/\n/g, "\n * ")}
*/

@@ -14,3 +18,3 @@ `;

}
if (obj["$ref"]) {
if (obj.$ref) {
return "ref";

@@ -17,0 +21,0 @@ }

@@ -1,3 +0,4 @@

import { OpenAPI2, OpenAPI2Schemas, OpenAPI3, OpenAPI3Schemas, SwaggerToTSOptions } from "./types";
import { OpenAPI2, OpenAPI3, SchemaObject, SwaggerToTSOptions } from "./types/index";
export * from "./types/index";
export declare const WARNING_MESSAGE = "/**\n* This file was auto-generated by openapi-typescript.\n* Do not make direct changes to the file.\n*/\n\n\n";
export default function swaggerToTS(schema: OpenAPI2 | OpenAPI2Schemas | OpenAPI3 | OpenAPI3Schemas, options?: SwaggerToTSOptions): string;
export default function swaggerToTS(schema: OpenAPI2 | OpenAPI3 | Record<string, SchemaObject>, options?: SwaggerToTSOptions): string;

@@ -1,15 +0,102 @@

import { OpenAPI2SchemaObject } from "./OpenAPI2";
import { OpenAPI3SchemaObject } from "./OpenAPI3";
export * from "./OpenAPI2";
export * from "./OpenAPI3";
export interface Property {
interfaceType: string;
optional: boolean;
export interface OpenAPI2 {
swagger: string;
paths?: Record<string, PathItemObject>;
definitions?: Record<string, SchemaObject>;
parameters?: ParameterObject[];
responses?: Record<string, ResponseObject>;
}
export interface OpenAPI3 {
openapi: string;
paths?: Record<string, PathItemObject>;
components?: {
schemas?: Record<string, ReferenceObject | SchemaObject>;
responses?: Record<string, ReferenceObject | ResponseObject>;
parameters?: Record<string, ReferenceObject | ParameterObject>;
headers?: Record<string, ReferenceObject | HeaderObject>;
links?: Record<string, ReferenceObject | LinkObject>;
};
}
export interface HeaderObject {
type?: string;
description?: string;
schema: ReferenceObject | SchemaObject;
}
export interface PathItemObject {
$ref?: string;
summary?: string;
description?: string;
get?: OperationObject;
put?: OperationObject;
post?: OperationObject;
delete?: OperationObject;
options?: OperationObject;
head?: OperationObject;
patch?: OperationObject;
trace?: OperationObject;
parameters?: (ReferenceObject | ParameterObject)[];
}
export interface LinkObject {
operationRef?: string;
operationId?: string;
parameters?: (ReferenceObject | ParameterObject)[];
requestBody?: RequestBody;
description?: string;
}
export interface OperationObject {
description?: string;
tags?: string[];
summary?: string;
operationId?: string;
parameters?: (ReferenceObject | ParameterObject)[];
responses?: Record<string, ReferenceObject | ResponseObject>;
requestBody?: RequestBody;
}
export interface ParameterObject {
name?: string;
in?: "query" | "header" | "path" | "cookie" | "formData" | "body";
description?: string;
required?: boolean;
deprecated?: boolean;
schema?: ReferenceObject | SchemaObject;
}
export declare type ReferenceObject = {
$ref: string;
};
export interface ResponseObject {
description?: string;
headers?: Record<string, ReferenceObject | HeaderObject>;
schema?: ReferenceObject | SchemaObject;
links?: Record<string, ReferenceObject | LinkObject>;
content?: {
[contentType: string]: {
schema: ReferenceObject | SchemaObject;
};
};
}
export interface RequestBody {
description?: string;
content?: {
[contentType: string]: {
schema: ReferenceObject | SchemaObject;
};
};
}
export interface SchemaObject {
title?: string;
description?: string;
required?: string[];
enum?: string[];
type?: string;
items?: ReferenceObject | SchemaObject;
allOf?: SchemaObject;
properties?: Record<string, ReferenceObject | SchemaObject>;
additionalProperties?: boolean | ReferenceObject | SchemaObject;
nullable?: boolean;
oneOf?: (ReferenceObject | SchemaObject)[];
anyOf?: (ReferenceObject | SchemaObject)[];
}
export interface SwaggerToTSOptions {
prettierConfig?: string;
propertyMapper?: (schemaObject: OpenAPI2SchemaObject | OpenAPI3SchemaObject, property: Property) => Property;
rawSchema?: boolean;
version?: number;
}
{
"name": "openapi-typescript",
"description": "Generate TypeScript types from Swagger OpenAPI specs",
"version": "2.4.2",
"version": "3.0.0-alpha.0",
"license": "ISC",

@@ -36,6 +36,6 @@ "bin": {

"dependencies": {
"chalk": "^4.1.0",
"js-yaml": "^3.14.0",
"meow": "^8.0.0",
"prettier": "^2.1.2"
"js-yaml": "^4.0.0",
"kleur": "^4.1.3",
"meow": "^9.0.0",
"prettier": "^2.2.1"
},

@@ -48,12 +48,13 @@ "devDependencies": {

"@types/jest": "^26.0.14",
"@types/js-yaml": "^3.12.5",
"@types/js-yaml": "^4.0.0",
"@types/prettier": "^2.1.5",
"@typescript-eslint/eslint-plugin": "^4.4.1",
"@typescript-eslint/parser": "^4.4.1",
"codecov": "^3.8.1",
"eslint": "^7.11.0",
"eslint-config-prettier": "^6.13.0",
"eslint-config-prettier": "^7.0.0",
"eslint-plugin-prettier": "^3.1.4",
"jest": "^26.5.3",
"ts-jest": "^26.4.1",
"typescript": "^4.0.3"
"typescript": "^4.1.3"
},

@@ -60,0 +61,0 @@ "engines": {

[![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/master/graph/badge.svg)](https://codecov.io/gh/drwpow/openapi-typescript)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-23-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-27-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

@@ -10,3 +11,3 @@

🚀 Convert [OpenAPI 3.0][openapi3] and [OpenAPI 2.0 (Swagger)][openapi2] schemas to TypeScript interfaces using Node.js.
🚀 Convert [OpenAPI 3.0][openapi3] and [2.0 (Swagger)][openapi2] schemas to TypeScript interfaces using Node.js.

@@ -44,7 +45,38 @@ 💅 The output is prettified with [Prettier][prettier] (and can be customized!).

_Thanks to @psmyrdek for this feature!_
_Thanks to @psmyrdek for the remote spec feature!_
#### 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"];
```
The reason for all the `["…"]` everywhere is because OpenAPI lets you use more characters than are valid TypeScript identifiers. The goal of this project is to generate _all_ of your schema, not merely the parts that are “TypeScript-safe.”
Also note that there’s a special `operations` interface that you can import `OperationObjects` by their [operationId][openapi-operationid]:
```ts
import { operations } from './generated-schema.ts';
type getUsersById = operations["getUsersById"];
```
This is the only place where our generation differs from your schema as-written, but it’s done so as a convenience and shouldn’t cause any issues (you can still use deep references as-needed).
_Thanks to @gr2m for the operations feature!_
#### Outputting to `stdout`
```bash
npx openapi-typescript schema.yaml
```
#### Generating multiple schemas
In your `package.json`, for each schema you’d like to transform add one `generate:specs:[name]` npm-script. Then combine them all into one `generate:specs` script, like so:
In your `package.json`, for each schema you’d like to transform add one `generate:specs:[name]` npm-script. Then combine
them all into one `generate:specs` script, like so:

@@ -60,2 +92,9 @@ ```json

If you use [npm-run-all][npm-run-all], you can shorten this:
```json
"scripts": {
"generate:specs": "run-p generate:specs:*",
```
You can even specify unique options per-spec, if needed. To generate them all together, run:

@@ -77,2 +116,3 @@

| `--prettier-config [location]` | | | (optional) Path to your custom Prettier configuration for output |
| `--raw-schema` | | `false` | Generate TS types from partial schema (e.g. having `components.schema` at the top level) |

@@ -87,3 +127,3 @@ ### Node

const { readFileSync } = require("fs");
const swaggerToTS = require("openapi-typescript");
const swaggerToTS = require("openapi-typescript").default;

@@ -94,165 +134,36 @@ const input = JSON.parse(readFileSync("spec.json", "utf8")); // Input can be any JS object (OpenAPI format)

The Node API is a bit more flexible: it will only take a JS object as input (OpenAPI format), and
return a string of TS definitions. This lets you pull from any source (a Swagger server, local
files, etc.), and similarly lets you parse, post-process, and save the output anywhere.
The Node API is a bit more flexible: it will only take a JS object as input (OpenAPI format), and return a string of TS
definitions. This lets you pull from any source (a Swagger server, local files, etc.), and similarly lets you parse,
post-process, and save the output anywhere.
If your specs are in YAML, you’ll have to convert them to JS objects using a library such as
[js-yaml][js-yaml]. If you’re batching large folders of specs, [glob][glob] may also come in handy.
If your specs are in YAML, you’ll have to convert them to JS objects using a library such as [js-yaml][js-yaml]. If
you’re batching large folders of specs, [glob][glob] may also come in handy.
#### PropertyMapper
## Migrating from v1 to v2
In order to allow more control over how properties are parsed, and to specifically handle
`x-something`-properties, the `propertyMapper` option may be specified as the optional 2nd
parameter.
[Migrating from v1 to v2](./docs/migrating-from-v1.md)
This is a function that, if specified, is called for each property and allows you to change how
openapi-typescript handles parsing of Swagger files.
## Project Goals
An example on how to use the `x-nullable` property to control if a property is optional:
1. Support converting any OpenAPI 3.0 or 2.0 (Swagger) schema to TypeScript types, no matter how complicated
1. The generated TypeScript types **must** match your schema as closely as possible (i.e. don’t convert names to
`PascalCase` or follow any TypeScript-isms; faithfully reproduce your schema as closely as possible, capitalization
and all)
1. This library is a TypeScript generator, not a schema validator.
```js
const getNullable = (d: { [key: string]: any }): boolean => {
const nullable = d["x-nullable"];
if (typeof nullable === "boolean") {
return nullable;
}
return true;
};
## Contributing
const output = swaggerToTS(swagger, {
propertyMapper: (swaggerDefinition, property): Property => ({
...property,
optional: getNullable(swaggerDefinition),
}),
});
```
PRs are welcome! Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) guide. Opening an issue beforehand to discuss is
encouraged but not required.
_Thanks to @atlefren for this feature!_
## Upgrading from v1 to v2
Some options were removed in openapi-typescript v2 that will break apps using v1, but it does so in exchange for more control, more stability, and more resilient types.
TL;DR:
```diff
-import { OpenAPI2 } from './generated';
+import { definitions } from './generated';
-type MyType = OpenAPI2.MyType;
+type MyType = definitions['MyType'];
```
#### In-depth explanation
In order to explain the change, let’s go through an example with the following Swagger definition (partial):
```yaml
swagger: 2.0
definitions:
user:
type: object
properties:
role:
type: object
properties:
access:
enum:
- admin
- user
user_role:
type: object
role:
type: string
team:
type: object
properties:
users:
type: array
items:
$ref: user
```
This is how **v1** would have generated those types:
```ts
declare namespace OpenAPI2 {
export interface User {
role?: UserRole;
}
export interface UserRole {
access?: "admin" | "user";
}
export interface UserRole {
role?: string;
}
export interface Team {
users?: User[];
}
}
```
Uh oh. It tried to be intelligent, and keep interfaces shallow by transforming `user.role` into `UserRole.` However, we also have another `user_role` entry that has a conflicting `UserRole` interface. This is not what we want.
v1 of this project made certain assumptions about your schema that don’t always hold true. This is how **v2** generates types from that same schema:
```ts
export interface definitions {
user: {
role?: {
access?: "admin" | "user";
};
};
user_role: {
role?: string;
};
team: {
users?: definitions["user"][];
};
}
```
This matches your schema more accurately, and doesn’t try to be clever by keeping things shallow. It’s also more predictable, with the generated types matching your schema naming. In your code here’s what would change:
```diff
-UserRole
+definitions['user']['role'];
```
While this is a change, it’s more predictable. Now you don’t have to guess what `user_role` was renamed to; you simply chain your type from the Swagger definition you‘re used to.
#### Better \$ref generation
openapi-typescript v1 would attempt to resolve and flatten `$ref`s. This was bad because it would break on circular references (which both Swagger and TypeScript allow), and resolution also slowed it down.
In v2, your `$ref`s are preserved as-declared, and TypeScript does all the work. Now the responsibility is on your schema to handle collisions rather than openapi-typescript, which is a better approach in general.
#### No Wrappers
The `--wrapper` CLI flag was removed because it was awkward having to manage part of your TypeScript definition in a CLI flag. In v2, simply compose the wrapper yourself however you’d like in TypeScript:
```ts
import { components as Schema1 } from './generated/schema-1.ts';
import { components as Schema2 } from './generated/schema-2.ts';
declare namespace OpenAPI3 {
export Schema1;
export Schema2;
}
```
#### No CamelCasing
The `--camelcase` flag was removed because it would mangle object names incorrectly or break trying to sanitize them (for example, you couldn’t run camelcase on a schema with `my.obj` and `my-obj`—they both would transfom to the same thing causing unexpected results).
OpenAPI allows for far more flexibility in naming schema objects than JavaScript, so that should be carried over from your schema. In v2, the naming of generated types maps 1:1 with your schema name.
[glob]: https://www.npmjs.com/package/glob
[js-yaml]: https://www.npmjs.com/package/js-yaml
[namespace]: https://www.typescriptlang.org/docs/handbook/namespaces.html
[npm-run-all]: https://www.npmjs.com/package/npm-run-all
[openapi-operationid]: https://swagger.io/specification/#operation-object
[openapi2]: https://swagger.io/specification/v2/
[openapi3]: https://swagger.io/specification
[namespace]: https://www.typescriptlang.org/docs/handbook/namespaces.html
[prettier]: https://npmjs.com/prettier
## Contributors ✨
### Contributors ✨

@@ -266,38 +177,44 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<tr>
<td align="center"><a href="https://pow.rs"><img src="https://avatars3.githubusercontent.com/u/1369770?v=4" width="100px;" alt=""/><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"><a href="http://smyrdek.com"><img src="https://avatars1.githubusercontent.com/u/6187417?v=4" width="100px;" alt=""/><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"><a href="https://danielenman.com"><img src="https://avatars3.githubusercontent.com/u/432487?v=4" width="100px;" alt=""/><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"><a href="http://atlefren.net"><img src="https://avatars2.githubusercontent.com/u/1829927?v=4" width="100px;" alt=""/><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"><a href="http://www.timdewolf.com"><img src="https://avatars0.githubusercontent.com/u/4455209?v=4" width="100px;" alt=""/><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"><a href="https://github.com/tombarton"><img src="https://avatars1.githubusercontent.com/u/6222711?v=4" width="100px;" alt=""/><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"><a href="http://www.viig.no"><img src="https://avatars0.githubusercontent.com/u/1080888?v=4" width="100px;" alt=""/><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>
<td align="center"><a href="https://pow.rs"><img src="https://avatars3.githubusercontent.com/u/1369770?v=4?s=100" width="100px;" alt=""/><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"><a href="http://smyrdek.com"><img src="https://avatars1.githubusercontent.com/u/6187417?v=4?s=100" width="100px;" alt=""/><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"><a href="https://danielenman.com"><img src="https://avatars3.githubusercontent.com/u/432487?v=4?s=100" width="100px;" alt=""/><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"><a href="http://atlefren.net"><img src="https://avatars2.githubusercontent.com/u/1829927?v=4?s=100" width="100px;" alt=""/><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"><a href="http://www.timdewolf.com"><img src="https://avatars0.githubusercontent.com/u/4455209?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/tombarton"><img src="https://avatars1.githubusercontent.com/u/6222711?v=4?s=100" width="100px;" alt=""/><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"><a href="http://www.viig.no"><img src="https://avatars0.githubusercontent.com/u/1080888?v=4?s=100" width="100px;" alt=""/><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"><a href="https://toot.cafe/@sorin"><img src="https://avatars1.githubusercontent.com/u/2109702?v=4" width="100px;" alt=""/><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"><a href="https://github.com/scvnathan"><img src="https://avatars3.githubusercontent.com/u/73474?v=4" width="100px;" alt=""/><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"><a href="https://lbenie.xyz/"><img src="https://avatars1.githubusercontent.com/u/7316046?v=4" width="100px;" alt=""/><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"><a href="https://boris.sh"><img src="https://avatars1.githubusercontent.com/u/17952318?v=4" width="100px;" alt=""/><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"><a href="https://twitter.com/antonk52"><img src="https://avatars1.githubusercontent.com/u/5817809?v=4" width="100px;" alt=""/><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"><a href="https://github.com/tshelburne"><img src="https://avatars3.githubusercontent.com/u/1202267?v=4" width="100px;" alt=""/><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"><a href="https://typeofweb.com"><img src="https://avatars0.githubusercontent.com/u/1338731?v=4" width="100px;" alt=""/><br /><sub><b>Michał Miszczyszyn</b></sub></a><br /><a href="https://github.com/drwpow/openapi-typescript/commits?author=mmiszy" title="Code">💻</a></td>
<td align="center"><a href="https://toot.cafe/@sorin"><img src="https://avatars1.githubusercontent.com/u/2109702?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/scvnathan"><img src="https://avatars3.githubusercontent.com/u/73474?v=4?s=100" width="100px;" alt=""/><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"><a href="https://lbenie.xyz/"><img src="https://avatars1.githubusercontent.com/u/7316046?v=4?s=100" width="100px;" alt=""/><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"><a href="https://boris.sh"><img src="https://avatars1.githubusercontent.com/u/17952318?v=4?s=100" width="100px;" alt=""/><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"><a href="https://twitter.com/antonk52"><img src="https://avatars1.githubusercontent.com/u/5817809?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/tshelburne"><img src="https://avatars3.githubusercontent.com/u/1202267?v=4?s=100" width="100px;" alt=""/><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"><a href="https://typeofweb.com"><img src="https://avatars0.githubusercontent.com/u/1338731?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/skh-"><img src="https://avatars1.githubusercontent.com/u/1292598?v=4" width="100px;" alt=""/><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"><a href="https://github.com/BlooJeans"><img src="https://avatars2.githubusercontent.com/u/1751182?v=4" width="100px;" alt=""/><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"><a href="https://www.selbekk.io"><img src="https://avatars1.githubusercontent.com/u/1307267?v=4" width="100px;" alt=""/><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"><a href="https://mause.me"><img src="https://avatars2.githubusercontent.com/u/1405026?v=4" width="100px;" alt=""/><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"><a href="https://github.com/henhal"><img src="https://avatars3.githubusercontent.com/u/9608258?v=4" width="100px;" alt=""/><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></td>
<td align="center"><a href="https://dev.to/gr2m"><img src="https://avatars3.githubusercontent.com/u/39992?v=4" width="100px;" alt=""/><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"><a href="http://samn.co.uk"><img src="https://avatars2.githubusercontent.com/u/408983?v=4" width="100px;" alt=""/><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>
<td align="center"><a href="https://github.com/skh-"><img src="https://avatars1.githubusercontent.com/u/1292598?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/BlooJeans"><img src="https://avatars2.githubusercontent.com/u/1751182?v=4?s=100" width="100px;" alt=""/><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"><a href="https://www.selbekk.io"><img src="https://avatars1.githubusercontent.com/u/1307267?v=4?s=100" width="100px;" alt=""/><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"><a href="https://mause.me"><img src="https://avatars2.githubusercontent.com/u/1405026?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/henhal"><img src="https://avatars3.githubusercontent.com/u/9608258?v=4?s=100" width="100px;" alt=""/><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></td>
<td align="center"><a href="https://dev.to/gr2m"><img src="https://avatars3.githubusercontent.com/u/39992?v=4?s=100" width="100px;" alt=""/><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"><a href="http://samn.co.uk"><img src="https://avatars2.githubusercontent.com/u/408983?v=4?s=100" width="100px;" alt=""/><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"><a href="https://rendall.dev"><img src="https://avatars2.githubusercontent.com/u/293263?v=4" width="100px;" alt=""/><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"><a href="https://massaioli.wordpress.com"><img src="https://avatars3.githubusercontent.com/u/149178?v=4" width="100px;" alt=""/><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"><a href="https://rendall.dev"><img src="https://avatars2.githubusercontent.com/u/293263?v=4?s=100" width="100px;" alt=""/><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"><a href="https://massaioli.wordpress.com"><img src="https://avatars3.githubusercontent.com/u/149178?v=4?s=100" width="100px;" alt=""/><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"><a href="http://jankuca.com"><img src="https://avatars3.githubusercontent.com/u/367262?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/th-m"><img src="https://avatars3.githubusercontent.com/u/13792029?v=4?s=100" width="100px;" alt=""/><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"><a href="https://asithadesilva.com"><img src="https://avatars1.githubusercontent.com/u/3814354?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/MikeYermolayev"><img src="https://avatars2.githubusercontent.com/u/8783498?v=4?s=100" width="100px;" alt=""/><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>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- 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!
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
Contributions of any kind welcome!

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