OpenAPIのYAMLをVSCodeで分割管理する

本記事は**OpenAPI3.0**を使用しています

## OpenAPIのつらいところ

APIの数が増えていくと、数千行、Exampleまで丁寧に書いている、あっという間に数万行に達してしまいます。

## 開発環境 ##

VSCodeに必要な拡張を入れましょう

### VSCodeの拡張 ###

```json:extensions.json
{
    "recommendations": [
        // OpenAPI (Swagger) Editor
        "42crunch.vscode-openapi",
        // OpenApi Designer
        "philosowaffle.openapi-designer",
        // Prettier
        "esbenp.prettier-vscode"
    ]
}
```

#### OpenAPI (Swagger) Editor ####

ID: [42crunch.vscode-openapi](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi)

- インストールしておくと`$ref`の参照先YAMLにコードジャンプできます。 APIの数が増えるとファイルが数十・数百と増えていくのコードジャンプできるのは非常に便利です

#### OpenApi Designer ####

ID: [philosowaffle.openapi-designer](https://marketplace.visualstudio.com/items?itemName=philosowaffle.openapi-designer)

- プレビュー表示する拡張
- 分割したopenapi.ymlでもプレビュー表示してくれるのが特長です
- yamlファイルを編集して保存すると、プレビューも自動更新されます(ホットリロード)
- プレビュー画面はコマンドパレットから起動 `ctrl-shft-p > OpenApi Designer: Preview`

#### Prettier ####

ID: [esbenp.prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)

- YAMLのフォーマッタ(https://prettier.io/)

### ツール ###

#### YAML結合 ####

https://github.com/APIDevTools/swagger-cli

分割されたままだと他のツールを使うときに不便なのでswagger-cliを用いて結合しています。

```sh
swagger-cli bundle -r openapi/openapi.yml -o build/openapi.json
```

出力形式はyamlとjsonどちらも対応しています

#### 静的HTML生成 ReDoc ####

https://github.com/Redocly/redoc

- 結合したopenapi.jsonから静的なHTMLを生成するツールです
- HTMLを作成するツールはいくつかあるのですが、ReDocが一番キレイで見やすいと思います
- 成果物が単一のHTMLファイルなので共有するのも簡単です。
- 
```sh
redoc-cli bundle build/openapi.json --options.menuToggle --options.pathInMiddlePanel  -o build/redoc-static.html
```

自分はオプションで以下の2つをONにしています

- `--options.menuToggle`:  左のmenuをトグルできるようにする
- `--options.pathInMiddlePanel`: 中央にAPIのエンドポイントパスを表示する

#### Swagger UI ####

ReDocではなくSwaggerUIのほうが見やすいという方は、dockerを使用してローカルにSwaggerUIをホストしましょう

```sh
docker run -p 8081:8080 -v $(pwd)/openapi:/usr/share/nginx/html/openapi -e API_URL=openapi/openapi.yml swaggerapi/swagger-ui
```

#### Mockサーバー Prism ####

https://github.com/stoplightio/prism

ドキュメント通りにAPIのMockサーバーを建てることができます。戻り値はexampleを返します。

```sh
prism mock openapi/openapi.yml
```

## ファイル分割とディレクトリ構造 ##

**横展開しやすいこと**を考えて末にたどり着いたディレクトリ構造です。

- 再利用はあまり意識しない
- 自分が編集しているAPIにのみ集中できるようにする(視界に他のAPIが入らないようにする)
- 分割のデメリットはコードジャンプで補う
- API追加・編集作業をルーチン化できるように分ける
- ディレクトリ名はキャメルケース、ファイル名はケバブケースに統一する
- openapi.ymlはエンドポイント俯瞰のためにシンプルに保つ

### 実例 ###

```text
./
 +- openapi
    |- openapi.yml
    +- components       分割したYAMLファイルの置き場
         |- errors        エラー系の戻り値の構造とExample
         |- examples      正常系の戻り値の例
         |- parameters    APIのパラメタ
         |    |- header     headerのパラメタ
         |    |- path       pathパラメタ
         |    +- query      queryStringパラメタ
         |
         |- paths         openapi.ymlのpaths
         |- requestBody   リクエストボディ(POST/PUTのBody)
         +- schemas       各APIのスキーマ
```

- `openapi`ディレクトリに全ファイルをまとめておくとdockerでmountするときに便利です。
- `openapi.yml`はエンドポイントの一覧になります。エンドポイントを俯瞰しやすくなります。
- `components`内にドキュメントの詳細を書いていきます。
- `components/paths`には各エンドポイントのGET/POST/PUT/DELETEなどの処理の記述をしていきます
- `components/schema`には戻り値の構造を記述、
- `components/exampleには戻り値の例を定義します。
- `components/errors`, `components/requestBody`, `components/parameters`は再利用を意識して管理しておきます
- `components/parameters`はheader, path, queryに分けています。これは同じパラメタ名がpathとquery両方に存在するケースがあったためです。

これは一例なので状況に応じて構造を変えましょう。どのエンドポイントが、どのコンポーネントを使っているかわかりやすくすることが重要です。

## まとめ ##

- OpenAPIはすぐに肥大化するのでファイル分割しよう
- OpenAPIを分割してもVSCodeの拡張を活用しよう
- 分割したyamlでは他のツールと連携しづらいので結合できるようしよう
- ReDocなどを使ってopenapi.jsonからHTMLを作成し共有しよう
- 保守しやすくするためにディレクトリ構造を工夫しよう