Inspired by pont.
When I first had the idea for automatically generate typescript from json schema, I found pont
. But it was in an early unstable stage, and I do not like the output code style, and the worst is it can not process some bad defined openapi doc type.
So after some trying and compare some other tools, I deside to make a new wheel -- ts-gear
.
Ts-gear parse openapi doc and then generate your service code by one command.
The service code includes request functions and data type definitions.
Ts-gear works with various kind of none standard openapi definition doc with high compatibility.
With this tool all openapi doc definition and request methods would be converted to typescript request functions automatically, and when the doc updates, just rerun tsg
, typescript will report any type updates.
If you have tried pont
, OpenAPI Generator
, swagger-codegen
or oazapfts
and some other tools, but got errors, just try this.
These features make ts-gear
different with pont
, OpenAPI Generator
, swagger-codegen
or oazapfts
and some others, if you know some thing better, please let me know.
- high compatibility with various kind of openapi doc definition.
Most other code generators depends on the standard openapi spec doc.
But in real world, especially in my case, all doc has some definition errors.
-
Many
$ref
does not has correspondingdefinition
. -
Many unregular charators occur in names and properties those can not be used as variable or type name, such as "输出参数".
-
Too hard to parse generic types as
ReplyVO<PageVO<List>>
. -
Many javascript key word conflict such as
Map
,Set
.
ts-gear
try the best to solve all thses issues.
-
Each request is an independ function, best for TREE SHAKE.
-
Try the best to generate generic types, if fail, you can update config
keepGeneric: false
to generate your service that at least can work. -
Use prettier to output service files, and the prettier format can be configured.
-
Use
ts-morph
for most ast operation, so most error occur in code generating step, not runtime step. -
Automatically Support OpenAPI Specification v2 and v3, no need to configure.
A good example is a better doc.
Clone and run to see how ts-gear
works.
See https://github.com/superwf/ts-gear-example
npm install ts-gear -D
// or by yarn
yarn add ts-gear -D
tsg -i
generate an initial configuration file src/tsg.config.ts
.
🐾 Why in src
directory ?
Most cases src
will be included in typescript system by tsconfig.json
. Put it in src will confirm it will be automatically taken over by typescript.
Skip this step if there is already a configuration file.
// default use "src/tsg.config.ts"
npx tsg
// or assign another config file
npx tsg -c other_dir/tsg.config.ts
// or if only need update one project, use -p for the project name
npx tsg -p pet
The service directory structure should look like as below.
▾ src/
tsg.config.ts
▾ service/
▾ pet/
definition.ts
request.ts
index.ts
[more directory information](#Directory information)
After the command line operation, use the generated file in service
directory.
For example, in src/store/pet.ts
import { getPetPetId } from '../../service/pet'
export const findPet = (petId: number) => {
return getPetPetId({
path: {
petId,
}
}).then(pet => {
console.log(pet)
// pet will be the instance of Pet, it has Pet properties.
return pet
})
}
process openapi doc steps as shown below.
-
read user config file.
-
filter projects by name if there are command line params.
-
fetch each project swagger doc.
-
translate if transate engine is assigned.
-
format unregular charators in $ref and definitions.
-
process generic type names.
-
assemble requests and definitions to global map variables.
-
prepare project dest directory.
-
generate and write enum and definitions.
-
generate and write request.
-
write project directory "index.ts".
-
Here are many languages support. If the swagger doc is defined generally standard, this tool is enough.
-
oazapfts use typescript native api to generate ts file, but non-standard swagge doc generated code could not work out of box.
tsg.config.ts
example
import { Project, fetchRequester, axiosRequester } from 'ts-gear'
const projects: Project[] = [
{ ... }
]
export default projects
Option name | type | required | default | description |
---|---|---|---|---|
name | string | true | your project name | |
dest | string | true | parent directory of project, relative to tsg.config.ts example: 'service' |
|
source | string | true | swagger doc url remote url or local json file |
|
fetchApiDocOption | RequestInit | (() => RequestInit | Promise<RequestInit>) | false | request remote openapi doc parameters for fetch |
|
apiFilter | RegExp | (({pathname: string, httpMethod: HttpMethod}) => boolean) | false | some project mix too mach useless api use this option could avoid those to be written in your api file |
|
importRequesterStatement | string | true | example: import { requester } from "./myCustomRequester" , make sure provide a requester , see Requester |
|
preferClass | boolean | false | false | generate class rather than class |
withHost | boolean | false | false | request with swagger doc host in when invoke the requester func |
withBasePath | boolean | false | false | request with swagger doc basePath in when invoke the requester func |
keepGeneric | boolean | false | true | try parse available generic type |
translationEngine | 'baidu' | 'google' | false | translate special charators in swagger doc definitions | |
translationSerial | boolean | false | true | translate words serially |
translateIntervalPerWord | number | false | 2000 | works when translateSerial is true when too much translate words will definitely result translate request error add interval time between translate unit=milliseconds |
translationDebug | boolean | false | false | show translate debug info |
shouldGenerateMock | boolean | false | generate mock data switch | |
shouldExportRequestOptionType | boolean | true | true | should export request function option types |
shouldExportResponseType | boolean | true | true | should export request function response types |
prettierConfig | Options | false | prettier v2 options | |
generateRequestFunctionName | (arg: GenerateRequestFunctionNameParameter) => string | false | generate request function name method | |
generateRequestFunction | please read the source | false | use this option to generate your function all by your self | |
transformJS | boolean | false | false | should generate js file |
useCache | boolean | false | false | use cache |
EOL | string | false | false | custom EOF |
nullableFalseAsRequired | boolean | false | false | nullable as required |
simplifyRequestOption | boolean | false | false | simple type of request option, remove query or body level |
stripBodyPropWhenOnlyOneBodyProp | boolean | false | false | when request prop only has one prop, and this props is a schema, then remove this level prop. |
requestOptionUnionType | string | false | undefined | add an union type to request parameter type, read more from src/type , this is conflict with simplifyRequestOption and will make simplifyRequestOption not work |
shouldForceSkipRequestHeaderOption | boolean | false | false | should force set the header request option to optional |
hooks | object | false | undefined | see Hooks |
requester
is a request function made by your condition.
ts-gear
has tow example, fetch
and axios
. Read the code in ts-gear
for reference, copy and modify to compatible with your own project. The example code is not out of box.
fetch
example, write a file insrc/requester.ts
import generateRequester from 'ts-gear/lib/requester/fetch'
export const requester = generateRequester({
... // some general fetch init config use for each request
})
Use it in your tsg.config.ts
{
importRequesterStatement: 'import { requester } from "../../requester"'
}
axios
example, write a file insrc/requester.ts
import generateRequester from 'ts-gear/lib/requester/axios'
const instance = axios.create({
... // some general axios config use for each request
})
export const requester = generateRequester(instance)
Use it in your tsg.config.ts
, same as fetch
.
{
importRequesterStatement: 'import { requester } from "../../requester"'
}
Note: Important, the requester function must be an async function, or return a promise.
-
The
definition.ts
is generated by thedefinitions
part ofswagger spec
, includes all the base data structures. -
The
request.ts
is generated by thepaths
part ofswagger spec
,each request function naming rule ishttp request + api path
,for example:
"paths": {
"/pet": {
"post": { // will generate `postPet` function
...
},
},
"/pet/findByTags": {
"get": { // will generate 'getPetFindByTags' function
...
},
},
"/pet/{petId}": {
"get": { // will generate 'getPetPetId' function
...
},
},
- The
index.ts
is entry file fordefinition.ts
andrequest.ts
.
Each request function parameter type and return type are mapped to the swagger definition.
If you prefer to use your owne request way, you can only use the definition.ts
for data type.
Use hooks to inject custom logic between code generate steps.
-
beforeWriteTs: (o: { project: Project } & PrepareToWrite) => Promise
-
afterWriteTs: (o: { project: Project } & PrepareToWrite) => Promise
This tool only has a few kind fixtures for dev and test. Issues are welcomed when you meet some errors, remember to provide your swagger doc for testing fixtures.