Compare commits

..

20 Commits

Author SHA1 Message Date
592c5f3732 Column extensions eqOrIsNull and neqOrIsNotNull 2023-01-14 20:17:57 +06:00
f44a78a5f5 small improvement of openBaseWebSocketFlow 2023-01-14 15:20:52 +06:00
e0bdd5dfdc improvements in microutils 2023-01-14 13:22:07 +06:00
99c0f06b72 repos update 2023-01-14 13:15:59 +06:00
66fc6df3d7 Improvements in 'StartLauncherPlugin#start' methods 2023-01-08 13:52:53 +06:00
a36425a905 start 0.16.6 2023-01-08 13:51:34 +06:00
d920fee6d4 Merge pull request #216 from InsanusMokrassar/0.16.5
0.16.5
2023-01-04 20:21:15 +06:00
23590be5de Update CHANGELOG.md 2023-01-04 20:20:25 +06:00
94acc3c93b Update libs.versions.toml 2023-01-04 08:56:46 +06:00
5616326a3b start 0.16.5 2023-01-04 08:50:19 +06:00
7601860c5c Merge pull request #214 from InsanusMokrassar/0.16.4
0.16.4
2022-12-27 19:03:35 +06:00
8b43d785cc update changelog 2022-12-27 18:51:01 +06:00
b62d3a0b7d launchInCurrentThread 2022-12-27 18:50:41 +06:00
fad73c7213 start 0.16.4 2022-12-27 18:49:04 +06:00
2403c7c2b0 Merge pull request #213 from InsanusMokrassar/0.16.3
0.16.3
2022-12-25 13:24:37 +06:00
fa090bf920 Update StartLauncherPlugin.kt 2022-12-25 10:29:16 +06:00
a83ee86340 improvements in startup launcher 2022-12-25 10:26:44 +06:00
204955bcce add template for startup and readme 2022-12-19 17:51:05 +06:00
ee56e9543a start 0.16.3 2022-12-17 17:27:15 +06:00
96fdff6ffd Merge pull request #212 from InsanusMokrassar/0.16.2
0.16.2
2022-12-16 13:59:47 +06:00
39 changed files with 622 additions and 84 deletions

View File

@@ -1,5 +1,34 @@
# Changelog # Changelog
## 0.16.6
* `Startup`:
* `Launcher`:
* Improvements in `StartLauncherPlugin#start` methods
* Add opportunity to pass second argument on `JVM` platform as log level
* `Repos`:
* `Ktor`:
* `Client`:
* All clients repos got opportunity to customize their flows
* `Exposed`:
* Extensions `eqOrIsNull` and `neqOrIsNotNull` for `Column`
## 0.16.5
* `Versions`:
* `Ktor`: `2.2.1` -> `2.2.2`
## 0.16.4
* `Coroutines`:
* Create `launchInCurrentThread`
## 0.16.3
* `Startup`:
* `Launcher`:
* All starting API have been moved into `StartLauncherPlugin` and do not require serialize/deserialize cycle for now
## 0.16.2 ## 0.16.2
* `Versions`: * `Versions`:

View File

@@ -22,6 +22,7 @@ kotlin {
dependencies { dependencies {
api libs.kt.coroutines.android api libs.kt.coroutines.android
} }
dependsOn(jvmMain)
} }
} }
} }

View File

@@ -0,0 +1,9 @@
package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
fun <T> launchInCurrentThread(block: suspend CoroutineScope.() -> T): T {
val scope = CoroutineScope(Dispatchers.Unconfined)
return scope.launchSynchronously(block)
}

View File

