openapi-typescript
Advanced tools
Comparing version 3.0.0-rc.0 to 3.0.0
@@ -59,2 +59,3 @@ #!/usr/bin/env node | ||
} catch (err) { | ||
process.exitCode = 1; // needed for async functions | ||
throw new Error(red(`❌ ${err}`)); | ||
@@ -61,0 +62,0 @@ } |
@@ -39,3 +39,3 @@ const yaml = require("js-yaml"); | ||
if (isYamlSpec(rawSpec, pathToSpec)) { | ||
return yaml.safeLoad(rawSpec); | ||
return yaml.load(rawSpec); | ||
} | ||
@@ -42,0 +42,0 @@ } catch (err) { |
@@ -60,11 +60,14 @@ '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(/\r?\n/g, "\n * ")} | ||
*/\n`; | ||
} | ||
function fromEntries(entries) { | ||
return entries.reduce((obj, [key, val]) => _objectSpread2(_objectSpread2({}, obj), {}, { | ||
[key]: val | ||
}), {}); | ||
function isRef(obj) { | ||
return !!obj.$ref; | ||
} | ||
@@ -76,3 +79,3 @@ function nodeType(obj) { | ||
if (obj["$ref"]) { | ||
if (obj.$ref) { | ||
return "ref"; | ||
@@ -143,2 +146,3 @@ } | ||
function tsIntersectionOf(types) { | ||
if (types.length === 1) return types[0]; | ||
return `(${types.join(") & (")})`; | ||
@@ -150,393 +154,389 @@ } | ||
function tsUnionOf(types) { | ||
if (types.length === 1) return types[0]; | ||
return `(${types.join(") | (")})`; | ||
} | ||
function unrefComponent(components, ref) { | ||
const [type, object] = ref.match(/(?<=\[")([^"]+)/g); | ||
return components[type][object]; | ||
function transformSchemaObjMap(obj, options) { | ||
let output = ""; | ||
let required = options && 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.replace(/\n+$/, "\n"); | ||
} | ||
function isOpenAPI2Reference(additionalProperties) { | ||
return additionalProperties.$ref !== undefined; | ||
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 | ||
}); | ||
case "enum": | ||
{ | ||
output += tsUnionOf(node.enum.map(item => typeof item === "string" ? `'${item.replace(/'/g, "\\'")}'` : item)); | ||
break; | ||
} | ||
if (property.optional) { | ||
if (Array.isArray(node.required)) { | ||
node.required = node.required.filter(r => r !== key); | ||
case "object": | ||
{ | ||
if ((!node.properties || !Object.keys(node.properties).length) && !node.allOf && !node.additionalProperties) { | ||
output += `{ [key: string]: any }`; | ||
break; | ||
} | ||
} else { | ||
node.required = [...(node.required || []), key]; | ||
} | ||
return [key, _objectSpread2(_objectSpread2({}, val), {}, { | ||
type: property.interfaceType, | ||
description: property.description | ||
})]; | ||
})); | ||
return node; | ||
}); | ||
} | ||
let properties = transformSchemaObjMap(node.properties || {}, { | ||
required: node.required | ||
}); | ||
let additionalProperties; | ||
function generateTypesV2(input, options) { | ||
const rawSchema = options && options.rawSchema; | ||
let definitions; | ||
if (node.additionalProperties) { | ||
if (node.additionalProperties === true) { | ||
additionalProperties = `{ [key: string]: any }`; | ||
} else if (typeof node.additionalProperties === "object") { | ||
const oneOf = node.additionalProperties.oneOf || undefined; | ||
const anyOf = node.additionalProperties.anyOf || undefined; | ||
if (rawSchema) { | ||
definitions = input; | ||
} else { | ||
const document = input; | ||
if (oneOf) { | ||
additionalProperties = `{ [key: string]: ${transformOneOf(oneOf)}; }`; | ||
} else if (anyOf) { | ||
additionalProperties = `{ [key: string]: ${transformAnyOf(anyOf)}; }`; | ||
} else { | ||
additionalProperties = `{ [key: string]: ${transformSchemaObj(node.additionalProperties) || "any"}; }`; | ||
} | ||
} | ||
} | ||
if (!document.definitions) { | ||
throw new Error(`⛔️ 'definitions' missing from schema https://swagger.io/specification/v2/#definitions-object`); | ||
} | ||
output += tsIntersectionOf([...(node.allOf ? node.allOf.map(transformSchemaObj) : []), ...(properties ? [`{\n${properties}\n}`] : []), ...(additionalProperties ? [additionalProperties] : [])]); | ||
break; | ||
} | ||
definitions = document.definitions; | ||
} | ||
case "array": | ||
{ | ||
if (Array.isArray(node.items)) { | ||
output += tsTupleOf(node.items.map(transformSchemaObj)); | ||
} else { | ||
output += tsArrayOf(node.items ? transformSchemaObj(node.items) : "any"); | ||
} | ||
const propertyMapped = options ? propertyMapper(definitions, options.propertyMapper) : definitions; | ||
break; | ||
} | ||
function getAdditionalPropertiesType(additionalProperties) { | ||
if (isOpenAPI2Reference(additionalProperties)) { | ||
return transformRef(additionalProperties.$ref, rawSchema ? "definitions/" : ""); | ||
} | ||
case "anyOf": | ||
{ | ||
output += transformAnyOf(node.anyOf); | ||
break; | ||
} | ||
return nodeType(additionalProperties); | ||
case "oneOf": | ||
{ | ||
output += transformOneOf(node.oneOf); | ||
break; | ||
} | ||
} | ||
function transform(node) { | ||
switch (nodeType(node)) { | ||
case "ref": | ||
{ | ||
return transformRef(node.$ref, rawSchema ? "definitions/" : ""); | ||
} | ||
if (node.nullable) { | ||
output += ") | null"; | ||
} | ||
case "string": | ||
case "number": | ||
case "boolean": | ||
{ | ||
return nodeType(node) || "any"; | ||
} | ||
return output; | ||
} | ||
case "enum": | ||
{ | ||
return tsUnionOf(node.enum.map(item => typeof item === "number" || typeof item === "boolean" ? item : `'${item}'`)); | ||
} | ||
function transformHeaderObjMap(headerMap) { | ||
let output = ""; | ||
Object.entries(headerMap).forEach(([k, v]) => { | ||
if (!v.schema) return; | ||
if (v.description) output += comment(v.description); | ||
const required = v.required ? "" : "?"; | ||
output += ` "${k}"${required}: ${transformSchemaObj(v.schema)}\n`; | ||
}); | ||
return output; | ||
} | ||
case "object": | ||
{ | ||
if ((!node.properties || !Object.keys(node.properties).length) && !node.allOf && !node.additionalProperties) { | ||
return `{ [key: string]: any }`; | ||
} | ||
function transformParametersArray(parameters, globalParams) { | ||
let output = ""; | ||
let mappedParams = {}; | ||
parameters.forEach(paramObj => { | ||
if (paramObj.$ref && globalParams) { | ||
const paramName = paramObj.$ref.split("/").pop(); | ||
let properties = createKeys(node.properties || {}, node.required); | ||
if (node.additionalProperties) { | ||
properties += `[key: string]: ${getAdditionalPropertiesType(node.additionalProperties) || "any"};\n`; | ||
if (globalParams[paramName]) { | ||
const reference = globalParams[paramName]; | ||
if (!mappedParams[reference.in]) mappedParams[reference.in] = {}; | ||
mappedParams[reference.in][reference.name || paramName] = _objectSpread2(_objectSpread2({}, reference), {}, { | ||
schema: { | ||
$ref: paramObj.$ref | ||
} | ||
}); | ||
} | ||
return tsIntersectionOf([...(node.allOf ? node.allOf.map(transform) : []), ...(properties ? [`{ ${properties} }`] : [])]); | ||
} | ||
case "array": | ||
{ | ||
return tsArrayOf(transform(node.items)); | ||
} | ||
return; | ||
} | ||
return ""; | ||
} | ||
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]) => { | ||
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}: ${paramObj.schema ? transformSchemaObj(paramObj.schema) : "unknown"};\n`; | ||
}); | ||
output += ` }\n`; | ||
}); | ||
return output; | ||
} | ||
function createKeys(obj, required = []) { | ||
let output = ""; | ||
Object.entries(obj).forEach(([key, value]) => { | ||
if (value.description) { | ||
output += comment(value.description); | ||
} | ||
const resType = res => res === 204 || res >= 300 && res < 400 ? "never" : "unknown"; | ||
output += `"${key}"${!required || !required.includes(key) ? "?" : ""}: `; | ||
output += transform(value); | ||
output += ";\n"; | ||
}); | ||
return output; | ||
} | ||
function transformResponsesObj(responsesObj) { | ||
let output = ""; | ||
Object.entries(responsesObj).forEach(([httpStatusCode, response]) => { | ||
if (response.description) output += comment(response.description); | ||
const statusCode = Number(httpStatusCode) || `"${httpStatusCode}"`; | ||
return `export interface definitions { | ||
${createKeys(propertyMapped, Object.keys(propertyMapped))} | ||
}`; | ||
} | ||
function generateTypesV3(input, options) { | ||
const { | ||
rawSchema = false | ||
} = options || {}; | ||
let { | ||
paths = {}, | ||
components = { | ||
schemas: {} | ||
if (response.$ref) { | ||
output += ` ${statusCode}: ${transformRef(response.$ref)};\n`; | ||
return; | ||
} | ||
} = input; | ||
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 (!response.content && !response.schema || response.content && !Object.keys(response.content).length) { | ||
output += ` ${statusCode}: ${resType(statusCode)};\n`; | ||
return; | ||
} | ||
} | ||
const operations = {}; | ||
const propertyMapped = options ? propertyMapper(components.schemas, options.propertyMapper) : components.schemas; | ||
output += ` ${statusCode}: {\n`; | ||
function transform(node) { | ||
switch (nodeType(node)) { | ||
case "ref": | ||
{ | ||
return transformRef(node.$ref, rawSchema ? "schemas/" : ""); | ||
} | ||
if (response.headers && Object.keys(response.headers).length) { | ||
if (response.headers.$ref) { | ||
output += ` headers: ${transformRef(response.headers.$ref)};\n`; | ||
} else { | ||
output += ` headers: {\n ${transformHeaderObjMap(response.headers)}\n }\n`; | ||
} | ||
} | ||
case "string": | ||
case "number": | ||
case "boolean": | ||
{ | ||
return nodeType(node) || "any"; | ||
} | ||
if (response.content && Object.keys(response.content).length) { | ||
output += ` content: {\n`; | ||
Object.entries(response.content).forEach(([contentType, contentResponse]) => { | ||
output += ` "${contentType}": ${transformSchemaObj(contentResponse.schema)};\n`; | ||
}); | ||
output += ` }\n`; | ||
} else if (response.schema) { | ||
output += ` schema: ${transformSchemaObj(response.schema)};\n`; | ||
} | ||
case "enum": | ||
{ | ||
return tsUnionOf(node.enum.map(item => typeof item === "number" || typeof item === "boolean" ? item : `'${item.replace(/'/g, "\\'")}'`)); | ||
} | ||
output += ` }\n`; | ||
}); | ||
return output; | ||
} | ||
case "oneOf": | ||
{ | ||
return tsUnionOf(node.oneOf.map(transform)); | ||
} | ||
function transformOperationObj(operation, globalParams) { | ||
let output = ""; | ||
case "anyOf": | ||
{ | ||
return tsIntersectionOf(node.anyOf.map(anyOf => tsPartial(transform(anyOf)))); | ||
} | ||
if (operation.parameters) { | ||
output += ` parameters: {\n ${transformParametersArray(operation.parameters, globalParams)}\n }\n`; | ||
} | ||
case "object": | ||
{ | ||
if ((!node.properties || !Object.keys(node.properties).length) && !node.allOf && !node.additionalProperties) { | ||
return `{ [key: string]: any }`; | ||
} | ||
if (operation.responses) { | ||
output += ` responses: {\n ${transformResponsesObj(operation.responses)}\n }\n`; | ||
} | ||
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]); | ||
} | ||
if (operation.requestBody) { | ||
if (isRef(operation.requestBody)) { | ||
output += ` requestBody: ${transformRef(operation.requestBody.$ref)};\n`; | ||
} else { | ||
const { | ||
description, | ||
content | ||
} = operation.requestBody; | ||
if (description) output += comment(description); | ||
case "array": | ||
{ | ||
if (Array.isArray(node.items)) { | ||
return tsTupleOf(node.items.map(transform)); | ||
} else { | ||
return tsArrayOf(node.items ? transform(node.items) : "any"); | ||
} | ||
} | ||
if (content && Object.keys(content).length) { | ||
output += ` requestBody: {\n content: {\n`; | ||
Object.entries(content).forEach(([k, v]) => { | ||
output += ` "${k}": ${transformSchemaObj(v.schema)};\n`; | ||
}); | ||
output += ` }\n }\n`; | ||
} else { | ||
output += ` requestBody: unknown;\n`; | ||
} | ||
} | ||
return ""; | ||
} | ||
function createKeys(obj, required) { | ||
let output = ""; | ||
Object.entries(obj).forEach(([key, value]) => { | ||
if (value.description) { | ||
output += comment(value.description); | ||
} | ||
return output; | ||
} | ||
output += `"${key}"${!required || !required.includes(key) ? "?" : ""}: `; | ||
function transformPathsObj(paths, { | ||
operations, | ||
parameters | ||
}) { | ||
let output = ""; | ||
Object.entries(paths).forEach(([url, pathItem]) => { | ||
if (pathItem.description) output += comment(pathItem.description); | ||
if (value.nullable) { | ||
output += "("; | ||
} | ||
if (pathItem.$ref) { | ||
output += ` "${url}": ${transformRef(pathItem.$ref)};\n`; | ||
return; | ||
} | ||
output += transform(value.schema ? value.schema : value); | ||
output += ` "${url}": {\n`; | ||
["get", "put", "post", "delete", "options", "head", "patch", "trace"].forEach(method => { | ||
const operation = pathItem[method]; | ||
if (!operation) return; | ||
if (operation.description) output += comment(operation.description); | ||
if (value.nullable) { | ||
output += ") | null"; | ||
if (operation.operationId) { | ||
output += ` "${method}": operations["${operation.operationId}"];\n`; | ||
operations[operation.operationId] = operation; | ||
return; | ||
} | ||
output += ";\n"; | ||
output += ` "${method}": {\n ${transformOperationObj(operation, parameters)}\n }\n`; | ||
}); | ||
return output; | ||
} | ||
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 (pathItem.parameters) { | ||
output += ` parameters: {\n ${transformParametersArray(pathItem.parameters, parameters)}\n }\n`; | ||
} | ||
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; | ||
} | ||
output += ` }\n`; | ||
}); | ||
return output; | ||
} | ||
if (paramProps.description) output += comment(paramProps.description); | ||
output += `"${paramName}"${paramProps.required === true ? "" : "?"}: ${transform(paramProps.schema)};\n`; | ||
}); | ||
output += `}\n`; | ||
}); | ||
output += `}\n`; | ||
return output; | ||
} | ||
function transformAll(schema, { | ||
version, | ||
rawSchema | ||
}) { | ||
let output = ""; | ||
let operations = {}; | ||
function transformOperation(operation) { | ||
let output = ""; | ||
output += `{\n`; | ||
if (rawSchema) { | ||
switch (version) { | ||
case 2: | ||
{ | ||
return `export interface definitions {\n ${transformSchemaObjMap(schema, { | ||
required: Object.keys(schema) | ||
})}\n}`; | ||
} | ||
if (operation.parameters) { | ||
output += transformParameters(operation.parameters); | ||
case 3: | ||
{ | ||
return `export interface schemas {\n ${transformSchemaObjMap(schema, { | ||
required: Object.keys(schema) | ||
})}\n }\n\n`; | ||
} | ||
} | ||
} | ||
if (operation.requestBody) { | ||
output += `requestBody: {\n`; | ||
Object.entries(operation.requestBody.content || {}).forEach(([contentType, { | ||
schema | ||
}]) => { | ||
output += `"${contentType}": ${transform(schema)};\n`; | ||
}); | ||
output += `}\n`; | ||
} | ||
output += `export interface paths {\n`; | ||
output += `responses: {\n`; | ||
Object.entries(operation.responses).forEach(([statusCodeString, response]) => { | ||
const statusCode = Number(statusCodeString) || statusCodeString; | ||
if (!response) return; | ||
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`; | ||
return; | ||
} | ||
output += `${statusCode}: {\n`; | ||
Object.entries(response.content).forEach(([contentType, encodedResponse]) => { | ||
output += `"${contentType}": ${transform(encodedResponse.schema)};\n`; | ||
}); | ||
output += `}\n`; | ||
if (schema.paths) { | ||
output += transformPathsObj(schema.paths, { | ||
operations, | ||
parameters: schema.components && schema.components.parameters || schema.parameters | ||
}); | ||
output += `}\n`; | ||
output += `}\n`; | ||
return output; | ||
} | ||
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); | ||
output += `}\n\n`; | ||
if (isMethod) { | ||
operation = operation; | ||
switch (version) { | ||
case 2: | ||
{ | ||
output += `export interface definitions {\n ${transformSchemaObjMap(schema.definitions || {}, { | ||
required: Object.keys(schema.definitions) | ||
})}\n}\n\n`; | ||
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)}`; | ||
} | ||
if (schema.parameters) { | ||
const required = Object.keys(schema.parameters); | ||
output += `export interface parameters {\n ${transformSchemaObjMap(schema.parameters, { | ||
required | ||
})}\n }\n\n`; | ||
} | ||
}); | ||
if (pathItem.parameters) { | ||
output += transformParameters(pathItem.parameters); | ||
if (schema.responses) { | ||
output += `export interface responses {\n ${transformResponsesObj(schema.responses)}\n }\n\n`; | ||
} | ||
break; | ||
} | ||
output += `}\n`; | ||
}); | ||
return output; | ||
} | ||
case 3: | ||
{ | ||
output += `export interface components {\n`; | ||
if (rawSchema) { | ||
return `export interface schemas { | ||
${createKeys(propertyMapped, Object.keys(propertyMapped))} | ||
}`; | ||
} | ||
if (schema.components) { | ||
if (schema.components.schemas) { | ||
const required = Object.keys(schema.components.schemas); | ||
output += ` schemas: {\n ${transformSchemaObjMap(schema.components.schemas, { | ||
required | ||
})}\n }\n`; | ||
} | ||
let finalOutput = ""; | ||
if (schema.components.responses) { | ||
output += ` responses: {\n ${transformResponsesObj(schema.components.responses)}\n }\n`; | ||
} | ||
if (Object.keys(paths).length) { | ||
finalOutput += `export interface paths { | ||
${transformPaths(paths)} | ||
} | ||
if (schema.components.parameters) { | ||
const required = Object.keys(schema.components.parameters); | ||
output += ` parameters: {\n ${transformSchemaObjMap(schema.components.parameters, { | ||
required | ||
})}\n }\n`; | ||
} | ||
`; | ||
} | ||
if (schema.components.requestBodies) { | ||
const required = Object.keys(schema.components.requestBodies); | ||
output += ` requestBodies: {\n ${transformSchemaObjMap(schema.components.requestBodies, { | ||
required | ||
})}\n }\n`; | ||
} | ||
finalOutput += "export interface operations {\n"; | ||
if (schema.components.headers) { | ||
output += ` headers: {\n ${transformHeaderObjMap(schema.components.headers)} }\n`; | ||
} | ||
} | ||
for (const [operationId, operation] of Object.entries(operations)) { | ||
if (operation.description) finalOutput += comment(operation.description); | ||
finalOutput += `"${operationId}": ${transformOperation(operation)}`; | ||
output += `}\n\n`; | ||
break; | ||
} | ||
} | ||
finalOutput += "\n}\n\n"; | ||
finalOutput += "export interface components {\n"; | ||
output += `export interface operations {\n`; | ||
if (components.parameters && Object.keys(components.parameters).length) { | ||
finalOutput += ` | ||
parameters: { | ||
${createKeys(components.parameters, Object.keys(components.parameters))} | ||
}\n`; | ||
if (Object.keys(operations).length) { | ||
Object.entries(operations).forEach(([operationId, operation]) => { | ||
if (operation.description) output += comment(operation.description); | ||
output += ` "${operationId}": {\n ${transformOperationObj(operation, schema.components && schema.components.parameters)};\n }\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; | ||
output += `}\n`; | ||
return output.trim(); | ||
} | ||
@@ -553,18 +553,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 = { | ||
@@ -571,0 +561,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 = `/** | ||
@@ -15,13 +15,5 @@ * This file was auto-generated by openapi-typescript. | ||
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; | ||
} | ||
} | ||
let output = `${WARNING_MESSAGE} | ||
${transformAll(schema, { version, rawSchema: options && options.rawSchema })} | ||
`; | ||
let prettierOptions = { parser: "typescript" }; | ||
@@ -28,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(/\r?\n/g, "\n * ")} | ||
*/\n`; | ||
} | ||
@@ -10,2 +13,5 @@ export function fromEntries(entries) { | ||
} | ||
export function isRef(obj) { | ||
return !!obj.$ref; | ||
} | ||
export function nodeType(obj) { | ||
@@ -15,3 +21,3 @@ if (!obj || typeof obj !== "object") { | ||
} | ||
if (obj["$ref"]) { | ||
if (obj.$ref) { | ||
return "ref"; | ||
@@ -67,2 +73,4 @@ } | ||
export function tsIntersectionOf(types) { | ||
if (types.length === 1) | ||
return types[0]; | ||
return `(${types.join(") & (")})`; | ||
@@ -74,2 +82,4 @@ } | ||
export function tsUnionOf(types) { | ||
if (types.length === 1) | ||
return types[0]; | ||
return `(${types.join(") | (")})`; | ||
@@ -81,4 +91,1 @@ } | ||
} | ||
export function isOpenAPI2Reference(additionalProperties) { | ||
return additionalProperties.$ref !== undefined; | ||
} |
@@ -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,104 @@ | ||
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>; | ||
requestBodies?: Record<string, ReferenceObject | RequestBody>; | ||
headers?: Record<string, ReferenceObject | HeaderObject>; | ||
links?: Record<string, ReferenceObject | LinkObject>; | ||
}; | ||
} | ||
export interface HeaderObject { | ||
type?: string; | ||
description?: string; | ||
required?: boolean; | ||
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)[]; | ||
requestBody?: ReferenceObject | RequestBody; | ||
responses?: Record<string, ReferenceObject | ResponseObject>; | ||
} | ||
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; | ||
} |
@@ -1,4 +0,5 @@ | ||
import { OpenAPI2, OpenAPI2Reference, OpenAPI2SchemaObject, OpenAPI3 } from "./types"; | ||
import { OpenAPI2, OpenAPI3, ReferenceObject } from "./types"; | ||
export declare function comment(text: string): string; | ||
export declare function fromEntries(entries: [string, any][]): Record<string, unknown>; | ||
export declare function isRef(obj: any): obj is ReferenceObject; | ||
declare type SchemaObjectType = "anyOf" | "array" | "boolean" | "enum" | "number" | "object" | "oneOf" | "ref" | "string"; | ||
@@ -14,3 +15,2 @@ export declare function nodeType(obj: any): SchemaObjectType | undefined; | ||
export declare function unrefComponent(components: any, ref: string): any; | ||
export declare function isOpenAPI2Reference(additionalProperties: OpenAPI2SchemaObject | OpenAPI2Reference | boolean): additionalProperties is OpenAPI2Reference; | ||
export {}; |
{ | ||
"name": "openapi-typescript", | ||
"description": "Generate TypeScript types from Swagger OpenAPI specs", | ||
"version": "3.0.0-rc.0", | ||
"version": "3.0.0", | ||
"license": "ISC", | ||
@@ -36,6 +36,6 @@ "bin": { | ||
"dependencies": { | ||
"js-yaml": "^3.14.0", | ||
"kleur": "^3.0.3", | ||
"meow": "^8.0.0", | ||
"prettier": "^2.2.0" | ||
"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.1.2" | ||
"typescript": "^4.1.3" | ||
}, | ||
@@ -60,0 +61,0 @@ "engines": { |
119
README.md
[![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-24-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 --> | ||
@@ -45,4 +44,28 @@ | ||
_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` | ||
@@ -91,2 +114,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) | | ||
@@ -101,3 +125,3 @@ ### Node | ||
const { readFileSync } = require("fs"); | ||
const swaggerToTS = require("openapi-typescript"); | ||
const swaggerToTS = require("openapi-typescript").default; | ||
@@ -115,31 +139,2 @@ const input = JSON.parse(readFileSync("spec.json", "utf8")); // Input can be any JS object (OpenAPI format) | ||
#### PropertyMapper | ||
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. | ||
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. | ||
An example on how to use the `x-nullable` property to control if a property is optional: | ||
```js | ||
const getNullable = (d: { [key: string]: any }): boolean => { | ||
const nullable = d["x-nullable"]; | ||
if (typeof nullable === "boolean") { | ||
return nullable; | ||
} | ||
return true; | ||
}; | ||
const output = swaggerToTS(swagger, { | ||
propertyMapper: (swaggerDefinition, property): Property => ({ | ||
...property, | ||
optional: getNullable(swaggerDefinition), | ||
}), | ||
}); | ||
``` | ||
_Thanks to @atlefren for this feature!_ | ||
## Migrating from v1 to v2 | ||
@@ -164,5 +159,6 @@ | ||
[js-yaml]: https://www.npmjs.com/package/js-yaml | ||
[openapi2]: https://swagger.io/specification/v2/ | ||
[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 | ||
@@ -180,36 +176,39 @@ [prettier]: https://npmjs.com/prettier | ||
<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="http://jankuca.com"><img src="https://avatars3.githubusercontent.com/u/367262?v=4" 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://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 --> | ||
@@ -216,0 +215,0 @@ |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
103197
29
0
16
1268
214
3
+ Addedargparse@2.0.1(transitive)
+ Addedjs-yaml@4.1.0(transitive)
+ Addedkleur@4.1.5(transitive)
+ Addedmeow@9.0.0(transitive)
- Removedargparse@1.0.10(transitive)
- Removedesprima@4.0.1(transitive)
- Removedjs-yaml@3.14.1(transitive)
- Removedkleur@3.0.3(transitive)
- Removedmeow@8.1.2(transitive)
- Removedsprintf-js@1.0.3(transitive)
Updatedjs-yaml@^4.0.0
Updatedkleur@^4.1.3
Updatedmeow@^9.0.0
Updatedprettier@^2.2.1