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
144
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 3.2.3 to 3.3.0-next.0

4

bin/cli.js

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

const meow = require("meow");
const { default: swaggerToTS } = require("../dist/cjs/index.js");
const { default: openapiTS } = require("../dist/cjs/index.js");
const { loadSpec } = require("./loaders");

@@ -76,3 +76,3 @@

// 2. generate schema (the main part!)
const result = swaggerToTS(spec, {
const result = openapiTS(spec, {
immutableTypes: cli.flags.immutableTypes,

@@ -79,0 +79,0 @@ prettierConfig: cli.flags.prettierConfig,

import { OpenAPI2, OpenAPI3, SchemaObject, SwaggerToTSOptions } from "./types";
export * from "./types";
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 | OpenAPI3 | Record<string, SchemaObject>, options?: SwaggerToTSOptions): string;
export default function openapiTS(schema: OpenAPI2 | OpenAPI3 | Record<string, SchemaObject>, options?: SwaggerToTSOptions): string;

@@ -30,6 +30,7 @@ "use strict";

`;
function swaggerToTS(schema, options) {
function openapiTS(schema, options) {
const version = (options && options.version) || utils_1.swaggerVersion(schema);
let output = `${exports.WARNING_MESSAGE}
${index_1.transformAll(schema, {
formatter: options && typeof options.formatter === "function" ? options.formatter : undefined,
immutableTypes: (options && options.immutableTypes) || false,

@@ -59,3 +60,3 @@ rawSchema: options && options.rawSchema,

}
exports.default = swaggerToTS;
exports.default = openapiTS;
//# sourceMappingURL=index.js.map

@@ -1,4 +0,5 @@

import { HeaderObject } from "../types";
export declare function transformHeaderObjMap(headerMap: Record<string, HeaderObject>, { immutableTypes }: {
import { HeaderObject, SchemaFormatter } from "../types";
export declare function transformHeaderObjMap(headerMap: Record<string, HeaderObject>, options: {
formatter?: SchemaFormatter;
immutableTypes: boolean;
}): string;

@@ -6,3 +6,3 @@ "use strict";

const schema_1 = require("./schema");
function transformHeaderObjMap(headerMap, { immutableTypes }) {
function transformHeaderObjMap(headerMap, options) {
let output = "";

@@ -14,7 +14,5 @@ Object.entries(headerMap).forEach(([k, v]) => {

output += utils_1.comment(v.description);
const readonly = utils_1.tsReadonly(immutableTypes);
const readonly = utils_1.tsReadonly(options.immutableTypes);
const required = v.required ? "" : "?";
output += ` ${readonly}"${k}"${required}: ${schema_1.transformSchemaObj(v.schema, {
immutableTypes,
})}\n`;
output += ` ${readonly}"${k}"${required}: ${schema_1.transformSchemaObj(v.schema, options)}\n`;
});

@@ -21,0 +19,0 @@ return output;

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

import { SchemaFormatter } from "../types";
interface TransformOptions {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -6,3 +8,3 @@ rawSchema?: boolean;

}
export declare function transformAll(schema: any, { immutableTypes, rawSchema, version }: TransformOptions): string;
export declare function transformAll(schema: any, { formatter, immutableTypes, rawSchema, version }: TransformOptions): string;
export {};

@@ -10,3 +10,3 @@ "use strict";

const schema_1 = require("./schema");
function transformAll(schema, { immutableTypes, rawSchema, version }) {
function transformAll(schema, { formatter, immutableTypes, rawSchema, version }) {
const readonly = utils_1.tsReadonly(immutableTypes);

@@ -19,2 +19,3 @@ let output = "";

return `export interface definitions {\n ${schema_1.transformSchemaObjMap(schema, {
formatter,
immutableTypes,

@@ -26,2 +27,3 @@ required: Object.keys(schema),

return `export interface schemas {\n ${schema_1.transformSchemaObjMap(schema, {
formatter,
immutableTypes,

@@ -47,2 +49,3 @@ required: Object.keys(schema),

output += `export interface definitions {\n ${schema_1.transformSchemaObjMap(schema.definitions, {
formatter,
immutableTypes,

@@ -55,2 +58,3 @@ required: Object.keys(schema.definitions),

output += `export interface parameters {\n ${schema_1.transformSchemaObjMap(schema.parameters, {
formatter,
immutableTypes,

@@ -62,2 +66,3 @@ required,

output += `export interface responses {\n ${responses_1.transformResponsesObj(schema.responses, {
formatter,
immutableTypes,

@@ -74,2 +79,3 @@ })}\n }\n\n`;

output += ` ${readonly}schemas: {\n ${schema_1.transformSchemaObjMap(schema.components.schemas, {
formatter,
immutableTypes,

@@ -81,2 +87,3 @@ required,

output += ` ${readonly}responses: {\n ${responses_1.transformResponsesObj(schema.components.responses, {
formatter,
immutableTypes,

@@ -88,2 +95,3 @@ })}\n }\n`;

output += ` ${readonly}parameters: {\n ${schema_1.transformSchemaObjMap(schema.components.parameters, {
formatter,
immutableTypes,

@@ -95,2 +103,3 @@ required,

output += ` ${readonly}requestBodies: {\n ${responses_1.transformRequestBodies(schema.components.requestBodies, {
formatter,
immutableTypes,

@@ -101,2 +110,3 @@ })}\n }\n`;

output += ` ${readonly}headers: {\n ${headers_1.transformHeaderObjMap(schema.components.headers, {
formatter,
immutableTypes,

@@ -103,0 +113,0 @@ })} }\n`;

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

import { RequestBody } from "../types";
import { RequestBody, SchemaFormatter } from "../types";
interface Options {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -4,0 +5,0 @@ }

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

import { SchemaFormatter } from "types";
interface TransformSchemaObjMapOptions {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -7,2 +9,3 @@ required?: string[];

interface Options {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -9,0 +12,0 @@ }

@@ -13,3 +13,6 @@ "use strict";

output += `${readonly}"${key}"${required.includes(key) ? "" : "?"}: `;
output += transformSchemaObj(value.schema || value, { immutableTypes: options.immutableTypes });
output += transformSchemaObj(value.schema || value, {
formatter: options.formatter,
immutableTypes: options.immutableTypes,
});
output += `;\n`;

@@ -34,74 +37,80 @@ });

}
switch (utils_1.nodeType(node)) {
case "ref": {
output += utils_1.transformRef(node.$ref);
break;
}
case "string":
case "number":
case "boolean": {
output += utils_1.nodeType(node) || "any";
break;
}
case "enum": {
const items = [];
node.enum.forEach((item) => {
if (typeof item === "string")
items.push(`'${item.replace(/'/g, "\\'")}'`);
else if (typeof item === "number" || typeof item === "boolean")
items.push(item);
else if (item === null && !node.nullable)
items.push("null");
});
output += utils_1.tsUnionOf(items);
break;
}
case "object": {
const isAnyOfOrOneOfOrAllOf = "anyOf" in node || "oneOf" in node || "allOf" in node;
if (!isAnyOfOrOneOfOrAllOf &&
(!node.properties || !Object.keys(node.properties).length) &&
!node.additionalProperties) {
output += `{ ${readonly}[key: string]: any }`;
const overriddenType = options.formatter && options.formatter(node);
if (overriddenType) {
output += overriddenType;
}
else {
switch (utils_1.nodeType(node)) {
case "ref": {
output += utils_1.transformRef(node.$ref);
break;
}
let properties = transformSchemaObjMap(node.properties || {}, {
immutableTypes: options.immutableTypes,
required: node.required,
});
let additionalProperties;
if (node.additionalProperties) {
if (node.additionalProperties === true || Object.keys(node.additionalProperties).length === 0) {
additionalProperties = `{ [key: string]: any }`;
case "string":
case "number":
case "boolean": {
output += utils_1.nodeType(node) || "any";
break;
}
case "enum": {
const items = [];
node.enum.forEach((item) => {
if (typeof item === "string")
items.push(`'${item.replace(/'/g, "\\'")}'`);
else if (typeof item === "number" || typeof item === "boolean")
items.push(item);
else if (item === null && !node.nullable)
items.push("null");
});
output += utils_1.tsUnionOf(items);
break;
}
case "object": {
const isAnyOfOrOneOfOrAllOf = "anyOf" in node || "oneOf" in node || "allOf" in node;
if (!isAnyOfOrOneOfOrAllOf &&
(!node.properties || !Object.keys(node.properties).length) &&
!node.additionalProperties) {
output += `{ ${readonly}[key: string]: any }`;
break;
}
else if (typeof node.additionalProperties === "object") {
const oneOf = node.additionalProperties.oneOf || undefined;
const anyOf = node.additionalProperties.anyOf || undefined;
if (oneOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformOneOf(oneOf, options)}; }`;
let properties = transformSchemaObjMap(node.properties || {}, {
immutableTypes: options.immutableTypes,
required: node.required,
});
let additionalProperties;
if (node.additionalProperties) {
if (node.additionalProperties === true || Object.keys(node.additionalProperties).length === 0) {
additionalProperties = `{ [key: string]: any }`;
}
else if (anyOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformAnyOf(anyOf, options)}; }`;
else if (typeof node.additionalProperties === "object") {
const oneOf = node.additionalProperties.oneOf || undefined;
const anyOf = node.additionalProperties.anyOf || undefined;
if (oneOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformOneOf(oneOf, options)}; }`;
}
else if (anyOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformAnyOf(anyOf, options)}; }`;
}
else {
additionalProperties = `{ ${readonly}[key: string]: ${transformSchemaObj(node.additionalProperties, options) || "any"}; }`;
}
}
else {
additionalProperties = `{ ${readonly}[key: string]: ${transformSchemaObj(node.additionalProperties, options) || "any"}; }`;
}
}
output += utils_1.tsIntersectionOf([
...(node.allOf ? node.allOf.map((node) => transformSchemaObj(node, options)) : []),
...(node.anyOf ? [transformAnyOf(node.anyOf, options)] : []),
...(node.oneOf ? [transformOneOf(node.oneOf, options)] : []),
...(properties ? [`{\n${properties}\n}`] : []),
...(additionalProperties ? [additionalProperties] : []),
]);
break;
}
output += utils_1.tsIntersectionOf([
...(node.allOf ? node.allOf.map((node) => transformSchemaObj(node, options)) : []),
...(node.anyOf ? [transformAnyOf(node.anyOf, options)] : []),
...(node.oneOf ? [transformOneOf(node.oneOf, options)] : []),
...(properties ? [`{\n${properties}\n}`] : []),
...(additionalProperties ? [additionalProperties] : []),
]);
break;
}
case "array": {
if (Array.isArray(node.items)) {
output += `${readonly}${utils_1.tsTupleOf(node.items.map((node) => transformSchemaObj(node, options)))}`;
case "array": {
if (Array.isArray(node.items)) {
output += `${readonly}${utils_1.tsTupleOf(node.items.map((node) => transformSchemaObj(node, options)))}`;
}
else {
output += `${readonly}${utils_1.tsArrayOf(node.items ? transformSchemaObj(node.items, options) : "any")}`;
}
break;
}
else {
output += `${readonly}${utils_1.tsArrayOf(node.items ? transformSchemaObj(node.items, options) : "any")}`;
}
break;
}

@@ -108,0 +117,0 @@ }

@@ -102,4 +102,7 @@ export interface OpenAPI2 {

anyOf?: (ReferenceObject | SchemaObject)[];
format?: string;
}
export declare type SchemaFormatter = (schemaObj: SchemaObject) => string | undefined;
export interface SwaggerToTSOptions {
formatter?: SchemaFormatter;
immutableTypes?: boolean;

@@ -106,0 +109,0 @@ prettierConfig?: string;

import { OpenAPI2, OpenAPI3, SchemaObject, SwaggerToTSOptions } from "./types";
export * from "./types";
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 | OpenAPI3 | Record<string, SchemaObject>, options?: SwaggerToTSOptions): string;
export default function openapiTS(schema: OpenAPI2 | OpenAPI3 | Record<string, SchemaObject>, options?: SwaggerToTSOptions): string;

@@ -14,6 +14,7 @@ import path from "path";

`;
export default function swaggerToTS(schema, options) {
export default function openapiTS(schema, options) {
const version = (options && options.version) || swaggerVersion(schema);
let output = `${WARNING_MESSAGE}
${transformAll(schema, {
formatter: options && typeof options.formatter === "function" ? options.formatter : undefined,
immutableTypes: (options && options.immutableTypes) || false,

@@ -20,0 +21,0 @@ rawSchema: options && options.rawSchema,

@@ -1,4 +0,5 @@

import { HeaderObject } from "../types";
export declare function transformHeaderObjMap(headerMap: Record<string, HeaderObject>, { immutableTypes }: {
import { HeaderObject, SchemaFormatter } from "../types";
export declare function transformHeaderObjMap(headerMap: Record<string, HeaderObject>, options: {
formatter?: SchemaFormatter;
immutableTypes: boolean;
}): string;
import { comment, tsReadonly } from "../utils";
import { transformSchemaObj } from "./schema";
export function transformHeaderObjMap(headerMap, { immutableTypes }) {
export function transformHeaderObjMap(headerMap, options) {
let output = "";

@@ -10,7 +10,5 @@ Object.entries(headerMap).forEach(([k, v]) => {

output += comment(v.description);
const readonly = tsReadonly(immutableTypes);
const readonly = tsReadonly(options.immutableTypes);
const required = v.required ? "" : "?";
output += ` ${readonly}"${k}"${required}: ${transformSchemaObj(v.schema, {
immutableTypes,
})}\n`;
output += ` ${readonly}"${k}"${required}: ${transformSchemaObj(v.schema, options)}\n`;
});

@@ -17,0 +15,0 @@ return output;

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

import { SchemaFormatter } from "../types";
interface TransformOptions {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -6,3 +8,3 @@ rawSchema?: boolean;

}
export declare function transformAll(schema: any, { immutableTypes, rawSchema, version }: TransformOptions): string;
export declare function transformAll(schema: any, { formatter, immutableTypes, rawSchema, version }: TransformOptions): string;
export {};

@@ -7,3 +7,3 @@ import { comment, tsReadonly } from "../utils";

import { transformSchemaObjMap } from "./schema";
export function transformAll(schema, { immutableTypes, rawSchema, version }) {
export function transformAll(schema, { formatter, immutableTypes, rawSchema, version }) {
const readonly = tsReadonly(immutableTypes);

@@ -16,2 +16,3 @@ let output = "";

return `export interface definitions {\n ${transformSchemaObjMap(schema, {
formatter,
immutableTypes,

@@ -23,2 +24,3 @@ required: Object.keys(schema),

return `export interface schemas {\n ${transformSchemaObjMap(schema, {
formatter,
immutableTypes,

@@ -44,2 +46,3 @@ required: Object.keys(schema),

output += `export interface definitions {\n ${transformSchemaObjMap(schema.definitions, {
formatter,
immutableTypes,

@@ -52,2 +55,3 @@ required: Object.keys(schema.definitions),

output += `export interface parameters {\n ${transformSchemaObjMap(schema.parameters, {
formatter,
immutableTypes,

@@ -59,2 +63,3 @@ required,

output += `export interface responses {\n ${transformResponsesObj(schema.responses, {
formatter,
immutableTypes,

@@ -71,2 +76,3 @@ })}\n }\n\n`;

output += ` ${readonly}schemas: {\n ${transformSchemaObjMap(schema.components.schemas, {
formatter,
immutableTypes,

@@ -78,2 +84,3 @@ required,

output += ` ${readonly}responses: {\n ${transformResponsesObj(schema.components.responses, {
formatter,
immutableTypes,

@@ -85,2 +92,3 @@ })}\n }\n`;

output += ` ${readonly}parameters: {\n ${transformSchemaObjMap(schema.components.parameters, {
formatter,
immutableTypes,

@@ -92,2 +100,3 @@ required,

output += ` ${readonly}requestBodies: {\n ${transformRequestBodies(schema.components.requestBodies, {
formatter,
immutableTypes,

@@ -98,2 +107,3 @@ })}\n }\n`;

output += ` ${readonly}headers: {\n ${transformHeaderObjMap(schema.components.headers, {
formatter,
immutableTypes,

@@ -100,0 +110,0 @@ })} }\n`;

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

import { RequestBody } from "../types";
import { RequestBody, SchemaFormatter } from "../types";
interface Options {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -4,0 +5,0 @@ }

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

import { SchemaFormatter } from "types";
interface TransformSchemaObjMapOptions {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -7,2 +9,3 @@ required?: string[];

interface Options {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -9,0 +12,0 @@ }

@@ -10,3 +10,6 @@ import { comment, nodeType, transformRef, tsArrayOf, tsIntersectionOf, tsPartial, tsTupleOf, tsUnionOf, } from "../utils";

output += `${readonly}"${key}"${required.includes(key) ? "" : "?"}: `;
output += transformSchemaObj(value.schema || value, { immutableTypes: options.immutableTypes });
output += transformSchemaObj(value.schema || value, {
formatter: options.formatter,
immutableTypes: options.immutableTypes,
});
output += `;\n`;

@@ -28,74 +31,80 @@ });

}
switch (nodeType(node)) {
case "ref": {
output += transformRef(node.$ref);
break;
}
case "string":
case "number":
case "boolean": {
output += nodeType(node) || "any";
break;
}
case "enum": {
const items = [];
node.enum.forEach((item) => {
if (typeof item === "string")
items.push(`'${item.replace(/'/g, "\\'")}'`);
else if (typeof item === "number" || typeof item === "boolean")
items.push(item);
else if (item === null && !node.nullable)
items.push("null");
});
output += tsUnionOf(items);
break;
}
case "object": {
const isAnyOfOrOneOfOrAllOf = "anyOf" in node || "oneOf" in node || "allOf" in node;
if (!isAnyOfOrOneOfOrAllOf &&
(!node.properties || !Object.keys(node.properties).length) &&
!node.additionalProperties) {
output += `{ ${readonly}[key: string]: any }`;
const overriddenType = options.formatter && options.formatter(node);
if (overriddenType) {
output += overriddenType;
}
else {
switch (nodeType(node)) {
case "ref": {
output += transformRef(node.$ref);
break;
}
let properties = transformSchemaObjMap(node.properties || {}, {
immutableTypes: options.immutableTypes,
required: node.required,
});
let additionalProperties;
if (node.additionalProperties) {
if (node.additionalProperties === true || Object.keys(node.additionalProperties).length === 0) {
additionalProperties = `{ [key: string]: any }`;
case "string":
case "number":
case "boolean": {
output += nodeType(node) || "any";
break;
}
case "enum": {
const items = [];
node.enum.forEach((item) => {
if (typeof item === "string")
items.push(`'${item.replace(/'/g, "\\'")}'`);
else if (typeof item === "number" || typeof item === "boolean")
items.push(item);
else if (item === null && !node.nullable)
items.push("null");
});
output += tsUnionOf(items);
break;
}
case "object": {
const isAnyOfOrOneOfOrAllOf = "anyOf" in node || "oneOf" in node || "allOf" in node;
if (!isAnyOfOrOneOfOrAllOf &&
(!node.properties || !Object.keys(node.properties).length) &&
!node.additionalProperties) {
output += `{ ${readonly}[key: string]: any }`;
break;
}
else if (typeof node.additionalProperties === "object") {
const oneOf = node.additionalProperties.oneOf || undefined;
const anyOf = node.additionalProperties.anyOf || undefined;
if (oneOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformOneOf(oneOf, options)}; }`;
let properties = transformSchemaObjMap(node.properties || {}, {
immutableTypes: options.immutableTypes,
required: node.required,
});
let additionalProperties;
if (node.additionalProperties) {
if (node.additionalProperties === true || Object.keys(node.additionalProperties).length === 0) {
additionalProperties = `{ [key: string]: any }`;
}
else if (anyOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformAnyOf(anyOf, options)}; }`;
else if (typeof node.additionalProperties === "object") {
const oneOf = node.additionalProperties.oneOf || undefined;
const anyOf = node.additionalProperties.anyOf || undefined;
if (oneOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformOneOf(oneOf, options)}; }`;
}
else if (anyOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformAnyOf(anyOf, options)}; }`;
}
else {
additionalProperties = `{ ${readonly}[key: string]: ${transformSchemaObj(node.additionalProperties, options) || "any"}; }`;
}
}
else {
additionalProperties = `{ ${readonly}[key: string]: ${transformSchemaObj(node.additionalProperties, options) || "any"}; }`;
}
}
output += tsIntersectionOf([
...(node.allOf ? node.allOf.map((node) => transformSchemaObj(node, options)) : []),
...(node.anyOf ? [transformAnyOf(node.anyOf, options)] : []),
...(node.oneOf ? [transformOneOf(node.oneOf, options)] : []),
...(properties ? [`{\n${properties}\n}`] : []),
...(additionalProperties ? [additionalProperties] : []),
]);
break;
}
output += tsIntersectionOf([
...(node.allOf ? node.allOf.map((node) => transformSchemaObj(node, options)) : []),
...(node.anyOf ? [transformAnyOf(node.anyOf, options)] : []),
...(node.oneOf ? [transformOneOf(node.oneOf, options)] : []),
...(properties ? [`{\n${properties}\n}`] : []),
...(additionalProperties ? [additionalProperties] : []),
]);
break;
}
case "array": {
if (Array.isArray(node.items)) {
output += `${readonly}${tsTupleOf(node.items.map((node) => transformSchemaObj(node, options)))}`;
case "array": {
if (Array.isArray(node.items)) {
output += `${readonly}${tsTupleOf(node.items.map((node) => transformSchemaObj(node, options)))}`;
}
else {
output += `${readonly}${tsArrayOf(node.items ? transformSchemaObj(node.items, options) : "any")}`;
}
break;
}
else {
output += `${readonly}${tsArrayOf(node.items ? transformSchemaObj(node.items, options) : "any")}`;
}
break;
}

@@ -102,0 +111,0 @@ }

@@ -102,4 +102,7 @@ export interface OpenAPI2 {

anyOf?: (ReferenceObject | SchemaObject)[];
format?: string;
}
export declare type SchemaFormatter = (schemaObj: SchemaObject) => string | undefined;
export interface SwaggerToTSOptions {
formatter?: SchemaFormatter;
immutableTypes?: boolean;

@@ -106,0 +109,0 @@ prettierConfig?: string;

{
"name": "openapi-typescript",
"description": "Generate TypeScript types from Swagger OpenAPI specs",
"version": "3.2.3",
"version": "3.3.0-next.0",
"engines": {

@@ -6,0 +6,0 @@ "node": ">= 10.0.0"

@@ -24,3 +24,3 @@ [![version(scoped)](https://img.shields.io/npm/v/openapi-typescript.svg)](https://www.npmjs.com/package/openapi-typescript)

### CLI
### 🖥️ CLI

@@ -118,3 +118,3 @@ #### 🗄️ Reading specs from file system

### Node
### 🐢 Node

@@ -127,6 +127,6 @@ ```bash

const { readFileSync } = require("fs");
const swaggerToTS = require("openapi-typescript").default;
const openapiTS = require("openapi-typescript").default;
const input = JSON.parse(readFileSync("spec.json", "utf8")); // Input can be any JS object (OpenAPI format)
const output = swaggerToTS(input); // Outputs TypeScript defs as a string (to be parsed, or written to a file)
const output = openapiTS(input); // Outputs TypeScript defs as a string (to be parsed, or written to a file)
```

@@ -141,8 +141,33 @@

## Migrating from v1 to v2
#### Custom Formatter
[Migrating from v1 to v2](./docs/migrating-from-v1.md)
If using the Node.js API, you can optionally pass a **formatter** to openapi-typescript. This is useful if you want to override the default types and substitute your own.
## Project Goals
For example, say your schema has the following property:
```yaml
properties:
updated_at:
type: string
format: date-time
```
By default, this will generate a type `updated_at?: string;`. But we can override this by passing a formatter to the Node API, like so:
```js
const types = openapiTS(mySchema, {
formatter(node: SchemaObject) {
if (node.format === 'date-time') {
return "Date"; // return the TypeScript “Date” type, as a string
}
// for all other schema objects, let openapi-typescript decide (return undefined)
});
```
This will generate `updated_at?: Date` instead. Note that you will still have to do the parsing of your data yourself. But this will save you from having to also update all your types.
_Note: you don’t have to use `.format`—this is just an example! You can use any property on a schema object to overwrite its generated type if desired._
## 🏅 Project Goals
1. Support converting any OpenAPI 3.0 or 2.0 (Swagger) schema to TypeScript types, no matter how complicated

@@ -154,3 +179,3 @@ 1. The generated TypeScript types **must** match your schema as closely as possible (i.e. don’t convert names to

## Contributing
## 🤝 Contributing

@@ -164,2 +189,3 @@ PRs are welcome! Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) guide. Opening an issue beforehand to discuss is

[npm-run-all]: https://www.npmjs.com/package/npm-run-all
[openapi-format]: https://swagger.io/specification/#data-types
[openapi-operationid]: https://swagger.io/specification/#operation-object

@@ -166,0 +192,0 @@ [openapi2]: https://swagger.io/specification/v2/

@@ -17,3 +17,3 @@ import path from "path";

export default function swaggerToTS(
export default function openapiTS(
schema: OpenAPI2 | OpenAPI3 | Record<string, SchemaObject>,

@@ -28,2 +28,3 @@ options?: SwaggerToTSOptions

${transformAll(schema, {
formatter: options && typeof options.formatter === "function" ? options.formatter : undefined,
immutableTypes: (options && options.immutableTypes) || false,

@@ -30,0 +31,0 @@ rawSchema: options && options.rawSchema,

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

import { HeaderObject } from "../types";
import { HeaderObject, SchemaFormatter } from "../types";
import { comment, tsReadonly } from "../utils";

@@ -7,3 +7,3 @@ import { transformSchemaObj } from "./schema";

headerMap: Record<string, HeaderObject>,
{ immutableTypes }: { immutableTypes: boolean }
options: { formatter?: SchemaFormatter; immutableTypes: boolean }
): string {

@@ -17,8 +17,6 @@ let output = "";

const readonly = tsReadonly(immutableTypes);
const readonly = tsReadonly(options.immutableTypes);
const required = v.required ? "" : "?";
output += ` ${readonly}"${k}"${required}: ${transformSchemaObj(v.schema, {
immutableTypes,
})}\n`;
output += ` ${readonly}"${k}"${required}: ${transformSchemaObj(v.schema, options)}\n`;
});

@@ -25,0 +23,0 @@

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

import { OperationObject, PathItemObject } from "../types";
import { OperationObject, PathItemObject, SchemaFormatter } from "../types";
import { comment, tsReadonly } from "../utils";

@@ -10,2 +10,3 @@ import { transformHeaderObjMap } from "./headers";

interface TransformOptions {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -16,3 +17,3 @@ rawSchema?: boolean;

export function transformAll(schema: any, { immutableTypes, rawSchema, version }: TransformOptions): string {
export function transformAll(schema: any, { formatter, immutableTypes, rawSchema, version }: TransformOptions): string {
const readonly = tsReadonly(immutableTypes);

@@ -29,2 +30,3 @@

return `export interface definitions {\n ${transformSchemaObjMap(schema, {
formatter,
immutableTypes,

@@ -36,2 +38,3 @@ required: Object.keys(schema),

return `export interface schemas {\n ${transformSchemaObjMap(schema, {
formatter,
immutableTypes,

@@ -61,2 +64,3 @@ required: Object.keys(schema),

output += `export interface definitions {\n ${transformSchemaObjMap(schema.definitions, {
formatter,
immutableTypes,

@@ -71,2 +75,3 @@ required: Object.keys(schema.definitions),

output += `export interface parameters {\n ${transformSchemaObjMap(schema.parameters, {
formatter,
immutableTypes,

@@ -80,2 +85,3 @@ required,

output += `export interface responses {\n ${transformResponsesObj(schema.responses, {
formatter,
immutableTypes,

@@ -95,2 +101,3 @@ })}\n }\n\n`;

output += ` ${readonly}schemas: {\n ${transformSchemaObjMap(schema.components.schemas, {
formatter,
immutableTypes,

@@ -104,2 +111,3 @@ required,

output += ` ${readonly}responses: {\n ${transformResponsesObj(schema.components.responses, {
formatter,
immutableTypes,

@@ -113,2 +121,3 @@ })}\n }\n`;

output += ` ${readonly}parameters: {\n ${transformSchemaObjMap(schema.components.parameters, {
formatter,
immutableTypes,

@@ -122,2 +131,3 @@ required,

output += ` ${readonly}requestBodies: {\n ${transformRequestBodies(schema.components.requestBodies, {
formatter,
immutableTypes,

@@ -130,2 +140,3 @@ })}\n }\n`;

output += ` ${readonly}headers: {\n ${transformHeaderObjMap(schema.components.headers, {
formatter,
immutableTypes,

@@ -132,0 +143,0 @@ })} }\n`;

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

import { RequestBody } from "../types";
import { RequestBody, SchemaFormatter } from "../types";
import { comment, transformRef, tsReadonly } from "../utils";

@@ -10,2 +10,3 @@ import { transformHeaderObjMap } from "./headers";

interface Options {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -12,0 +13,0 @@ }

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

import { SchemaFormatter } from "types";
import {

@@ -13,2 +14,3 @@ comment,

interface TransformSchemaObjMapOptions {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -33,3 +35,6 @@ required?: string[];

// 3. transform
output += transformSchemaObj(value.schema || value, { immutableTypes: options.immutableTypes });
output += transformSchemaObj(value.schema || value, {
formatter: options.formatter,
immutableTypes: options.immutableTypes,
});

@@ -44,2 +49,3 @@ // 4. close

interface Options {
formatter?: SchemaFormatter;
immutableTypes: boolean;

@@ -69,81 +75,87 @@ }

// transform core type
switch (nodeType(node)) {
case "ref": {
output += transformRef(node.$ref);
break;
}
case "string":
case "number":
case "boolean": {
output += nodeType(node) || "any";
break;
}
case "enum": {
const items: Array<string | number | boolean> = [];
(node.enum as unknown[]).forEach((item) => {
if (typeof item === "string") items.push(`'${item.replace(/'/g, "\\'")}'`);
else if (typeof item === "number" || typeof item === "boolean") items.push(item);
else if (item === null && !node.nullable) items.push("null");
});
output += tsUnionOf(items);
break;
}
case "object": {
const isAnyOfOrOneOfOrAllOf = "anyOf" in node || "oneOf" in node || "allOf" in node;
// if empty object, then return generic map type
if (
!isAnyOfOrOneOfOrAllOf &&
(!node.properties || !Object.keys(node.properties).length) &&
!node.additionalProperties
) {
output += `{ ${readonly}[key: string]: any }`;
// pass in formatter, if specified
const overriddenType = options.formatter && options.formatter(node);
if (overriddenType) {
output += overriddenType;
} else {
// transform core type
switch (nodeType(node)) {
case "ref": {
output += transformRef(node.$ref);
break;
}
case "string":
case "number":
case "boolean": {
output += nodeType(node) || "any";
break;
}
case "enum": {
const items: Array<string | number | boolean> = [];
(node.enum as unknown[]).forEach((item) => {
if (typeof item === "string") items.push(`'${item.replace(/'/g, "\\'")}'`);
else if (typeof item === "number" || typeof item === "boolean") items.push(item);
else if (item === null && !node.nullable) items.push("null");
});
output += tsUnionOf(items);
break;
}
case "object": {
const isAnyOfOrOneOfOrAllOf = "anyOf" in node || "oneOf" in node || "allOf" in node;
let properties = transformSchemaObjMap(node.properties || {}, {
immutableTypes: options.immutableTypes,
required: node.required,
});
// if empty object, then return generic map type
if (
!isAnyOfOrOneOfOrAllOf &&
(!node.properties || !Object.keys(node.properties).length) &&
!node.additionalProperties
) {
output += `{ ${readonly}[key: string]: any }`;
break;
}
// if additional properties, add an intersection with a generic map type
let additionalProperties: string | undefined;
if (node.additionalProperties) {
if (node.additionalProperties === true || Object.keys(node.additionalProperties).length === 0) {
additionalProperties = `{ [key: string]: any }`;
} else if (typeof node.additionalProperties === "object") {
const oneOf: any[] | undefined = (node.additionalProperties as any).oneOf || undefined; // TypeScript does a really bad job at inference here, so we enforce a type
const anyOf: any[] | undefined = (node.additionalProperties as any).anyOf || undefined; // "
if (oneOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformOneOf(oneOf, options)}; }`;
} else if (anyOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformAnyOf(anyOf, options)}; }`;
} else {
additionalProperties = `{ ${readonly}[key: string]: ${
transformSchemaObj(node.additionalProperties, options) || "any"
}; }`;
let properties = transformSchemaObjMap(node.properties || {}, {
immutableTypes: options.immutableTypes,
required: node.required,
});
// if additional properties, add an intersection with a generic map type
let additionalProperties: string | undefined;
if (node.additionalProperties) {
if (node.additionalProperties === true || Object.keys(node.additionalProperties).length === 0) {
additionalProperties = `{ [key: string]: any }`;
} else if (typeof node.additionalProperties === "object") {
const oneOf: any[] | undefined = (node.additionalProperties as any).oneOf || undefined; // TypeScript does a really bad job at inference here, so we enforce a type
const anyOf: any[] | undefined = (node.additionalProperties as any).anyOf || undefined; // "
if (oneOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformOneOf(oneOf, options)}; }`;
} else if (anyOf) {
additionalProperties = `{ ${readonly}[key: string]: ${transformAnyOf(anyOf, options)}; }`;
} else {
additionalProperties = `{ ${readonly}[key: string]: ${
transformSchemaObj(node.additionalProperties, options) || "any"
}; }`;
}
}
}
}
output += tsIntersectionOf([
// append allOf/anyOf/oneOf first
...(node.allOf ? (node.allOf as any[]).map((node) => transformSchemaObj(node, options)) : []),
...(node.anyOf ? [transformAnyOf(node.anyOf, options)] : []),
...(node.oneOf ? [transformOneOf(node.oneOf, options)] : []),
...(properties ? [`{\n${properties}\n}`] : []), // then properties (line breaks are important!)
...(additionalProperties ? [additionalProperties] : []), // then additional properties
]);
output += tsIntersectionOf([
// append allOf/anyOf/oneOf first
...(node.allOf ? (node.allOf as any[]).map((node) => transformSchemaObj(node, options)) : []),
...(node.anyOf ? [transformAnyOf(node.anyOf, options)] : []),
...(node.oneOf ? [transformOneOf(node.oneOf, options)] : []),
...(properties ? [`{\n${properties}\n}`] : []), // then properties (line breaks are important!)
...(additionalProperties ? [additionalProperties] : []), // then additional properties
]);
break;
}
break;
}
case "array": {
if (Array.isArray(node.items)) {
output += `${readonly}${tsTupleOf(node.items.map((node: any) => transformSchemaObj(node, options)))}`;
} else {
output += `${readonly}${tsArrayOf(node.items ? transformSchemaObj(node.items as any, options) : "any")}`;
case "array": {
if (Array.isArray(node.items)) {
output += `${readonly}${tsTupleOf(node.items.map((node: any) => transformSchemaObj(node, options)))}`;
} else {
output += `${readonly}${tsArrayOf(node.items ? transformSchemaObj(node.items as any, options) : "any")}`;
}
break;
}
break;
}

@@ -150,0 +162,0 @@ }

@@ -108,5 +108,10 @@ export interface OpenAPI2 {

anyOf?: (ReferenceObject | SchemaObject)[]; // V3 ONLY
format?: string; // V3 ONLY
}
export type SchemaFormatter = (schemaObj: SchemaObject) => string | undefined;
export interface SwaggerToTSOptions {
/** Specify a formatter */
formatter?: SchemaFormatter;
/** Generates immutable types (readonly properties and readonly array) */

@@ -113,0 +118,0 @@ immutableTypes?: boolean;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc