Open20

FirebaseCloudFunctionsで使用する言語をJavascriptからTypeScriptに乗り換えたい

sukedonsukedon

TypeScriptを使ってみたらいい感じだったので既存のjsプロジェクトも乗り換えたい

sukedonsukedon

とりあえずTypeScriptの作業で参考にしたの貼ってく

sukedonsukedon

null許容型?というか「型は指定するけどnullも入るかもよ」っていうのは記述の仕方がいくつかあるのかな。

C#だったらそもそも参照型は

string someField = null;

っていうのが成立するけど、TypeScriptでやりたかったら
変数宣言だと

let someField:string|null = null;

で、typeの宣言だと

type someType = {
    someField?:string,
    someField2:string|null
}

みたいな記述がいけるけど、どれが普通なんだろ

sukedonsukedon

JSON.parseがオブジェクトをanyで返してくれるのはいいんだけど、型のキャストを必須にするメソッドはないだろうか

sukedonsukedon

ライブラリで型定義してるファイルは大体~~.d.tsっていうファイルなんだけど、これはそういうルールなんだろうか

sukedonsukedon

https://typescriptbook.jp/reference/declaration-file

  • 型定義ファイル有り
    TypeScriptで書かれたパッケージ
    JavaScriptで書かれたパッケージだが.d.tsファイルを同梱している
  • 型定義ファイル有りだが別途インストールが必要
    JavaScriptで書かれたパッケージだが、 DefinitelyTypedに登録されている
  • 型定義ファイル無し
    JavaScriptで書かれたパッケージで型定義ファイルが存在しない

理解した

TypeScriptはJavaScriptにコンパイルされるときに型情報は無くなってしまいます。そのままJavaScriptパッケージを利用すると型定義の恩恵を得ることができません。しかし型定義ファイルを同梱することにより補完やコードチェックとして利用することができます。

javascriptでCloudFunctionsを書いてたときに補完が聞いてたのはFirebase側が.d.tsファイルを用意してくれてたからか

sukedonsukedon

https://firebase.google.com/docs/functions/config-env?hl=ja
CloudFunctionsの環境変数について、1年前は

firebase functions:config

を使用するよう書いてあったけど、最新のドキュメントだと変わってるみたい。(configも一応今も使える)

functionsフォルダに.envファイルを追加してその中に記述すればOK
dotenvというパッケージを使用するのでその導入だけしておく

npm install dotenv --save

envファイルの中身

HOGE=hogeValue

アクセス方法

require('dotenv').config() //ファイル冒頭とかでやっておく
console(process.env.HOGE);
sukedonsukedon

普通の環境変数だったら.envファイルでいいけど、secretとかpasswordは隠したい。

https://firebase.google.com/docs/functions/config-env?hl=ja#secrets-billing

Secret Manager では、6 個のアクティブなシークレット バージョンを無料で使用できます。つまり、1 つの Firebase プロジェクトで 1 か月あたり 6 個のシークレットを無料で使用できます。

7個以上使うと課金対象になっちゃうらしい

firebase functions:secrets:set SECRET_NAME

で設定できるはずだけど、エラー出た。

Error: functions:secrets:set is not a Firebase command

バージョンが古いとか?

ファイルベースの構成には、次のバージョン以上の Firebase CLI と Cloud Functions for Firebase が必要です。
firebase-functions v3.18.0
firebase-tools v 10.2.0

バージョンの確認する
https://mebee.info/2020/02/21/post-5185/

% firebase --version   
9.10.0

やっぱ古い。どうやってアップデートするの

https://mebee.info/2020/02/21/post-5185/
https://parashuto.com/rriver/tools/updating-node-js-and-npm

sukedonsukedon

Firebaseをアップデートしたのでsecretを設定しようとしたらエラー

Error: HTTP Error: 403, Secret Manager API has not been used in project *******  
before or it is disabled. Enable it by visiting 
https://console.developers.google.com/apis/api/secretmanager.googleapis.com/overview?project=******* then retry. 
If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.

https://console.developers.google.com/apis/api/secretmanager.googleapis.com/overview?project=*******
にアクセスして、有効にする

firebase functions:secrets:set SECRET_NAME

も無事動いた。↑のコマンドを打つと値の入力を促す表示が出てくる。

値を確認したいときは

firebase functions:secrets:access SECRET_NAME
sukedonsukedon

全く意識してなかったが、どうやらJavaScriptにはモジュールシステムとして、CommonJSとESMというものがあるらしい。
ふわっとした理解だけど、JavaScriptは自由な言語なのでなんでもできるが故にライブラリ(もといパッケージ?機能群)同士を活用するためにはライブラリ間の共通の最低限のルールを決めておく必要がある。それがモジュールシステム。みたいな

それでFirebaseCloudFunctionではデフォルトでCommonJSが使用されているが、依存するライブラリによってはESMに移行しないとTypeScriptからJavaScriptへのトランスパイルに失敗するらしい。

自分のプロジェクトTでFirebaseCloudFunction(TypeScript)を使用したときは、依存するライブラリの数がそんなに多くなかったのと、どれもCommonJSで正常に動くライブラリだったので気にせず実装できていた。

ただ、別のプロジェクトRでは、slackのライブラリおうとしたタイミングで

node_modules/@slack/socket-mode/dist/SocketModeClient.d.ts:2:8 - error TS1259: Module '"functions/node_modules/@types/ws/index"' can only be default-imported using the 'esModuleInterop' flag

2 import WebSocket from 'ws';
         ~~~~~~~~~

  node_modules/@types/ws/index.d.ts:353:1
    353 export = WebSocket;
        ~~~~~~~~~~~~~~~~~~~
    This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.


Found 1 error in node_modules/@slack/socket-mode/dist/SocketModeClient.d.ts:2

というエラーが出た。
これはslackライブラリがesModuleで動く想定なのにCommonJSから呼び出そうとしててデフォルトインポート(import WebSocket from 'ws';の部分)に失敗してる的な。

それを解決するにはcompilerOptionで"esModuleInterop": true を追記してあげればいいんだけど、
なんか他のエラー出たので寝るところですおやすみなさい