@@ -6,7 +6,7 @@ fun <T> CoroutineScope.launchSynchronously(block: suspend CoroutineScope.() -> T
var result: Result<T>? = null var result: Result<T>? = null
val objectToSynchronize = Object() val objectToSynchronize = Object()
synchronized(objectToSynchronize) { synchronized(objectToSynchronize) {
launch { launch(start = CoroutineStart.UNDISPATCHED) {
result = safelyWithResult(block) result = safelyWithResult(block)
}.invokeOnCompletion { }.invokeOnCompletion {
synchronized(objectToSynchronize) { synchronized(objectToSynchronize) {

View File

@@ -0,0 +1,47 @@
package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import kotlin.test.Test
import kotlin.test.assertEquals
class LaunchInCurrentThreadTests {
@Test
fun simpleTestThatLaunchInCurrentThreadWorks() {
val expectedResult = 10
val result = launchInCurrentThread {
expectedResult
}
assertEquals(expectedResult, result)
}
@Test
fun simpleTestThatSeveralLaunchInCurrentThreadWorks() {
val testData = 0 until 100
testData.forEach {
val result = launchInCurrentThread {
it
}
assertEquals(it, result)
}
}
@Test
fun simpleTestThatLaunchInCurrentThreadWillCorrectlyHandleSuspensionsWorks() {
val testData = 0 until 100
suspend fun test(data: Any): Any {
return withContext(Dispatchers.Default) {
delay(1)
data
}
}
testData.forEach {
val result = launchInCurrentThread {
test(it)
}
assertEquals(it, result)
}
}
}

View File

@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.16.2 version=0.16.6
android_code_version=170 android_code_version=174

View File

@@ -13,7 +13,7 @@ jb-dokka = "1.7.20"
klock = "3.4.0" klock = "3.4.0"
uuid = "0.6.0" uuid = "0.6.0"
ktor = "2.2.1" ktor = "2.2.2"
gh-release = "2.4.1" gh-release = "2.4.1"

View File

@@ -19,7 +19,7 @@ import kotlinx.coroutines.isActive
* connection. Must return true in case if must be reconnected. By default always reconnecting * connection. Must return true in case if must be reconnected. By default always reconnecting
*/ */
@Warning("This feature is internal and should not be used directly. It is can be changed without any notification and warranty on compile-time or other guaranties") @Warning("This feature is internal and should not be used directly. It is can be changed without any notification and warranty on compile-time or other guaranties")
inline fun <reified T : Any> openBaseWebSocketFlow( inline fun <T : Any> openBaseWebSocketFlow(
noinline checkReconnection: suspend (Throwable?) -> Boolean = { true }, noinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
noinline webSocketSessionRequest: suspend SendChannel<T>.() -> Unit noinline webSocketSessionRequest: suspend SendChannel<T>.() -> Unit
): Flow<T> { ): Flow<T> {
@@ -57,7 +57,7 @@ inline fun <reified T : Any> HttpClient.openWebSocketFlow(
): Flow<T> { ): Flow<T> {
pluginOrNull(WebSockets) ?: error("Plugin $WebSockets must be installed for using createStandardWebsocketFlow") pluginOrNull(WebSockets) ?: error("Plugin $WebSockets must be installed for using createStandardWebsocketFlow")
return openBaseWebSocketFlow<T>(checkReconnection) { return openBaseWebSocketFlow(checkReconnection) {
val block: suspend DefaultClientWebSocketSession.() -> Unit = { val block: suspend DefaultClientWebSocketSession.() -> Unit = {
while (isActive) { while (isActive) {
send(receiveDeserialized<T>()) send(receiveDeserialized<T>())

View File

@@ -0,0 +1,23 @@
package dev.inmo.micro_utils.repos.exposed
import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNotNull
import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull
import org.jetbrains.exposed.sql.SqlExpressionBuilder.neq
fun <T> Column<T?>.eqOrIsNull(
value: T?
) = if (value == null) {
isNull()
} else {
eq(value)
}
fun <T> Column<T?>.neqOrIsNotNull(
value: T?
) = if (value == null) {
isNotNull()
} else {
neq(value)
}

View File

@@ -1,12 +1,17 @@
package dev.inmo.micro_utils.repos.ktor.client.crud package dev.inmo.micro_utils.repos.ktor.client.crud
import dev.inmo.micro_utils.ktor.client.createStandardWebsocketFlow
import dev.inmo.micro_utils.ktor.common.* import dev.inmo.micro_utils.ktor.common.*
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.ktor.common.crud.deletedObjectsIdsFlowRouting
import dev.inmo.micro_utils.repos.ktor.common.crud.newObjectsFlowRouting
import dev.inmo.micro_utils.repos.ktor.common.crud.updatedObjectsFlowRouting
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.util.reflect.TypeInfo import io.ktor.util.reflect.TypeInfo
import io.ktor.util.reflect.typeInfo import io.ktor.util.reflect.typeInfo
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.* import kotlinx.serialization.*
class KtorCRUDRepoClient<ObjectType, IdType, InputValue> ( class KtorCRUDRepoClient<ObjectType, IdType, InputValue> (
@@ -21,6 +26,15 @@ class KtorCRUDRepoClient<ObjectType, IdType, InputValue> (
baseUrl: String, baseUrl: String,
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType, contentType: ContentType,
newObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, newObjectsFlowRouting),
),
updatedObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
),
deletedObjectsIdsFlow: Flow<IdType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
),
noinline idSerializer: suspend (IdType) -> String noinline idSerializer: suspend (IdType) -> String
) = KtorCRUDRepoClient( ) = KtorCRUDRepoClient(
KtorReadCRUDRepoClient( KtorReadCRUDRepoClient(
@@ -35,7 +49,10 @@ class KtorCRUDRepoClient<ObjectType, IdType, InputValue> (
KtorWriteCrudRepoClient<ObjectType, IdType, InputValue>( KtorWriteCrudRepoClient<ObjectType, IdType, InputValue>(
baseUrl, baseUrl,
httpClient, httpClient,
contentType contentType,
newObjectsFlow,
updatedObjectsFlow,
deletedObjectsIdsFlow
) )
) )
@@ -44,11 +61,23 @@ class KtorCRUDRepoClient<ObjectType, IdType, InputValue> (
subpart: String, subpart: String,
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType, contentType: ContentType,
newObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, newObjectsFlowRouting),
),
updatedObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
),
deletedObjectsIdsFlow: Flow<IdType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
),
noinline idSerializer: suspend (IdType) -> String noinline idSerializer: suspend (IdType) -> String
) = KtorCRUDRepoClient<ObjectType, IdType, InputValue>( ) = KtorCRUDRepoClient<ObjectType, IdType, InputValue>(
buildStandardUrl(baseUrl, subpart), buildStandardUrl(baseUrl, subpart),
httpClient, httpClient,
contentType, contentType,
newObjectsFlow,
updatedObjectsFlow,
deletedObjectsIdsFlow,
idSerializer idSerializer
) )
} }
@@ -80,11 +109,23 @@ inline fun <reified ObjectType, reified IdType, reified InputValue> KtorCRUDRepo
subpart: String, subpart: String,
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType, contentType: ContentType,
newObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, newObjectsFlowRouting),
),
updatedObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
),
deletedObjectsIdsFlow: Flow<IdType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
),
noinline idSerializer: suspend (IdType) -> String noinline idSerializer: suspend (IdType) -> String
) = KtorCRUDRepoClient<ObjectType, IdType, InputValue>( ) = KtorCRUDRepoClient<ObjectType, IdType, InputValue>(
buildStandardUrl(baseUrl, subpart), buildStandardUrl(baseUrl, subpart),
httpClient, httpClient,
contentType, contentType,
newObjectsFlow,
updatedObjectsFlow,
deletedObjectsIdsFlow,
idSerializer idSerializer
) )

View File

@@ -53,19 +53,22 @@ class KtorWriteCrudRepoClient<ObjectType, IdType, InputValue> (
inline operator fun <reified ObjectType, reified IdType, reified InputValue> invoke( inline operator fun <reified ObjectType, reified IdType, reified InputValue> invoke(
baseUrl: String, baseUrl: String,
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType contentType: ContentType,
newObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, newObjectsFlowRouting),
),
updatedObjectsFlow: Flow<ObjectType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
),
deletedObjectsIdsFlow: Flow<IdType> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
),
) = KtorWriteCrudRepoClient<ObjectType, IdType, InputValue>( ) = KtorWriteCrudRepoClient<ObjectType, IdType, InputValue>(
baseUrl, baseUrl,
httpClient, httpClient,
httpClient.createStandardWebsocketFlow( newObjectsFlow,
buildStandardUrl(baseUrl, newObjectsFlowRouting), updatedObjectsFlow,
), deletedObjectsIdsFlow,
httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
),
httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
),
{ {
contentType(contentType) contentType(contentType)
setBody(it) setBody(it)

View File

@@ -1,10 +1,14 @@
package dev.inmo.micro_utils.repos.ktor.client.key.value package dev.inmo.micro_utils.repos.ktor.client.key.value
import dev.inmo.micro_utils.ktor.client.createStandardWebsocketFlow
import dev.inmo.micro_utils.ktor.common.* import dev.inmo.micro_utils.ktor.common.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.ktor.common.key_value.onNewValueRoute
import dev.inmo.micro_utils.repos.ktor.common.key_value.onValueRemovedRoute
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.http.encodeURLQueryComponent import io.ktor.http.encodeURLQueryComponent
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.* import kotlinx.serialization.*
class KtorKeyValueRepoClient<Key, Value> ( class KtorKeyValueRepoClient<Key, Value> (
@@ -20,6 +24,12 @@ class KtorKeyValueRepoClient<Key, Value> (
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType, contentType: ContentType,
noinline idSerializer: suspend (Key) -> String, noinline idSerializer: suspend (Key) -> String,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
noinline valueSerializer: suspend (Value) -> String noinline valueSerializer: suspend (Value) -> String
) = KtorKeyValueRepoClient( ) = KtorKeyValueRepoClient(
KtorReadKeyValueRepoClient( KtorReadKeyValueRepoClient(
@@ -28,7 +38,9 @@ class KtorKeyValueRepoClient<Key, Value> (
KtorWriteKeyValueRepoClient( KtorWriteKeyValueRepoClient(
baseUrl, baseUrl,
httpClient, httpClient,
contentType contentType,
onNewValue,
onValueRemoved
) )
) )
inline operator fun <reified Key, reified Value> invoke( inline operator fun <reified Key, reified Value> invoke(
@@ -37,12 +49,20 @@ class KtorKeyValueRepoClient<Key, Value> (
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType, contentType: ContentType,
noinline idSerializer: suspend (Key) -> String, noinline idSerializer: suspend (Key) -> String,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
noinline valueSerializer: suspend (Value) -> String noinline valueSerializer: suspend (Value) -> String
) = KtorKeyValueRepoClient( ) = KtorKeyValueRepoClient(
buildStandardUrl(baseUrl, subpart), buildStandardUrl(baseUrl, subpart),
httpClient, httpClient,
contentType, contentType,
idSerializer, idSerializer,
onNewValue,
onValueRemoved,
valueSerializer valueSerializer
) )
} }

View File

@@ -60,17 +60,19 @@ class KtorWriteKeyValueRepoClient<Key, Value>(
inline operator fun <reified Key, reified Value> invoke( inline operator fun <reified Key, reified Value> invoke(
baseUrl: String, baseUrl: String,
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType contentType: ContentType,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
) = KtorWriteKeyValueRepoClient<Key, Value>( ) = KtorWriteKeyValueRepoClient<Key, Value>(
baseUrl, baseUrl,
httpClient, httpClient,
contentType, contentType,
httpClient.createStandardWebsocketFlow( onNewValue,
buildStandardUrl(baseUrl, onNewValueRoute), onValueRemoved,
),
httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
typeInfo<List<Key>>(), typeInfo<List<Key>>(),
typeInfo<List<Value>>(), typeInfo<List<Value>>(),
typeInfo<Map<Key, Value>>() typeInfo<Map<Key, Value>>()

View File

@@ -1,10 +1,15 @@
package dev.inmo.micro_utils.repos.ktor.client.key.values package dev.inmo.micro_utils.repos.ktor.client.key.values
import dev.inmo.micro_utils.ktor.client.createStandardWebsocketFlow
import dev.inmo.micro_utils.ktor.common.* import dev.inmo.micro_utils.ktor.common.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.onDataClearedRoute
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.onNewValueRoute
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.onValueRemovedRoute
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.http.encodeURLQueryComponent import io.ktor.http.encodeURLQueryComponent
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.* import kotlinx.serialization.*
class KtorKeyValuesRepoClient<Key, Value> ( class KtorKeyValuesRepoClient<Key, Value> (
@@ -20,6 +25,15 @@ class KtorKeyValuesRepoClient<Key, Value> (
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType, contentType: ContentType,
noinline keySerializer: suspend (Key) -> String, noinline keySerializer: suspend (Key) -> String,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
onDataCleared: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onDataClearedRoute),
),
noinline valueSerializer: suspend (Value) -> String noinline valueSerializer: suspend (Value) -> String
) = KtorKeyValuesRepoClient( ) = KtorKeyValuesRepoClient(
KtorReadKeyValuesRepoClient( KtorReadKeyValuesRepoClient(
@@ -32,7 +46,10 @@ class KtorKeyValuesRepoClient<Key, Value> (
KtorWriteKeyValuesRepoClient( KtorWriteKeyValuesRepoClient(
baseUrl, baseUrl,
httpClient, httpClient,
contentType contentType,
onNewValue,
onValueRemoved,
onDataCleared
) )
) )
inline operator fun <reified Key : Any, reified Value : Any> invoke( inline operator fun <reified Key : Any, reified Value : Any> invoke(
@@ -41,12 +58,24 @@ class KtorKeyValuesRepoClient<Key, Value> (
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType, contentType: ContentType,
noinline keySerializer: suspend (Key) -> String, noinline keySerializer: suspend (Key) -> String,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
onDataCleared: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onDataClearedRoute),
),
noinline valueSerializer: suspend (Value) -> String noinline valueSerializer: suspend (Value) -> String
) = KtorKeyValuesRepoClient( ) = KtorKeyValuesRepoClient(
buildStandardUrl(baseUrl, subpart), buildStandardUrl(baseUrl, subpart),
httpClient, httpClient,
contentType, contentType,
keySerializer, keySerializer,
onNewValue,
onValueRemoved,
onDataCleared,
valueSerializer valueSerializer
) )
} }
@@ -59,13 +88,25 @@ inline fun <reified Key : Any, reified Value : Any> KtorKeyValuesRepoClient(
keySerializer: SerializationStrategy<Key>, keySerializer: SerializationStrategy<Key>,
valueSerializer: SerializationStrategy<Value>, valueSerializer: SerializationStrategy<Value>,
serialFormat: StringFormat, serialFormat: StringFormat,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
onDataCleared: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onDataClearedRoute),
),
) = KtorKeyValuesRepoClient<Key, Value>( ) = KtorKeyValuesRepoClient<Key, Value>(
baseUrl, baseUrl,
httpClient, httpClient,
contentType, contentType,
{ {
serialFormat.encodeToString(keySerializer, it).encodeURLQueryComponent() serialFormat.encodeToString(keySerializer, it).encodeURLQueryComponent()
} },
onNewValue,
onValueRemoved,
onDataCleared
) { ) {
serialFormat.encodeToString(valueSerializer, it).encodeURLQueryComponent() serialFormat.encodeToString(valueSerializer, it).encodeURLQueryComponent()
} }
@@ -77,13 +118,25 @@ inline fun <reified Key : Any, reified Value : Any> KtorKeyValuesRepoClient(
keySerializer: SerializationStrategy<Key>, keySerializer: SerializationStrategy<Key>,
valueSerializer: SerializationStrategy<Value>, valueSerializer: SerializationStrategy<Value>,
serialFormat: BinaryFormat, serialFormat: BinaryFormat,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
onDataCleared: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onDataClearedRoute),
),
) = KtorKeyValuesRepoClient<Key, Value>( ) = KtorKeyValuesRepoClient<Key, Value>(
baseUrl, baseUrl,
httpClient, httpClient,
contentType, contentType,
{ {
serialFormat.encodeHex(keySerializer, it) serialFormat.encodeHex(keySerializer, it)
} },
onNewValue,
onValueRemoved,
onDataCleared
) { ) {
serialFormat.encodeHex(valueSerializer, it) serialFormat.encodeHex(valueSerializer, it)
} }

View File

@@ -84,20 +84,23 @@ class KtorWriteKeyValuesRepoClient<Key : Any, Value : Any>(
inline operator fun <reified Key : Any, reified Value : Any> invoke( inline operator fun <reified Key : Any, reified Value : Any> invoke(
baseUrl: String, baseUrl: String,
httpClient: HttpClient, httpClient: HttpClient,
contentType: ContentType contentType: ContentType,
onNewValue: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onNewValueRoute),
),
onValueRemoved: Flow<Pair<Key, Value>> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
onDataCleared: Flow<Key> = httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onDataClearedRoute),
),
) = KtorWriteKeyValuesRepoClient<Key, Value>( ) = KtorWriteKeyValuesRepoClient<Key, Value>(
baseUrl, baseUrl,
httpClient, httpClient,
contentType, contentType,
httpClient.createStandardWebsocketFlow( onNewValue,
buildStandardUrl(baseUrl, onNewValueRoute), onValueRemoved,
), onDataCleared,
httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onValueRemovedRoute),
),
httpClient.createStandardWebsocketFlow(
buildStandardUrl(baseUrl, onDataClearedRoute),
),
typeInfo<Key>(), typeInfo<Key>(),
typeInfo<Value>(), typeInfo<Value>(),
typeInfo<Map<Key, List<Value>>>() typeInfo<Map<Key, List<Value>>>()

