Flutter✕Firebase(CloudFunctions+FireStore編)

---
# :book: Flutterの記事を整理し本にしました :book:
https://zenn.dev/kazutxt/books/flutter_practice_introduction

* <font color="red"><b>本稿の記事を含む様々な記事を体系的に整理し本にまとめました</b></font>
* 今後はこちらを最新化するため、<font color="red"><b>最新情報はこちらをご確認くださ</b>い</font>
* 10万文字を超える超大作になっています(笑)

---

# はじめに
## 概要
* FlutterとFirebaseのfunctionsを使って、リクエスト制御を実装します
    * cronやfirestoreトリガなども取り扱います

## 対象読者
* FlutterでFirebase(mBaaS)によるリクエスト制御を行ってみたい人

## 関連記事
* [Flutter系の記事のまとめ](https://qiita.com/kazutxt/items/524acb1c134015682ccf)

## スタート(前提条件)
* 2020/12/21時点の情報で執筆しています
    * <font color="red">Beta版ということもあり、メソッド名が変更になったり過去の参考文献がそのままで動かない事がよくあります。</font>
    * 逆に今後の正式版までの間に、本稿の情報が古くなる可能性もありますので、ご容赦ください
* flutterの基本概念を理解されているとより理解できると思います。
* Firebaseをflutterで使えるようになるまでの初期設定は省略します。

## ゴール(達成できること)
* flutter✕FirebaseのCloudFunctionsでリクエスト制御ができるようになります

## スコープ外(ふれないもの)
* AWS Lambdaなどの他のサービスとの比較は行いません
* ローカルでのシミュレータ動作は行いません。

## 開発環境
* flutterWebを用いているため、現時点でbetaのチャンネルを使っています

```  .sh
% flutter --version
Flutter 1.25.0-8.1.pre • channel beta • https://github.com/flutter/flutter.git
Framework • revision 8f89f6505b (5 days ago) • 2020-12-15 15:07:52 -0800
Engine • revision 92ae191c17
Tools • Dart 2.12.0 (build 2.12.0-133.2.beta)
```

---

# 本編
## 全体像/結論
* FirebaseのCloudFunctionsを設定し、flutterから呼び出すことで実現できます
* cron実行も可能です
* Web上からログや実行状態を確認することもできます。

## Part1:事前準備

* 無料版では使えないので、アップグレードして、Blazeにする必要があります
* `npminstall -g firebase-tools`でツールを入れます
* `firebase init functions`でFunction用の初期環境設定を行います。既存プロジェクトにかぶせて実施もできます
    * 言語：javascript
    * ESLint：Yes
    * dependency install : Yes
        * functionsフォルダが作成され、index.jsが作られます。

## Part2:実装
### リクエスト

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

exports.helloWorld = functions.https.onRequest((request, response) => {
   functions.logger.info("Hello logs!", {structuredData: true});
   response.send("Hello from Firebase!");
});

```

![func1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/6657c65a-8dcd-5d39-42bd-d1a4ff75a832.png)


### cronでの定期実行

``` index.js
// 5分おき
exports.timer1 = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
 functions.logger.info("timer1 start", {structuredData: true});
 return null;
 });

 //3分おき
 exports.timer2 = functions.pubsub.schedule('*/3 * * * *').onRun((context) => {
functions.logger.info("timer2 start", {structuredData: true});
return null;
});

```
![func2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/41440a4d-50fd-5145-be5b-25b2da38fb1a.png)


### DBイベントトリガ
``` index.js
// DBWriteEvent
exports.db1 = functions.firestore.document('testCollection1/testDocument1').onWrite((change,context)=>{
    functions.logger.info("DBChange", {structuredData: true}); 
});
```

![func3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/5891461d-adf1-0cba-a0fa-655cde401251.png)

#### DBデータの読み出し
``` index.js
admin.initializeApp();
const db = admin.firestore();

exports.getDB1 = functions.https.onRequest((request, response) => {
    functions.logger.info("getDB: logs!", {structuredData: true});

    var docRef = db.doc("testCollection1/testDocument1");
    docRef.get().then(doc=>{
        if(doc.exists){
            response.send(doc.data())
        }else{
            response.send("nodata")
        }
        return null;
    }).catch(error => {
        response.send("error")
    })
```

![func4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/aa6ebac5-5be5-e059-dfb9-d6646b864694.png)


## Part3:デプロイ
``` .sh
% firebase deploy --only functions

=== Deploying to '{PROJECTNAME}'...

i deploying functions
Running command: npm --prefix "$RESOURCE_DIR" run lint

> functions@ lint 
{PATH}/functions
> eslint .

✔  functions: Finished running predeploy script.
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔  functions: required API cloudbuild.googleapis.com is enabled
✔  functions: required API cloudfunctions.googleapis.com is enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (36.98 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: creating Node.js 12 function helloWorld(us-central1)...
✔  functions[helloWorld(us-central1)]: Successful create operation. 
Function URL (helloWorld): {URL}
✔  Deploy complete!

```

---

# 補足
## 備考
* 環境構築の時点で`ESLint`を入れなかったところrun buildがないと言われデプロイができませんでした。
    * package.jsonにscript/buildを足したところ動きましたが、少し違和感がありました。
* デプロイ時に403エラーが発生しましたが、`firebase logout`をしたあと`firebase login`したらうまく動きました


## 追記
* 2020/12/21 初稿