diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 493ed2a0e72..b5c564a71a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,6 +4,8 @@ kt = "1.7.20" kt-serialization = "1.4.1" kt-coroutines = "1.6.4" +kslog = "0.5.4" + jb-compose = "1.2.1" jb-exposed = "0.41.1" jb-dokka = "1.7.20" @@ -60,6 +62,7 @@ ktor-server-websockets = { module = "io.ktor:ktor-server-websockets", version.re ktor-server-statusPages = { module = "io.ktor:ktor-server-status-pages", version.ref = "ktor" } ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" } +kslog = { module = "dev.inmo:kslog", version.ref = "kslog" } klock = { module = "com.soywiz.korlibs.klock:klock", version.ref = "klock" } uuid = { module = "com.benasher44:uuid", version.ref = "uuid" } diff --git a/mppProjectWithSerialization.gradle b/mppProjectWithSerialization.gradle index 615ec80d132..05177943155 100644 --- a/mppProjectWithSerialization.gradle +++ b/mppProjectWithSerialization.gradle @@ -23,7 +23,7 @@ kotlin { commonMain { dependencies { implementation kotlin('stdlib') - implementation libs.kt.serialization + api libs.kt.serialization } } commonTest { diff --git a/mppProjectWithSerializationAndCompose.gradle b/mppProjectWithSerializationAndCompose.gradle index eff5f7fe0c0..e5fa8355c23 100644 --- a/mppProjectWithSerializationAndCompose.gradle +++ b/mppProjectWithSerializationAndCompose.gradle @@ -23,7 +23,7 @@ kotlin { commonMain { dependencies { implementation kotlin('stdlib') - implementation libs.kt.serialization + api libs.kt.serialization implementation compose.runtime } } diff --git a/settings.gradle b/settings.gradle index ccd2dc06d84..069bd208c00 100644 --- a/settings.gradle +++ b/settings.gradle @@ -32,6 +32,8 @@ String[] includes = [ ":serialization:base64", ":serialization:encapsulator", ":serialization:typed_serializer", + ":startup:plugin", + ":startup:launcher", ":fsm:common", ":fsm:repos:common", diff --git a/startup/launcher/build.gradle b/startup/launcher/build.gradle new file mode 100644 index 00000000000..5b3c3a61734 --- /dev/null +++ b/startup/launcher/build.gradle @@ -0,0 +1,17 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" +} + +apply from: "$mppJavaProjectPresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api internalProject("micro_utils.startup.plugin") + api libs.kslog + } + } + } +} diff --git a/startup/launcher/src/commonMain/kotlin/Config.kt b/startup/launcher/src/commonMain/kotlin/Config.kt new file mode 100644 index 00000000000..f52ad983aea --- /dev/null +++ b/startup/launcher/src/commonMain/kotlin/Config.kt @@ -0,0 +1,9 @@ +package dev.inmo.micro_utils.startup.launcher + +import dev.inmo.micro_utils.startup.plugin.ServerPlugin +import kotlinx.serialization.Serializable + +@Serializable +data class Config( + val plugins: List +) diff --git a/startup/launcher/src/commonMain/kotlin/ServerLauncher.kt b/startup/launcher/src/commonMain/kotlin/ServerLauncher.kt new file mode 100644 index 00000000000..9f63ef3add7 --- /dev/null +++ b/startup/launcher/src/commonMain/kotlin/ServerLauncher.kt @@ -0,0 +1,38 @@ +package dev.inmo.micro_utils.startup.launcher + +import dev.inmo.micro_utils.startup.plugin.ServerPlugin +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObject +import org.koin.core.Koin +import org.koin.core.module.Module +import org.koin.dsl.module + +class ServerLauncher : ServerPlugin { + val defaultJson = Json { + ignoreUnknownKeys = true + } + + override fun Module.setupDI(config: JsonObject) { + val pluginsConfig = defaultJson.decodeFromJsonElement(Config.serializer(), config) + + single { pluginsConfig } + + includes( + pluginsConfig.plugins.map { + module { + with(it) { + setupDI(config) + } + } + } + ) + } + + override suspend fun Koin.startPlugin() { + get().plugins.forEach { + with(it) { + startPlugin() + } + } + } +} diff --git a/startup/launcher/src/jvmMain/kotlin/ServerLauncher.kt b/startup/launcher/src/jvmMain/kotlin/ServerLauncher.kt new file mode 100644 index 00000000000..b412f331e92 --- /dev/null +++ b/startup/launcher/src/jvmMain/kotlin/ServerLauncher.kt @@ -0,0 +1,24 @@ +package dev.inmo.micro_utils.startup.launcher + +import dev.inmo.kslog.common.KSLog +import dev.inmo.kslog.common.i +import dev.inmo.micro_utils.startup.plugin.ServerPlugin +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObject +import org.koin.core.Koin +import org.koin.core.module.Module +import org.koin.dsl.module +import java.io.File + +suspend fun main(args: Array) { + + KSLog.default = KSLog("PlaguBot") + val (configPath) = args + val file = File(configPath) + KSLog.i("Start read config from ${file.absolutePath}") + val json = defaultJsonFormat.parseToJsonElement(file.readText()).jsonObject + val config = defaultJsonFormat.decodeFromJsonElement(Config.serializer(), json) + KSLog.i("Config has been read") + + PlaguBot(json, config).start().join() +} diff --git a/startup/plugin/build.gradle b/startup/plugin/build.gradle new file mode 100644 index 00000000000..f7e590a535b --- /dev/null +++ b/startup/plugin/build.gradle @@ -0,0 +1,17 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" +} + +apply from: "$mppJavaProjectPresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api libs.koin + api libs.kt.serialization + } + } + } +} diff --git a/startup/plugin/src/commonMain/kotlin/ServerPlugin.kt b/startup/plugin/src/commonMain/kotlin/ServerPlugin.kt new file mode 100644 index 00000000000..91cfc36f0b5 --- /dev/null +++ b/startup/plugin/src/commonMain/kotlin/ServerPlugin.kt @@ -0,0 +1,34 @@ +package dev.inmo.micro_utils.startup.plugin + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.JsonObject +import org.koin.core.Koin +import org.koin.core.module.Module + +@Serializable(ServerPlugin.Companion::class) +interface ServerPlugin { + fun Module.setupDI(config: JsonObject) {} + + suspend fun Koin.startPlugin() {} + + companion object : KSerializer { + override val descriptor: SerialDescriptor + get() = String.serializer().descriptor + + override fun deserialize(decoder: Decoder): ServerPlugin { + val kclass = Class.forName(decoder.decodeString()).kotlin + return (kclass.objectInstance ?: kclass.constructors.first { it.parameters.isEmpty() }.call()) as ServerPlugin + } + + override fun serialize(encoder: Encoder, value: ServerPlugin) { + encoder.encodeString( + value::class.java.canonicalName + ) + } + } +}