View File

@@ -1,10 +1,8 @@
package dev.inmo.micro_utils.startup.launcher package dev.inmo.micro_utils.startup.launcher
import dev.inmo.kslog.common.i import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin.setupDI
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import org.koin.core.KoinApplication import org.koin.core.KoinApplication
import org.koin.core.context.startKoin
import org.koin.dsl.module
/** /**
* Will create [KoinApplication], init, load modules using [StartLauncherPlugin] and start plugins using the same base * Will create [KoinApplication], init, load modules using [StartLauncherPlugin] and start plugins using the same base
@@ -13,19 +11,7 @@ import org.koin.dsl.module
* @param rawConfig It is expected that this [JsonObject] will contain serialized [Config] ([StartLauncherPlugin] will * @param rawConfig It is expected that this [JsonObject] will contain serialized [Config] ([StartLauncherPlugin] will
* deserialize it in its [StartLauncherPlugin.setupDI] * deserialize it in its [StartLauncherPlugin.setupDI]
*/ */
@Deprecated("Fully replaced with StartLauncherPlugin#start", ReplaceWith("StartLauncherPlugin.start(rawConfig)", "dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin"))
suspend fun start(rawConfig: JsonObject) { suspend fun start(rawConfig: JsonObject) {
with(StartLauncherPlugin) { StartLauncherPlugin.start(rawConfig)
logger.i("Start initialization")
val koinApp = KoinApplication.init()
koinApp.modules(
module {
setupDI(rawConfig)
}
)
logger.i("Modules loaded")
startKoin(koinApp)
logger.i("Koin started")
startPlugin(koinApp.koin)
logger.i("App has been setup")
}
} }

