OpenAPI Generator を使って typescript-fetch のソースコードを生成してみる
OpenAPI でスキーマを書くとクライアントサイドのソースコードが自動生成できると聞いたのでやってみた。
スキーマ記述
色々とエディタもあるようだが今回は Swagger Editor を使ってスキーマを記述する。
で書けるが、私は手元で書こうと思い Docker を使った。
https://github.com/swagger-api/swagger-editor#docker
に Docker での起動について記載がある。
docker pull swaggerapi/swagger-editor
docker run -d -p 80:8080 swaggerapi/swagger-editor
デフォルトだと OpenAPI 2 系のサンプルが起動するので、エディタ上部メニューの
Edit > Convert to OpenAPI 3
で 3 系にコンバートしてからサンプルを書き換えるといいと思う。
OpenAPI Generator でクライアントサイドコード生成
ローカルにインストールするのが面倒なので、こちらも Docker を使う。
https://github.com/OpenAPITools/openapi-generator#16---docker
に記載の通り、基本コマンドは
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
-i <OpenAPI のスキーマファイル> \
-g <対象言語> \
-o <出力先>
である。
Docker に慣れている人は間違わないと思うが、スキーマファイルと出力先はカレントディレクトリを /local に置き換えて記述したパスになるので注意。
私は今回 typescript-fetch で生成しようと思ったので、下記のドキュメントを参考にしつつ
https://openapi-generator.tech/docs/generators/typescript-fetch
次のコマンドでソースコードを生成した。
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
-i /local/src/lib/openapi.yaml \
-g typescript-fetch \
-o /local/src/lib/api \
--additional-properties=modelPropertyNaming=snake_case,supportsES6=true,typescriptThreePlus=true
追加したオプションは次の通り。
- modelPropertyNaming=snake_case
- もともと書いていたコードでスネークケースにしていたので。
- supportES6=true
- 現時点で必要かどうかわからないがとりあえず true にしておいた。
- typesciptThreePlus=true
- これを true にしないと『“GlobalFetch” が無い』みたいなエラーになる。ドキュメントによると現在のデフォルト値は true らしいが、この記事を書いた日時点での Docker での生成ではデフォルト値 false だった。
こうすると指定したディレクトリにソースコードが生成される。
生成したソースコードを使う
さて自動生成したはいいが使い方は書いていない。
もしかしたらどこかに書いてあるのかもしれないが見つからない。
下記の記事を参考にしたが、オプションによって微妙に違うかもしれないので、自分でもソースコードを読んで使い方を把握する必要がある。
OpenAPI Generator typescript-fetch を使う
私が今回作った API の名前は BlogsApi だったので、インスタンス生成はこうなる。API のパスは環境変数を設定しているのでそれを呼び出している。
import { BlogsApi, Configuration } from 'src/lib/api/index'
const conf = new Configuration({
basePath: process.env.REACT_APP_API_BASE_URL,
})
const blogsApi = new BlogsApi(conf)
あとは生成したソースコードを見つつ API 呼び出しメソッドを呼べばいいが……。
呼び出した結果、TypeScript のエラーとなって使えなかった。
該当部分のソースは
(json['data'] as Array<any>).map(JsonToModel)
みたいな感じで、出ていたエラーは『json.data.map is not a function』であった。
私が実装したバックエンドの API が間違っているのかと思ったが、私は既存実装にて json[‘data’] にあたる部分を配列として扱い map 処理も行っているし、レスポンスをコンソールに書き出しても json[‘data’] は確かに配列に見える。
自分の TypeScript/JavaScript 力ではこの該当部分のコードでなぜエラーが起こるのかわからなかった。
そのため、使えそうなら既存実装を置き換えようと思ったのだが、結局生成したコードを使用するには至らなかった。
以上