ゼロからFirebase Functions開発環境を構築する

Firebase Functionsを利用し、ある機能実現の要望があったので、
ゼロから、構築、サンプル作成の手順を作って見た。

作業環境はMacOS Mojave

### 1) まずはbrewを利用して npm　インストールすること

```command:terminal
$brew install npm
```

### 2) 次は、開発ディレクトリを作って置こう。

```command:terminal
$ mkdir firebase
```

### 3) firebase toolsをインストールしよう

```command:terminal
$ npm install --global firebase-tools
$ firebase --version
7.8.0

```
ちなみに今の最新版は７.８.０

### 4)firebaseの初期化

先にお試しに firebase init コマンドを打ってみる

```command:terminal
$ firebase init
Error: Command requires authentication, please run firebase login

```
先にログインしてねと怒られるので

```command:terminal
$ firebase login

/// ログインして、認証に通ると、

Waiting for authentication...
✔  Success! Logged in as xxxx@mailaddress.com
```

 再度、firebase initを実行すると、以下の様に表示

```command:terminal

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  /Users/XXXX/Project/firebase

? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter t
o confirm your choices. 
❯◉ 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 
 ◉ Emulators: Set up local emulators for Firebase features
 
```
取りあえず、全部チェックして置こうぜ〜

### 5) プロジェクトの構成
以下の様、既存登録されたプロジェクトから選択するか、新規プロジェクトを作成する選択ですが、コンソールから作成することが便利なので、一応、Googleのデベロッパーコンソールにログインして、プロジェットを登録する。

https://console.firebase.google.com/?pli=1

一応、Location 設定は一回設定すると変更できないので、「asia-northeast1 東京」を選択すること.

一応、成功された場合の出力画面は以下の様だ
————————| Start |——————

```command:terminal

$ firebase init

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  /Users/XXXX/Project/firebase

? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to conf
irm your choices. Database: Deploy Firebase Realtime Database Rules, Firestore: Deploy rules and create indexes for Fir
estore, Functions: Configure and deploy Cloud Functions, Hosting: Configure and deploy Firebase Hosting sites, Storage:
 Deploy Cloud Storage security rules, Emulators: Set up local emulators for Firebase features

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add, 
but for now we'll just set up a default project.

? Please select an option: Use an existing project
? Select a default Firebase project for this directory: enixmart (enixmart)
i  Using project enixmart (enixmart)

=== Database Setup

Firebase Realtime Database Rules allow you to define how your data should be
structured and when your data can be read from and written to.

? What file should be used for Database Rules? database.rules.json
? File database.rules.json already exists. Do you want to overwrite it with the Database Rules for enixmart from the Fi
rebase Console? Yes
✔  Database Rules for enixmart have been downloaded to database.rules.json.
Future modifications to database.rules.json will update Database Rules when you run
firebase deploy.

=== Firestore Setup

Firestore Security Rules allow you to define how and when to allow
requests. You can keep these rules in your project directory
and publish them with firebase deploy.

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

Firestore indexes allow you to perform complex queries while
maintaining performance that scales with the size of the result
set. You can keep index definitions in your project directory
and publish them with firebase deploy.

? What file should be used for Firestore indexes? firestore.indexes.json

=== Functions Setup

A functions directory will be created in your project with a Node.js
package pre-configured. Functions can be deployed with firebase deploy.

? What language would you like to use to write Cloud Functions? TypeScript
? Do you want to use TSLint to catch probable bugs and enforce style? Yes
✔  Wrote functions/package.json
✔  Wrote functions/tslint.json
✔  Wrote functions/tsconfig.json
✔  Wrote functions/src/index.ts
✔  Wrote functions/.gitignore
? Do you want to install dependencies with npm now? Yes

> protobufjs@6.8.8 postinstall /Users/XXXX/Project/firebase/functions/node_modules/protobufjs
> node scripts/postinstall

npm notice created a lockfile as package-lock.json. You should commit this file.
added 269 packages from 198 contributors and audited 732 packages in 30.555s
found 0 vulnerabilities


=== Hosting Setup

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.

? What do you want to use as your public directory? public
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
✔  Wrote public/index.html

=== Storage Setup

Firebase Storage Security Rules allow you to define how and when to allow
uploads and downloads. You can keep these rules in your project directory
and publish them with firebase deploy.

? What file should be used for Storage Rules? storage.rules

=== Emulators Setup
? Which Firebase emulators do you want to set up? Press Space to select emulators, then Enter to confirm your choices. 
Functions, Firestore, Database, Hosting, Pubsub
? Which port do you want to use for the functions emulator? 5001
? Which port do you want to use for the firestore emulator? 8080
? Which port do you want to use for the database emulator? 9000
? Which port do you want to use for the hosting emulator? 5000
? Which port do you want to use for the pubsub emulator? 8085
? Would you like to download the emulators now? Yes
i  firestore: downloading cloud-firestore-emulator-v1.10.2.jar...
Progress: =============================================================================================> (100% of 64MB
i  database: downloading firebase-database-emulator-v4.2.0.jar...
Progress: =============================================================================================> (100% of 18MB
i  pubsub: downloading pubsub-emulator-0.1.0.zip...
Progress: =============================================================================================> (100% of 37MB

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...
i  Writing gitignore file to .gitignore...

✔  Firebase initialization complete!

```

