Firebase Cloud Functions ってどうやって使うん？(使い方)

追記：その前にここ

https://firebase.google.com/docs/functions/video-series?hl=ja

---

<b>「Firebase Cloud Functions ってどうやって使うん？ 使い方がよくわからんのやけど？？？」</b>

と思ってggっては

<b>「これはもう使い方知ってる人向けの記事や…
ほんとのほんとの最初の一歩の初期設定が知りたいんや…」</b>

と、心が折れてた、２週間くらい昔の自分へお届けしたい備忘録メッセージ。

（どうせ後で「どうやって使うの？教えて〜！」と質問されたときにはきっと私もう忘れてる！から書いとこ！）

よ〜し、まずは使うための下準備だ！

# 以下、未来の自分へ

---

公式：参考リンク

https://firebase.google.com/docs/functions/get-started?authuser=0

# 最初にわかってなかったこと： Cloud Functionsの各functionの「呼び出し方」

Cloud Functions ってどうやって呼び出すの？
→ functionを呼び出すタイミングは、deploy したソースコード内に「トリガー」を書いてコントロールする。

例えば、「〇〇を削除したら」とか「〇〇を書き込んだら」とか。
トリガーで指定した操作が行われた時に、サーバにupしておいたfunctionが動いて、指定した動きをしてくれる。

例）「pets 内の任意のペットのドキュメントが削除されたタイミングで、このファンクションは実行される」など。

"何が起きた時に実行されるか"、は サーバにdeployした function の各ソースコード内に書かれているので
何かしら呼び出しの function を各 page ファイルに書くことは（少なくとも今回私はして）ない。

例えば、 「onDelete」で、データを含むドキュメントが削除されたときにトリガーされる。
Cloud Firestore 関数トリガーについて
https://firebase.google.com/docs/functions/firestore-events?hl=ja#function_triggers

# deployする時は

functions フォルダ下ではなく、最上ディレクトリ直下で deploy する

# まずはターミナルを使って、「firebase-tools」を使えるようにしよう

グローバルにインストールするよ

グローバルだからどこで叩いてもいいのかな…？
わからん。（知識不足）
不安だったので私はmacのユーザーのすぐ下に移動してから次のコマンドを入力したよ▼

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

これで `firebase` というコマンドが使えるようになるよ。


## firebaseにログイン

```
firebase login
```
でログインしよう。
もうログインしてるときにアカウントが違う場合は

```
firebase logout
```
でログアウトできるよ。

# projectのフォルダに移動して、以下のコマンドを実行

## firebase init firestore

```
firebase init firestore
```

---

もしこんなの（↓）が出たら

```
❯❯❯ firebase init firestore
nodenv: firebase: command not found

The `firebase' command exists in these Node versions:
  8.17.0
  10.15.3
  12.20.0
```
nodeのバージョンが上記の3つにしか対応してないけど、
現在のプロジェクトで使ってるnodeのバージョンが上記以外だから動かないよ〜
という意味なので
nodeのバージョンを変更しよう。
私は `12.20.0` にしたよ。

ちなみに、nodeのバージョンの管理をnodenvでしてるけど
nodenvを更新したいときはanyenvでアップデートできるよ。

```
anyenv update
```
でOK
参考：
https://www.to-r.net/media/anyenv/
https://qiita.com/turara/items/6b7f4a8e3770a7074072

---

途中できかれる質問はデフォルトでいいみたい。（みたい、って…）
正直よくわかってないので違ったらごめん。

```
? What file should be used for Firestore Rules? firestore.rules

? What file should be used for Firestore indexes? firestore.indexes.json
```
`firestore.rules` は
https://console.firebase.google.com/project/【プロジェクト名】/firestore/rules
で設定した、ルールと同じものが入ったよ。
多分「ローカルからコマンドラインでルールを変更→反映させるために必要なので、
ローカルにルールにまつわるファイル作るけど、ファイル名どうする？」みたいなことをきかれてるよ。

※ちなみに、ルールをローカルで変更したら、
ターミナルを使って、

```
firebase deploy --only firestore:rules
```
とすれば、ルールの変更がデプロイされるよ。

参考：
https://firebase.google.com/docs/firestore/security/get-started?hl=ja
https://qiita.com/zaburo/items/e82cff108690eb0493c0

# firebase init functions

```
firebase init functions
```
あとは質問には素直に答えれば、ヨシ！

>すでに現在のディレクトリで Firebase hosting を使っている場合は `firebase.json` に Cloud Functions の設定を追加してくれる。上書きで消される事は無い。言語として TypeScript を選ぶと適当に TypeScript 環境を設定してくれる。プログラムは functions/src/index.ts に関数を書く。

引用元：
https://qiita.com/propella/items/65db803e2a0e18fa2cbc


# 下準備ここまで

これでとりあえずターミナルで下準備としてインストールしないといけないやつは終わり。

ふと見上げると勝手に`functions`フォルダができていた。
ありがてぇ。ありがてぇ。
![スクリーンショット 2021-05-15 19.17.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321986/847681f4-86c6-db41-6009-71e9e87d6fe2.png)

※このあとlintの使用はやめて消しました。
参考： https://tsukada.sumito.jp/2019/12/11/firebase-deploy時のeslintを無効にする/


# functionsフォルダ内に色々書いていく
あとは見様見真似で書いていこう。
（※正直間違ってるかもしれないのであまり信用しないで欲しい。詳しい人にちゃんときいてね！）

## Firebase Admin SDK

![スクリーンショット 2021-05-15 20.20.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321986/4fa41737-53ed-d786-908f-d9c06cc5e289.png)

https://console.firebase.google.com/project/【プロジェクト名】/settings/serviceaccounts/adminsdk
から、
「新しい秘密鍵を生成」して
`【プロジェクト名】-firebase-adminsdk-xxxxxxxxxxxxx.json` を作る。

## functionsフォルダ直下に .cert フォルダを作成

functionsフォルダ直下に `.cert` フォルダを作成して
そこに `【プロジェクト名】-firebase-adminsdk-xxxxxxxxxxxxx.json` を入れる。

### 注） gitにupしないように！
<b>gitにupしない</b>ように、
functionsフォルダ直下の
`.gitignore` に `.cert/` を追記しよう。

```.gitignore
node_modules/
.cert/
```

## index.jsでrequireする

今回は下記のような構成なので
`index.js` でrequireする。

```javascript
📁functions
∟📄index.js // ←ここでrequire
∟📁.cert
　∟📄【project名】-firebase-adminsdk-xxxxxxxxxxx.json // ←デプロイに必要
∟📁funcs
　∟📁pet
　　∟📄deletePet.js　// ←これを
```

以下、`index.js`

```javascript
const admin = require('firebase-admin')
const serviceAccount = require('./.cert/【project名】-firebase-adminsdk-xxxxxxxxxxx.json')

