mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-26 03:58:45 +00:00
complete improvements in repos ktor parts
This commit is contained in:
parent
eaa143f7d7
commit
78903cd4eb
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
## 0.11.0
|
## 0.11.0
|
||||||
|
|
||||||
|
* `Ktor`
|
||||||
|
*
|
||||||
|
* `Repos`
|
||||||
|
* `Ktor`:
|
||||||
|
* Fully rewritten work with all declared repositories
|
||||||
|
|
||||||
## 0.10.8
|
## 0.10.8
|
||||||
|
|
||||||
* `Common`
|
* `Common`
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package dev.inmo.micro_utils.ktor.client
|
||||||
|
|
||||||
|
import io.ktor.client.plugins.ClientRequestException
|
||||||
|
import io.ktor.client.statement.HttpResponse
|
||||||
|
import io.ktor.http.isSuccess
|
||||||
|
|
||||||
|
inline fun HttpResponse.throwOnUnsuccess(
|
||||||
|
unsuccessMessage: () -> String
|
||||||
|
) {
|
||||||
|
if (status.isSuccess()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ClientRequestException(this, unsuccessMessage())
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package dev.inmo.micro_utils.ktor.server
|
||||||
|
|
||||||
|
import io.ktor.server.application.ApplicationCall
|
||||||
|
import io.ktor.server.response.responseType
|
||||||
|
import io.ktor.util.InternalAPI
|
||||||
|
import io.ktor.util.reflect.TypeInfo
|
||||||
|
|
||||||
|
@InternalAPI
|
||||||
|
suspend fun <T : Any> ApplicationCall.respond(
|
||||||
|
message: T,
|
||||||
|
typeInfo: TypeInfo
|
||||||
|
) {
|
||||||
|
response.responseType = typeInfo
|
||||||
|
response.pipeline.execute(this, message as Any)
|
||||||
|
}
|
@ -104,6 +104,13 @@ interface OneToManyKeyValueRepo<Key, Value> : ReadOneToManyKeyValueRepo<Key, Val
|
|||||||
}
|
}
|
||||||
typealias KeyValuesRepo<Key,Value> = OneToManyKeyValueRepo<Key, Value>
|
typealias KeyValuesRepo<Key,Value> = OneToManyKeyValueRepo<Key, Value>
|
||||||
|
|
||||||
|
class DelegateBasedOneToManyKeyValueRepo<Key, Value>(
|
||||||
|
readDelegate: ReadOneToManyKeyValueRepo<Key, Value>,
|
||||||
|
writeDelegate: WriteOneToManyKeyValueRepo<Key, Value>
|
||||||
|
) : OneToManyKeyValueRepo<Key, Value>,
|
||||||
|
ReadOneToManyKeyValueRepo<Key, Value> by readDelegate,
|
||||||
|
WriteOneToManyKeyValueRepo<Key, Value> by writeDelegate
|
||||||
|
|
||||||
suspend inline fun <Key, Value> WriteOneToManyKeyValueRepo<Key, Value>.remove(
|
suspend inline fun <Key, Value> WriteOneToManyKeyValueRepo<Key, Value>.remove(
|
||||||
keysAndValues: List<Pair<Key, List<Value>>>
|
keysAndValues: List<Pair<Key, List<Value>>>
|
||||||
) = remove(keysAndValues.toMap())
|
) = remove(keysAndValues.toMap())
|
||||||
|
@ -80,6 +80,10 @@ class MapWriteOneToManyKeyValueRepo<Key, Value>(
|
|||||||
_onValueRemoved.emit(k to v)
|
_onValueRemoved.emit(k to v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (map[k] ?.isEmpty() == true) {
|
||||||
|
map.remove(k)
|
||||||
|
_onDataCleared.emit(k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import dev.inmo.micro_utils.ktor.client.*
|
|||||||
import dev.inmo.micro_utils.ktor.common.*
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
import dev.inmo.micro_utils.pagination.*
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.countRouting
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
|
@ -3,6 +3,7 @@ package dev.inmo.micro_utils.repos.ktor.client.crud
|
|||||||
import dev.inmo.micro_utils.ktor.common.*
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
import dev.inmo.micro_utils.pagination.*
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.countRouting
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
|
@ -11,11 +11,7 @@ import io.ktor.client.request.*
|
|||||||
import io.ktor.client.statement.HttpResponse
|
import io.ktor.client.statement.HttpResponse
|
||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
import io.ktor.http.contentType
|
import io.ktor.http.contentType
|
||||||
import io.ktor.util.reflect.TypeInfo
|
|
||||||
import io.ktor.util.reflect.typeInfo
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.builtins.*
|
|
||||||
|
|
||||||
class KtorWriteStandardCrudRepoClient<ObjectType, IdType, InputValue> (
|
class KtorWriteStandardCrudRepoClient<ObjectType, IdType, InputValue> (
|
||||||
private val baseUrl: String,
|
private val baseUrl: String,
|
||||||
@ -50,7 +46,7 @@ class KtorWriteStandardCrudRepoClient<ObjectType, IdType, InputValue> (
|
|||||||
buildStandardUrl(baseUrl, deleteByIdRouting)
|
buildStandardUrl(baseUrl, deleteByIdRouting)
|
||||||
) {
|
) {
|
||||||
deleteByIdSetup(ids)
|
deleteByIdSetup(ids)
|
||||||
}.status
|
}.throwOnUnsuccess { "Unable to delete $ids" }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -4,8 +4,12 @@ import dev.inmo.micro_utils.ktor.client.*
|
|||||||
import dev.inmo.micro_utils.ktor.common.*
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
import dev.inmo.micro_utils.pagination.*
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.containsRoute
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.countRoute
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.valueParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.keyParameterName
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.reversedParameterName
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
@ -4,9 +4,8 @@ import dev.inmo.micro_utils.ktor.common.*
|
|||||||
import dev.inmo.micro_utils.pagination.*
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.*
|
import dev.inmo.micro_utils.repos.ktor.common.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
import dev.inmo.micro_utils.repos.ktor.common.containsRoute
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.containsByKeyRoute
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.reversedParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.reversedParameterName
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.call.body
|
import io.ktor.client.call.body
|
||||||
@ -83,7 +82,7 @@ class KtorReadStandardKeyValueRepoClient<Key, Value>(
|
|||||||
override suspend fun count(): Long = httpClient.get(
|
override suspend fun count(): Long = httpClient.get(
|
||||||
buildStandardUrl(
|
buildStandardUrl(
|
||||||
baseUrl,
|
baseUrl,
|
||||||
countRouting
|
dev.inmo.micro_utils.repos.ktor.common.countRoute
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
contentType(contentType)
|
contentType(contentType)
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
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.client.createStandardWebsocketFlow
|
||||||
|
import dev.inmo.micro_utils.ktor.client.throwOnUnsuccess
|
||||||
import dev.inmo.micro_utils.ktor.common.*
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
import dev.inmo.micro_utils.pagination.*
|
|
||||||
import dev.inmo.micro_utils.repos.WriteStandardKeyValueRepo
|
import dev.inmo.micro_utils.repos.WriteStandardKeyValueRepo
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.request.get
|
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.util.InternalAPI
|
import io.ktor.util.InternalAPI
|
||||||
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.coroutines.flow.Flow
|
||||||
import kotlinx.serialization.*
|
|
||||||
|
|
||||||
class KtorWriteStandardKeyValueRepoClient<Key, Value>(
|
class KtorWriteStandardKeyValueRepoClient<Key, Value>(
|
||||||
private val baseUrl: String,
|
private val baseUrl: String,
|
||||||
@ -35,7 +31,7 @@ class KtorWriteStandardKeyValueRepoClient<Key, Value>(
|
|||||||
body = toUnset
|
body = toUnset
|
||||||
bodyType = objectsListTypeInfo
|
bodyType = objectsListTypeInfo
|
||||||
contentType(contentType)
|
contentType(contentType)
|
||||||
}.status
|
}.throwOnUnsuccess { "Unable to unset data with values $toUnset" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(InternalAPI::class)
|
@OptIn(InternalAPI::class)
|
||||||
@ -46,7 +42,7 @@ class KtorWriteStandardKeyValueRepoClient<Key, Value>(
|
|||||||
body = toUnset
|
body = toUnset
|
||||||
bodyType = idsListTypeInfo
|
bodyType = idsListTypeInfo
|
||||||
contentType(contentType)
|
contentType(contentType)
|
||||||
}.status
|
}.throwOnUnsuccess { "Unable to unset $toUnset" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(InternalAPI::class)
|
@OptIn(InternalAPI::class)
|
||||||
@ -57,7 +53,7 @@ class KtorWriteStandardKeyValueRepoClient<Key, Value>(
|
|||||||
body = toSet
|
body = toSet
|
||||||
bodyType = idsToObjectsMapTypeInfo
|
bodyType = idsToObjectsMapTypeInfo
|
||||||
contentType(contentType)
|
contentType(contentType)
|
||||||
}.status
|
}.throwOnUnsuccess { "Unable to set $toSet" }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -0,0 +1,159 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.pagination.*
|
||||||
|
import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.reversedParameterName
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.call.body
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.util.reflect.TypeInfo
|
||||||
|
import io.ktor.util.reflect.typeInfo
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
class KtorReadStandardKeyValuesRepoClient<Key, Value>(
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val httpClient: HttpClient,
|
||||||
|
private val contentType: ContentType,
|
||||||
|
private val paginationResultValuesTypeInfo: TypeInfo,
|
||||||
|
private val paginationResultKeysTypeInfo: TypeInfo,
|
||||||
|
private val keySerializer: suspend (Key) -> String,
|
||||||
|
private val valueSerializer: suspend (Value) -> String
|
||||||
|
) : ReadOneToManyKeyValueRepo<Key, Value> {
|
||||||
|
override suspend fun get(
|
||||||
|
k: Key,
|
||||||
|
pagination: Pagination,
|
||||||
|
reversed: Boolean
|
||||||
|
): PaginationResult<Value> = httpClient.get(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
getRoute,
|
||||||
|
pagination.asUrlQueryParts + (reversedParameterName to reversed.toString()) + (keyParameterName to keySerializer(k))
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
contentType(contentType)
|
||||||
|
}.body(paginationResultValuesTypeInfo)
|
||||||
|
|
||||||
|
override suspend fun keys(
|
||||||
|
pagination: Pagination,
|
||||||
|
reversed: Boolean
|
||||||
|
): PaginationResult<Key> = httpClient.get(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
keysRoute,
|
||||||
|
pagination.asUrlQueryParts + (reversedParameterName to reversed.toString())
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
contentType(contentType)
|
||||||
|
}.body(paginationResultKeysTypeInfo)
|
||||||
|
|
||||||
|
override suspend fun keys(
|
||||||
|
v: Value,
|
||||||
|
pagination: Pagination,
|
||||||
|
reversed: Boolean
|
||||||
|
): PaginationResult<Key> = httpClient.get(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
keysRoute,
|
||||||
|
pagination.asUrlQueryParts + (reversedParameterName to reversed.toString()) + (valueParameterName to valueSerializer(v))
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
contentType(contentType)
|
||||||
|
}.body(paginationResultKeysTypeInfo)
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key): Boolean = httpClient.get(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
containsRoute,
|
||||||
|
keyParameterName to keySerializer(k)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
contentType(contentType)
|
||||||
|
}.body()
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key, v: Value): Boolean = httpClient.get(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
containsRoute,
|
||||||
|
keyParameterName to keySerializer(k),
|
||||||
|
valueParameterName to valueSerializer(v)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
contentType(contentType)
|
||||||
|
}.body()
|
||||||
|
|
||||||
|
override suspend fun count(): Long = httpClient.get(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
countRouting
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
contentType(contentType)
|
||||||
|
}.body()
|
||||||
|
|
||||||
|
override suspend fun count(k: Key): Long = httpClient.get(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
countRouting,
|
||||||
|
keyParameterName to keySerializer(k),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
contentType(contentType)
|
||||||
|
}.body()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified Key, reified Value> KtorReadStandardKeyValuesRepoClient(
|
||||||
|
baseUrl: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
contentType: ContentType,
|
||||||
|
noinline keySerializer: suspend (Key) -> String,
|
||||||
|
noinline valueSerializer: suspend (Value) -> String
|
||||||
|
) = KtorReadStandardKeyValuesRepoClient<Key, Value>(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
typeInfo<PaginationResult<Value>>(),
|
||||||
|
typeInfo<PaginationResult<Key>>(),
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
inline fun <reified Key, reified Value> KtorReadStandardKeyValuesRepoClient(
|
||||||
|
baseUrl: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
idsSerializer: KSerializer<Key>,
|
||||||
|
valueSerializer: KSerializer<Value>,
|
||||||
|
serialFormat: StringFormat,
|
||||||
|
contentType: ContentType,
|
||||||
|
) = KtorReadStandardKeyValuesRepoClient<Key, Value>(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
{
|
||||||
|
serialFormat.encodeToString(idsSerializer, it).encodeURLQueryComponent()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
serialFormat.encodeToString(valueSerializer, it).encodeURLQueryComponent()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified Key, reified Value> KtorReadStandardKeyValuesRepoClient(
|
||||||
|
baseUrl: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
idsSerializer: KSerializer<Key>,
|
||||||
|
valuesSerializer: KSerializer<Value>,
|
||||||
|
serialFormat: BinaryFormat,
|
||||||
|
contentType: ContentType,
|
||||||
|
) = KtorReadStandardKeyValuesRepoClient<Key, Value>(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
{
|
||||||
|
serialFormat.encodeHex(idsSerializer, it)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
serialFormat.encodeHex(valuesSerializer, it)
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.http.ContentType
|
||||||
|
import io.ktor.http.encodeURLQueryComponent
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
class KtorStandardKeyValuesRepoClient<Key, Value> (
|
||||||
|
readDelegate: ReadOneToManyKeyValueRepo<Key, Value>,
|
||||||
|
writeDelegate: WriteOneToManyKeyValueRepo<Key, Value>
|
||||||
|
) : OneToManyKeyValueRepo<Key, Value> by DelegateBasedOneToManyKeyValueRepo(
|
||||||
|
readDelegate,
|
||||||
|
writeDelegate
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
inline operator fun <reified Key : Any, reified Value : Any> invoke(
|
||||||
|
baseUrl: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
contentType: ContentType,
|
||||||
|
noinline keySerializer: suspend (Key) -> String,
|
||||||
|
noinline valueSerializer: suspend (Value) -> String
|
||||||
|
) = KtorStandardKeyValuesRepoClient(
|
||||||
|
KtorReadStandardKeyValuesRepoClient(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer
|
||||||
|
),
|
||||||
|
KtorWriteStandardKeyValuesRepoClient(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType
|
||||||
|
)
|
||||||
|
)
|
||||||
|
inline operator fun <reified Key : Any, reified Value : Any> invoke(
|
||||||
|
baseUrl: String,
|
||||||
|
subpart: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
contentType: ContentType,
|
||||||
|
noinline keySerializer: suspend (Key) -> String,
|
||||||
|
noinline valueSerializer: suspend (Value) -> String
|
||||||
|
) = KtorStandardKeyValuesRepoClient(
|
||||||
|
buildStandardUrl(baseUrl, subpart),
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified Key : Any, reified Value : Any> KtorStandardKeyValuesRepoClient(
|
||||||
|
baseUrl: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
contentType: ContentType,
|
||||||
|
keySerializer: SerializationStrategy<Key>,
|
||||||
|
valueSerializer: SerializationStrategy<Value>,
|
||||||
|
serialFormat: StringFormat,
|
||||||
|
) = KtorStandardKeyValuesRepoClient<Key, Value>(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
{
|
||||||
|
serialFormat.encodeToString(keySerializer, it).encodeURLQueryComponent()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
serialFormat.encodeToString(valueSerializer, it).encodeURLQueryComponent()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified Key : Any, reified Value : Any> KtorStandardKeyValuesRepoClient(
|
||||||
|
baseUrl: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
contentType: ContentType,
|
||||||
|
keySerializer: SerializationStrategy<Key>,
|
||||||
|
valueSerializer: SerializationStrategy<Value>,
|
||||||
|
serialFormat: BinaryFormat,
|
||||||
|
) = KtorStandardKeyValuesRepoClient<Key, Value>(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
{
|
||||||
|
serialFormat.encodeHex(keySerializer, it)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
serialFormat.encodeHex(valueSerializer, it)
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.ktor.client.createStandardWebsocketFlow
|
||||||
|
import dev.inmo.micro_utils.ktor.client.throwOnUnsuccess
|
||||||
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.WriteOneToManyKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.request.post
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.util.InternalAPI
|
||||||
|
import io.ktor.util.reflect.TypeInfo
|
||||||
|
import io.ktor.util.reflect.typeInfo
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class KtorWriteStandardKeyValuesRepoClient<Key : Any, Value : Any>(
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val httpClient: HttpClient,
|
||||||
|
private val contentType: ContentType,
|
||||||
|
override val onNewValue: Flow<Pair<Key, Value>>,
|
||||||
|
override val onValueRemoved: Flow<Pair<Key, Value>>,
|
||||||
|
override val onDataCleared: Flow<Key>,
|
||||||
|
private val keyTypeInfo: TypeInfo,
|
||||||
|
private val valueTypeInfo: TypeInfo,
|
||||||
|
private val keyToValuesMapTypeInfo: TypeInfo
|
||||||
|
) : WriteOneToManyKeyValueRepo<Key, Value> {
|
||||||
|
|
||||||
|
@OptIn(InternalAPI::class)
|
||||||
|
override suspend fun add(toAdd: Map<Key, List<Value>>) {
|
||||||
|
httpClient.post(
|
||||||
|
buildStandardUrl(baseUrl, addRoute)
|
||||||
|
) {
|
||||||
|
body = toAdd
|
||||||
|
bodyType = keyToValuesMapTypeInfo
|
||||||
|
contentType(contentType)
|
||||||
|
}.throwOnUnsuccess { "Unable to add $toAdd" }
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(InternalAPI::class)
|
||||||
|
override suspend fun remove(toRemove: Map<Key, List<Value>>) {
|
||||||
|
httpClient.post(
|
||||||
|
buildStandardUrl(baseUrl, removeRoute)
|
||||||
|
) {
|
||||||
|
body = toRemove
|
||||||
|
bodyType = keyToValuesMapTypeInfo
|
||||||
|
contentType(contentType)
|
||||||
|
}.throwOnUnsuccess { "Unable to remove $toRemove" }
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(InternalAPI::class)
|
||||||
|
override suspend fun clear(k: Key) {
|
||||||
|
httpClient.post(
|
||||||
|
buildStandardUrl(baseUrl, clearRoute)
|
||||||
|
) {
|
||||||
|
body = k
|
||||||
|
bodyType = keyTypeInfo
|
||||||
|
contentType(contentType)
|
||||||
|
}.throwOnUnsuccess { "Unable to clear data with key $k" }
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(InternalAPI::class)
|
||||||
|
override suspend fun clearWithValue(v: Value) {
|
||||||
|
httpClient.post(
|
||||||
|
buildStandardUrl(baseUrl, clearWithValueRoute)
|
||||||
|
) {
|
||||||
|
body = v
|
||||||
|
bodyType = valueTypeInfo
|
||||||
|
contentType(contentType)
|
||||||
|
}.throwOnUnsuccess { "Unable to clear data with value $v" }
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(InternalAPI::class)
|
||||||
|
override suspend fun set(toSet: Map<Key, List<Value>>) {
|
||||||
|
httpClient.post(
|
||||||
|
buildStandardUrl(baseUrl, setRoute)
|
||||||
|
) {
|
||||||
|
body = toSet
|
||||||
|
bodyType = keyToValuesMapTypeInfo
|
||||||
|
contentType(contentType)
|
||||||
|
}.throwOnUnsuccess { "Unable to set data $toSet" }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
inline operator fun <reified Key : Any, reified Value : Any> invoke(
|
||||||
|
baseUrl: String,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
contentType: ContentType
|
||||||
|
) = KtorWriteStandardKeyValuesRepoClient<Key, Value>(
|
||||||
|
baseUrl,
|
||||||
|
httpClient,
|
||||||
|
contentType,
|
||||||
|
httpClient.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, onNewValueRoute),
|
||||||
|
),
|
||||||
|
httpClient.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, onValueRemovedRoute),
|
||||||
|
),
|
||||||
|
httpClient.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, onDataClearedRoute),
|
||||||
|
),
|
||||||
|
typeInfo<Key>(),
|
||||||
|
typeInfo<Value>(),
|
||||||
|
typeInfo<Map<Key, List<Value>>>()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common
|
||||||
|
|
||||||
|
const val containsRoute = "contains"
|
@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common
|
||||||
|
|
||||||
|
const val countRoute = "count"
|
@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common
|
||||||
|
|
||||||
|
const val countRouting = "count"
|
@ -3,4 +3,3 @@ package dev.inmo.micro_utils.repos.ktor.common.crud
|
|||||||
const val getByPaginationRouting = "getByPagination"
|
const val getByPaginationRouting = "getByPagination"
|
||||||
const val getByIdRouting = "getById"
|
const val getByIdRouting = "getById"
|
||||||
const val containsRouting = "contains"
|
const val containsRouting = "contains"
|
||||||
const val countRouting = "count"
|
|
||||||
|
@ -3,8 +3,8 @@ package dev.inmo.micro_utils.repos.ktor.common.key_value
|
|||||||
const val getRoute = "get"
|
const val getRoute = "get"
|
||||||
const val valuesRoute = "values"
|
const val valuesRoute = "values"
|
||||||
const val keysRoute = "keys"
|
const val keysRoute = "keys"
|
||||||
const val containsRoute = "contains"
|
const val containsRoute = dev.inmo.micro_utils.repos.ktor.common.containsRoute
|
||||||
const val countRoute = "count"
|
const val countRoute = dev.inmo.micro_utils.repos.ktor.common.countRoute
|
||||||
|
|
||||||
const val onNewValueRoute = "onNewValue"
|
const val onNewValueRoute = "onNewValue"
|
||||||
const val onValueRemovedRoute = "onValueRemoved"
|
const val onValueRemovedRoute = "onValueRemoved"
|
||||||
|
@ -5,7 +5,7 @@ const val keysRoute = "keys"
|
|||||||
const val containsByKeyRoute = "containsByKey"
|
const val containsByKeyRoute = "containsByKey"
|
||||||
const val containsByKeyValueRoute = "containsByKeyValue"
|
const val containsByKeyValueRoute = "containsByKeyValue"
|
||||||
const val countByKeyRoute = "countByKey"
|
const val countByKeyRoute = "countByKey"
|
||||||
const val countRoute = "count"
|
const val countRoute = dev.inmo.micro_utils.repos.ktor.common.countRoute
|
||||||
|
|
||||||
const val onNewValueRoute = "onNewValue"
|
const val onNewValueRoute = "onNewValue"
|
||||||
const val onValueRemovedRoute = "onValueRemoved"
|
const val onValueRemovedRoute = "onValueRemoved"
|
||||||
|
@ -21,7 +21,7 @@ class CRUDTests {
|
|||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun testCRUDFunctions() {
|
fun testCRUDFunctions() {
|
||||||
runTest() {
|
runTest {
|
||||||
val map = mutableMapOf<Int, ComplexData>()
|
val map = mutableMapOf<Int, ComplexData>()
|
||||||
val repo = MapCRUDRepo<ComplexData, Int, SimpleData>(
|
val repo = MapCRUDRepo<ComplexData, Int, SimpleData>(
|
||||||
map,
|
map,
|
||||||
|
@ -22,8 +22,8 @@ import kotlin.test.*
|
|||||||
class KVTests {
|
class KVTests {
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun testCRUDFunctions() {
|
fun testKVFunctions() {
|
||||||
runTest() {
|
runTest {
|
||||||
val map = mutableMapOf<Int, ComplexData>()
|
val map = mutableMapOf<Int, ComplexData>()
|
||||||
val repo = MapKeyValueRepo<Int, ComplexData>(map)
|
val repo = MapKeyValueRepo<Int, ComplexData>(map)
|
||||||
val server = io.ktor.server.engine.embeddedServer(
|
val server = io.ktor.server.engine.embeddedServer(
|
||||||
|
141
repos/ktor/common/src/jvmTest/kotlin/KVsTests.kt
Normal file
141
repos/ktor/common/src/jvmTest/kotlin/KVsTests.kt
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import dev.inmo.micro_utils.pagination.firstPageWithOneElementPagination
|
||||||
|
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.client.key_value.KtorStandardKeyValueRepoClient
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.client.one_to_many.KtorStandardKeyValuesRepoClient
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.server.one_to_many.configureStandardKeyValuesRepoRoutes
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.plugins.logging.Logging
|
||||||
|
import io.ktor.http.ContentType
|
||||||
|
import io.ktor.serialization.kotlinx.KotlinxWebsocketSerializationConverter
|
||||||
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
|
import io.ktor.server.application.install
|
||||||
|
import io.ktor.server.cio.CIO
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||||
|
import io.ktor.server.routing.routing
|
||||||
|
import io.ktor.server.websocket.WebSockets
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class KVsTests {
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@Test
|
||||||
|
fun testKVsFunctions() {
|
||||||
|
runTest {
|
||||||
|
val map = mutableMapOf<Int, MutableList<ComplexData>>()
|
||||||
|
val repo = MapOneToManyKeyValueRepo(map)
|
||||||
|
val server = io.ktor.server.engine.embeddedServer(
|
||||||
|
CIO,
|
||||||
|
23456,
|
||||||
|
"127.0.0.1"
|
||||||
|
) {
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
install(WebSockets) {
|
||||||
|
contentConverter = KotlinxWebsocketSerializationConverter(Json)
|
||||||
|
}
|
||||||
|
routing {
|
||||||
|
configureStandardKeyValuesRepoRoutes(
|
||||||
|
repo,
|
||||||
|
Int.serializer(),
|
||||||
|
ComplexData.serializer(),
|
||||||
|
Json {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.start(false)
|
||||||
|
val client = HttpClient {
|
||||||
|
install(io.ktor.client.plugins.contentnegotiation.ContentNegotiation) {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
install(Logging)
|
||||||
|
install(io.ktor.client.plugins.websocket.WebSockets) {
|
||||||
|
contentConverter = KotlinxWebsocketSerializationConverter(Json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val crudClient = KtorStandardKeyValuesRepoClient(
|
||||||
|
"http://127.0.0.1:23456",
|
||||||
|
client,
|
||||||
|
ContentType.Application.Json,
|
||||||
|
Int.serializer(),
|
||||||
|
ComplexData.serializer(),
|
||||||
|
Json
|
||||||
|
)
|
||||||
|
|
||||||
|
val dataInOneKey = ComplexData(1, title = "Example1")
|
||||||
|
val dataInMultipleKeys = ComplexData(2, title = "Example2")
|
||||||
|
val repeatCount = 3
|
||||||
|
|
||||||
|
val dataList = listOf(
|
||||||
|
1 to listOf(dataInOneKey)
|
||||||
|
) + (0 until repeatCount).map {
|
||||||
|
(it + 2) to listOf(dataInMultipleKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
dataList.forEachIndexed { i, (id, data) ->
|
||||||
|
crudClient.set(id, data)
|
||||||
|
assertEquals(i + 1, map.size)
|
||||||
|
assertEquals(map.size.toLong(), crudClient.count())
|
||||||
|
assertEquals(i + 1L, crudClient.count())
|
||||||
|
dataList.take(i + 1).forEach { (id, data) ->
|
||||||
|
assertContentEquals(data, map[id])
|
||||||
|
assertContentEquals(data, crudClient.getAll(id))
|
||||||
|
assertContentEquals(map[id], crudClient.getAll(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataList.forEach { (key, data) ->
|
||||||
|
assertTrue(crudClient.contains(key))
|
||||||
|
assertContentEquals(data, crudClient.getAll(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
dataList.mapNotNull { if (it.second.contains(dataInMultipleKeys)) it.first else null },
|
||||||
|
getAllWithNextPaging(firstPageWithOneElementPagination) {
|
||||||
|
crudClient.keys(dataInMultipleKeys, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
dataList.mapNotNull { if (it.second.contains(dataInOneKey)) it.first else null },
|
||||||
|
getAllWithNextPaging(firstPageWithOneElementPagination) {
|
||||||
|
crudClient.keys(dataInOneKey, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
dataList.map { it.first },
|
||||||
|
getAllWithNextPaging(firstPageWithOneElementPagination) {
|
||||||
|
crudClient.keys(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
dataList.map { it.first },
|
||||||
|
getAllWithNextPaging(firstPageWithOneElementPagination) {
|
||||||
|
crudClient.keys(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(dataList.size.toLong(), crudClient.count())
|
||||||
|
|
||||||
|
crudClient.remove(dataList.filter { it.second.contains(dataInMultipleKeys) })
|
||||||
|
println(map)
|
||||||
|
assertEquals(
|
||||||
|
dataList.filter { it.second.contains(dataInOneKey) }.size.toLong(),
|
||||||
|
crudClient.count()
|
||||||
|
)
|
||||||
|
|
||||||
|
crudClient.remove(dataList.filter { it.second.contains(dataInOneKey) })
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
crudClient.count()
|
||||||
|
)
|
||||||
|
|
||||||
|
server.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import dev.inmo.micro_utils.ktor.server.*
|
|||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
import dev.inmo.micro_utils.pagination.extractPagination
|
import dev.inmo.micro_utils.pagination.extractPagination
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.countRouting
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
import io.ktor.server.application.call
|
import io.ktor.server.application.call
|
||||||
|
@ -4,6 +4,7 @@ import dev.inmo.micro_utils.ktor.common.decodeHex
|
|||||||
import dev.inmo.micro_utils.ktor.server.*
|
import dev.inmo.micro_utils.ktor.server.*
|
||||||
import dev.inmo.micro_utils.pagination.extractPagination
|
import dev.inmo.micro_utils.pagination.extractPagination
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.countRouting
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
|
@ -6,8 +6,12 @@ import dev.inmo.micro_utils.ktor.server.*
|
|||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
import dev.inmo.micro_utils.pagination.extractPagination
|
import dev.inmo.micro_utils.pagination.extractPagination
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.containsRoute
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.countRoute
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.valueParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.keyParameterName
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.reversedParameterName
|
||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
import io.ktor.server.application.call
|
import io.ktor.server.application.call
|
||||||
import io.ktor.server.routing.Route
|
import io.ktor.server.routing.Route
|
||||||
|
@ -4,21 +4,20 @@ import dev.inmo.micro_utils.ktor.common.*
|
|||||||
import dev.inmo.micro_utils.ktor.server.*
|
import dev.inmo.micro_utils.ktor.server.*
|
||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
import dev.inmo.micro_utils.pagination.extractPagination
|
import dev.inmo.micro_utils.pagination.extractPagination
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
|
||||||
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.containsRoute
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.countRoute
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.valueParameterName
|
import dev.inmo.micro_utils.repos.ktor.common.reversedParameterName
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.call
|
import io.ktor.server.application.call
|
||||||
import io.ktor.server.response.respond
|
import io.ktor.server.response.respond
|
||||||
import io.ktor.server.response.responseType
|
|
||||||
import io.ktor.server.routing.Route
|
import io.ktor.server.routing.Route
|
||||||
import io.ktor.server.routing.get
|
import io.ktor.server.routing.get
|
||||||
import io.ktor.util.InternalAPI
|
import io.ktor.util.InternalAPI
|
||||||
import io.ktor.util.reflect.typeInfo
|
import io.ktor.util.reflect.typeInfo
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.serializer
|
|
||||||
|
|
||||||
@OptIn(InternalAPI::class)
|
@OptIn(InternalAPI::class)
|
||||||
inline fun <reified Key, reified Value> Route.configureReadStandardKeyValueRepoRoutes (
|
inline fun <reified Key, reified Value> Route.configureReadStandardKeyValueRepoRoutes (
|
||||||
@ -26,6 +25,9 @@ inline fun <reified Key, reified Value> Route.configureReadStandardKeyValueRepoR
|
|||||||
noinline idDeserializer: suspend (String) -> Key,
|
noinline idDeserializer: suspend (String) -> Key,
|
||||||
noinline valueDeserializer: suspend (String) -> Value
|
noinline valueDeserializer: suspend (String) -> Value
|
||||||
) {
|
) {
|
||||||
|
val paginationWithValuesTypeInfo = typeInfo<PaginationResult<Value>>()
|
||||||
|
val paginationWithKeysTypeInfo = typeInfo<PaginationResult<Key>>()
|
||||||
|
|
||||||
get(getRoute) {
|
get(getRoute) {
|
||||||
val key = idDeserializer(
|
val key = idDeserializer(
|
||||||
call.getQueryParameterOrSendError(idParameterName) ?: return@get
|
call.getQueryParameterOrSendError(idParameterName) ?: return@get
|
||||||
@ -36,13 +38,14 @@ inline fun <reified Key, reified Value> Route.configureReadStandardKeyValueRepoR
|
|||||||
} ?: call.respond(HttpStatusCode.NoContent)
|
} ?: call.respond(HttpStatusCode.NoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
val paginationWithValuesTypeInfo = typeInfo<PaginationResult<Value>>()
|
|
||||||
get(valuesRoute) {
|
get(valuesRoute) {
|
||||||
val pagination = call.request.queryParameters.extractPagination
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
val reversed = call.getQueryParameter(reversedParameterName) ?.toBoolean() ?: false
|
val reversed = call.getQueryParameter(reversedParameterName) ?.toBoolean() ?: false
|
||||||
|
|
||||||
call.response.responseType = paginationWithValuesTypeInfo
|
call.respond(
|
||||||
call.response.pipeline.execute(call, originalRepo.values(pagination, reversed) as Any)
|
originalRepo.values(pagination, reversed),
|
||||||
|
paginationWithValuesTypeInfo
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
get(keysRoute) {
|
get(keysRoute) {
|
||||||
@ -53,7 +56,8 @@ inline fun <reified Key, reified Value> Route.configureReadStandardKeyValueRepoR
|
|||||||
}
|
}
|
||||||
|
|
||||||
call.respond(
|
call.respond(
|
||||||
value ?.let { originalRepo.keys(value, pagination, reversed) } ?: originalRepo.keys(pagination, reversed)
|
value ?.let { originalRepo.keys(value, pagination, reversed) } ?: originalRepo.keys(pagination, reversed),
|
||||||
|
paginationWithKeysTypeInfo
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,9 +66,7 @@ inline fun <reified Key, reified Value> Route.configureReadStandardKeyValueRepoR
|
|||||||
call.getQueryParameterOrSendError(idParameterName) ?: return@get
|
call.getQueryParameterOrSendError(idParameterName) ?: return@get
|
||||||
)
|
)
|
||||||
|
|
||||||
call.respond(
|
call.respond(originalRepo.contains(key))
|
||||||
originalRepo.contains(key)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get(countRoute) {
|
get(countRoute) {
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.routing.Route
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
inline fun <reified Key : Any, reified Value : Any> Route.configureStandardKeyValuesRepoRoutes (
|
||||||
|
originalRepo: OneToManyKeyValueRepo<Key, Value>,
|
||||||
|
noinline idDeserializer: suspend (String) -> Key,
|
||||||
|
noinline valueDeserializer: suspend (String) -> Value
|
||||||
|
) {
|
||||||
|
configureReadStandardKeyValuesRepoRoutes(originalRepo, idDeserializer, valueDeserializer)
|
||||||
|
configureWriteStandardKeyValuesRepoRoutes(originalRepo)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified Key : Any, reified Value : Any> Route.configureStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo: OneToManyKeyValueRepo<Key, Value>,
|
||||||
|
idsSerializer: DeserializationStrategy<Key>,
|
||||||
|
valueSerializer: DeserializationStrategy<Value>,
|
||||||
|
serialFormat: StringFormat
|
||||||
|
) = configureStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo,
|
||||||
|
{
|
||||||
|
serialFormat.decodeFromString(idsSerializer, it.decodeURLQueryComponent())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serialFormat.decodeFromString(valueSerializer, it.decodeURLQueryComponent())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
inline fun <reified Key : Any, reified Value : Any> Route.configureStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo: OneToManyKeyValueRepo<Key, Value>,
|
||||||
|
idsSerializer: DeserializationStrategy<Key>,
|
||||||
|
valueSerializer: DeserializationStrategy<Value>,
|
||||||
|
serialFormat: BinaryFormat
|
||||||
|
) = configureStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo,
|
||||||
|
{
|
||||||
|
serialFormat.decodeHex(idsSerializer, it)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serialFormat.decodeHex(valueSerializer, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,107 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.ktor.server.*
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.pagination.extractPagination
|
||||||
|
import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.*
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.containsRoute
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.application.call
|
||||||
|
import io.ktor.server.response.respond
|
||||||
|
import io.ktor.server.routing.Route
|
||||||
|
import io.ktor.server.routing.get
|
||||||
|
import io.ktor.util.InternalAPI
|
||||||
|
import io.ktor.util.reflect.typeInfo
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
@OptIn(InternalAPI::class)
|
||||||
|
inline fun <reified Key, reified Value> Route.configureReadStandardKeyValuesRepoRoutes (
|
||||||
|
originalRepo: ReadOneToManyKeyValueRepo<Key, Value>,
|
||||||
|
noinline idDeserializer: suspend (String) -> Key,
|
||||||
|
noinline valueDeserializer: suspend (String) -> Value
|
||||||
|
) {
|
||||||
|
val paginationWithValuesTypeInfo = typeInfo<PaginationResult<Value>>()
|
||||||
|
val paginationWithKeysTypeInfo = typeInfo<PaginationResult<Key>>()
|
||||||
|
|
||||||
|
get(getRoute) {
|
||||||
|
val key = idDeserializer(
|
||||||
|
call.getQueryParameterOrSendError(keyParameterName) ?: return@get
|
||||||
|
)
|
||||||
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
|
val reversed = call.getQueryParameter(reversedParameterName) ?.toBoolean() ?: false
|
||||||
|
|
||||||
|
call.respond(
|
||||||
|
originalRepo.get(key, pagination, reversed),
|
||||||
|
paginationWithValuesTypeInfo
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(keysRoute) {
|
||||||
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
|
val reversed = call.getQueryParameterOrSendError(reversedParameterName) ?.toBoolean() ?: false
|
||||||
|
val value = call.getQueryParameter(valueParameterName) ?.let {
|
||||||
|
valueDeserializer(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
call.respond(
|
||||||
|
value ?.let { originalRepo.keys(value, pagination, reversed) } ?: originalRepo.keys(pagination, reversed),
|
||||||
|
paginationWithKeysTypeInfo
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(containsRoute) {
|
||||||
|
val key = idDeserializer(
|
||||||
|
call.getQueryParameterOrSendError(keyParameterName) ?: return@get
|
||||||
|
)
|
||||||
|
val value = call.getQueryParameter(valueParameterName) ?.let {
|
||||||
|
valueDeserializer(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
call.respond(
|
||||||
|
value ?.let { originalRepo.contains(key, value) } ?: originalRepo.contains(key)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(dev.inmo.micro_utils.repos.ktor.common.countRoute) {
|
||||||
|
val id = call.getQueryParameter(keyParameterName) ?.let {
|
||||||
|
idDeserializer(it)
|
||||||
|
}
|
||||||
|
call.respond(
|
||||||
|
id ?.let { originalRepo.count(it) } ?: originalRepo.count()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified Key, reified Value> Route.configureReadStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo: ReadOneToManyKeyValueRepo<Key, Value>,
|
||||||
|
idsSerializer: DeserializationStrategy<Key>,
|
||||||
|
valueSerializer: DeserializationStrategy<Value>,
|
||||||
|
serialFormat: StringFormat
|
||||||
|
) = configureReadStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo,
|
||||||
|
{
|
||||||
|
serialFormat.decodeFromString(idsSerializer, it.decodeURLQueryComponent())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serialFormat.decodeFromString(valueSerializer, it.decodeURLQueryComponent())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
inline fun <reified Key, reified Value> Route.configureReadStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo: ReadOneToManyKeyValueRepo<Key, Value>,
|
||||||
|
idsSerializer: DeserializationStrategy<Key>,
|
||||||
|
valueSerializer: DeserializationStrategy<Value>,
|
||||||
|
serialFormat: BinaryFormat
|
||||||
|
) = configureReadStandardKeyValuesRepoRoutes(
|
||||||
|
originalRepo,
|
||||||
|
{
|
||||||
|
serialFormat.decodeHex(idsSerializer, it)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serialFormat.decodeHex(valueSerializer, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.ktor.server.*
|
||||||
|
import dev.inmo.micro_utils.repos.WriteOneToManyKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import io.ktor.server.application.call
|
||||||
|
import io.ktor.server.request.receive
|
||||||
|
import io.ktor.server.response.respond
|
||||||
|
import io.ktor.server.routing.Route
|
||||||
|
import io.ktor.server.routing.post
|
||||||
|
import io.ktor.util.reflect.typeInfo
|
||||||
|
|
||||||
|
inline fun <reified Key : Any, reified Value : Any> Route.configureWriteStandardKeyValuesRepoRoutes (
|
||||||
|
originalRepo: WriteOneToManyKeyValueRepo<Key, Value>
|
||||||
|
) {
|
||||||
|
includeWebsocketHandling(
|
||||||
|
onNewValueRoute,
|
||||||
|
originalRepo.onNewValue
|
||||||
|
)
|
||||||
|
|
||||||
|
includeWebsocketHandling(
|
||||||
|
onValueRemovedRoute,
|
||||||
|
originalRepo.onValueRemoved
|
||||||
|
)
|
||||||
|
|
||||||
|
includeWebsocketHandling(
|
||||||
|
onDataClearedRoute,
|
||||||
|
originalRepo.onDataCleared
|
||||||
|
)
|
||||||
|
|
||||||
|
val mapType = typeInfo<Map<Key, List<Value>>>()
|
||||||
|
|
||||||
|
post(addRoute) {
|
||||||
|
originalRepo.add(call.receive(mapType))
|
||||||
|
call.respond(HttpStatusCode.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(setRoute) {
|
||||||
|
originalRepo.set(call.receive(mapType))
|
||||||
|
call.respond(HttpStatusCode.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(removeRoute) {
|
||||||
|
originalRepo.remove(call.receive(mapType))
|
||||||
|
call.respond(HttpStatusCode.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(clearRoute) {
|
||||||
|
originalRepo.clear(call.receive())
|
||||||
|
call.respond(HttpStatusCode.OK)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(clearWithValueRoute) {
|
||||||
|
originalRepo.clearWithValue(call.receive())
|
||||||
|
call.respond(HttpStatusCode.OK)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user