💧

【orval】OpenAPIから型とhookを自動生成する 【SWR】

2023/11/20に公開

Overview

Generate typescript models
Generate HTTP Calls
Generate Mocks with MSW

The default generated client use axios and can be used by your favourite Javascript framework like Angular, React or Vue. It's just a function who takes an instance of axios in argument and return an object where each key is a function who setup a call HTTP.

Orval can also generate the following client:
React query with axios

ざっくり

  • 型、HTTP コール関数、モックを生成してくれる。
  • react-query の hook も生成してくれる

Installation

インストール

npm i orval -D
installation

スクリプト追加

package.jsonに以下を追加

{
  "scripts": {
    "generate:types": "orval --config ./orval.config.ts"
  }
}

orval のセットアップ

  • API 定義の変更時に自動的に input を行いたいが今回は、手動で swagger から json をダウンロードする
  • mode: split
    • tagert(types/api)に対して、api.ts,msw.ts,schemas.ts3 分割で出力する
      • 結構量あったので分けてみた
  • hooksで生成後に prettier,eslint を走らせる
    • プロジェクトの設定に合わせるため
  • overrideについては後述
import { defineConfig } from "orval";

export default defineConfig({
  receipt: {
    input: {
      target: "./swagger.json",
    },
    output: {
      target: "./src/types/api/",
      mock: true,
      client: "swr",
      mode: "split", //出力形式
      clean: true,
      override: {
        //TODO: 現状生成されたhooksが認証ヘッダーを考慮できていないため使えない
        //生成後にaxiosのレスポンスの型がanyと推論されてしまう
        //https://orval.dev/guides/custom-axios
        //https://v4.orval.dev/guides/react-query#how-to-add-headers
        mutator: {
          path: "./src/libs/customInstance.ts",
        },
      },
    },
    hooks: {
      afterAllFilesWrite: [
        'prettier --write "./src/**/*.{ts,tsx}"',
        "eslint src --ext ts --ext tsx --fix",
      ],
    },
  },
});

実行

npm run generate:typesを実行することで型や hooks が出力されます 🥳

override

成果物について

  • overrideに追記を行うことで、生成される hooks をカスタマイズできる。
  • 私が参画しているプロジェクトではリクエストの際にheadertokenを載せる必要があるが、生成される hook には現状 header の考慮がない
    • というか大体そう(?)
  • 生成される hook の response の型の any が含まれている
    • axiosのインスタンスで型定義をジェネリクスで受け取れるようにカスタマイズする必要がある

対応方針

下記 2 つを行うことで上記の問題は解決出来そう。
既に私が参画したチームでは API 連携が進んでいたのと、今回は一旦型定義のみを参照したかったため断念しました(インスタンスを変更するためデグレのリスクがかなり大きいので、、、)

↑ はまた別の機会で対応出来ればします!

Discussion