Swaggerをファイル分割したまま編集できるようにしてみた in Docker

以下のブログに移行しました。


[Swaggerをファイル分割しながら、編集できるものを作成しました。
![swagger-multi-file-in-docler-eyecatch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92083/363e25ff-9f3c-c1ce-e472-b19eb04ede93.jpeg)](https://blog.ryou103.com/post/swagger-multi-file-in-docker/)



<!--
# 作ったもの

swaggerファイルをpathsやcomponentsなどファイル分割して画面を確認しながら編集ができるもの

[swagger-multi-file-docker(Github)](https://github.com/RyoheiTomiyama/swagger-multi-file-docker)

<img width="1549" alt="スクリーンショット 2018-10-20 16.36.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/92083/8346d667-1f42-141d-c863-7ee7ed7c9839.png">


分割されたファイルを監視して変更があったら、swagger.ymlというファイルにまとめ、それをswagger-uiで表示する。
１ファイルにまとめるのに[swagger-merger](https://github.com/WindomZ/swagger-merger#readme)という、CLIツールを使用しました。

初回は、dockerイメージをビルド

```
$ docker-compose build
```

開発するときは、コンテナを起動するだけ

```
$ docker-compose up -d
```

あとは、http://localhost:8000 で確認しながら、作業ができます。



# なぜ作ったのか

swaggerは、デフォルトのままでもファイル分割が若干できるのだが、swagger-uiでうまく表示されなかったりなど、エラーが起こったり、使い勝手が悪いのです。
結局、１ファイルにまとめた方が良いという結果になったのだが、数千行になるファイル管理はしたくないので、ファイル分割して編集したものをマージしたいのだが調べてもでてくるのは、コマンドライン上でファイルをまとめるものばかり。だから、編集→コマンドライン→ブラウザの作業を繰り返し行わなければならない。

[multi-file-swagger](https://www.npmjs.com/package/multi-file-swagger)
[OpenAPI Spec 3.0でのSwagger Specの分割管理 - Qiita](https://qiita.com/funa1g/items/f5952e1d77de95a155ae)

swagger-uiで確認しながら、編集できるようなものが見つからなかったので、作りました。



# 仕組み

## フォルダ構造

```
docs/    # swagger-uiファイルとswagger.ymlの出力先
src/     # 編集するswaggerファイル達
 ├ index.yml
 ├ components/
 └ paths/
swagger-watch/   # ファイル監視システム
docker-compose.yml   # swagger-uiとswagger-watchのコンテナ
```

## ファイル監視

ファイル監視はこんな感じ。
[gaze](https://github.com/shama/gaze)というファイル監視モジュールを使用しています。
（本当はchokidarを使う予定だったのですが、docker内だと動かなかったので、gazeに変更）

```javascript
// swagger-watch/index.js
const { Gaze } = require('gaze');
const path = require('path');
const merger = require('swagger-merger');

function resolve_path (dir) {
  return path.join(__dirname, '..', dir);
}

function multi_file() {
  const file_path = resolve_path('./src/index.yml');
  const dest_file_path = resolve_path('./docs/swagger.yml');
  const option = {
    input: file_path,
    output: dest_file_path,
  };
  merger(option).catch(err => {
    console.error(err);
  });
}
function watch() {
  const gaze = new Gaze(resolve_path('./src/**'));
  gaze.on('error', (err) => { throw err; });
  gaze.on('all', (event, file) => {
    console.log(event, file);
    multi_file();
  });
  const restart = () => {
    gaze.close();
    watch();
  }
  gaze.on('added', (watcher) => restart());
  gaze.on('removed', (watcher) => restart());
}
watch();
```

### function watch()

src内のファイルを監視（新規ファイルの監視にも対応）

### function multi_file()

`src/index.yml`をエントリーポイントとして、`docs/swagger.yml`に出力する。
分割されたファイルのマージには、[swagger-merger](https://github.com/WindomZ/swagger-merger#readme)を利用しました。

## Dockerコンテナ

```yml
# docker-compose.yml
version: '3'
services:
  swagger-ui:
    image: swaggerapi/swagger-ui
    ports:
      - 8000:8080
    volumes:
      - ./docs:/usr/share/nginx/html
  swagger-watch:
    build: ./swagger-watch
    volumes:
      - /app/node_modules
      - ./swagger-watch:/app
      - ./src:/src
      - ./docs/swagger.yml:/docs/swagger.yml
    working_dir: /app
    command: 'node index.js'
```

### swagger-ui

swaggerが用意しているUIツールです。
出力された`docs/swagger.yml`を共有して表示させます。

<img width="1469" alt="スクリーンショット 2018-10-20 0.22.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/92083/a65bd425-2f58-27a4-4d00-1e626bdaac06.png">


### swagger-watch

ファイルを監視して、`docs/swagger.yml`を出力させるコンテナです。

`./swagger-watch`： ファイル監視システム。
`./src`： 編集するswaggerファイル
`./docs/swagger.yml`： 出力先
を共有しています。


## ファイル分割について

swaggerファイルのエントリーポイントとなる`./src/index.yml`はこちら。
pathsとcomponentsを参照先を$refで定義しています。

```yml
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  $ref: './paths/index.yml'
components:
  $ref: './components/index.yml'
```

`./paths/index.yml`や`./components/index.yml`では、さらに参照するようにしているので、schemaごとにファイル管理することなどが可能となっています。（pet.yml, pets.yml, error.yml...）


# 最後に

これで、快適にswaggerを利用することができるようになりました。
さらにswagger.ymlをdocs以下に出力するようにしたので、Githubにリポジトリを置けば、GithubPagesで公開することも可能となっています。

↓ こんな感じ
https://ryoheitomiyama.github.io/swagger-multi-file-docker/

是非利用してみてください〜。

-->