🎽

【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