TkDodo / openapi-zod-client

Generate a zodios (typescript http client with zod validation) from a (json/yaml) OpenAPI spec

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

openapi-zod-client

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

Usage

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

Example

tl;dr

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);

TODO

  • handle default values (output z.default(xxx))
  • handle OA spec format: date-time -> output z.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 -> output z.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")

Contributing:

  • pnpm i && pnpm gen

About

Generate a zodios (typescript http client with zod validation) from a (json/yaml) OpenAPI spec


Languages

Language:TypeScript 98.9%Language:Handlebars 1.0%Language:JavaScript 0.1%