/**
 * initialize admin
 */
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
})

// 他で使ってるやつ たとえば
exports.scheduledBackup = require('./funcs/auth/hogehoge.js')
exports.scheduledBackup = require('./funcs/common/hugahuga.js')
exports.scheduledBackup = require('./funcs/scheduled/hogehoge.js')
exports.scheduledBackup = require('./funcs/user/hugahuga.js')

// 今回作ったやつ
exports.scheduledBackup = require('./funcs/pet/deletePet.js')
```

# Blazeプランにアップグレード
FreeプランでFirebase Cloud Functionsは使えないのでアップグレードする。

# 権限の付与

必要であれば、下記のURLから（Google Cloud Platform の 「IAM」 から）権限の付与を行う。
https://console.cloud.google.com/iam-admin/iam?folder=&organizationId=&project=【プロジェクト名】

例えば定期バックアップをとるfunctionsを走らせるために、
（参考： https://qiita.com/AyakoKataoka/items/003dae46773e32b9258b）

`【プロジェクト名】@appspot.gserviceaccount.com` アカウントに対して
`Cloud Datastore インポート / エクスポート管理者` の権限を付与した。

※権限周りでエラー出て気づいたので関連リンク貼っとく
https://stackoverflow.com/questions/61225348/firestore-backup-function-errors-with-permission-denied-the-caller-does-not-ha
https://cloud.google.com/firestore/docs/quickstart-servers#set_up_authentication
https://cloud.google.com/firestore/docs/security/iam#roles

# そういえば Google Cloud SDK 認証

エラーが出たので解消するために確認していたら、
gcloudのログインが別のgoogleアカウントになっていたので、メモを残しておく。

（確か、一定時間経ったデータを自動で消すために
lifesycleを設定する際に使ったような気がするので直接関係ないかもしれない。
うろ覚え…）

```
gcloud config list
```
で、別のアカウントでログインしてないか確認する。

別のアカウントでログインしていたら

```
gcloud auth login
```
ログインし直して
プロジェクトを確認

```
gcloud projects list
```
プロジェクトを設定し直し

```
gcloud config set project 【プロジェクト名】
```
確認

```
gcloud config list
```

# デプロイ
デプロイするときには `.cert` 内に `【project名】-firebase-adminsdk-xxxxxxxxxxx.json` が必要。
また、全てのfunctionsをデプロイするととても重くなるので
該当のものだけ単体でデプロイするのがいい。時間がかかるので。

```zsh
firebase deploy --only functions // これだと全部デプロイされる
```

```zsh
firebase deploy --only functions:deletePet // これだと指定したfunctionのみデプロイされる
```

```zsh
firebase deploy --only functions:deletePet,functions:addPet
// 複数指定したい時はカンマでつなげる。カンマの後ろに空白は入れない。入れると動かない。
```

# 確認

以下のURL（firebaseのコンソールの「functions」）から、デプロイされたfunctionの一覧が確認できる。
各functionの一番右側の「…」から、「ログを確認」することができる。
（console.log的な感じで確認したいときはここから。）
https://console.firebase.google.com/project/【プロジェクト名】/functions/list

# deployで失敗したら

以下のコマンドでログを確認できる。
```
firebase functions:log
```

また、以下のURLからログ等詳しく参照できる。
https://console.cloud.google.com/functions/list?project=【プロジェクト名】

# おしまい！
あとはfunctionsのフォルダの下のソースコード頑張って書くだけ！
頑張れ過去＆未来の私！

functions等の追加・削除の履歴はここから見れる
https://console.cloud.google.com/home/activity?hl=ja&orgonly=true