View File

@@ -4,6 +4,8 @@ import dev.inmo.kslog.common.i
import dev.inmo.kslog.common.taggedLogger import dev.inmo.kslog.common.taggedLogger
import dev.inmo.kslog.common.w import dev.inmo.kslog.common.w
import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin.setupDI
import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin.startPlugin
import dev.inmo.micro_utils.startup.plugin.StartPlugin import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -12,7 +14,11 @@ import kotlinx.coroutines.launch
import kotlinx.serialization.SerialFormat import kotlinx.serialization.SerialFormat
import kotlinx.serialization.StringFormat import kotlinx.serialization.StringFormat
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonObject
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.KoinApplication
import org.koin.core.context.startKoin
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.dsl.binds import org.koin.dsl.binds
import org.koin.dsl.module import org.koin.dsl.module
@@ -23,26 +29,20 @@ import org.koin.dsl.module
object StartLauncherPlugin : StartPlugin { object StartLauncherPlugin : StartPlugin {
internal val logger = taggedLogger(this) internal val logger = taggedLogger(this)
/** fun Module.setupDI(config: Config, rawJsonObject: JsonObject? = null) {
* Will deserialize [Config] from [config], register it in receiver [Module] (as well as [CoroutineScope] and val rawJsonObject = rawJsonObject ?: defaultJson.encodeToJsonElement(Config.serializer(), config).jsonObject
* [kotlinx.serialization.json.Json])
*
* Besides, in this method will be called [StartPlugin.setupDI] on each plugin from [Config.plugins]. In case when
* some plugin will not be loaded correctly it will be reported throw the [logger]
*/
override fun Module.setupDI(config: JsonObject) {
val pluginsConfig = defaultJson.decodeFromJsonElement(Config.serializer(), config)
single { pluginsConfig } single { rawJsonObject }
single { config }
single { CoroutineScope(Dispatchers.Default) } single { CoroutineScope(Dispatchers.Default) }
single { defaultJson } binds arrayOf(StringFormat::class, SerialFormat::class) single { defaultJson } binds arrayOf(StringFormat::class, SerialFormat::class)
includes( includes(
pluginsConfig.plugins.mapNotNull { config.plugins.mapNotNull {
runCatching { runCatching {
module { module {
with(it) { with(it) {
setupDI(config) setupDI(rawJsonObject)
} }
} }
}.onFailure { e -> }.onFailure { e ->
@@ -52,11 +52,28 @@ object StartLauncherPlugin : StartPlugin {
) )
} }
/**
* Will deserialize [Config] from [config], register it in receiver [Module] (as well as [CoroutineScope] and
* [kotlinx.serialization.json.Json])
*
* Besides, in this method will be called [StartPlugin.setupDI] on each plugin from [Config.plugins]. In case when
* some plugin will not be loaded correctly it will be reported throw the [logger]
*/
override fun Module.setupDI(config: JsonObject) {
logger.i("Koin for current module has started setup")
setupDI(
defaultJson.decodeFromJsonElement(Config.serializer(), config),
config
)
logger.i("Koin for current module has been setup")
}
/** /**
* Takes [CoroutineScope] and [Config] from the [koin], and call starting of each plugin from [Config.plugins] * Takes [CoroutineScope] and [Config] from the [koin], and call starting of each plugin from [Config.plugins]
* ASYNCHRONOUSLY. Just like in [setupDI], in case of fail in some plugin it will be reported using [logger] * ASYNCHRONOUSLY. Just like in [setupDI], in case of fail in some plugin it will be reported using [logger]
*/ */
override suspend fun startPlugin(koin: Koin) { override suspend fun startPlugin(koin: Koin) {
logger.i("Start starting of subplugins")
val scope = koin.get<CoroutineScope>() val scope = koin.get<CoroutineScope>()
koin.get<Config>().plugins.map { plugin -> koin.get<Config>().plugins.map { plugin ->
scope.launch { scope.launch {
@@ -66,11 +83,61 @@ object StartLauncherPlugin : StartPlugin {
startPlugin(koin) startPlugin(koin)
} }
}.onFailure { e -> }.onFailure { e ->
logger.w("Unable to load bot part of $plugin", e) logger.w("Unable to start plugin $plugin", e)
}.onSuccess { }.onSuccess {
logger.i("Complete loading of $plugin") logger.i("Complete loading of $plugin")
} }
} }
}.joinAll() }.joinAll()
logger.i("Complete subplugins start")
}
/**
* Will create [KoinApplication], init, load modules using [StartLauncherPlugin] and start plugins using the same base
* plugin. It is basic [start] method which accepts both [config] and [rawConfig] which suppose to be the same or
* at least [rawConfig] must contain serialized variant of [config]
*
* @param rawConfig It is expected that this [JsonObject] will contain serialized [Config] ([StartLauncherPlugin] will
* deserialize it in its [StartLauncherPlugin.setupDI]
*/
suspend fun start(config: Config, rawConfig: JsonObject) {
logger.i("Start initialization")
val koinApp = KoinApplication.init()
koinApp.modules(
module {
setupDI(config, rawConfig)
}
)
logger.i("Modules loaded")
startKoin(koinApp)
logger.i("Koin started")
startPlugin(koinApp.koin)
logger.i("App has been setup")
}
/**
* Call [start] with deserialized [Config] as config and [rawConfig] as is
*
* @param rawConfig It is expected that this [JsonObject] will contain serialized [Config]
*/
suspend fun start(rawConfig: JsonObject) {
start(defaultJson.decodeFromJsonElement(Config.serializer(), rawConfig), rawConfig)
}
/**
* Call [start] with deserialized [Config] as is and serialize it to [JsonObject] to pass as the first parameter
* to the basic [start] method
*
* @param config Will be converted to [JsonObject] as raw config. That means that all plugins from [config] will
* receive serialized version of [config] in [StartPlugin.setupDI] method
*/
suspend fun start(config: Config) {
start(config, defaultJson.encodeToJsonElement(Config.serializer(), config).jsonObject)
} }
} }

View File

@@ -1,7 +1,7 @@
import dev.inmo.micro_utils.startup.launcher.Config import dev.inmo.micro_utils.startup.launcher.Config
import dev.inmo.micro_utils.startup.launcher.HelloWorldPlugin import dev.inmo.micro_utils.startup.launcher.HelloWorldPlugin
import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin
import dev.inmo.micro_utils.startup.launcher.defaultJson import dev.inmo.micro_utils.startup.launcher.defaultJson
import dev.inmo.micro_utils.startup.launcher.start
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
@@ -23,7 +23,7 @@ class StartupLaunchingTests {
runTest { runTest {
val job = launch { val job = launch {
start(emptyJson) StartLauncherPlugin.start(emptyJson)
} }
job.join() job.join()
} }
@@ -37,7 +37,7 @@ class StartupLaunchingTests {
runTest { runTest {
val job = launch { val job = launch {
start(emptyJson) StartLauncherPlugin.start(emptyJson)
} }
job.join() job.join()
} }

View File

@@ -5,6 +5,7 @@ import dev.inmo.kslog.common.i
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
@Deprecated("Useless due to including of the same functionality in StrtLauncherPlugin")
object PluginsStarter { object PluginsStarter {
init { init {
KSLog.default = KSLog("Launcher") KSLog.default = KSLog("Launcher")
@@ -15,19 +16,10 @@ object PluginsStarter {
* app inside of [dev.inmo.micro_utils.startup.plugin.StartPluginSerializer] using its * app inside of [dev.inmo.micro_utils.startup.plugin.StartPluginSerializer] using its
* [dev.inmo.micro_utils.startup.plugin.StartPluginSerializer.registerPlugin] method * [dev.inmo.micro_utils.startup.plugin.StartPluginSerializer.registerPlugin] method
*/ */
suspend fun startPlugins(json: JsonObject) { suspend fun startPlugins(json: JsonObject) = StartLauncherPlugin.start(json)
start(json)
}
/** /**
* Will convert [config] to [JsonObject] with auto registration of [dev.inmo.micro_utils.startup.plugin.StartPlugin]s * Will convert [config] to [JsonObject] with auto registration of [dev.inmo.micro_utils.startup.plugin.StartPlugin]s
* in [dev.inmo.micro_utils.startup.plugin.StartPluginSerializer] * in [dev.inmo.micro_utils.startup.plugin.StartPluginSerializer]
*/ */
suspend fun startPlugins(config: Config) { suspend fun startPlugins(config: Config) = StartLauncherPlugin.start(config)
KSLog.i("Start convert config to JSON")
val json = defaultJson.encodeToJsonElement(Config.serializer(), config).jsonObject
KSLog.i("Config has been read")
start(json)
}
} }

View File

@@ -1,6 +1,7 @@
package dev.inmo.micro_utils.startup.launcher package dev.inmo.micro_utils.startup.launcher
import dev.inmo.kslog.common.KSLog import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.LogLevel
import dev.inmo.kslog.common.i import dev.inmo.kslog.common.i
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import java.io.File import java.io.File
@@ -23,15 +24,30 @@ import java.io.File
* In that case in `build/distributions` folder you will be able to find zip and tar files with all required * In that case in `build/distributions` folder you will be able to find zip and tar files with all required
* tools for application running (via their `bin/app_name` binary). In that case yoy will not need to pass * tools for application running (via their `bin/app_name` binary). In that case yoy will not need to pass
* `--args=...` and launch will look like `./bin/app_name sample.config.json` * `--args=...` and launch will look like `./bin/app_name sample.config.json`
*
* ## Debug mode
*
* You may pass the second parameter, one of [LogLevel] enum variants to setup [KSLog] minimal logging level. Sample:
*
* ```bash
* ./gradlew run --args="sample.config.json DEBUG" // enable debugging output
* ```
*
* OR
* ```bash
* ./gradlew run --args="sample.config.json WARNING" // enable logging since WARNING
* ```
*
* **Default level is [LogLevel.INFO]**
*/ */
suspend fun main(args: Array<String>) { suspend fun main(args: Array<String>) {
KSLog.default = KSLog("Launcher") KSLog.default = KSLog("Launcher", args.getOrNull(1) ?.let { LogLevel.valueOf(it) } ?: LogLevel.INFO)
val (configPath) = args val (configPath) = args
val file = File(configPath) val file = File(configPath)
KSLog.i("Start read config from ${file.absolutePath}") KSLog.i("Start read config from ${file.absolutePath}")
val json = defaultJson.parseToJsonElement(file.readText()).jsonObject val json = defaultJson.parseToJsonElement(file.readText()).jsonObject
KSLog.i("Config has been read") KSLog.i("Config has been read")
start(json) StartLauncherPlugin.start(json)
} }

View File

@@ -0,0 +1,10 @@
# How to use
In case you have multiplatform project and wish to use startup plugin, this template may help you to create new modules.
1. Copy-paste whole template folder (you may clone this folder to your project and actualize some data to copy your prepared template)
2. Replace `group_name` by your project (or root module) group name
3. Replace `module_name` by the name of your new module name
You may read about the `build.gradle` structure in these templates in project
[KotlinMultiplatformProjectTemplate](https://github.com/InsanusMokrassar/KotlinMultiplatformProjectTemplate).

View File

@@ -0,0 +1,18 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
alias(libs.plugins.compose)
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":${rootProject.name}.module_name.common")
}
}
}
}

View File

@@ -0,0 +1,15 @@
package group_name.module_name.client
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object ClientPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
}
}

