Cloud Functions 最低限（セットアップ＋HTTPトリガー）


ここではCloud Functions(for Firebase)を利用するための最低限の手順をメモしてます。
なお、本編で扱うのはHTTPリスクエストによるトリガーなので、Firestoreトリガー等は[こちら](https://qiita.com/zaburo/items/fa810a22cc132ae1317d)をご覧ください。

## インストールと利用設定

Cloud Functions(以下,functions）の開発をするためにはfirebase-toolsがいるのでインストールする。

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

で、作業場所でinitする。

```bash
mkdir test
cd test
firebase init
```

すると、いろいろ聞いてくる。

### どの機能使う？

上下矢印で移動し、スペースで選択できる。Functionsを選ぶ。

```bash
? Which Firebase CLI features do you want to set up for this folder? ...

 ◯ Database: Deploy Firebase Realtime Database Rules
 ◯ Firestore: Deploy rules and create indexes for Firestore
❯◉ Functions: Configure and deploy Cloud Functions
 ◯ Hosting: Configure and deploy Firebase Hosting sites
 ◯ Storage: Deploy Cloud Storage security rules
```

### どのプロジェクト使う？

だいたい既存プロジェクトがあると思うんドエ、existing projectを選ぶ（1つしかプロジェクトが無いと、直接プロジェうと名が表示されるはずなのでそれを選ぶ）。

```bash
? Please select an option: (Use arrow keys)

❯ Use an existing project
  Create a new project
  Add Firebase to an existing Google Cloud Platform project
  Don't set up a default project
```

複数ある場合は、プロジェクトリストが表示されるので利用するものを選ぶ。

### どの言語使う？

おとなしくJSにしておく。

```bash
? What language would you like to use to write Cloud Functions? (Use arrow keys)

❯ JavaScript
  TypeScript
```

### ESLintつかう？

標準Noらしいので、そのままReturn。

```
? Do you want to use ESLint to catch probable bugs and enforce style? (y/N)
```

### 依存ファイル入れる？

標準Yesなので、そのままReturn。

```
? Do you want to install dependencies with npm now? (Y/n)
```

で、作業ディレクトリ直下に、functionsディレクトリができており、その中にindex.jsができてるので、それをいじる。

## 実装

最初からhelloWorldが実装され、コメントアウトされているので、コメントインして実行してみる。

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

// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//

exports.helloWorld = functions.https.onRequest((request, response) => {
 response.send("Hello from Firebase!");
});
```

## 実行

いちおうログインコマンドを打ってみる。ログインされていればAleady logged inとかでる。

```bash
firebase login
```

ログインできていればdeployする。

```bash
firebase deploy
```

デプロイが完了すると、コンソールにURLが表示されるのでそれを実行する。

> URLはfirebase console(web)のFunctionsからも確認できます。

## ローカルで実行

```
firebase serve
```

```bash
Error: Port 5000 is not open, could not start functions emulator.
```

```bash
firebase emulators:start &
```

```bash
firebase serve
```

表示される(localhostの）URLを実行してみます。

## パラメータを受け取る

### GET

QueryStringの値はquery['param_name']で取得できるようです。

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

exports.helloWorld = functions.https.onRequest((request, response) => {

    //パラメータ取得
    const name = request.query['name'];
    const age = request.query['age'];

    //response
    response.send("こんにちは。" + name + "さん。" + age + "歳ですね。");
});
```

### POST

postの値はbody['param_name']で取得できるようです。

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

exports.helloWorld = functions.https.onRequest((request, response) => {

    //パラメータ取得
    const name = request.body['name'];
    const age = request.body['age'];

    //response
    response.send("こんにちは。" + name + "さん。" + age + "歳ですね。");
});
```


## DB(Firestore)を利用する

FunctionsからFirestoreを利用するにはfirebase-adminを利用するようです。
インストールがまだならインストールします。

```bash
npm install -g firebase-admin
```

下記はcollectionとdocを指定して取得する例です。

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

const db = admin.firestore();

exports.helloDB = functions.https.onRequest((request, response) => {
    db.collection('users').doc('12345').get()
        .then(doc => {
            if (doc.exists) {
                response.send(doc.data());
            } else {
                response.send("no data");
            }
        })
        .catch(e => {
            response.send("not found");
        });
});
```

### ローカル環境での利用

普通にfirebase serveをするとエラーとなりました。どうやらクラウドにあるfirestoreを見に行けてないようです。
serveでfirestoreを利用するには、環境変数に認証情報を読み込ませて置く必要があるようです。

ずっと使うなら.bash_profileなどに記述してもいいかもしれません。

```bash
export GOOGLE_APPLICATION_CREDENTIALS=~/serviceAccountKey.json
```

そもそもサービスアカウント（の秘密鍵）って何？って言う人は[ここ](https://firebase.google.com/docs/admin/setup?hl=ja)を参考にしてください。

## その他

本格的にAPI作る場合はexpress入れたほうがノウハウの共有とかできていいのかな。