CLIアプリをJSON APIとしてデプロイする

[![https://gyazo.com/304c28e7e55f9506374121bbe6de5364](https://i.gyazo.com/304c28e7e55f9506374121bbe6de5364.png)](https://gyazo.com/304c28e7e55f9506374121bbe6de5364)

## console.logだけでAPIを構築する

さて、百聞一見にしかずなので、console.logのみでAPIを構築していきましょう。
とりあえず、--nameでユーザ名が渡されたらそのユーザのプロダクトが配列で返ってくるようなCLIアプリを書いてみます。

```
$ mkdir cli-app-demo
$ cd cli-app-demo
$ yarn init -y
$ touch cli.js
```

コマンドラインパーサをインストールしましょう。
substack製のminimistの方が多機能でユーザも多いですが、軽量なのでmriもおすすめです。

```
$ yarn add mri // or minimist
```

cli.js

```js
'use strict'
const parse = require('mri') // or require('minimist')

// node cli.js --name tj
const { name } = parse(process.argv.slice(2))

// 適当なJSON
const jsers = {
  tj: ['express', 'koa', 'mocha', 'stylus', 'co'],
  sindersorhus: ['ava', 'chalk', 'xo', 'yaomen'],
  rauchg: ['socket.io', 'next.js'],
  kittens: ['babel', 'yarn'],
  gaearon: ['redux', 'creaet-react-app'],
  substack: ['browserify', 'tape'],
}

console.log(jsers[name] || jsers)
```

```sh
$ node cli.js --name tj
[ 'express', 'koa', 'mocha', 'stylus', 'co' ]

$ chmod +x cli.js
$ cli.js --name kittens
[ 'babel', 'yarn' ]
```

よさそうです。
それにしてもtjはやばい。
さて、準備は整ったのでAPIサーバへと変換しましょう。

といっても、`cli-to-api`を叩くだけです。

```
$ yarn add cli-to-api
$ yarn run cli-to-api cli.js -o server.js

$ node server.js
listening on 3000
```

```
$ curl localhost:3000?name=tj
["express","koa","mocha","stylus","co"]
```

グレート！
CLIツールを書いているつもりがAPIサーバが完成しました。


<div name="2816" id="2816" class="graf graf--mixtapeEmbed graf-after--p"><a href="https://github.com/akameco/cli-to-api" data-href="https://github.com/akameco/cli-to-api" class="markup--anchor markup--mixtapeEmbed-anchor" title="https://github.com/akameco/cli-to-api" rel="nofollow"><strong class="markup--strong markup--mixtapeEmbed-strong">akameco/cli-to-api</strong><br><em class="markup--em markup--mixtapeEmbed-em">cli-to-api - transform cli to JSON API Server</em>github.com</a><a href="https://github.com/akameco/cli-to-api" class="js-mixtapeImage mixtapeImage u-ignoreBlock" data-media-id="f63a7a57ace4e8e574dc0c7b8e628292" data-thumbnail-img-id="0*SBKt9ei6-1xJZUK0." style="background-image: url(https://cdn-images-1.medium.com/fit/c/160/160/0*SBKt9ei6-1xJZUK0.);"></a></div>


クエリなしのシンプルな例やfsを使って外部ファイルを読み込むサンプルがあるので、確認してみてください。あと、よかったらスターください。


## デプロイ
よくこういう状況があります。

> 「今から3分以内にこのクエリでこんなjsonを返すAPIをつくって公開して。時間厳守ね。」

こんなときは、upを使って秒でデプロイしましょう。

<a href="https://github.com/apex/up" data-href="https://github.com/apex/up" class="markup--anchor markup--mixtapeEmbed-anchor" title="https://github.com/apex/up" rel="nofollow"><strong class="markup--strong markup--mixtapeEmbed-strong">apex/up</strong><br><em class="markup--em markup--mixtapeEmbed-em">up - Deploy infinitely scalable serverless apps, apis, and sites in seconds.</em>github.com</a>

upはtj製のサーバーレス構築ツールです。
up.jsonを用意してupと叩けばアプリケーションがAWS Lambdaにデプロイされ、一瞬で全世界にAPIが公開されます。
初回は構成があるので20秒ぐらいかかりますが、以降は5秒ぐらいでデプロイできるので最高です。
100万リクエストまで無料なので50個ぐらい雑なAPIたててるけど今のところ無料で使えているので、こういう感じのAPIはどんどんAWS Lambdaにデプロイすればいいと思います。

さて、up.jsonの作成ですが、touch-altを使い時短します。
これはtouchで新規ファイルを作成する際、テンプレートが登録されているファイルを代わりに作成します。
これでup.jsonの雛形ができました。
あとはupするだけ。

```
$ touch up.json
```

```
{
	"name": "console-api"
}
```

`up url`でデプロイ先のurlが取得できるので、展開してcurlに食べさせます。

```
$ up

$ curl `up url`?name=tj
["express","koa","mocha","stylus","co"]
```

これで、無事にconsole.logのみをJSON APIとしてデプロイできました。

upについて詳しく知りたい人は、GitHubやtj本人の記事などを見てください。
あと、touch-alt、readmeとか.babelrcの雛形生成するのに便利なので使ってください。

[**akameco/touch-alt** <br>*touch-alt - Create from a template instead of a new file*](https://github.com/akameco/touch-alt)


## How to Work?
さて、どのようにして動いているでしょうか？
一言で言うと、Babelでトランスパイルしているだけです。

それを行っているプラグインが**babel-plugin-api-over-console**です。

[**akameco/babel-plugin-api-over-console**<br> *babel-plugin-api-over-console - transfrom to JSON Server from CLI app!!!*](https://github.com/akameco/babel-plugin-api-over-console)



このプラグインが行っているのは、`console.log`の変換と`process.argv`の変換です。
そして、babel-templateを用いて、処理をexpressの`app.get('/', callback)`のコールバックでラップします。
それほど難しい処理はしてないので、あとはコードを見てください。
個人的にはjQueryを書くよりBabel Pluginを書く方が楽ですね。

さて、Babel Pluginの詳しい話ですが、Web上に良い資料があるのでそれを参考にするとよいです。

まずは、thejameskyle先生のBabel Handbookに目を通すのがよいと思います。
https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md

astexplorerを使うと非常に直感的に理解ができてよいです。
https://astexplorer.net/

Babel Pluginのテストは、babel-plugin-testerを使うとよいです。
snapshotテストで簡単にテストできます。
babel-plugin-api-over-consoleでも使っているので参考にしてください。
https://github.com/babel-utils/babel-plugin-tester

また、consoleでASTを確認するのにbabel-logを使うと便利です。
https://github.com/babel-utils/babel-log

他の知見としては、BabelのレポジトリからFlowtypeの型定義ファイルを持ってくると開発がスムーズです。
https://github.com/babel/babel/blob/7.0/lib/types.js

babel公式のAPIについてのドキュメントも必須です。
こちらをにらめっこしながら書くことになると思います。
しかし、コメントまわりなどの処理を書こうとするとここに載っていないAPIを使うことになり、Babelのコードの読みに行く必要があります。
https://babeljs.io/docs/core-packages/babel-types/

## おわりに
いちいちexpressでlocalhostで出力確認とかしないでconsole.logだけでいいので、雑にやる分にはいいのではないでしょうか？

もし気に入ってくれたなら、スターをくれると嬉しいです。

<div name="2816" id="2816" class="graf graf--mixtapeEmbed graf-after--p"><a href="https://github.com/akameco/cli-to-api" data-href="https://github.com/akameco/cli-to-api" class="markup--anchor markup--mixtapeEmbed-anchor" title="https://github.com/akameco/cli-to-api" rel="nofollow"><strong class="markup--strong markup--mixtapeEmbed-strong">akameco/cli-to-api</strong><br><em class="markup--em markup--mixtapeEmbed-em">cli-to-api - transform cli to JSON API Server</em>github.com</a><a href="https://github.com/akameco/cli-to-api" class="js-mixtapeImage mixtapeImage u-ignoreBlock" data-media-id="f63a7a57ace4e8e574dc0c7b8e628292" data-thumbnail-img-id="0*SBKt9ei6-1xJZUK0." style="background-image: url(https://cdn-images-1.medium.com/fit/c/160/160/0*SBKt9ei6-1xJZUK0.);"></a></div>

[**akameco/babel-plugin-api-over-console**<br> *babel-plugin-api-over-console - transfrom to JSON Server from CLI app!!!*](https://github.com/akameco/babel-plugin-api-over-console)

なにか議論があれば、コメント欄、Twitterで議論しましょう。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あ、ありのまま今起こったことを話すぜ。<br>「CLIアプリをJSON APIとしてデプロイできるようになった。」<br>な、何を言っているのかわからねーと思うが、俺も何をしたいかわからない<a href="https://t.co/1lBV45NO8o">https://t.co/1lBV45NO8o</a> <a href="https://t.co/WhDnSUFH1k">pic.twitter.com/WhDnSUFH1k</a></p>&mdash; 無職.js (@akameco) <a href="https://twitter.com/akameco/status/902476165775888385">2017年8月29日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">最高の開発環境を見てくれ <a href="https://t.co/eHom7QO2F3">pic.twitter.com/eHom7QO2F3</a></p>&mdash; 無職.js (@akameco) <a href="https://twitter.com/akameco/status/902915113539198976">August 30, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

本記事は、[Medium](https://medium.com/@akameco/cli%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92json-api%E3%81%A8%E3%81%97%E3%81%A6%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B-e699f7fbef4b) からの転載です。よかったらフォローしてください。