Generates a zodios (typescript http client with zod validation) from a (json/yaml) OpenAPI spec (or just make your own output template and do w/e you want with the generated schemas/endpoints/etc !)
-
can be used programmatically (do w/e you want with the computed schemas/endpoints)
-
or used as a CLI (generates a prettier .ts file with deduplicated variables when pointing to the same schema/$ref)
-
client typesafety using zodios
-
tested (using vitest) against official OpenAPI specs samples
with local install:
pnpm i -D openapi-zod-client
pnpm openapi-zod-client "./input/file.json" -o "./output/client.ts"
or directly
pnpx openapi-zod-client "./input/file.yaml" -o "./output/client.ts"
you can pass a custom handlebars template and/or a custom prettier config with something like pnpm openapi-zod-client ./example/petstore.yaml -o ./example/petstore-schemas.ts -t ./example/schemas-only.hbs -p ./example/prettier-custom.json
, there is an example here
-
You can check an example input (the petstore example when you open/reset editor.swagger.io) and output
-
there's also an example of a programmatic usage
-
or you can check the tests in the
src
folder which are mostly just inline snapshots of the outputs
input:
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
"200":
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
"201":
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
"200":
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
output:
import { Zodios } from "@zodios/core";
import { z } from "zod";
const v7LgRCMpuZ0 = z.object({ id: z.bigint(), name: z.string(), tag: z.string().optional() }).optional();
const vWZd2G8UeSs = z.array(v7LgRCMpuZ0).optional();
const v77smkx5YEB = z.object({ code: z.bigint(), message: z.string() }).optional();
const variables = {
Error: v77smkx5YEB,
Pet: v7LgRCMpuZ0,
Pets: vWZd2G8UeSs,
createPets: v77smkx5YEB,
listPets: v77smkx5YEB,
showPetById: v77smkx5YEB,
};
const endpoints = [
{
method: "get",
path: "/pets",
requestFormat: "json",
parameters: [
{
name: "limit",
type: "Query",
schema: z.bigint().optional(),
},
],
response: variables["Pets"],
},
{
method: "post",
path: "/pets",
requestFormat: "json",
response: variables["Error"],
},
{
method: "get",
path: "/pets/{petId}",
requestFormat: "json",
response: variables["Pet"],
},
] as const;
export const api = new Zodios("baseurl", endpoints);
- handle default values (output
z.default(xxx)
) - handle OA spec
format: date-time
-> outputz.date()
/preprocess
? - handle string/number constraints -> output z.
min max length email url uuid startsWith endsWith regex trim nonempty gt gte lt lte int positive nonnegative negative nonpositive multipleOf
- handle OA
prefixItems
-> outputz.tuple
- handle recursive schemas -> output
z.lazy()
- add an argument to control which response should be added (currently by status code === "200" or when there is a "default")
pnpm i && pnpm gen