View File

@@ -0,0 +1,20 @@
package group_name.module_name.client
import group_name.module_name.common.CommonJSPlugin
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object ClientJSPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
with(CommonJSPlugin) { setupDI(config) }
with(ClientPlugin) { setupDI(config) }
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
CommonJSPlugin.startPlugin(koin)
ClientPlugin.startPlugin(koin)
}
}

View File

@@ -0,0 +1,9 @@
package group_name.module_name.client
import dev.inmo.micro_utils.startup.plugin.createStartupPluginAndRegister
@ExperimentalStdlibApi
@EagerInitialization
@JsExport
@ExperimentalJsExport
private val jsModuleLoader = createStartupPluginAndRegister("template.ClientJSPlugin") { ClientJSPlugin }

View File

@@ -0,0 +1,21 @@
package group_name.module_name.client
import group_name.module_name.common.CommonJVMPlugin
import group_name.module_name.common.CommonJVMPlugin.setupDI
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object ClientJVMPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
with(CommonJVMPlugin) { setupDI(config) }
with(ClientPlugin) { setupDI(config) }
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
CommonJVMPlugin.startPlugin(koin)
ClientPlugin.startPlugin(koin)
}
}

View File

@@ -0,0 +1 @@
<manifest package="group_name.module_name.client"/>

