[[orval]]を使って、[[OpenAPI Specification]]から[[Zod]]の[[TypeScript]]スキーマコードを自動生成する方法。
## 前提条件
- [[Bun]] v1.1.6
## Bunのプロジェクト作成
```console
mkdir orval-sample
cd orval-sample
bun init . -y
```
## インストール
[[orval]]を[[devDependencies]]としてインストール。[[Zod]]は通常の[[dependencies]]として。
```console
bun add --dev orval
bun add zod
```
## yamlファイル作成
[[Swagger Editor]]の[サンプル](https://editor.swagger.io/)をそのまま拝借する。`spec.yaml`として作成。
```yaml
openapi: 3.0.0
info:
title: ReqRes API
description: Fake data CRUD API
version: "1"
servers:
- url: https://reqres.in/api
components:
schemas:
User:
type: object
properties:
id:
type: integer
email:
type: string
first_name:
type: string
last_name:
type: string
avatar:
type: string
required: ["id"]
paths:
/users:
get:
summary: Fetches a user list
parameters:
- in: query
name: page
schema:
type: integer
- in: query
name: per_page
schema:
type: integer
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
page:
type: integer
per_page:
type: integer
total:
type: integer
total_pages:
type: integer
data:
type: array
items:
$ref: '#/components/schemas/User'
```
## 設定ファイルの作成
`orval.config.ts`を作成。
```ts
import { defineConfig } from "orval";
export default defineConfig({
petstore: {
output: {
client: "zod",
mode: "single",
target: "./zod",
},
input: {
target: "./spec.yaml",
},
},
});
```
## 実行
`zod`ディレクトリを作成。
```console
mkdir zod
```
そして実行。
```console
bun x orval
```
## 結果確認
`zod/reqResAPI.ts`が作成されている。
```ts
/**
* Generated by orval v6.28.2 🍺
* Do not edit manually.
* ReqRes API
* Fake data CRUD API
* OpenAPI spec version: 1
*/
import {
z as zod
} from 'zod'
/**
* @summary Fetches a user list
*/
export const getUsersQueryParams = zod.object({
"page": zod.number().optional(),
"per_page": zod.number().optional()
})
export const getUsersResponse = zod.object({
"page": zod.number().optional(),
"per_page": zod.number().optional(),
"total": zod.number().optional(),
"total_pages": zod.number().optional(),
"data": zod.array(zod.object({
"id": zod.number(),
"email": zod.string().optional(),
"first_name": zod.string().optional(),
"last_name": zod.string().optional(),
"avatar": zod.string().optional()
})).optional()
})
```