main tags rss
github x

apigen-ts – Simple TypeScript API Client Generator

OpenAPI / Swagger is a good way to describe API contracts between backend / frontend or different services. Nowadays frontend is almost always TypeScript + some framework (React, Vue, Angular, etc). Backend in turn can be in NodeJS (and then in principle you can share contracts with code reuse), or in another language (e.g. Python / Go / Scala / Rust) and then code reuse and API synchronization becomes a problem.

OpenAPI can solve this problem through codegen – backend should qualitatively describe the available API methods and data types, after that you can use the client generation utility and get ready typed TypeScript code.

OpenAPI has a standard tool for such generation, but it has a number of problems:

In JavaScript ecosystem it is common to use npm (or yarn / pnpm – whatever you like more) as a package manager. But the point is the same: packages are written in JavaScript, installed from one place, versioned.

In npm you can find several alternative apigen utilities written in TypeScript which provides a better development experience. I used one of those too (swagger-typescript-api), until they changed interfaces a few times and I had to fix my several projects. I tried to find an alternative in npm, but all available generators (as of late 2023) also have their own problems: generate a lot of files, are difficult to configure, break compatibility between versions, require to install additional packages.

Meet apigen-ts

I have a couple of projects in NestJS / FastAPI in support mode, for which I just need a stable API client generation utility that is simple and won't change often. So I wrote my own TypeScript HTTP API generation package from Swagger specification – apigen-ts.

Originally I wrote apigen-ts for personal projects, but then I share it to my friends and they also started to use apigen-ts in their projects. Now I want to share it with the community, maybe it will be useful for someone too. So library features:

Usage

Usage is as simple as possible and is divided into two steps: generating a client from specification (local file or remote url; yaml or json), using the generated typed client in the app.

Generation of an arbitrary client can be performed by command:

npx -y apigen-ts https://petstore3.swagger.io/api/v3/openapi.json ./api-client.ts

Or you can install apigen-ts as a dev dependency (npm i -D apigen-ts) and create a task to generate the client in package.json:

{
  "name": "my-frontend",
  "scripts": {
    "apigen": "apigen-ts http://127.0.0.1:3000/docs-json ./api-client.ts --parse-dates && tsc --noEmit"
  }
}

Then use: npm run apigen or yarn apigen.

Generated file contains a client class named ApiClient and TypeScript types used in API endpoints. Next you can use them in app code in the following way:

import { ApiClient, Pet } from "./api-client";

const api = new ApiClient({
  baseUrl: "https://example.com",
  headers: { Authorization: "secret-token" },
});

// GET https://example.com/pet/findByStatus?status=sold
await api.pet.findPetsByStatus({ status: "sold" }); // -> Pet[]

Generator tries to create method names in format like {domain}.{operation}. The types used in Swagger spec can be imported directly into code (in example above Pet is generated type). This approach makes it easy to track changes in contract and fix the application code where types are updated or methods are changed (of course if you describe your Swagger well). Just run new api generation and check frontend code for errors afterwards with TypeScript.

Also apigen-ts works well in CI pipelines, when on new commits to the backend part you run frontend api client generation and check code compatibility.

The generated client uses native fetch API (does not require additional packages) and can be used both in browser and NodeJS environment. If you use prettier in your project, the generated client will be automatically formatted according to project settings.

More configuration options and customization abilities can be in readme.

Conclusion

Backend ↔ frontend (or backend ↔ backend) communication is monotonous and repetitive work from project to project. Do not waste time and effort on manual writing of api clients. Instead use simple tools to automate process and keep code quality.


You can support this project with a star ⭐️ or leave an issue / feature request on Github page.