View File

@@ -0,0 +1,21 @@
package group_name.module_name.client
import group_name.module_name.common.CommonAndroidPlugin
import group_name.module_name.common.CommonAndroidPlugin.setupDI
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object ClientAndroidPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
with(CommonAndroidPlugin) { setupDI(config) }
with(ClientPlugin) { setupDI(config) }
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
CommonAndroidPlugin.startPlugin(koin)
ClientPlugin.startPlugin(koin)
}
}

View File

@@ -0,0 +1,7 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"

View File

@@ -0,0 +1,11 @@
package group_name.module_name.common
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.module.Module
object CommonPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
}
}

View File

@@ -0,0 +1 @@
package group_name.module_name.common

View File

@@ -0,0 +1,17 @@
package group_name.module_name.common
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object CommonJSPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
with (CommonPlugin) { setupDI(config) }
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
CommonPlugin.startPlugin(koin)
}
}

View File

@@ -0,0 +1,9 @@
package group_name.module_name.common
import dev.inmo.micro_utils.startup.plugin.createStartupPluginAndRegister
@ExperimentalStdlibApi
@EagerInitialization
@JsExport
@ExperimentalJsExport
private val jsModuleLoader = createStartupPluginAndRegister("template.CommonJSPlugin") { CommonJSPlugin }

