- Notifications
You must be signed in to change notification settings - Fork16
TypeScript code generator via OpenAPI scheme.
License
Himenon/openapi-typescript-code-generator
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
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# orpnpm i -D @himenon/openapi-typescript-code-generator# oryarn add -D @himenon/openapi-typescript-code-generator
The example shown here can be cloned from theDEMO repository to see how it works.
import*asfsfrom"fs";import{CodeGenerator}from"@himenon/openapi-typescript-code-generator";constmain=()=>{constcodeGenerator=newCodeGenerator("your/openapi/spec.yml");constcode=codeGenerator.generateTypeDefinition();fs.writeFileSync("client.ts",code,{encoding:"utf-8"});};main();
import*asfsfrom"fs";import{CodeGenerator}from"@himenon/openapi-typescript-code-generator";import*asTemplatesfrom"@himenon/openapi-typescript-code-generator/dist/templates";importtype*asTypesfrom"@himenon/openapi-typescript-code-generator/dist/types";constmain=()=>{constcodeGenerator=newCodeGenerator("your/openapi/spec.yml");constapiClientGeneratorTemplate:Types.CodeGenerator.CustomGenerator<Templates.FunctionalApiClient.Option>={generator:Templates.FunctionalApiClient.generator,option:{},};constcode=codeGenerator.generateTypeDefinition([codeGenerator.getAdditionalTypeDefinitionCustomCodeGenerator(),apiClientGeneratorTemplate,]);fs.writeFileSync("client.ts",code,{encoding:"utf-8"});};main();
This library provides three types of templates
import*asTemplatesfrom"@himenon/openapi-typescript-code-generator/dist/templates";Templates.ClassApiClient.generator;Templates.FunctionalApiClient.generator;Templates.CurryingFunctionalApiClient.generator;
We provide a class-based API client. Please inject the API client dependency and use it instead ofconstructor
.
exportinterfaceRequestArgs{httpMethod:HttpMethod;url:string;headers:ObjectLike|any;requestBody?:ObjectLike|any;requestBodyEncoding?:Record<string,Encoding>;queryParameters?:QueryParameters|undefined;}exportinterfaceApiClient<RequestOption>{request:<T=SuccessResponses>(requestArgs:RequestArgs,options?:RequestOption)=>Promise<T>;}exportclassClient<RequestOption>{privatebaseUrl:string;constructor(privateapiClient:ApiClient<RequestOption>,baseUrl:string,){this.baseUrl=baseUrl.replace(/\/$/,"");}publicasynccreatePublisherV2<RequestContentTypeextendsRequestContentType$createPublisherV2>(params:Params$createPublisherV2<RequestContentType>,option?:RequestOption,):Promise<Response$createPublisherV2$Status$200["application/json"]>{consturl=this.baseUrl+`/create/v2/publisher/{id}`;constheaders={"Content-Type":params.headers["Content-Type"],Accept:"application/json",};constrequestEncodings={"application/x-www-form-urlencoded":{color:{style:"form",explode:false,},},"application/json":{color:{style:"form",explode:false,},},};returnthis.apiClient.request({httpMethod:"POST", url, headers,requestBody:params.requestBody,requestBodyEncoding:requestEncodings[params.headers["Content-Type"]],},option,);}}
We also provide a function-based API client that replaces the class-based API client withcreateClient
. Please inject the API client dependency and use it.
exportinterfaceRequestArgs{httpMethod:HttpMethod;url:string;headers:ObjectLike|any;requestBody?:ObjectLike|any;requestBodyEncoding?:Record<string,Encoding>;queryParameters?:QueryParameters|undefined;}exportinterfaceApiClient<RequestOption>{request:<T=SuccessResponses>(requestArgs:RequestArgs,options?:RequestOption)=>Promise<T>;}exportconstcreateClient=<RequestOption>(apiClient:ApiClient<RequestOption>,baseUrl:string)=>{const_baseUrl=baseUrl.replace(/\/$/,"");return{createPublisherV2:<RequestContentTypeextendsRequestContentType$createPublisherV2>(params:Params$createPublisherV2<RequestContentType>,option?:RequestOption,):Promise<Response$createPublisherV2$Status$200["application/json"]>=>{consturl=_baseUrl+`/create/v2/publisher/{id}`;constheaders={"Content-Type":params.headers["Content-Type"],Accept:"application/json",};constrequestEncodings={"application/x-www-form-urlencoded":{color:{style:"form",explode:false,},},"application/json":{color:{style:"form",explode:false,},},};returnapiClient.request({httpMethod:"POST", url, headers,requestBody:params.requestBody,requestBodyEncoding:requestEncodings[params.headers["Content-Type"]],},option,);},};};
Tree shaking support
We also provide a curried function-based API client that requires injection of API client for eachoperationId
. The first function argument demandsApiClient
while the second function argument demandsRequestArgs
. TheApiClient
interface is different from the others, as it requiresuri
as an argument.
This is designed for use cases that utilizetree shaking.
exportinterfaceRequestArgs{httpMethod:HttpMethod;uri:string;// <------------------ Note that the uriheaders:ObjectLike|any;requestBody?:ObjectLike|any;requestBodyEncoding?:Record<string,Encoding>;queryParameters?:QueryParameters|undefined;}exportinterfaceApiClient<RequestOption>{request:<T=SuccessResponses>(requestArgs:RequestArgs,options?:RequestOption)=>Promise<T>;}exportconstcreatePublisherV2=<RequestOption>(apiClient:ApiClient<RequestOption>)=><RequestContentTypeextendsRequestContentType$createPublisherV2>(params:Params$createPublisherV2<RequestContentType>,option?:RequestOption,):Promise<Response$createPublisherV2$Status$200["application/json"]>=>{consturi=`/create/v2/publisher/{id}`;constheaders={"Content-Type":params.headers["Content-Type"],Accept:"application/json",};constrequestEncodings={"application/x-www-form-urlencoded":{color:{style:"form",explode:false,},},"application/json":{color:{style:"form",explode:false,},},};returnapiClient.request({httpMethod:"POST", uri, headers,requestBody:params.requestBody,requestBodyEncoding:requestEncodings[params.headers["Content-Type"]],},option,);};
import*asfsfrom"fs";import{CodeGenerator}from"@himenon/openapi-typescript-code-generator";import*asTemplatesfrom"@himenon/openapi-typescript-code-generator/dist/templates";importtype*asTypesfrom"@himenon/openapi-typescript-code-generator/dist/types";constmain=()=>{constcodeGenerator=newCodeGenerator("your/openapi/spec.yml");constapiClientGeneratorTemplate:Types.CodeGenerator.CustomGenerator<Templates.FunctionalApiClient.Option>={generator:Templates.FunctionalApiClient.generator,option:{},};consttypeDefCode=codeGenerator.generateTypeDefinition();constapiClientCode=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*asfsfrom"fs";import{CodeGenerator}from"@himenon/openapi-typescript-code-generator";importtype*asTypesfrom"@himenon/openapi-typescript-code-generator/dist/types";/** Write the definition of the Code Template here. */constcustomGenerator:Types.CodeGenerator.CustomGenerator<{}>={/** .... */};constcodeGenerator=newCodeGenerator("your/openapi/spec.yml");constcode=codeGenerator.generateCode([customGenerator]);fs.writeFileSync("output/file/name",code,{encoding:"utf-8"});
A self-defined code generator can return an array ofstring
.
import*asTypesfrom"@himenon/openapi-typescript-code-generator/dist/types";interfaceOption{showLog?:boolean;}constgenerator:Types.CodeGenerator.GenerateFunction<Option>=(payload:Types.CodeGenerator.Params[],option):string[]=>{if(option&&option.showLog){console.log("show log message");}return["Hello world"];};constcustomGenerator: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*asTypesfrom"@himenon/openapi-typescript-code-generator/dist/types";interfaceOption{}constgenerator:Types.CodeGenerator.GenerateFunction<Option>=(payload:Types.CodeGenerator.Params[],option):string[]=>{returnpayload.map(params=>{return`function${params.operationId}() { console.log("${params.comment}") }`;});};constcustomGenerator:Types.CodeGenerator.CustomGenerator<Option>={generator:generator,option:{},};
Convert a Data Type with the followingformat
to any type definition.
components:schemas:Binary:type:stringformat:binaryIntOrString:type:stringformat:int-or-stringAandB:type:stringformat: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";constoption: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",},},],},};constcodeGenerator=newCodeGenerator(inputFilename,option);
The typedef generated by this will look like this
exportnamespaceSchemas{exporttypeBinary=Blob;exporttypeIntOrString=number|string;exporttypeAandB=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*asTypesfrom"@himenon/openapi-typescript-code-generator/dist/types";import{TsGenerator}from"@himenon/openapi-typescript-code-generator/dist/api";interfaceOption{}constfactory=TsGenerator.Factory.create();constgenerator:Types.CodeGenerator.GenerateFunction<Option>=(payload:Types.CodeGenerator.Params[],option,):Types.CodeGenerator.IntermediateCode[]=>{returnpayload.map(params=>{returnfactory.InterfaceDeclaration.create({export:true,name:params.functionName,members:[],});});};constcustomGenerator: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 ofstring
orts.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 forTemplates.FunctionalApiClient
. The reason it is not included ingenerateTypeDefinition
is that you may not use the type definition generated by this function depending on your usage.
※ The reason it is not included ingenerateTypeDefinition
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.Parser
This 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 filecomponents/ 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!
- Be typedef first.
- Typedefs should not contain any entities (file size should be 0 when typedefs are converted to
.js
) - The directory structure should be mapped to the typedef structure.
- No dependency on any API client library.
- Can be extended by TypeScript AST.
- Conform to the OpenAPI specification.
- It should be a single file to maintain portability.
git clone https://github.com/Himenon/openapi-typescript-code-generator.gitcd openapi-typescript-code-generatorpnpm i#### your changepnpm buildpnpm run test:code:genpnpm run update:snapshot# if you changedpnpm runtest
TypeScript AST
@himenon/openapi-typescript-code-generator, MIT
Validation Design
- Copyright (c) 2018 Kogo Software LLC -https://github.com/kogosoftwarellc/open-api/tree/master/packages/openapi-schema-validator#readme
About
TypeScript code generator via OpenAPI scheme.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Contributors10
Uh oh!
There was an error while loading.Please reload this page.