diff --git a/startup/launcher/build.gradle b/startup/launcher/build.gradle index 5e762e51950..c4905f21051 100644 --- a/startup/launcher/build.gradle +++ b/startup/launcher/build.gradle @@ -1,6 +1,7 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" + id "application" } apply from: "$mppJavaProjectPresetPath" @@ -14,3 +15,12 @@ kotlin { } } } + +application { + mainClassName = "dev.inmo.micro_utils.startup.launcher.ServerLauncherKt" +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} diff --git a/startup/launcher/src/commonMain/kotlin/HelloWorldPlugin.kt b/startup/launcher/src/commonMain/kotlin/HelloWorldPlugin.kt new file mode 100644 index 00000000000..81842523b23 --- /dev/null +++ b/startup/launcher/src/commonMain/kotlin/HelloWorldPlugin.kt @@ -0,0 +1,13 @@ +package dev.inmo.micro_utils.startup.launcher + +import dev.inmo.kslog.common.i +import dev.inmo.kslog.common.logger +import dev.inmo.micro_utils.startup.plugin.ServerPlugin +import org.koin.core.Koin + +object HelloWorldPlugin : ServerPlugin { + override suspend fun startPlugin(koin: Koin) { + super.startPlugin(koin) + logger.i("Hello world") + } +} diff --git a/startup/launcher/src/commonMain/kotlin/Start.kt b/startup/launcher/src/commonMain/kotlin/Start.kt new file mode 100644 index 00000000000..ae17d7a668b --- /dev/null +++ b/startup/launcher/src/commonMain/kotlin/Start.kt @@ -0,0 +1,24 @@ +package dev.inmo.micro_utils.startup.launcher + +import dev.inmo.kslog.common.i +import kotlinx.serialization.json.JsonObject +import org.koin.core.KoinApplication +import org.koin.core.context.GlobalContext +import org.koin.dsl.module + +suspend fun start(rawConfig: JsonObject) { + with(StartupLauncherPlugin) { + logger.i("Start initialization") + val koinApp = KoinApplication.init() + koinApp.modules( + module { + setupDI(rawConfig) + } + ) + logger.i("Modules loaded") + GlobalContext.startKoin(koinApp) + logger.i("Koin started") + startPlugin(koinApp.koin) + logger.i("App has been setup") + } +} diff --git a/startup/launcher/src/commonMain/kotlin/StartupLauncher.kt b/startup/launcher/src/commonMain/kotlin/StartupLauncherPlugin.kt similarity index 97% rename from startup/launcher/src/commonMain/kotlin/StartupLauncher.kt rename to startup/launcher/src/commonMain/kotlin/StartupLauncherPlugin.kt index 9640df8f299..4e98131747c 100644 --- a/startup/launcher/src/commonMain/kotlin/StartupLauncher.kt +++ b/startup/launcher/src/commonMain/kotlin/StartupLauncherPlugin.kt @@ -14,7 +14,7 @@ import org.koin.core.Koin import org.koin.core.module.Module import org.koin.dsl.module -object StartupLauncher : ServerPlugin { +object StartupLauncherPlugin : ServerPlugin { internal val logger = taggedLogger(this) override fun Module.setupDI(config: JsonObject) { val pluginsConfig = defaultJson.decodeFromJsonElement(Config.serializer(), config) diff --git a/startup/launcher/src/jvmMain/kotlin/Main.kt b/startup/launcher/src/jvmMain/kotlin/Main.kt new file mode 100644 index 00000000000..d4f1789f2b4 --- /dev/null +++ b/startup/launcher/src/jvmMain/kotlin/Main.kt @@ -0,0 +1,18 @@ +package dev.inmo.micro_utils.startup.launcher + +import dev.inmo.kslog.common.KSLog +import dev.inmo.kslog.common.i +import kotlinx.serialization.json.jsonObject +import java.io.File + +suspend fun main(args: Array) { + + KSLog.default = KSLog("ServerLauncher") + val (configPath) = args + val file = File(configPath) + KSLog.i("Start read config from ${file.absolutePath}") + val json = defaultJson.parseToJsonElement(file.readText()).jsonObject + KSLog.i("Config has been read") + + start(json) +} diff --git a/startup/launcher/src/jvmMain/kotlin/ServerLauncher.kt b/startup/launcher/src/jvmMain/kotlin/ServerLauncher.kt deleted file mode 100644 index 2a72b7707af..00000000000 --- a/startup/launcher/src/jvmMain/kotlin/ServerLauncher.kt +++ /dev/null @@ -1,36 +0,0 @@ -package dev.inmo.micro_utils.startup.launcher - -import dev.inmo.kslog.common.KSLog -import dev.inmo.kslog.common.i -import dev.inmo.micro_utils.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.serialization.json.jsonObject -import org.koin.core.KoinApplication -import org.koin.core.context.GlobalContext -import org.koin.dsl.module -import java.io.File - -suspend fun main(args: Array) { - - KSLog.default = KSLog("ServerLauncher") - val (configPath) = args - val file = File(configPath) - KSLog.i("Start read config from ${file.absolutePath}") - val json = defaultJson.parseToJsonElement(file.readText()).jsonObject - KSLog.i("Config has been read") - - with(StartupLauncher) { - logger.i("Start initialization") - val koinApp = KoinApplication.init() - koinApp.modules( - module { - setupDI(json) - } - ) - logger.i("Modules loaded") - GlobalContext.startKoin(koinApp) - logger.i("Koin started") - startPlugin(koinApp.koin) - logger.i("Behaviour builder has been setup") - } -} diff --git a/startup/launcher/src/jvmTest/kotlin/StartupLaunchingTests.kt b/startup/launcher/src/jvmTest/kotlin/StartupLaunchingTests.kt new file mode 100644 index 00000000000..7f9f80aea50 --- /dev/null +++ b/startup/launcher/src/jvmTest/kotlin/StartupLaunchingTests.kt @@ -0,0 +1,39 @@ +import dev.inmo.micro_utils.coroutines.launchSynchronously +import dev.inmo.micro_utils.startup.launcher.Config +import dev.inmo.micro_utils.startup.launcher.HelloWorldPlugin +import dev.inmo.micro_utils.startup.launcher.defaultJson +import dev.inmo.micro_utils.startup.launcher.start +import kotlinx.coroutines.launch +import kotlinx.serialization.json.jsonObject +import kotlin.test.Test + +class StartupLaunchingTests { + @Test(timeout = 1000L) + fun CheckThatEmptyPluginsListLeadsToEndOfMain() { + val emptyJson = defaultJson.encodeToJsonElement( + Config.serializer(), + Config(emptyList()) + ).jsonObject + + launchSynchronously { + val job = launch { + start(emptyJson) + } + job.join() + } + } + @Test(timeout = 1000L) + fun CheckThatHelloWorldPluginsListLeadsToEndOfMain() { + val emptyJson = defaultJson.encodeToJsonElement( + Config.serializer(), + Config(listOf(HelloWorldPlugin)) + ).jsonObject + + launchSynchronously { + val job = launch { + start(emptyJson) + } + job.join() + } + } +} diff --git a/startup/plugin/build.gradle b/startup/plugin/build.gradle index 851613c225e..9177a9e7e61 100644 --- a/startup/plugin/build.gradle +++ b/startup/plugin/build.gradle @@ -12,6 +12,7 @@ kotlin { api libs.koin api libs.kt.serialization api libs.kslog + api libs.kt.reflect api project(":micro_utils.coroutines") } } diff --git a/startup/plugin/src/commonMain/kotlin/ServerPlugin.kt b/startup/plugin/src/commonMain/kotlin/ServerPlugin.kt index 25019809ad5..f40ad8c6db5 100644 --- a/startup/plugin/src/commonMain/kotlin/ServerPlugin.kt +++ b/startup/plugin/src/commonMain/kotlin/ServerPlugin.kt @@ -1,34 +1,13 @@ 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) +@Serializable(ServerPluginSerializer::class) interface ServerPlugin { fun Module.setupDI(config: JsonObject) {} suspend fun startPlugin(koin: Koin) {} - - 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 - ) - } - } } diff --git a/startup/plugin/src/commonMain/kotlin/ServerPluginSerializer.kt b/startup/plugin/src/commonMain/kotlin/ServerPluginSerializer.kt new file mode 100644 index 00000000000..72cc877b175 --- /dev/null +++ b/startup/plugin/src/commonMain/kotlin/ServerPluginSerializer.kt @@ -0,0 +1,5 @@ +package dev.inmo.micro_utils.startup.plugin + +import kotlinx.serialization.KSerializer + +expect object ServerPluginSerializer : KSerializer diff --git a/startup/plugin/src/jvmMain/kotlin/ServerPluginSerializer.kt b/startup/plugin/src/jvmMain/kotlin/ServerPluginSerializer.kt new file mode 100644 index 00000000000..3875b65ac53 --- /dev/null +++ b/startup/plugin/src/jvmMain/kotlin/ServerPluginSerializer.kt @@ -0,0 +1,23 @@ +package dev.inmo.micro_utils.startup.plugin + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +actual object ServerPluginSerializer : 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 + ) + } +}