chore(MP-23): network DI client, frontend architecture guards, detekt & ktlint setup, docs, ping DI factory (#21)
* chore(MP-21): snapshot pre-refactor state (Epic 1) * chore(MP-22): scaffold new repo structure, relocate Docker Compose, move frontend/backend modules, update Makefile; add docs mapping and env template * MP-22 Epic 2: Erfolgreich umgesetzt und verifiziert * MP-23 Epic 3: Gradle/Build Governance zentralisieren
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
actual fun isDevelopmentMode(): Boolean =
|
||||
kotlinx.browser.window.location.hostname == "localhost"
|
||||
@@ -0,0 +1,67 @@
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.window.ComposeViewport
|
||||
import kotlinx.browser.document
|
||||
import org.w3c.dom.HTMLElement
|
||||
import at.mocode.clients.shared.di.initKoin
|
||||
import at.mocode.frontend.core.network.networkModule
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.context.GlobalContext
|
||||
import org.koin.core.qualifier.named
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
fun main() {
|
||||
console.log("[WebApp] main() entered")
|
||||
// Initialize DI (Koin) with shared modules + network module
|
||||
try {
|
||||
initKoin { modules(networkModule) }
|
||||
console.log("[WebApp] Koin initialized with networkModule")
|
||||
} catch (e: dynamic) {
|
||||
console.warn("[WebApp] Koin initialization warning:", e)
|
||||
}
|
||||
// Simple smoke request using DI apiClient
|
||||
try {
|
||||
val client = GlobalContext.get().get<HttpClient>(named("apiClient"))
|
||||
MainScope().launch {
|
||||
try {
|
||||
val resp: String = client.get("/api/ping/health").body()
|
||||
console.log("[WebApp] /api/ping/health → ", resp)
|
||||
} catch (e: dynamic) {
|
||||
console.warn("[WebApp] /api/ping/health failed:", e?.message ?: e)
|
||||
}
|
||||
}
|
||||
} catch (e: dynamic) {
|
||||
console.warn("[WebApp] Unable to resolve apiClient from Koin:", e)
|
||||
}
|
||||
fun startApp() {
|
||||
try {
|
||||
console.log("[WebApp] startApp(): readyState=", document.asDynamic().readyState)
|
||||
val root = document.getElementById("ComposeTarget") as HTMLElement
|
||||
console.log("[WebApp] ComposeTarget exists? ", (root != null))
|
||||
ComposeViewport(root) {
|
||||
MainApp()
|
||||
}
|
||||
// Remove the static loading placeholder if present
|
||||
(document.querySelector(".loading") as? HTMLElement)?.let { it.parentElement?.removeChild(it) }
|
||||
console.log("[WebApp] ComposeViewport mounted, loading placeholder removed")
|
||||
} catch (e: Exception) {
|
||||
console.error("Failed to start Compose Web app", e)
|
||||
val fallbackTarget = (document.getElementById("ComposeTarget") ?: document.body) as HTMLElement
|
||||
fallbackTarget.innerHTML =
|
||||
"<div style='padding: 50px; text-align: center;'>❌ Failed to load app: ${e.message}</div>"
|
||||
}
|
||||
}
|
||||
|
||||
// Start immediately if DOM is already parsed, otherwise wait for DOMContentLoaded.
|
||||
val state = document.asDynamic().readyState as String?
|
||||
if (state == "interactive" || state == "complete") {
|
||||
console.log("[WebApp] DOM already ready (", state, ") → starting immediately")
|
||||
startApp()
|
||||
} else {
|
||||
console.log("[WebApp] Waiting for DOMContentLoaded, current state:", state)
|
||||
document.addEventListener("DOMContentLoaded", { startApp() })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user