Cloud Functions for Firebase で json-server を動かす

簡単にMockサーバが作成できるjson-serverをCloud Functions for Firebaseで簡単に動かす方法についてまとめてみました。

# json-serverとは
「コーディング不要で30秒以内にREST　APIが作成出来る」が謳い文句のライブラリで、JSON形式のレスポンスを返すMockサーバが簡単に作成できます。

```json
{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ]
}
```

のようにJSON形式で返す値を定義すれば、

```bash

$ curl localhost:3000/posts/1
{
  "id": 1,
  "title": "json-server",
  "author": "typicode"
}
```

と値が返ってくるREST APIサーバが作成できます。

https://github.com/typicode/json-server

# Cloud Functions for Firebaseとは
Firebaseの機能やHTTPSのリクエストのイベントをトリガーに、色々な処理を実行できるサービスです。

https://firebase.google.com/docs/functions/

# 動かす
サンプルコードは[GitHub](https://github.com/keitaro1020/json-server-on-cloud-functions)にあげてあります。

## Cloud Functions for Firebaseプロジェクトを作る
[公式ドキュメント](https://firebase.google.com/docs/functions/get-started)
firebase-toolsをインストールし、firebaseにログインします。

```bash
$ npm install -g firebase-tools
$ firebase login
```

プロジェクト用のディレクトリを作成し、initコマンドで雛形を作成します。

```bash
$ mkdir json-server-on-cloud-functions
$ cd json-server-on-cloud-functions
$ firebase init functions
```

作成すると以下のようなディレクトリ構成になります。

```
.
├── firebase.json
└── functions
    ├── index.js
    └── package.json
```

## json-serverのFunctionを作る
functionsディレクトリでjson-serverをインストールします

```
$ cd functions
$ npm install json-server
```

json-serverのデータをfunctionsディレクトリに作成します。

```functions/db.json
(例)
{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}
```

functions/index.jsを編集します。

```js
const functions = require('firebase-functions');

const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()

server.use(middlewares)
server.use(router)

exports.mock = functions.https.onRequest(server);
```

## デプロイする
以下のコマンドでデプロイします

```bash
$ firebase -P {firebase project} deploy --only functions
```

下記のように表示されればデプロイ完了です。

```
=== Deploying to '{firebase project}'...

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (49.01 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: creating function mock...
✔  functions[mock]: Successful create operation. 
Function URL (mock): https://us-central1-{firebase project}.cloudfunctions.net/mock

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/{firebase project}/overview
```

プロジェクトで最初のデプロイの際、`Error: An unexpected error has occurred.`とエラーが出ることがあったのですが、気にせずもう一回実行したら正常にデプロイできました。

表示されたURLにアクセスするとMockサーバができていることがわかります。

```bash
$ curl https://us-central1-{firebase project}.cloudfunctions.net/mock/posts
[
  {
    "id": 1,
    "title": "json-server",
    "author": "typicode"
  }
]
$ curl https://us-central1-{firebase project}.cloudfunctions.net/mock/comments/1
{
  "id": 1,
  "body": "some comment",
  "postId": 1
}
```

## CIでデプロイする
CIツールからデプロイする際に必要となる`FIREBASE_TOKEN`を取得します

```bash
$ firebase login:ci

Visit this URL on any device to log in:
https://accounts.google.com/o/oauth2/auth?client_id=....

Waiting for authentication...

✔  Success! Use this token to login on a CI server:

{FIREBASE_TOKEN}

Example: firebase deploy --token "$FIREBASE_TOKEN"
```

取得したFIREBASE_TOKENを使ってCIでのデプロイを行います。以下にGitlab CIの例を記載します。

```yaml
functions deploy:
  image: node:8
  script:
    - npm install -g firebase-tools
    - cd functions
    - npm install
    - cd ..
    - firebase -P {firebase project} deploy --only functions --token "$FIREBASE_TOKEN"
```

# 参考
- https://qiita.com/koki_cheese/items/013d4e6ab5aefc792388
- http://konifar.hatenablog.com/entry/2017/06/27/171128