🤖
生成AIの力を借りてFastAPIからいい感じの型定義を生成する
よくある FastAPI からの型自動生成のやつ。
出力全般ほぼ Claude 頼みだが、間に挟まる主観的な判断の一部まで任せられたのが面白い + 今後も使いそうなのでメモ。
フロー整理
- FastAPI から OpenAPI の JSON ファイルを取得
- (任意)生成後に認識しづらい箇所を LLM で修正
- 加工後の openapi.json +
openapi-generator-cli
で型定義ファイルを生成 - クライアント側でコール
必要に応じて 2,3 をループ
コードメモ
2. LLM による修正フロー
スキーマによるところがかなり大きいので、あまり詳細を乗せず方針メインで記述。
というよりこの 「読みにくい」箇所の判断もおおかた LLM に任せている。
(どのパスにも重複している文字、除去しても判別に困らない文字、…など方向性を与えて置換する処理を書いてもらっている)
基本方針
- パス名から関数名を生成
- 不要なパスの除去(
/api
や/v1, /v2
など) - 大文字/小文字変換
- キャメルケースに変換
- ...
- 不要なパスの除去(
-
openapi-generator-cli
に対応するための修正-
operationId
の付与
-
generateOpsIds.cjs
function removePath(str, reg) {
return str.replace(reg, "")
}
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
function camelCase(str) {
return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
}
function uncapitalize(str) {
return str.charAt(0).toLowerCase() + str.slice(1)
}
...
3. 実行ファイル例
ここまでの処理を $ npm run generate
で実行してくれるようなスクリプトを作成(してもらう)。
下記は一部パスだけ書き換えてあるが、基本生成物そのまま。
generate-api-client.sh
#!/bin/bash
# エラーが発生したら即座に終了
set -e
# スクリプトのディレクトリを取得
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
# 一時ファイルのパス
TEMP_OPENAPI_JSON="$PROJECT_ROOT/openapi.json"
TEMP_OPENAPI_WITH_IDS_JSON="$PROJECT_ROOT/openapi_with_operation_ids.json"
echo "Fetching OpenAPI JSON..."
# FASTAPI_URL -> 実際のURLに置き換え
curl -o $TEMP_OPENAPI_JSON FASTAPI_URL/openapi.json || { echo "Failed to fetch OpenAPI JSON"; exit 1; }
# echo "Generating operation IDs..."
node $SCRIPT_DIR/generateOpsIds.cjs || { echo "Failed to generate operation IDs"; exit 1; }
echo "Generating API client..."
openapi-generator-cli generate -i $TEMP_OPENAPI_WITH_IDS_JSON -g typescript-axios -o $PROJECT_ROOT/src/api --skip-validate-spec || { echo "Failed to generate API client"; exit 1; }
echo "Cleaning up temporary files..."
rm $TEMP_OPENAPI_JSON $TEMP_OPENAPI_WITH_IDS_JSON
echo "API client generation completed successfully."
package.json
"scripts": {
...
"generate": "bash path/to/generate-api-client.sh"
},
4. クライアント側で利用
型補完が効いたデータフェッチが可能(嬉しい)
// apiInstance.ts
import {
XXXXXApi,
YYYYYApi,
Configuration
} from "@/api" // $PROJECT_ROOT/src/api と対応
const apiConfig = new Configuration({
basePath: API_BASE_URL,
})
const xxxxApi = new XXXXXApi(apiConfig)
const yyyyApi = new YYYYYApi(apiConfig)
// useXXXX.ts
// - call sample1
await xxxxApi.postXXXX()
// - call sample2
await yyyyApi.postYYYY({
arg1,
arg2,
arg3,
...
})
Discussion