FastAPIを使ってOpenAPI仕様書と、TypeScriptクライアントを自動生成する
FastAPIを使うと色々便利そうだなとあらためて認識して触ってたのでメモしておきます。
FastAPI → OpenAPI仕様書
FastAPIはPythonでのWebAPI開発が簡単にできるフレームワークです。
Pythonの型ヒントをもとにデータ型のバリデーションもしてくれて、簡潔なコードでAPI開発ができます。
from fastapi import FastAPI from typing import Literal app = FastAPI() Animal = Literal["cat", "dog", "bird"] @app.get("/favorite-animal") async def favorite(name: Animal) -> str: return f"{name}s are cute!"
FastAPIの便利機能の一つが、ソースコードからOpenAPIによる仕様書を自動生成してくれる点です。
これにより仕様書を自分で書く必要がなくなります。
OpenAPI → TypeScriptのクライアント
フロントエンド側でAPIを呼び出すコードをTypeScriptで書く場合もOpenAPIがあると役立ちます。
OpenAPI TypeScript
OpenAPI TypeScript を使うと、APIのメソッドの入出力の型定義ファイルを生成できます。
インストール
npm i -D openapi-typescript typescript
tsconfig.json も追加します。
{ "compilerOptions": { "module": "ESNext", "moduleResolution": "Bundler", "noUncheckedIndexedAccess": true } }
型定義ファイルの生成
次のコマンドで型定義ファイルを生成できます。生成されるのは.d.tsファイル1つだけです。
npx openapi-typescript ./path/to/my/openapi.json -o ./path/to/my/schema.d.ts
openapi-fetch
OpenAPI TypeScriptはfetchやSWRやTanStack Quaryのラッパーの生成機能もあります。
npm i openapi-fetch
import createClient from "openapi-fetch"; import type { paths } from "./my-schema"; // 生成したd.tsファイル const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" }); const { data, error } = await client.GET("/blogposts/{post_id}", { params: { path: { post_id: "123" } }, });
非常に便利です。
@hey-api/openapi-ts
@hey-api/openapi-ts はOpenAPI TypeScriptよりも明示的にクライアントコードを生成するパッケージです。
https://github.com/hey-api/openapi-ts
まだ発展途上のようですが、頻繁にアップデートされています。
次のコマンドでデモを実行することができます。
npx @hey-api/openapi-ts \ -i https://get.heyapi.dev/hey-api/backend \ -o src/client
こんな感じでたくさんコードが生成されます。
src
└── client
├── client
│ ├── client.ts
│ ├── index.ts
│ ├── types.ts
│ └── utils.ts
├── client.gen.ts
├── core
│ ├── auth.ts
│ ├── bodySerializer.ts
│ ├── params.ts
│ ├── pathSerializer.ts
│ └── types.ts
├── index.ts
├── sdk.gen.ts
└── types.gen.ts
ただ、少し使ってみたところ、シンプルなAPIに対してでも多量のコードが生成され、認証がないAPIについても認証についてのコードが生成されるなど、個人的にはよくわからない挙動があったりで使いにくく感じました (理解が深まれば問題ないのかもしれませんが、学習コストが高そう)
OpenAPI → テスト(余談)
ちなみに、OpenAPIから property-based testing(PBT;仕様書通りの入出力ができるかのテスト)ができる Schemathesis というパッケージも存在します。
導入がとても簡単で、コマンドから実行したり
schemathesis run https://your-api.com/openapi.json
pytestで実行するスクリプトを作ったり
import schemathesis schema = schemathesis.openapi.from_url("https://your-api.com/openapi.json") @schema.parametrize() def test_api(case): case.call_and_validate() # Finds bugs automatically
Github Actionsに3行足すだけで実行できたりします
- uses: schemathesis/action@v2 with: schema: "https://your-api.com/openapi.json"
ただ、FastAPIから作成したOpenAPI仕様書だと両者の間に差異は無いはずなので、多くの場合でPBTはパスします。そのため有効性はあんまり高くない気がします…。
私が簡単に試した感じでは、Pythonにおいてはboolがintのsubclassであるのに対してSchemathesisのテストではboolとintを明確に区別することを期待していた関係でそこだけFailしてました。