Firebase cloud functionsをstorageトリガで起動、をエミュレータで動作確認

Firebase cloud functionsをstorageトリガで起動させることを、エミュレータで動作させたときのメモです。

# やったこと
・エミュレータ上のstorageにtest_data.txtをアップロード
・上記をトリガにしてエミュレータ上でcloud functionsを起動させる
・アップロードされたファイルのファイル名をcloud functionsがエミュレータ上のログに出す

### 注意
2022/7/13現在、
functions.storage.bucket("バケット名").object().onFinalize
でトリガとなるバケットを指定しても効果がなく、どのバケットにファイルをアップロードしてもトリガしてしまうようです。エミュレータのバグ？

# 前提
Firebaseのアカウントを取得し、プロジェクトを作成できている

# 手順（すべてPC上の操作でFirebaseコンソールは使いません）
●作業用フォルダを作成。てきとうな名前でよい
```
mkdir cloud-functions-test
cd cloud-functions-test
```

●FirebaseのCLIなどをインストール
```
npm install firebase
npm install -g firebase-tools
```

●Firebaseにログインし、Firebaseツールを認証
コマンド実行後、ブラウザが起動されるので、ログインします
```
firebase login
```

●エミュレータの初期設定
どの機能のエミュレータを有効化するかとか、どの機能はどのポートを使うか、を設定します
今回はcloud functionsとstorageを有効にしました
```
firebase init emulators
```
設定が終わるとエミュレータやstorageの定義ファイルが自動生成されます
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/72f099fa-609f-49d6-fa2a-fed151d47a2d.jpeg)


●cloud functionsの作成
既存のFirebaseプロジェクト使うかとか、javascript/typescriptから選べとか聞かれます
今回はtypescriptにしました
```
firebase init functions
cd functions
```
実行後、functionsフォルダやindex.ts等が自動生成されます
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/d483a760-cfd2-844f-be0e-ec99dbb61157.jpeg)


●index.tsにソースを書く
functions.region()でリージョンを指定。[参考](https://firebase.google.com/docs/functions/locations)
バケット名は環境変数から取得します
トリガはonFinalizeとしました。[参考](https://firebase.google.com/docs/functions/gcp-storage-events)
```javascript:index.ts
import * as functions from "firebase-functions";
//import * as admin  from "firebase-admin";
import * as path from "path";

//admin.initializeApp();

exports
.cf_test = functions.region("asia-northeast1").storage
          .bucket(process.env.BUCKET_NAME).object().onFinalize(async (object) => {
          const fileBucket = object.bucket;
          const filePath = object.name;
          const contentType = object.contentType;
          const metageneration = object.metageneration;

          functions.logger.log('buckt name='+process.env.BUCKET_NAME);
          functions.logger.log('fileBucket='+fileBucket);
          functions.logger.log('filePath='+filePath);
          functions.logger.log('contentType='+contentType);
          functions.logger.log('metageneration='+metageneration);

          const fileName = path.basename(filePath!);
          //ファイル名チェックするなど
          if (!fileName.startsWith('test_')) {
            return functions.logger.log('file name error');
          }

          //やりたい処理を記載
        });
```

●環境変数を作成
今回はバケット名を環境変数にしました
.envと.env.localを作成します。ローカル環境では.env.localのほうが優先されます
```:.env
BUCKET_NAME=prod_bucket
```
```:.env.local
BUCKET_NAME=local_bucket
```

●ビルド
```
npm run build
```

●エミュレータで動作確認
```
firebase emulators:start
```
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/b04269c8-40f3-1457-f0b4-d7227f9248fe.jpeg)

ブラウザで http://localhost:4001 を開く

storageのタブでフォルダ作ったりファイルを入れたりします
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/f78fd915-dc9f-09d5-cecc-4af2d62645d2.jpeg)


storageをトリガにしてcloud functionsが起動したことをログで確認します
![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/14908b7f-4941-c115-49dd-53aefd419fae.jpeg)


最初の注意に書きましたが、現状はエミュレータでは、どのバケットにファイルをアップロードしてもトリガしてしまうようです

# 参考
cloud functionsのソースサンプル集
https://github.com/firebase/functions-samples