Kotlin code を Kotlin/JS で JavaScript に transpile して Firebase Cloud Functions に deploy するまでの軌跡です。
環境
この記事は次の環境で実行した情報を記載しています。
- Apple M1
- macOS BigSur 11.6
Firebase Project については作成済みであることを前提としています。
Set up
IntelliJ IDEA を使って Kotlin/JS を setup します。
Firebase init
任意の場所に firebase init
で local に Firebase Project を setup します。
% firebase init
######## #### ######## ######## ######## ### ###### ########
## ## ## ## ## ## ## ## ## ## ##
###### ## ######## ###### ######## ######### ###### ######
## ## ## ## ## ## ## ## ## ## ##
## #### ## ## ######## ######## ## ## ###### ########
You're about to initialize a Firebase project in this directory:
/path/to/firebase-project
? Which Firebase features do you want to set up for this directory? Press Space
to select features, then Enter to confirm your choices. Functions: Configure a C
loud Functions directory and its files
=== 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: your-project-id (Your Project Name)
i Using project your-project-id (Your Project Name)
=== Functions Setup
A functions directory will be created in your project with sample code
pre-configured. Functions can be deployed with firebase deploy.
? What language would you like to use to write Cloud Functions? JavaScript
? Do you want to use ESLint to catch probable bugs and enforce style? No
✔ Wrote functions/package.json
✔ Wrote functions/index.js
✔ Wrote functions/.gitignore
? Do you want to install dependencies with npm now? No
i Writing configuration info to firebase.json...
i Writing project information to .firebaserc...
i Writing gitignore file to .gitignore...
✔ Firebase initialization complete!
firebase init
直後は次の状態になっています。
% ls -aR
. .. .DS_Store .firebaserc .gitignore firebase.json functions
./functions:
. .. .gitignore index.js package.json
※ functions/
下の file は一旦不要なので全て削除しておきます。
Install IntelliJ IDEA
Kotlin/JS の開発をするために JetBrains 社の web site から IntelliJ IDEA Community を download します。
PC の architecture 毎に dmg が用意されているため、適宜選択して download して install してください。
New Project
Install した IntelliJ IDEA を開き、
Menu > File > New > Project を選択します。
- 左の一覧から
Kotlin
を選択します。 - Location を
/path/to/firebase-project/functions
に設定します。 - Project Template から
Node.JS Application
を選択します。 - Project JDK を 16 に設定します。 (17 だと test 実行時に error が発生しました)
- Kotlin/JS Compiler を IR に設定します。
- お好みで Use experimental Node.js API (kotlinx-nodejs) を有効にしてください。
Project を作成すると、 src/
配下に Main.kt
や GreetingTest.kt
が sample として用意されています。
Build
Menu > Build > Build Project もしくは ./gradrew build
で build すると、
functions/build/js
に workspace として出力されます。
Kotlin で実装した module は functions/build/js/packages/{module name}/
に出力されます。
Workspaces について
Build Configuration
Kotlin の build を構成します。
firebase.json
functions の source は default が functions/
なので、
出力した functions/build/js/packages/{module name}/
に変更します。
また、 runtime
を設定しないと deploy で error が出るので node version を指定します。
{
"functions": {
"source": "functions/build/js/packages/{module name}/",
"runtime": "nodejs14"
}
}
Dependencies
利用する Library を Project に設定します。
serialization
や firebase-admin
についてはお好みでどうぞ。
plugins {
kotlin("js") version "1.6.0"
kotlin("plugin.serialization") version "1.5.31"
}
...
dependencies {
// JS, Basic Libraries
implementation(kotlin("stdlib-js", "1.6.0"))
implementation("org.jetbrains.kotlinx", "kotlinx-nodejs", "0.0.7") // Experimental
implementation("org.jetbrains.kotlinx", "kotlinx-coroutines-core-js", "1.6.0-RC")
implementation("org.jetbrains.kotlinx", "kotlinx-serialization-json", "1.3.1")
// Firebase
implementation(npm("firebase-admin", "^10.0.0"))
implementation(npm("firebase-functions", "^3.16.0"))
// Test
testImplementation(kotlin("test", "1.6.0"))
testImplementation(npm("firebase-functions-test", "^0.3.3"))
}
Implementation
準備が整ったところで Kotlin で Functions の実体を実装していきます。
Kotlin で実装するとはいえ、 JS の資産 (npm) を使うことになるため、 Kotlin と JS のつなぎこみが必要になります。
JS の code は js
関数で Kotlin に埋め込むことができます。
// firebase-functions module を JS code で require します。
private val functions = js("require(\"firebase-functions\")")
val log = js("require(\"firebase-functions/v1\").logger")
val structuredData = json("structuredData" to true)
また、外部で定義済みの変数などは external
修飾子で宣言することができます。
// Functions の exports が定義されていることを宣言します。
private external val exports: dynamic
onCall は次のような signature です。
suspend fun greeting(data: Json, context: Json): Json {
log.debug("greeting")
log.debug(data, structuredData)
return json(
"result" to "Hello, ${data["greeting"]}",
)
}
main 関数で export します。
fun main() {
log.debug("main")
exports.greeting = functions.https.onCall(::greeting)
}
Build して Firebase Local Emulator を起動するか、 Firebase に deploy すると、
greeting
が反映されて呼び出せるようになります。
% curl -i http://{host}/{your-project-id}/us-central1/greeting \
--header "Content-Type: application/json" \
-d '{"data":{"greeting":"Firebase!"}}'
HTTP/1.1 200 OK
x-powered-by: Express
vary: Origin
content-type: application/json; charset=utf-8
content-length: 40
date: Sun, 12 Dec 2021 03:50:44 GMT
connection: close
{"result":{"result":"Hello, Firebase!"}}
HttpsError
Coming soon
Test
Coming soon
Repository
Coming soon
参考
次の情報を参考にさせていただきました。 🙏
Firebase
Kotlin/JS
Kotlin Coroutine