Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7
Typed, single-file API client generator for OpenAPI schemas with minimal dependencies and maximum type safety.
License
vladkens/apigen-ts
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
- Generates ready to use
ApiClient
with types (usingfetch
) - Single output file, minimal third-party code
- Loads schemas from JSON / YAML, locally and remote
- Ability to customize
fetch
with your custom function - Automatic formating with Prettier
- Can parse dates from date-time format (
--parse-dates
flag) - Support OpenAPI v2, v3, v3.1
- Can be used with npx as well
npm install apigen-ts --save-dev
yarn add -D apigen-ts
# From filenpx apigen-ts ./openapi.json ./api-client.ts# From urlnpx apigen-ts https://petstore3.swagger.io/api/v3/openapi.json ./api-client.ts# From protected urlnpx apigen-ts https://secret-api.example.com ./api-client.ts -H"x-api-key: secret-key"
Runnpx apigen-ts --help
for more options. Examples of generated clientshere.
import{ApiClient}from"./api-client"constapi=newApiClient({baseUrl:"https://example.com/api",headers:{Authorization:"secret-token"},})
// GET /pet/{petId}awaitapi.pet.getPetById(1)// -> Pet// GET /pet/findByStatus?status=soldawaitapi.pet.findPetsByStatus({status:"sold"})// -> Pets[]// PUT /user/{username}; second arg body with type Userawaitapi.user.updateUser("username",{firstName:"John"})
const{ token}=awaitapi.auth.login({ usename, password})api.Config.headers={Authorization:token}awaitapi.protectedRoute.get()// here authenticated
npx apigen-ts ./openapi.json ./api-client.ts --parse-dates
constpet=awaitapi.pet.getPetById(1)constcreatedAt:Date=pet.createdAt// date parsed from string with format=date-time
You can generate string literal union instead of native enums in case you want to run in Node.js environment withtype-stripping. To achive this pass--inline-enums
command line argument or useinlineEnums: true
in Node.js API.
npx apigen-ts ./openapi.json ./api-client.ts --inline-enums
This will generate:
typeMyEnum="OptionA"|"OptionB"// instead ofenumMyEnum={OptionA="OptionA",OptionB="OptionB"}
An exception will be thrown for all unsuccessful return codes.
try{constpet=awaitapi.pet.getPetById(404)}catch(e){console.log(e)// parse error depend of your domain model, e is awaited response.json()}
Also you can define custom function to parse error:
classMyClientextendsApiClient{asyncParseError(rep:Response){// do what you wantreturn{code:"API_ERROR"}}}try{constapi=newMyClient()constpet=awaitapi.pet.getPetById(404)}catch(e){console.log(e)// e is { code: "API_ERROR" }}
You can modify how the endpoint url is created. By defaultURL constructor used to resolve endpoint url like:new URL(path, baseUrl)
which has specific resolvingrules. E.g.:
new URL("/v2/cats", "https://example.com/v1/") // -> https://example.com/v2/cats
new URL("v2/cats", "https://example.com/v1/") // -> https://example.com/v1/v2/cats
If you want to have custom endpoint url resolving rules, you can overridePrepareFetchUrl
method. For more details seeissue.
classMyClientextendsApiClient{PrepareFetchUrl(path:string){returnnewURL(`${this.Config.baseUrl}/${path}`.replace(/\/{2,}/g,"/"))}}constapi=newMyClient({baseUrl:"https://example.com/v1"})// will call: https://example.com/v1/pet/ instead of https://example.com/pet/constpet=awaitapi.pet.getPetById(404)
Create file likeapigen.mjs
with content:
import{apigen}from"apigen-ts"awaitapigen({source:"https://petstore3.swagger.io/api/v3/openapi.json",output:"./api-client.ts",// everything below is optionalname:"MyApiClient",// default "ApiClient"parseDates:true,// default falseinlineEnums:false,// default false, use string literal union instead of enumheaders:{"x-api-key":"secret-key"},// Custom HTTP headers to use when fetching schemaresolveName(ctx,op,proposal){// proposal is [string, string] which represents module.funcNameif(proposal[0]==="users")return// will use default proposalconst[a,b]=op.name.split("/").slice(3,5)// eg. /api/v1/store/items/searchreturn[a,`${op.method}_${b}`]// [store, 'get_items'] -> apiClient.store.get_items()},})
Then run with:node apigen.mjs
By defaultapigen-ts
generates noisy method names when used with FastAPI. This can be fixed bycustom resolving for operations ids.
fromfastapiimportFastAPIfromfastapi.routingimportAPIRouteapp=FastAPI()# add your routes heredefupdate_operation_ids(app:FastAPI)->None:forrouteinapp.routes:ifisinstance(route,APIRoute):ns=route.tags[0]ifroute.tagselse"general"route.operation_id=f"{ns}_{route.name}".lower()# this function should be after all routes addedupdate_operation_ids(app)
Note: If you want FastAPI to be added as preset, open PR please.
- openapi-typescript-codegen (npm): no single file mode#1263
- openapi-typescript (npm): low level api; no named types export to use in client code
- openapi-generator-cli (npm): wrapper around java lib
- swagger-typescript-api (npm): complicated configuration; user-api breaking changes between versions
About
Typed, single-file API client generator for OpenAPI schemas with minimal dependencies and maximum type safety.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Packages0
Uh oh!
There was an error while loading.Please reload this page.