Files
kotlin-cloudflare-worker/README.md
T

155 lines
3.7 KiB
Markdown
Raw Normal View History

2026-01-03 04:08:34 +08:00
# Kotlin cloudflare worker
A library to running kotlin/js on cloudflare worker.
# Get started
## Setup
> `kotlinx.coroutines` is required
```kotlin
plugins {
kotlin("multiplatform") version "2.2.21"
}
repositories {
mavenCentral()
maven("https://repo.maven.rtast.cn/releases")
}
```
```kotlin
// to get latest version of this lib, go to
// https://next.pkg.rtast.cn/#/releases/cn/rtast/kotlin-cfworker/kotlin-cloudflare-worker/
implementation("cn.rtast.kotlin-cfworker:kotlin-cloudflare-worker:1.0.1")
```
## Run app
```kotlin
kotlin {
js(IR) {
nodejs {
outputModuleName = "kotlin-cloudflare-worker"
binaries.executable()
}
}
}
```
> Minimal hello world app
```kotlin
/**
* DO NOT EDIT THIS FUNCTION
*/
fun main() {
@Suppress("unused_expression")
val eventListener = EventListener { event ->
val dyn = event.asDynamic()
event.asDynamic().respondWith(handleRequest(dyn.request as Request))
Unit
}
js("addEventListener('fetch', eventListener)")
}
@JsExport
fun handleRequest(request: Request): Promise<Response> = GlobalScope.promise {
val server = WorkerApplication().apply {
route("/") {
respondText("Hello kotlin cloudflare worker")
}
}
return@promise server.handle(request)
}
```
> Before run worker locally, you need to install wrangler and login
First, create `wrangler.toml` in your root project and configure it
```toml
name = "kotlin-cloudflare-worker" # any name you want
account_id = "<your account id>"
workers_dev = false
preview_urls = false
compatibility_date = "2022-08-11"
main = "kotlin-cloudflare-worker.js" # Set this value same as `outputModuleName`
```
Then run gradle task `gradlew compileProductionExecutableKotlinJs`,
copy wrangler.toml into `build/compileSync/js/main/productionExecutable/kotlin`,
and run `wrangler dev` command in `build/compileSync/js/main/productionExecutable/kotlin`,
## Deploy
Run gradle task, copy wrangler.toml, but use `wrangler deploy` to deploy to cloudflare worker
# Note
JavaScript uses a single-threaded execution model. All asynchronous work is ultimately driven by the event loop (
including Kotlin coroutines on JS).
Therefore, DO NOT create a CoroutineScope(Dispatchers.Default) or launch CPU-bound coroutines, as there is no real
background thread on JS targets.
All coroutines run on same event loop thread, and all coroutines not in same event loop will be dropped.
Example:
```kotlin
// DO NOT DO THIS
val scope = CoroutineScope(Dispatcher.DEFAULT)
fun blockingFunction() {
scope.launch {
// this block will never execute
}
}
// Instead of do this
fun main() {
@Suppress("unused_expression")
val eventListener = EventListener { event ->
val dyn = event.asDynamic()
event.asDynamic().respondWith(handleRequest(dyn.request as Request))
Unit
}
js("addEventListener('fetch', eventListener)")
}
@JsExport
fun handleRequest(request: Request): Promise<Response> = GlobalScope.promise {
return Promise.resolve(Response("Hello"))
}
```
# Http client
Cloudflare worker is not a standard nodejs environment, do http requests must
use fetch api(not `window.fetch`, this is browser api), use `cn.rtast.cfworker.client.fetch` instead,
# ByteArray and ByteBuffer cast
Kotlin cloudflare worker provided api to mutual conversion,
```kotlin
import cn.rtast.cfworker.util.toByteArray
import cn.rtast.cfworker.util.toArrayBuffer
val bb: ByteBuffer = ...
// convert ByteBuffer to ByteArray
val ba: ByteArray = bb.toByteArray()
// convert ByteArray to ByteBuffer
val bb2: ByteBuffer = ba.toArrayBuffer()
```
# Real instance
https://repo.maven.rtast.cn
> Yes, it the maven repository but built with kotlin/js with this lib