[multi-file-swagger] Swaggerファイルを分割してAPIドキュメントを管理する

# Intro
今まではAPIドキュメントの記述に `APIBlueprint` を使用していましたが今更ながら Swagger デビューしたのでナレッジの備忘録として記述しています :writing_hand:


# Swaggerとは
`Swagger`は [OAI(Open API Initiative)](https://www.openapis.org/) が採用しているREST APIを構築するためのオープンソースのフレームワークです。

OAI はマイクロソフトやGoogleなどによって結成され、Swaggerを用いてAPIの標準化を推し進めています。

競合するサービスやフレームワークも様々ありますが、下記にもあるように様々な会社・団体が推進していることから、Swaggerがメジャーではないかと思います（※参考程度の図）
![スクリーンショット 2019-06-19 16.23.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38342/e60702b2-bba4-9940-ea28-c9acb63d61af.png)

# SwaggerでAPIドキュメントを作成する
下記に記述したような `yaml` や `json` を[SwaggerEditor](https://editor.swagger.io/) で確認すると自動的にAPIドキュメントとして描画してくれます。

```yaml
openapi: 3.0.0
info:
  version: 1.0.0
  title: Swagger sample
  description: swagger sample description
paths:
  /users:
    get:
      summary: Usersを取得するAPIです。
      responses:
        '200':
          description: HTTPステータスコード200と以下の情報を含むJSONオブジェクトを返します。
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                    example: 1234567
        '400':
          description: HTTPステータスコード400と以下の情報を含むJSONオブジェクトを返します。
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: invalid_request
                  error_description:
                    type: string
                    example: アクセストークンが指定されていません
```

# 個人的に困った点
一定規模のドキュメントを書いていると想像できるように swagger ファイルが肥大化しがちです。案の定、段々と可読性が悪くなってきて辛くなってきました。

ベストプラクティスか分かりませんが、今回紹介するような形で Swagger ファイルを小さい単位に分割して管理することもできるようです。

# 分割して記述する

さきほどの swaggerファイルを分割して記述してみます。
[$ref](https://swagger.io/docs/specification/using-ref/) プロパティを記述することで、swaggerファイルの参照ができます。

`index.yaml` を中心にセクション単位で swaggerファイルを分割しています。

```
├── index.yaml
├── info
│   └── index.yaml
└── paths
    └── index.yaml
    └── users.yaml
```

```index.yaml
openapi: "3.0.0"
info:
  $ref: ./info/index.yaml
paths:
  $ref: ./paths/index.yaml
```

```info/index.yaml
version: 1.0.0
title: Swagger sample
description: swagger sample description
```

```paths/index.yaml
/users:
  $ref: ./users.yaml
```

```paths/users.yaml
get:
  summary: ユーザーを取得するAPIです。
  responses:
    '200':
      description: HTTPステータスコード200と以下の情報を含むJSONオブジェクトを返します。
      content:
        application/json:
          schema:
            type: object
            properties:
              user_id:
                type: string
                example: 1234567
    '400':
      description: HTTPステータスコード400と以下の情報を含むJSONオブジェクトを返します。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: invalid_request
              error_description:
                type: string
                example: アクセストークンが指定されていません
```

# 分割したら最後はくっつける
小分けにしたswaggerファイルを最終的に一つのファイルに結合する必要があります。

今回は [multi-file-swagger](https://www.npmjs.com/package/multi-file-swagger) を利用してswaggerファイルを1つに結合します。

## Usage
詳細は以下を参照ください。
https://www.npmjs.com/package/multi-file-swagger

以下を実行すると `compiled.yaml` という結合したファイルが出来上がります。

```
npm install -g multi-file-swagger
multi-file-swagger -o yaml index.yaml > compiled.yaml
```

[SwaggerEditor](https://editor.swagger.io/) で、さきほど作成した `compiled.yaml` を読み込むと元通りのAPIドキュメントの出来上がりです。

<img width="1421" alt="スクリーンショット 2019-07-13 19.50.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38342/886e7eca-c4e2-cebf-7c6e-d7b81a56dc5b.png">

# まとめ・感想
このような手法で管理することで Swaggerの肥大化を防ぐことができそうです。
一方このアプローチだと、記述して結合して確認の繰り返しが煩雑になりそうです。

もうちょっと上手く管理できないかと悶々してるので、ベストプラクティスあれば教えてください :relaxed:

あでゅ