Node + OpenAPI + ReDocでおしゃれなAPI開発環境を作る

# はじめに

こんにちは。夜に見てくれている方は、こんばんは。
どうも @little555 です。
夏季休暇なうでヒャッハー！しております。

この記事は株式会社富士通システムズウェブテクノロジーが企画する[いのべこ夏休みアドベントカレンダー 2020](https://qiita.com/jugemsan/items/5761773308fb1df0c23a)の20日目の記事です。
※毎回参加させていただき感謝の限りです。ありがとうございます！！

とりあえず本題に入る前に大切な**お約束**です。
`本記事の掲載内容は私自身の見解であり、所属する組織を代表するものではありません。`



# 背景

API作りたいけど、管理とか横展開がめんどくさいなぁ。
横展開用のドキュメントとか作りたくないなぁ。。。
いい感じに開発に組み込めないかなぁ。。。

そんな人が対象読者です。

そんなときはOpenAPI(Swagger)です。
YamlやJson形式でAPIの仕様を下記のような感じで定義できます。
<img width="700px" alt="Swagger Editor.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286339/1f3a4e02-757f-53db-9b62-c5d6c490ac5e.png">
参考：[Swagger Editor](https://editor.swagger.io)

でもこう、なんていうか。。。
ちょっと古い印象を受けませんか？

そこでいいツールないかなぁーと探していて、であったのがこのツール。
そう[**ReDoc**](https://github.com/Redocly/redoc)です

下記のようなおしゃれ度の高いAPI一覧を作ることができます。
<img width="700px" alt="ReDoc.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286339/1ad6f17f-58d5-fadc-adbc-fd357e4ee28c.png">
参考：[ReDoc Interactive Demo](https://redocly.github.io/redoc/)

おしゃれですね。自分のデザインセンスではとても作れません。
では、さっそく取り掛かっていきましょう。




# OpenAPI

とりあえず、まずは適当なOpenAPIを用意します。
公式のサンプルを取得するのが手っ取り早いでしょう。
[OpenAPI\-Specification/petstore\.yaml at master · OAI/OpenAPI\-Specification · GitHub](https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore.yaml)

DLしたら、ローカルで動かせるように一部書き換えましょう

```diff:./spec/petstore.yaml
servers:
- - url: http://petstore.swagger.io/v1/pets
+ - url: http://localhost:3000/v1
```




# ソースコード生成

次にソースコードを生成してみましょう。
[@openapitools/openapi\-generator\-cli](https://www.npmjs.com/package/@openapitools/openapi-generator-cli)はYamlからソースコードを生成してくれます。
素晴らしいですね。
さっそくインストールします。

```bash
$ npm init
$ npm i -D @openapitools/openapi-generator-cli
```

※いろんなプロジェクトで使いたい場合は`-g`オプションでインストールするのが推奨です。

次に`@openapitools/openapi-generator-cli`を利用し、ソースコードを生成します。

```json:package.json
  "scripts": {
    "validate": "openapi-generator validate -i ./spec/petstore.yaml", 
    "generate": "openapi-generator generate -g nodejs-express-server -i ./spec/petstore.yaml -o ./src"
  },
```

```bash
$ npm run generate
```

すると`src`配下にnode一式が生成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286339/825fafb7-7666-1d91-1268-b1d1de81729e.png)
起動するために階層を移動して操作したくないので、起動できるようにしておきましょう。
※src配下にも`package.json`がいるのでそれを利用する。

```diff:package.json
  "scripts": {
+     "clean": "rm -rf src",
+     "server": "cd src && npm run prestart && npm run start",
    "validate": "openapi-generator validate -i ./spec/petstore.yaml",
    "generate": "openapi-generator generate -g nodejs-express-server -i ./spec/petstore.yaml -o ./src"
  },
```

```bash
$ npm run server
```

起動後下記URLにアクセスするとAPI一覧が動かせます。
http://localhost:3000/api-doc/

<img width="700px" alt="LocalOpenAPI.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286339/23064559-f127-9c7c-7209-882a42d2f667.png">



# ReDoc

## 簡易表示

ReDocの素晴らしいところは`JavaScript`と`YAML`を読み込むだけで起動できることです。
※ただし、`ローカルのYAMLファイル`はReDocの利用するJavaScriptのロジックの関係で読み込めません。

サーバーを起動したのち、下記HTMLファイルを作成し開いてみてください。

```html
<!DOCTYPE html>
<html>
  <head>
    <title>ReDoc</title>
    <!-- needed for adaptive design -->
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">

    <!--
    ReDoc doesn't change outer page styles
    -->
    <style>
      body {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <redoc spec-url='http://localhost:3000/openapi'></redoc>
    <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
  </body>
</html>
```

<img width="700px" alt="LocalRedoc.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286339/a56eb4bc-d69f-d238-439b-adceaaf3daa8.png">

これだけです。これだけで表示できるのです。
すごい！


## expressで表示できるようにする

せっかくなので、自動生成されるソースコードにReDocを表示するための機構を組み込みます。
そのためには、生成されるソースの元となるテンプレートファイルを取得＆修正します。

まず、テンプレート元となるファイルを取得します。
https://github.com/OpenAPITools/openapi-generator/tree/v4.3.1/modules/openapi-generator/src/main/resources/nodejs-express-server
取得するのは次の2ファイルです。

- package.mustache
- expressServer.mustache

取得したら、次のように追記します。

```diff:./spec/template/package.mustache
  "dependencies": {
    ...
+    "redoc-express": "^1.0.0",
  },
```

```diff:./spec/template/expressServer.mustache
...
const config = require('./config');
+ const redoc = require('redoc-express');

...
    this.app.use('/api-doc', swaggerUI.serve, swaggerUI.setup(this.schema));
+     this.app.use('/redoc', redoc({title: '{{projectName}}', specUrl: '/openapi'}));
```

これでテンプレートの準備は整いました。

次は、変換時にテンプレートを読み込むように設定しましょう。

```diff:package.json
  "scripts": {
    "clean": "rm -rf src",
    "server": "cd src && npm run prestart && npm run start",
    "validate": "openapi-generator validate -i ./spec/petstore.yaml",
-     "generate": "openapi-generator generate -g nodejs-express-server -i ./spec/petstore.yaml -o ./src"
+     "generate": "openapi-generator generate -g nodejs-express-server -i ./spec/petstore.yaml -o ./src -t ./spec/template"
  },
```

再度変換して起動するとReDocが表示されます。

```bash
$ npm run generate
$ npm run server
```

http://localhost:3000/api-doc/
<img width="700px" alt="LocalRedoc.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286339/a56eb4bc-d69f-d238-439b-adceaaf3daa8.png">

## おまけ：単一のHTMLでRedocを表示したい

横展開していくと、「サーバーの起動方法がわからない」「参照しようにもネットワークが断絶してる」など、APIドキュメントを共有しにくい相手もいるでしょう。

そんな時に役に立つのが[**redoc\-cli**](https://www.npmjs.com/package/redoc-cli)です。

HTMLに全部内包して、単一のHTMLで表示できるようにしてくれる優れものです。

使い方は下記の通り

```bash
# 依存ライブラリのインストール
$ npm i react react-dom mobx@^4.2.0 styled-components core-js -D
# インストール
$ npm i redoc redoc-cli -D
```

起動用スクリプトの定義。

```diff:package.json
  "scripts": {
    "clean": "rm -rf src",
    "server": "cd src && npm run prestart && npm run start",
    "validate": "openapi-generator validate -i ./spec/petstore.yaml",
    "generate": "openapi-generator generate -g nodejs-express-server -i ./spec/petstore.yaml -o ./src -t ./spec/template",
    "create-doc" "redoc-cli bundle ./spec/petstore.yaml"
  },
```

実行！！！

```bash
$ npm run create-doc
```

そうすると`redoc-static.html`が生成されます。
これ一つでどこでも起動できる！便利！

# おわりに

とりあえず、言いたいことは**ReDocすごくいいよ！**に尽きます。
自分の大好きなチャットツールであるMattermostの[公式APIリファレンス](https://api.mattermost.com/)などもReDocで作られています。

結構使われていそうなので、みなさんも何かAPIを作る機会があればぜひ使ってみてください。

きれいなデザインはモチベを上げてくれます！

以上 @little555 でした。

# 参考資料

非常に参考になりました。ありがとうございます。

- [OpenAPI Generator \+ TypeScript で始める自動生成の型に守られた豊かなクライアント生活 \| GiFT（ギフト）株式会社](https://gift-tech.co.jp/articles/openapi-generator-typescript/)
- [ReDoc \- Angular な静的 Webページを生成できる REST API ドキュメンテーションツール \- Witch on the Other Shore](https://iktakahiro.hatenablog.com/entry/2017/06/09/090000)