Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/vladkens/apigen-ts
Typed HTTP client generator as single file without extra dependencies from OpenAPI schema
https://github.com/vladkens/apigen-ts
codegen http-client openapi openapi2 openapi3 openapi31 swagger typescript
Last synced: 5 days ago
JSON representation
Typed HTTP client generator as single file without extra dependencies from OpenAPI schema
- Host: GitHub
- URL: https://github.com/vladkens/apigen-ts
- Owner: vladkens
- License: mit
- Created: 2023-11-30T22:25:17.000Z (12 months ago)
- Default Branch: main
- Last Pushed: 2024-11-09T17:27:32.000Z (6 days ago)
- Last Synced: 2024-11-09T18:26:52.203Z (6 days ago)
- Topics: codegen, http-client, openapi, openapi2, openapi3, openapi31, swagger, typescript
- Language: TypeScript
- Homepage: https://npm.im/apigen-ts
- Size: 238 KB
- Stars: 29
- Watchers: 4
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
- Codeowners: .github/codeowners
Awesome Lists containing this project
README
# apigen-ts
[](https://npmjs.org/package/apigen-ts)
[](https://packagephobia.now.sh/result?p=apigen-ts)
[](https://npmjs.org/package/apigen-ts)
[](https://github.com/vladkens/apigen-ts/blob/main/LICENSE)
[](https://buymeacoffee.com/vladkens)
Simple typed OpenAPI client generator## Features
- Generates ready to use `ApiClient` with types (using `fetch`)
- 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## Install
```sh
yarn install -D apigen-ts
```## Usage
### 1. Generate
```sh
# From url
yarn apigen-ts https://petstore3.swagger.io/api/v3/openapi.json ./api-client.ts# From file
yarn apigen-ts ./openapi.json ./api-client.ts
```Run `yarn apigen-ts --help` for more options. Examples of generated clients [here](./examples/).
### 2. Import
```ts
import { ApiClient } from "./api-client"const api = new ApiClient({
baseUrl: "https://example.com/api",
headers: { Authorization: "secret-token" },
})
```### 3. Use
```ts
// GET /pet/{petId}
await api.pet.getPetById(1) // -> Pet// GET /pet/findByStatus?status=sold
await api.pet.findPetsByStatus({ status: "sold" }) // -> Pets[]// PUT /user/{username}; second arg body with type User
await api.user.updateUser("username", { firstName: "John" })
```## Advanced
### Login flow
```ts
const { token } = await api.auth.login({ usename, password })
api.Config.headers = { Authorization: token }await api.protectedRoute.get() // here authenticated
```### Automatic date parsing
```sh
yarn apigen-ts ./openapi.json ./api-client.ts --parse-dates
``````ts
const pet = await api.pet.getPetById(1)
const createdAt: Date = pet.createdAt // date parsed from string with format=date-time
```### Errors handling
An exception will be thrown for all unsuccessful return codes.
```ts
try {
const pet = await api.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:
```ts
class MyClient extends ApiClient {
async ParseError(rep: Response) {
// do what you want
return { code: "API_ERROR" }
}
}try {
const api = new MyClient()
const pet = await api.pet.getPetById(404)
} catch (e) {
console.log(e) // e is { code: "API_ERROR" }
}
```### Base url resolving
You can modify how the endpoint url is created. By default [URL constructor](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) used to resolve endpoint url like: `new URL(path, baseUrl)` which has specific resolving [rules](https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references). 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 override `PrepareFetchUrl` method. For more details see [issue](https://github.com/vladkens/apigen-ts/issues/2).
```ts
class MyClient extends ApiClient {
PrepareFetchUrl(path: string) {
return new URL(`${this.Config.baseUrl}/${path}`.replace(/\/{2,}/g, "/"))
}
}const api = new MyClient({ baseUrl: "https://example.com/v1" })
// will call: https://example.com/v1/pet/ instead of https://example.com/pet/
const pet = await api.pet.getPetById(404)
```### Node.js API
Create file like `apigen.mjs` with content:
```js
import { apigen } from "apigen-ts"await apigen({
source: "https://petstore3.swagger.io/api/v3/openapi.json",
output: "./api-client.ts",
// everything below is optional
name: "MyApiClient", // default "ApiClient"
parseDates: true, // default false
resolveName(ctx, op, proposal) {
// proposal is [string, string] which represents module.funcName
if (proposal[0] === "users") return // will use default proposalconst [a, b] = op.name.split("/").slice(3, 5) // eg. /api/v1/store/items/search
return [a, `${op.method}_${b}`] // [store, 'get_items'] -> apiClient.store.get_items()
},
})
```Then run with: `node apigen.mjs`
## Usage with different backend frameworks
### FastAPI
By default `apigen-ts` generates noisy method names when used with FastAPI. This can be fixed by [custom resolving](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#using-the-path-operation-function-name-as-the-operationid) for operations ids.
```py
from fastapi import FastAPI
from fastapi.routing import APIRouteapp = FastAPI()
# add your routes here
def update_operation_ids(app: FastAPI) -> None:
for route in app.routes:
if isinstance(route, APIRoute):
ns = route.tags[0] if route.tags else "general"
route.operation_id = f"{ns}_{route.name}".lower()# this function should be after all routes added
update_operation_ids(app)
```_Note: If you want FastAPI to be added as preset, open PR please._
## Compare
- [openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen) ([npm](https://www.npmjs.com/package/openapi-typescript-codegen)): no single file mode [#1263](https://github.com/ferdikoomen/openapi-typescript-codegen/issues/1263#issuecomment-1502890838)
- [openapi-typescript](https://github.com/drwpow/openapi-typescript) ([npm](https://www.npmjs.com/package/openapi-typescript)): low level api; no named types export to use in client code
- [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli) ([npm](https://www.npmjs.com/package/@openapitools/openapi-generator-cli)): wrapper around java lib
- [swagger-typescript-api](https://github.com/acacode/swagger-typescript-api) ([npm](https://www.npmjs.com/package/swagger-typescript-api)): complicated configuration; user-api breaking changes between versions## Development
- https://ts-ast-viewer.com
- https://jsonschemalint.com
- https://redocly.github.io/redoc/
- https://swagger.io/docs/specification/basic-structure/