
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Automatically generate OpenAPI specifications from opinionated Typescript types.
Automatically generate OpenAPI (formerly Swagger) specifications from opinionated Typescript types. Supports OpenAPI v3.1 and v3.0. Requires interfaces/types in a specific format.
ts-oas, you can use the generated specs for documentation, input validation (e.g. with AJV), and serialization — while still reusing the original types in your business logic, unit tests, and more.npm i ts-oas
Firstly, We need types for each API, compatible with the following format:
type Api = {
path: string;
method: HTTPMethod;
body?: Record<string, any>;
params?: Record<string, any>;
query?: Record<string, any>;
responses: Partial<Record<HttpStatusCode, any>>;
security?: Record<string, string[]>[];
};
We have interfaces.ts where our API types are present:
import { ApiMapper } from "ts-oas";
// ApiMapper only validates the type structure at compile time,
// it's optional, omit it if you need dependency-free interface files.
export type GetBarAPI = {
path: "/foo/bar/{id}";
method: "GET";
params: {
id: number;
};
query: {
from_date: Date;
};
responses: {
/** @contentType application/json */
"200": Bar;
"404": { success: false };
};
};
/**
* Sample description.
* @summary Add a Bar
*/
export type AddBarAPI = ApiMapper<{
path: "/foo/bar";
method: "POST";
body: Bar;
responses: {
/** No content */
"201": never;
};
}>;
export type Bar = {
/**
* Description for barName.
* @minLength 10
*/
barName: string;
barType: "one" | "two";
};
In script.ts file:
import { createProgram, TsOAS } from "ts-oas";
import { resolve } from "path";
// create a Typescript program. or any generic ts program can be used.
const tsProgram = createProgram(["interfaces.ts"], { strictNullChecks: true }, resolve());
// initiate the OAS generator.
const tsoas = new TsOAS(tsProgram, { ref: true });
// get the complete OAS. determine type names (Regex/exact name) to be considered for specs.
const specObject = tsoas.getOpenApiSpec([/API$/]); // all types that ends with "API"
// log results:
console.log(JSON.stringify(specObject, null, 4));
// or write into a ts file:
// writeFileSync("./schema.ts", `const spec = ${inspect(specObject, { depth: null })};\n`);
Run the above script.
{
"openapi": "3.1.0",
"info": {
"title": "OpenAPI specification",
"version": "1.0.0"
},
"components": {
"schemas": {
"Bar": {
"type": "object",
"properties": {
"barName": {
"description": "Description for barName.",
"minLength": 10,
"type": "string"
},
"barType": {
"enum": ["one", "two"],
"type": "string"
}
},
"required": ["barName", "barType"]
}
}
},
"paths": {
"/foo/bar/{id}": {
"get": {
"operationId": "GetBarAPI",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "number"
}
},
{
"name": "from_date",
"in": "query",
"required": true,
"schema": {
"type": "string",
"format": "date-time"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Bar"
}
}
}
},
"404": {
"description": "",
"content": {
"*/*": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"enum": [false]
}
},
"required": ["success"]
}
}
}
}
}
}
},
"/foo/bar": {
"post": {
"operationId": "AddBarAPI",
"description": "Sample description.",
"summary": "Add a Bar",
"requestBody": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Bar"
}
}
}
},
"responses": {
"201": {
"description": "No content"
}
}
}
}
}
}
Schemas with any format can be generated by:
const schema = tsoas.getSchemas(["Bar"]);
console.log(schema);
{
Bar: {
type: 'object',
properties: {
barName: {
description: 'Description for barName.',
minLength: 10,
type: 'string'
},
barType: { enum: [ 'one', 'two' ], type: 'string' }
},
required: [ 'barName', 'barType' ]
}
}
Command line tool is designed to behave just like the programmatic way. Once it has been installed, CLI can be executed using npx ts-oas, or just ts-oas if installed globally.
Usage: ts-oas <file-paths> <type-names> [options]
<file-paths> : Comma-separated list of relative .ts file paths which contain
types.
<type-names> : Comma-separated list of type names (Regex/exact name) to be
considered in files.
Options:
-c, --tsconfig-file Path to a JSON tsconfig file. [string]
-p, --options-file Path to a JSON file containing 'ts-oas' Options. Refer to
the documentation. [string]
-s, --spec-file Path to a JSON file containing additional OpenAPI
specifications. [string]
-e, --schema-only Only generates pure schemas from given types.
('spec-file' will be ignored.) [boolean]
-o, --output Path to a JSON file that will be used to write the
output. Will create the file if not existed. [string]
-h, --help Show help [boolean]
-v, --version Show version number [boolean]
Examples:
ts-oas ./interfaces/sample.ts myApi,mySecondApi
| Keyword | Fields | Examples |
|---|---|---|
| @default | any | @default foo @default 3 @default ["a", "b", "c"] |
| @format | strings | @format email |
| @items | arrays | @items.minimum 1 @items.format email @items {"type":"integer", "minimum":0} @default ["a", "b", "c"] |
| @$ref | any | @ref http://my-schema.org |
| @title | any | @title foo |
| @minimum @maximum @exclusiveMinimum @exclusiveMaximum | numbers | @minimum 10 @maximum 100 |
| @minLength @maxLength | strings | @minLength 10 @maxLength 100 |
| @minItems @maxItems | arrays | @minItems 10 @maxItems 100 |
| @minProperties @maxProperties | objects | @minProperties 10 @maxProperties 100 |
| @additionalProperties | objects | @additionalProperties |
| @ignore | any | @ignore |
| @pattern | strings | @pattern /^[0-9a-z]+$/g |
| @example | any | @example foo @example {"abc":true} @example require('./examples.ts').myExampleConst |
| @examples | any | @example ["foo", "bar"] @example require('./examples.ts').myExampleArrayConst |
| Keyword | Description |
|---|---|
| @summary | Provides a brief summary of the API endpoint |
| @operationId | Sets a unique identifier for the operation |
| @tags | Assigns tags to group related operations (comma-separated) |
| @deprecated | Marks the operation as deprecated |
| @ignore | Excludes the API type from the generated specification |
| @body.description | Adds a description for the request body |
| @body.contentType | Sets the content-type for the request body |
/**
* Sample description.
* @summary Summary of Endpoint
* @operationId addBar
* @tags foos,bars
* @deprecated
* @ignore
* @body.description Description for body of request.
* @body.contentType application/json
*/
export type AddBarAPI = ApiMapper<{
path: "/foo/bar";
method: "POST";
body: Bar;
responses: {
"201": {};
};
}>;
| Keyword | Description |
|---|---|
| @contentType | Sets the content-type for the response |
...
responses: {
/**
* Description for response 200.
* @contentType application/json
*/
"200": { success: true };
};
refdefault: false
Defines references for schemas based on their type references.
titlesdefault: false
Provides a title field in each schema, filled with its corresponding field name or type name.
ignoreRequireddefault: false
Ignores the required field in all schemas.
ignoreErrorsdefault: false
Ignores errors in Typescript files. May introduce wrong schemas.
uniqueNamesdefault: false
Replaces every type name with a unique hash to avoid duplication issues.
tsNodeRegisterdefault: false
Uses ts-node/register as a runtime argument, enabling direct execution of TypeScript on Node.js without precompiling.
nullableKeyworddefault: true
Provides nullable: true for nullable fields; otherwise, set type: "null".
defaultContentTypedefault: "*/*"
Sets the default content type for all operations. This can be overridden case-by-case (see the annotations section).
defaultNumberTypedefault: "number"
Sets the default schema type for number values, which can be overridden case-by-case (see the annotations section).
customKeywordsA list of custom keywords to consider in annotations.
customKeywordPrefixdefault: "x-"
The prefix added to all customKeywords.
customOperationPropertiesdefault: false
Whether to consider custom operation properties in the root of API types.
If true, avoid using ApiMapper, as it will override these properties.
schemaProcessorA function that runs over each generated schema.
ts-oas is highly inspired by typescript-json-schema. While using the so-called library, it took lots of workarounds to create compatible OpenAPI v3.0 specs. For example, modifying output schemas enforced us to use schema-walker tools which added lots of overhead in our scripts (Despite of compatible OpenAPI schemas in ts-oas, we added a schema-processor custom function as an option as well).
Contributions of any kind are welcome!
FAQs
Automatically generate OpenAPI specifications from opinionated Typescript types.
We found that ts-oas demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.