実際のプロジェットニーズにより、必要なモジュールのみ選ぶことであるが、今度は全部選択しておく。

### 6) firebase useコマンドで起動

```command:terminal
$ firebase use
Active Project: enixmart

Project aliases for /Users/XXXX/Project/firebase:

* default (enixmart)

Run firebase use --add to define a new project alias.

```

8) firebase エミュレータでHello from Firebase!を起動してみる
Firebase/functions/index.tsのDemo用実行コメントを外して、実行してみる。

```command:terminal
/index.ts
export const helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});

```
コマンドを実行する

```command:terminal
$ npm run serve
⚠  Your requested "node" version "8" doesn't match your global version "13"

✔  functions: Emulator started at http://localhost:5000

i  functions: Watching "/Users/XXXX/Project/firebase/functions" for Cloud Functions...

✔  functions[helloWorld]: http function initialized (http://localhost:5000/enixmart/us-central1/helloWorld).

```
9) Emulatorで成功したのでここままデプロイしてみると

```command:terminal
Error: Functions did not deploy properly.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! functions@ deploy: `firebase deploy --only functions`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the functions@ deploy script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

```
と怒られる。
package.jsonを以下の様に修正

```command:terminal
    "deploy": "firebase deploy --only functions",
    "deploy-rules": "firebase deploy --only firestore:rules,storage:rules”,
```
今度は、以下のエラーが出る

```command:terminal
Error: HTTP Error: 400, Project 'enixmart' is not a Cloud Firestore enabled project.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! functions@ deploy: `firebase deploy`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the functions@ deploy script.

```
クラウドStorage設定がまだ有効になっていない様だ。さっさとコンソールで設定を見直して、クラウドStorageを有効にする。
再度Deployしたら,

```command:terminal
 $npm run deploy
✔  functions: Finished running predeploy script.
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (31.59 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: updating Node.js 8 function helloWorld(us-central1)...
✔  functions[helloWorld(us-central1)]: Successful update operation. 

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/enixmart/overview

```

ついにかDeployに成功。

9) DemoのhelloWorld関数にリクエストを投げして、結果を見よう
コンソルのFunctionsダッシュボードから、helloWorldのトリガーリクエストURLをコピーして、ブラウザで開いて見る。

URL:https://us-central1-enixmart.cloudfunctions.net/helloWorld

Hello from Firebase!


じゃ、次回からは、本格の開発に参りましょ！
>iOS、Androidアプリの制作なら、https://origon.co.jp にお任せください
>信頼且つ満足できる製品を納品いたします

参考になった記事：
https://qiita.com/ovama-koffee/items/1dd1170268d277119e1a
https://qiita.com/kaba/items/35a82b470354b9db29ba
https://qiita.com/otsukayuhi/items/051d37a5eabb41957aa2