FirebaseのFunctionsで取り敢えずAPIを作ろう1

#FirebaseのFunctionsでAPIを作ろう　その１
GoogleのFirebaseってめちゃ便利ですよね，PHP派の私もいい加減あれこれ触ってます．
最近はNuxt使ってSSRアプリをHosting＋Functionsにデプロイしたりしてますが
いい加減実用的なものを作るべき段になりました．
備忘録もかねて作業内容をつらつらします．

＊今回はAPIまで行きません
＊随所に偏見が入ってますが見逃してください．

##～エミュレータの設定編
取り敢えずエミュレータの設定まで記事にします．
API的に動くところが一応見えます．

##目的
APIの定義は非常に広いと思いますが，ここでは取り敢えずDBに接続してデータを入れたり貰ったりするサーバ側のなんかと定義します．
で，いい加減PHP以外でサーバレスで何とかしたいということで，FirebaseのFunctions使っていきます．
DBはGCPのCloud SQLのMySQL8系です．
今回はあんまり関係ないです．
そこまで進んだら続編出すなり続き書くなりします．

##環境
OS：Windows10
エディタ（IDE）：PHP Storm
因みにnpm派です．現代は一周回ってnpmです（偏見）．yarnは捨てます．

##前提
基本的に以下に沿って行きます．
https://firebase.google.com/docs/functions/get-started?hl=ja

###Firebaseの設定
Firebaseのプロジェクトの作成とかです．
この辺は割愛します．
サイトからでもプロジェクトからでもいいです．
手順に沿って行くとFirestoreも使用するのでFunctionsとFirestoreも設定しておいてください．

###ディレクトリ構成
取り敢えずプロジェクトのディレクトリを作ります．
できたら中に入って

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

特にpackage.jsonとか無いので見た目変化ないですがいいです．
で，

```bash
firebase login
```

この辺も経験ある人はいつも通り．
ログイン済みの人はいりません．

```bash
firebase init firestore
```

と

```bash
firebase init functions
```

因みに言語は「JavaScript」を選択．
申し訳ないけど「TypeScript」はめんどくさいだけです（偏見２）．
複数人で開発するなら考えます．

###デプロイファイル
デプロイする，つまり実際にアップロード？して使用するファイルは「functions」ディレクトリの下になります．
基本的には「functions/index.js」です．
こいつを手順に沿って書いていきます．
以下のようになります．


functions/index.js

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

// The Firebase Admin SDK to access Cloud Firestore.
const admin = require('firebase-admin');
admin.initializeApp();

// このHTTPエンドポイントに渡されたテキストパラメーターを取得し、パス/ messages /：documentId / originalの下のCloudFirestoreに挿入します
exports.addMessage = functions.https.onRequest(async (req, res) => {
    // テキストパラメータを取得します。
    const original = req.query.text;
    // Firebase Admin SDKを使用して、新しいメッセージをCloudFirestoreにプッシュします。
    const writeResult = await admin.firestore().collection('messages').add({original: original});
    // メッセージの書き込みに成功したというメッセージを送り返します
    res.json({result: `Message with ID: ${writeResult.id} added.`});
});


// / messages /：documentId / originalに追加された新しいメッセージをリッスンし、メッセージの大文字バージョンを/ messages /：documentId / uppercaseに作成します
exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
    .onCreate((snap, context) => {
        // CloudFirestoreに書き込まれた内容の現在の値を取得します。
        const original = snap.data().original;

        // `context.params`を使用してパラメータ` {documentId} `にアクセスします
        functions.logger.log('Uppercasing', context.params.documentId, original);

        const uppercase = original.toUpperCase();

        // Cloud Firestoreへの書き込みなど、関数内で非同期タスクを実行する場合は、Promiseを返す必要があります。
        // Cloud Firestoreドキュメントに「大文字」フィールドを設定すると、Promiseが返されます。
        return snap.ref.set({uppercase}, {merge: true});
    });
```

ざっと解説すると以下の二つの関数があります
・addMessage：多分HTTP GETして取得した値をFirestoreに突っ込みます
・makeUppercase：多分firestoreに突っ込まれた値をアッパーケースにしてFirestoreに突っ込みます

###実行テストその1
さて，ローカル環境でテスト実行します．

```bash
firebase emulators:start
```

か

```bash
firebase emulators:start --only functions
```

いろんなサービスが入っている場合「--only functions」してあげないと他のサービスもエミュレートしようとして失敗して怒られます．

functions/に移動して

```bash
npm run serve
```

でもいいです．
「firebase emulators:start --only functions」が入ってます．

後，多分
http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme
こんな感じでアクセスできます．
Firebaseのコンソールで確認するとFirestoreのmessagesに”uppercaseme”が入っているのが確認できます．

###めでたしめでたし，と思っていたのか？
「addMessage」関数は動いてますが「makeUppercase」は動いていません．

https://firebase.google.com/docs/rules/emulator-setup
https://firebase.google.com/docs/emulator-suite/install_and_configure?hl=ja

この辺に書いてあります．
エミュレータの設定がいります．
で，Javaです．，，，Java?Javaﾅﾝﾃﾞ？
なんで今どきJavaなんですか私はJavaを許しません（偏見３）．

まあ，仕方なくJavaを入れます．
因みにこの段階でデプロイしてもちゃんと動くと思います．
でもテストせずにデプロイとか現実的にはあり得ないので，ちゃんと環境作ります．
個人的には自分のPCにJavaが入ってなくてびっくりです．
もうそういう時代っすよ．

Javaのインストールわからない方は以下のページを発見いたしましたのでご参照ください．
初学者の鬼門環境変数の何とやらです
https://masalib.hatenablog.com/entry/2020/11/28/131550#java%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

###エミュレータのインストール

```bash
firebase init emulators
```

これでインストール．
後で増やせばいいので一応FunctionsとFirestoreに絞るのが無難です．

再び以下にアクセス
http://localhost:5001/nexstimemanagementapi/us-central1/addMessage?text=uppercaseme

で，ちゃんと動いているかの確認ですが，
ちゃんとエミュレータが起動した後は本番のFirebaseには変化がありません．

http://localhost:4000 
とかにローカルのエミュレータが起動しますのでそちらで確認してください．

以下のような感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206742/0f575c9a-6f5f-2af2-465d-a5cc771c37f2.png)

###めでたしめでたし

ちょと古いですが以下の記事なぞ参考になると思います．
https://qiita.com/HALU5071/items/e43729ac5b06b0506fbe