
Security News
Feross on the 10 Minutes or Less Podcast: Nobody Reads the Code
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.
@himenon/openapi-typescript-code-generator
Advanced tools
OpenAPI Code Generator using TypeScript AST.
This library provides TypeScript type definitions and extracted parameters from OpenAPI v3.0.x compliant specifications. TypeScript AST is used to generate the code, which is accurately converted to TypeScript code. Since the parameters extracted from OpenAPI can be used freely, it can be used for automatic generation of API Client and Server Side code, load balancer configuration files, etc.
npm i -D @himenon/openapi-typescript-code-generator
# or
pnpm i -D @himenon/openapi-typescript-code-generator
# or
yarn add -D @himenon/openapi-typescript-code-generator
The example shown here can be cloned from the DEMO repository to see how it works.
import * as fs from "fs";
import { CodeGenerator } from "@himenon/openapi-typescript-code-generator";
const main = () => {
const codeGenerator = new CodeGenerator("your/openapi/spec.yml");
const code = codeGenerator.generateTypeDefinition();
fs.writeFileSync("client.ts", code, { encoding: "utf-8" });
};
main();
import * as fs from "fs";
import { CodeGenerator } from "@himenon/openapi-typescript-code-generator";
import * as Templates from "@himenon/openapi-typescript-code-generator/dist/templates";
import type * as Types from "@himenon/openapi-typescript-code-generator/dist/types";
const main = () => {
const codeGenerator = new CodeGenerator("your/openapi/spec.yml");
const apiClientGeneratorTemplate: Types.CodeGenerator.CustomGenerator<Templates.FunctionalApiClient.Option> = {
generator: Templates.FunctionalApiClient.generator,
option: {},
};
const code = codeGenerator.generateTypeDefinition([
codeGenerator.getAdditionalTypeDefinitionCustomCodeGenerator(),
apiClientGeneratorTemplate,
]);
fs.writeFileSync("client.ts", code, { encoding: "utf-8" });
};
main();
This library provides three types of templates
import * as Templates from "@himenon/openapi-typescript-code-generator/dist/templates";
Templates.ClassApiClient.generator;
Templates.FunctionalApiClient.generator;
Templates.CurryingFunctionalApiClient.generator;
Templates.ClassApiClient.generatorWe provide a class-based API client. Please inject the API client dependency and use it instead of constructor.
export interface RequestArgs {
httpMethod: HttpMethod;
url: string;
headers: ObjectLike | any;
requestBody?: ObjectLike | any;
requestBodyEncoding?: Record<string, Encoding>;
queryParameters?: QueryParameters | undefined;
}
export interface ApiClient<RequestOption> {
request: <T = SuccessResponses>(requestArgs: RequestArgs, options?: RequestOption) => Promise<T>;
}
export class Client<RequestOption> {
private baseUrl: string;
constructor(
private apiClient: ApiClient<RequestOption>,
baseUrl: string,
) {
this.baseUrl = baseUrl.replace(/\/$/, "");
}
public async createPublisherV2<RequestContentType extends RequestContentType$createPublisherV2>(
params: Params$createPublisherV2<RequestContentType>,
option?: RequestOption,
): Promise<Response$createPublisherV2$Status$200["application/json"]> {
const url = this.baseUrl + `/create/v2/publisher/{id}`;
const headers = {
"Content-Type": params.headers["Content-Type"],
Accept: "application/json",
};
const requestEncodings = {
"application/x-www-form-urlencoded": {
color: {
style: "form",
explode: false,
},
},
"application/json": {
color: {
style: "form",
explode: false,
},
},
};
return this.apiClient.request(
{
httpMethod: "POST",
url,
headers,
requestBody: params.requestBody,
requestBodyEncoding: requestEncodings[params.headers["Content-Type"]],
},
option,
);
}
}
Templates.FunctionalApiClient.generatorWe also provide a function-based API client that replaces the class-based API client with createClient. Please inject the API client dependency and use it.
export interface RequestArgs {
httpMethod: HttpMethod;
url: string;
headers: ObjectLike | any;
requestBody?: ObjectLike | any;
requestBodyEncoding?: Record<string, Encoding>;
queryParameters?: QueryParameters | undefined;
}
export interface ApiClient<RequestOption> {
request: <T = SuccessResponses>(requestArgs: RequestArgs, options?: RequestOption) => Promise<T>;
}
export const createClient = <RequestOption>(apiClient: ApiClient<RequestOption>, baseUrl: string) => {
const _baseUrl = baseUrl.replace(/\/$/, "");
return {
createPublisherV2: <RequestContentType extends RequestContentType$createPublisherV2>(
params: Params$createPublisherV2<RequestContentType>,
option?: RequestOption,
): Promise<Response$createPublisherV2$Status$200["application/json"]> => {
const url = _baseUrl + `/create/v2/publisher/{id}`;
const headers = {
"Content-Type": params.headers["Content-Type"],
Accept: "application/json",
};
const requestEncodings = {
"application/x-www-form-urlencoded": {
color: {
style: "form",
explode: false,
},
},
"application/json": {
color: {
style: "form",
explode: false,
},
},
};
return apiClient.request(
{
httpMethod: "POST",
url,
headers,
requestBody: params.requestBody,
requestBodyEncoding: requestEncodings[params.headers["Content-Type"]],
},
option,
);
},
};
};
Templates.CurryingFunctionalApiClient.generatorTree shaking support
We also provide a curried function-based API client that requires injection of API client for each operationId. The first function argument demands ApiClient while the second function argument demands RequestArgs. The ApiClient interface is different from the others, as it requires uri as an argument.
This is designed for use cases that utilize tree shaking.
export interface RequestArgs {
httpMethod: HttpMethod;
uri: string; // <------------------ Note that the uri
headers: ObjectLike | any;
requestBody?: ObjectLike | any;
requestBodyEncoding?: Record<string, Encoding>;
queryParameters?: QueryParameters | undefined;
}
export interface ApiClient<RequestOption> {
request: <T = SuccessResponses>(requestArgs: RequestArgs, options?: RequestOption) => Promise<T>;
}
export const createPublisherV2 =
<RequestOption>(apiClient: ApiClient<RequestOption>) =>
<RequestContentType extends RequestContentType$createPublisherV2>(
params: Params$createPublisherV2<RequestContentType>,
option?: RequestOption,
): Promise<Response$createPublisherV2$Status$200["application/json"]> => {
const uri = `/create/v2/publisher/{id}`;
const headers = {
"Content-Type": params.headers["Content-Type"],
Accept: "application/json",
};
const requestEncodings = {
"application/x-www-form-urlencoded": {
color: {
style: "form",
explode: false,
},
},
"application/json": {
color: {
style: "form",
explode: false,
},
},
};
return apiClient.request(
{
httpMethod: "POST",
uri,
headers,
requestBody: params.requestBody,
requestBodyEncoding: requestEncodings[params.headers["Content-Type"]],
},
option,
);
};
import * as fs from "fs";
import { CodeGenerator } from "@himenon/openapi-typescript-code-generator";
import * as Templates from "@himenon/openapi-typescript-code-generator/dist/templates";
import type * as Types from "@himenon/openapi-typescript-code-generator/dist/types";
const main = () => {
const codeGenerator = new CodeGenerator("your/openapi/spec.yml");
const apiClientGeneratorTemplate: Types.CodeGenerator.CustomGenerator<Templates.FunctionalApiClient.Option> = {
generator: Templates.FunctionalApiClient.generator,
option: {},
};
const typeDefCode = codeGenerator.generateTypeDefinition();
const apiClientCode = codeGenerator.generateCode([
{
generator: () => {
return [`import { Schemas, Responses } from "./types";`];
},
},
codeGenerator.getAdditionalTypeDefinitionCustomCodeGenerator(),
apiClientGeneratorTemplate,
]);
fs.writeFileSync("types.ts", typeDefCode, { encoding: "utf-8" });
fs.writeFileSync("apiClient.ts", apiClientCode, { encoding: "utf-8" });
};
main();
The examples in this section can be used in the following ways
import * as fs from "fs";
import { CodeGenerator } from "@himenon/openapi-typescript-code-generator";
import type * as Types from "@himenon/openapi-typescript-code-generator/dist/types";
/** Write the definition of the Code Template here. */
const customGenerator: Types.CodeGenerator.CustomGenerator<{}> = {
/** .... */
};
const codeGenerator = new CodeGenerator("your/openapi/spec.yml");
const code = codeGenerator.generateCode([customGenerator]);
fs.writeFileSync("output/file/name", code, { encoding: "utf-8" });
A self-defined code generator can return an array of string.
import * as Types from "@himenon/openapi-typescript-code-generator/dist/types";
interface Option {
showLog?: boolean;
}
const generator: Types.CodeGenerator.GenerateFunction<Option> = (payload: Types.CodeGenerator.Params[], option): string[] => {
if (option && option.showLog) {
console.log("show log message");
}
return ["Hello world"];
};
const customGenerator: Types.CodeGenerator.CustomGenerator<Option> = {
generator: generator,
option: {},
};
The self-defined code generator can accept parameters extracted from OpenAPI Schema. See Type definitions for available parameters.
import * as Types from "@himenon/openapi-typescript-code-generator/dist/types";
interface Option {}
const generator: Types.CodeGenerator.GenerateFunction<Option> = (payload: Types.CodeGenerator.Params[], option): string[] => {
return payload.map(params => {
return `function ${params.operationId}() { console.log("${params.comment}") }`;
});
};
const customGenerator: Types.CodeGenerator.CustomGenerator<Option> = {
generator: generator,
option: {},
};
Convert a Data Type with the following format to any type definition.
components:
schemas:
Binary:
type: string
format: binary
IntOrString:
type: string
format: int-or-string
AandB:
type: string
format: A-and-B
The option to convert the Data Type Format to an arbitrary type definition is defined as follows.
import { CodeGenerator, Option } from "@himenon/openapi-typescript-code-generator";
const option: Option = {
convertOption: {
formatConversions: [
{
selector: {
format: "binary",
},
output: {
type: ["Blob"],
},
},
{
selector: {
format: "int-or-string",
},
output: {
type: ["number", "string"],
},
},
{
selector: {
format: "A-and-B",
},
output: {
type: ["A", "B"],
multiType: "allOf",
},
},
],
},
};
const codeGenerator = new CodeGenerator(inputFilename, option);
The typedef generated by this will look like this
export namespace Schemas {
export type Binary = Blob;
export type IntOrString = number | string;
export type AandB = A & B;
}
You can extend your code using the API of TypeScript AST. You can directly use the API of TypeScript AST or use the wrapper API of TypeScript AST provided by this library.
import * as Types from "@himenon/openapi-typescript-code-generator/dist/types";
import { TsGenerator } from "@himenon/openapi-typescript-code-generator/dist/api";
interface Option {}
const factory = TsGenerator.Factory.create();
const generator: Types.CodeGenerator.GenerateFunction<Option> = (
payload: Types.CodeGenerator.Params[],
option,
): Types.CodeGenerator.IntermediateCode[] => {
return payload.map(params => {
return factory.InterfaceDeclaration.create({
export: true,
name: params.functionName,
members: [],
});
});
};
const customGenerator: Types.CodeGenerator.CustomGenerator<Option> = {
generator: generator,
option: {},
};
import { CodeGenerator } from "@himenon/openapi-typescript-code-generator";
Performs validation of the input OpenAPI Schema.
Generates code that converts OpenAPI Schema to TypeScript type definitions.
You can specify several of your own code generators, and the generators can use parameters extracted from OpenAPI Schema.
It internally performs the conversion of an array of string or ts.Statement as a string.
For example, creating a generator in units of file divisions increases the reusability of the generator.
It provides parameters extracted from OpenAPI Schema.
This is a type definition file for Templates.FunctionalApiClient. The reason it is not included in generateTypeDefinition is that you may not use the type definition generated by this function depending on your usage.
※ The reason it is not included in generateTypeDefinition is that you may not use the type definitions generated by this function depending on your application.
import { TsGenerator } from "@himenon/openapi-typescript-code-generator/dist/api";
This is a wrapper API for the TypeScript AST used internally. It is subject to change without notice.
import { OpenApiTools } from "@himenon/openapi-typescript-code-generator/dist/api";
OpenApiTools.ParserThis is the API for parsing OpenAPI Schema. It is subject to change without notice.
There is a limitation on the directory structure supported.
To simplify implementation when converting directory structures to TypeScript namespaces, Remote References using $ref should only be defined in the following directory structures.
If you want to extend it, please fork this repository and do it yourself.
spec.yml // entry file
components/
headers/
parameters/
pathItems/
requestBodies/
responses/
schemas/
paths/
$ref: http://.... Currently not supported. We hope to support it in the future.
First of all, thank you for your interest. When converting from the API specification to TypeScript code, resolving reference relationships can be particularly challenging, and there may not be enough test cases. Adding test cases is a very powerful support for stabilizing the behavior, so please report any bugs you find that are behaving strangely. Also, the basic design concepts of this repository can be found below. If you want to make changes that do not follow these concepts, please fork and extend them. If your changes are in line with the design concept, please submit a pull request or issue!
.js)git clone https://github.com/Himenon/openapi-typescript-code-generator.git
cd openapi-typescript-code-generator
pnpm i
#### your change
pnpm build
pnpm run test:code:gen
pnpm run update:snapshot # if you changed
pnpm run test
TypeScript AST
@himenon/openapi-typescript-code-generator, MIT
Validation Design
FAQs
OpenAPI Code Generator using TypeScript AST.
The npm package @himenon/openapi-typescript-code-generator receives a total of 2,957 weekly downloads. As such, @himenon/openapi-typescript-code-generator popularity was classified as popular.
We found that @himenon/openapi-typescript-code-generator 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
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

Research
/Security News
Campaign of 108 extensions harvests identities, steals sessions, and adds backdoors to browsers, all tied to the same C2 infrastructure.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.