refactor(build): enable Wasm by default and refactor modules for improved KMP compatibility
Enabled Wasm target across all relevant modules and removed conditional enablement logic. Refactored `core:core-utils` to move JVM-specific code to a new `backend:infrastructure:persistence` module for strict KMP compliance. Updated dependencies, adjusted Gradle configurations, and resolved circular dependencies.
This commit is contained in:
@@ -7,7 +7,6 @@ plugins {
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
jvm()
|
||||
js(IR) {
|
||||
@@ -15,12 +14,10 @@ kotlin {
|
||||
// nodejs()
|
||||
}
|
||||
|
||||
// WASM, nur wenn explizit aktiviert
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
// WASM enabled by default
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -10,7 +10,9 @@ plugins {
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
// Wasm is now a first-class citizen in our stack, so we enable it by default
|
||||
// val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
jvm()
|
||||
js {
|
||||
@@ -19,10 +21,9 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs { browser() }
|
||||
}
|
||||
// Always enable Wasm to match the rest of the KMP stack
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs { browser() }
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
|
||||
@@ -10,7 +10,6 @@ plugins {
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
jvm()
|
||||
js {
|
||||
@@ -19,11 +18,10 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
// Wasm enabled by default
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -42,11 +40,9 @@ kotlin {
|
||||
implementation(libs.sqldelight.driver.web)
|
||||
}
|
||||
|
||||
if (enableWasm) {
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.sqldelight.driver.web)
|
||||
}
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.sqldelight.driver.web)
|
||||
}
|
||||
|
||||
commonTest.dependencies {
|
||||
|
||||
+12
-4
@@ -6,10 +6,12 @@ import org.w3c.dom.Worker
|
||||
|
||||
actual class DatabaseDriverFactory {
|
||||
actual suspend fun createDriver(): SqlDriver {
|
||||
// Same as JS, we use a Web Worker for Wasm to support OPFS
|
||||
val worker = Worker(
|
||||
js("""new URL("sqlite.worker.js", import.meta.url)""")
|
||||
)
|
||||
// In Kotlin/Wasm, we cannot use the js() function inside a function body like in Kotlin/JS.
|
||||
// We need to use a helper function or a different approach.
|
||||
// However, for WebWorkerDriver, we need a Worker instance.
|
||||
|
||||
// Workaround for Wasm: Use a helper function to create the Worker
|
||||
val worker = createWorker()
|
||||
val driver = WebWorkerDriver(worker)
|
||||
|
||||
AppDatabase.Schema.create(driver).await()
|
||||
@@ -17,3 +19,9 @@ actual class DatabaseDriverFactory {
|
||||
return driver
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to create a Worker in Wasm
|
||||
// Note: Kotlin/Wasm JS interop is stricter.
|
||||
// We must return a type that Wasm understands as an external JS reference.
|
||||
// 'Worker' from org.w3c.dom is correct, but we need to ensure the stdlib is available.
|
||||
private fun createWorker(): Worker = js("new Worker(new URL('sqlite.worker.js', import.meta.url))")
|
||||
|
||||
@@ -11,7 +11,6 @@ version = "1.0.0"
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
jvm()
|
||||
|
||||
@@ -25,11 +24,10 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
// Wasm enabled by default
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
@@ -10,7 +10,6 @@ plugins {
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
jvm()
|
||||
js {
|
||||
@@ -19,10 +18,9 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs { browser() }
|
||||
}
|
||||
// Wasm enabled by default
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs { browser() }
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
@@ -52,11 +50,9 @@ kotlin {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
|
||||
if (enableWasm) {
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-11
@@ -2,28 +2,35 @@ package at.mocode.frontend.core.network
|
||||
|
||||
import kotlinx.browser.window
|
||||
|
||||
@Suppress("UnsafeCastFromDynamic", "EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
|
||||
@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
|
||||
actual object PlatformConfig {
|
||||
actual fun resolveApiBaseUrl(): String {
|
||||
// 1) Prefer a global JS variable (can be injected by index.html or nginx)
|
||||
val global =
|
||||
js("typeof globalThis !== 'undefined' ? globalThis : (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {}))")
|
||||
val fromGlobal = try {
|
||||
(global.API_BASE_URL as? String)?.trim().orEmpty()
|
||||
} catch (_: dynamic) {
|
||||
""
|
||||
}
|
||||
val fromGlobal = getGlobalApiBaseUrl()
|
||||
if (fromGlobal.isNotEmpty()) return fromGlobal.removeSuffix("/")
|
||||
|
||||
// 2) Try window location origin (same origin gateway/proxy setup)
|
||||
// In Wasm, we can access a window directly if we are in the browser main thread.
|
||||
// However, we need to be careful about exceptions.
|
||||
val origin = try {
|
||||
window.location.origin
|
||||
} catch (_: dynamic) {
|
||||
null
|
||||
window.location.origin
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
|
||||
if (!origin.isNullOrBlank()) return origin.removeSuffix("/")
|
||||
|
||||
// 3) Fallback to the local gateway
|
||||
return "http://localhost:8081"
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for JS interop in Wasm
|
||||
// Kotlin/Wasm does not support 'dynamic' type or complex js() blocks inside functions.
|
||||
// We must use top-level external functions or simple js() expressions.
|
||||
private fun getGlobalApiBaseUrl(): String = js("""
|
||||
(function() {
|
||||
var global = typeof globalThis !== 'undefined' ? globalThis : (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {}));
|
||||
return (global.API_BASE_URL && typeof global.API_BASE_URL === 'string') ? global.API_BASE_URL : "";
|
||||
})()
|
||||
""")
|
||||
|
||||
@@ -17,7 +17,6 @@ version = "1.0.0"
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
jvm()
|
||||
|
||||
@@ -29,12 +28,10 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
// WASM, nur wenn explizit aktiviert
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
// Wasm enabled by default
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -85,17 +82,14 @@ kotlin {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
|
||||
// WASM SourceSet, nur wenn aktiviert
|
||||
if (enableWasm) {
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7]
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7]
|
||||
|
||||
// Compose für shared UI components für WASM
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
}
|
||||
// Compose für shared UI components für WASM
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ version = "1.0.0"
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
jvm()
|
||||
|
||||
@@ -29,12 +28,10 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
// WASM, nur wenn explizit aktiviert
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
// Wasm enabled by default
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -85,17 +82,14 @@ kotlin {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
|
||||
// WASM SourceSet, nur wenn aktiviert
|
||||
if (enableWasm) {
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7]
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7]
|
||||
|
||||
// Compose für shared UI components für WASM
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
}
|
||||
// Compose für shared UI components für WASM
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,121 +1,79 @@
|
||||
@file:OptIn(ExperimentalKotlinGradlePluginApi::class, ExperimentalWasmDsl::class)
|
||||
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
/**
|
||||
* Shared Module: Gemeinsame Libraries und Utilities für alle Client-Features
|
||||
* KEINE EXECUTABLE - ist eine Library für andere Module
|
||||
*/
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
alias(libs.plugins.composeMultiplatform)
|
||||
alias(libs.plugins.composeCompiler)
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
alias(libs.plugins.composeMultiplatform)
|
||||
alias(libs.plugins.composeCompiler)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
jvm("desktop")
|
||||
|
||||
// JVM Target für Desktop
|
||||
jvm()
|
||||
|
||||
// JavaScript Target für Web
|
||||
js {
|
||||
browser {
|
||||
testTask {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
// ...
|
||||
}
|
||||
|
||||
// WASM, nur wenn explizit aktiviert
|
||||
if (enableWasm) {
|
||||
@OptIn(ExperimentalWasmDsl::class)
|
||||
wasmJs { browser() }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
|
||||
api(projects.core.coreUtils)
|
||||
api(projects.core.coreDomain)
|
||||
api(project(":frontend:core:domain"))
|
||||
|
||||
// Kotlinx core dependencies (coroutines, serialization, datetime)
|
||||
// KORREKTUR: Zugriff auf Bundle korrigiert.
|
||||
// In libs.versions.toml: [bundles] kotlinx-core = [...]
|
||||
// Gradle Accessor: libs.bundles.kotlinx.core
|
||||
// Falls das fehlschlägt, listen wir die Libs einzeln auf, um den Build zu fixen.
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
implementation(libs.kotlinx.datetime)
|
||||
|
||||
// HTTP Client
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.contentNegotiation)
|
||||
implementation(libs.ktor.client.serialization.kotlinx.json)
|
||||
implementation(libs.ktor.client.logging)
|
||||
implementation(libs.ktor.client.auth)
|
||||
|
||||
// Dependency Injection (Koin)
|
||||
implementation(libs.koin.core)
|
||||
implementation(libs.koin.compose)
|
||||
implementation(libs.koin.compose.viewmodel)
|
||||
|
||||
// Network module (provides DI `apiClient`)
|
||||
implementation(projects.frontend.core.network)
|
||||
|
||||
// Compose für shared UI components (common)
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
js(IR) {
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
commonTest.dependencies {
|
||||
implementation(libs.kotlin.test)
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
jvmMain.dependencies {
|
||||
implementation(libs.ktor.client.cio)
|
||||
}
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation(projects.frontend.core.domain)
|
||||
// implementation(projects.frontend.core.designSystem) // REMOVED: Circular dependency
|
||||
implementation(projects.frontend.core.navigation)
|
||||
implementation(projects.frontend.core.network)
|
||||
implementation(projects.frontend.core.localDb)
|
||||
|
||||
jsMain.dependencies {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
// Features - REMOVED: Circular dependency. Shared should NOT depend on features.
|
||||
// implementation(projects.frontend.features.authFeature)
|
||||
// implementation(projects.frontend.features.pingFeature)
|
||||
|
||||
// WASM SourceSet, nur wenn aktiviert
|
||||
if (enableWasm) {
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js) // WASM verwendet JS-Clients
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
// KMP Bundles
|
||||
implementation(libs.bundles.kmp.common)
|
||||
implementation(libs.bundles.compose.common)
|
||||
|
||||
}
|
||||
// Compose
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
implementation(compose.ui)
|
||||
implementation(compose.components.resources)
|
||||
implementation(compose.components.uiToolingPreview)
|
||||
|
||||
// Koin
|
||||
implementation(libs.koin.core)
|
||||
implementation(libs.koin.compose)
|
||||
implementation(libs.koin.compose.viewmodel)
|
||||
}
|
||||
}
|
||||
|
||||
commonTest {
|
||||
dependencies {
|
||||
implementation(libs.kotlin.test)
|
||||
}
|
||||
}
|
||||
|
||||
val desktopMain by getting {
|
||||
dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation(libs.kotlinx.coroutines.swing)
|
||||
}
|
||||
}
|
||||
|
||||
val jsMain by getting {
|
||||
dependencies {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
}
|
||||
|
||||
val wasmJsMain by getting {
|
||||
dependencies {
|
||||
implementation(libs.ktor.client.js)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// KMP Compile-Optionen
|
||||
tasks.withType<KotlinCompile> {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_25)
|
||||
freeCompilerArgs.addAll(
|
||||
"-opt-in=kotlin.RequiresOptIn"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<KotlinJsCompile>().configureEach {
|
||||
compilerOptions {
|
||||
target = "es2015"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ plugins {
|
||||
|
||||
kotlin {
|
||||
// Toolchain is now handled centrally in the root build.gradle.kts
|
||||
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
|
||||
|
||||
// JVM Target für Desktop
|
||||
jvm {
|
||||
@@ -62,13 +61,11 @@ kotlin {
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
// WASM, nur wenn explizit aktiviert
|
||||
if (enableWasm) {
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
// Wasm enabled by default
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -110,17 +107,14 @@ kotlin {
|
||||
implementation(compose.html.core)
|
||||
}
|
||||
|
||||
// WASM SourceSet, nur wenn aktiviert
|
||||
if (enableWasm) {
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7]
|
||||
val wasmJsMain = getByName("wasmJsMain")
|
||||
wasmJsMain.dependencies {
|
||||
implementation(libs.ktor.client.js) // WASM verwendet JS-Client [cite: 7]
|
||||
|
||||
// Compose für shared UI components für WASM
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
}
|
||||
// Compose für shared UI components für WASM
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
implementation(compose.material3)
|
||||
}
|
||||
|
||||
commonTest.dependencies {
|
||||
|
||||
Reference in New Issue
Block a user