View File

@@ -0,0 +1,17 @@
package group_name.module_name.common
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object CommonJVMPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
with (CommonPlugin) { setupDI(config) }
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
CommonPlugin.startPlugin(koin)
}
}

View File

@@ -0,0 +1 @@
<manifest package="group_name.module_name.common"/>

View File

@@ -0,0 +1,17 @@
package group_name.module_name.common
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object CommonAndroidPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
with (CommonPlugin) { setupDI(config) }
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
CommonPlugin.startPlugin(koin)
}
}

View File

@@ -0,0 +1,16 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
apply from: "$mppJavaProjectPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":${rootProject.name}.module_name.common")
}
}
}
}

View File

@@ -0,0 +1,15 @@
package group_name.module_name.server
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object ServerPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
}
}

View File

@@ -0,0 +1,20 @@
package group_name.module_name.server
import group_name.module_name.common.CommonJVMPlugin
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import kotlinx.serialization.json.JsonObject
import org.koin.core.Koin
import org.koin.core.module.Module
object ServerJVMPlugin : StartPlugin {
override fun Module.setupDI(config: JsonObject) {
with(CommonJVMPlugin) { setupDI(config) }
with(ServerPlugin) { setupDI(config) }
}
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
CommonJVMPlugin.startPlugin(koin)
ServerPlugin.startPlugin(koin)
}
}