mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-22 16:23:50 +00:00
add repos ktor and exposed
This commit is contained in:
parent
dc9529310c
commit
b84367f47c
16
repos/exposed/build.gradle
Normal file
16
repos/exposed/build.gradle
Normal 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 internalProject("micro_utils.repos.common")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed
|
||||||
|
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
|
||||||
|
abstract class AbstractExposedCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||||
|
flowsChannelsSize: Int = Channel.BUFFERED,
|
||||||
|
databaseName: String = ""
|
||||||
|
) :
|
||||||
|
AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||||
|
flowsChannelsSize,
|
||||||
|
databaseName
|
||||||
|
),
|
||||||
|
ExposedCRUDRepo<ObjectType, IdType>
|
@ -0,0 +1,37 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
|
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
abstract class AbstractExposedReadCRUDRepo<ObjectType, IdType>(
|
||||||
|
tableName: String
|
||||||
|
) :
|
||||||
|
ReadStandardCRUDRepo<ObjectType, IdType>,
|
||||||
|
ExposedCRUDRepo<ObjectType, IdType>,
|
||||||
|
Table(tableName)
|
||||||
|
{
|
||||||
|
override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> {
|
||||||
|
return transaction(db = database) {
|
||||||
|
selectAll().paginate(pagination).map {
|
||||||
|
it.asObject
|
||||||
|
}.createPaginationResult(
|
||||||
|
pagination,
|
||||||
|
selectAll().count()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override suspend fun getById(id: IdType): ObjectType? {
|
||||||
|
return transaction(db = database) {
|
||||||
|
select {
|
||||||
|
selectById(id)
|
||||||
|
}.limit(1).firstOrNull() ?.asObject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun contains(id: IdType): Boolean = transaction(db = database) {
|
||||||
|
select { selectById(id) }.limit(1).any()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.utils.repos.UpdatedValuePair
|
||||||
|
import com.insanusmokrassar.postssystem.utils.repos.WriteStandardCRUDRepo
|
||||||
|
import kotlinx.coroutines.channels.BroadcastChannel
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.asFlow
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||||
|
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||||
|
flowsChannelsSize: Int = 64,
|
||||||
|
databaseName: String = ""
|
||||||
|
) :
|
||||||
|
AbstractExposedReadCRUDRepo<ObjectType, IdType>(databaseName),
|
||||||
|
ExposedCRUDRepo<ObjectType, IdType>,
|
||||||
|
WriteStandardCRUDRepo<ObjectType, IdType, InputValueType>
|
||||||
|
{
|
||||||
|
protected val newObjectsChannel = BroadcastChannel<ObjectType>(flowsChannelsSize)
|
||||||
|
protected val updateObjectsChannel = BroadcastChannel<ObjectType>(flowsChannelsSize)
|
||||||
|
protected val deleteObjectsIdsChannel = BroadcastChannel<IdType>(flowsChannelsSize)
|
||||||
|
|
||||||
|
override val newObjectsFlow: Flow<ObjectType> = newObjectsChannel.asFlow()
|
||||||
|
override val updatedObjectsFlow: Flow<ObjectType> = updateObjectsChannel.asFlow()
|
||||||
|
override val deletedObjectsIdsFlow: Flow<IdType> = deleteObjectsIdsChannel.asFlow()
|
||||||
|
|
||||||
|
abstract val InsertStatement<Number>.asObject: ObjectType
|
||||||
|
abstract val selectByIds: SqlExpressionBuilder.(List<out IdType>) -> Op<Boolean>
|
||||||
|
|
||||||
|
protected abstract fun insert(value: InputValueType, it: InsertStatement<Number>)
|
||||||
|
protected abstract fun update(id: IdType, value: InputValueType, it: UpdateStatement)
|
||||||
|
|
||||||
|
protected open suspend fun onBeforeCreate(value: List<InputValueType>) {}
|
||||||
|
private fun createWithoutNotification(value: InputValueType): ObjectType {
|
||||||
|
return transaction(database) {
|
||||||
|
insert { insert(value, it) }.asObject
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun create(values: List<InputValueType>): List<ObjectType> {
|
||||||
|
onBeforeCreate(values)
|
||||||
|
return transaction(db = database) {
|
||||||
|
values.map { value -> createWithoutNotification(value) }
|
||||||
|
}.also {
|
||||||
|
it.forEach {
|
||||||
|
newObjectsChannel.send(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open suspend fun onBeforeUpdate(value: List<UpdatedValuePair<IdType, InputValueType>>) {}
|
||||||
|
private fun updateWithoutNotification(id: IdType, value: InputValueType): ObjectType? {
|
||||||
|
return transaction(db = database) {
|
||||||
|
update(
|
||||||
|
{
|
||||||
|
selectById(this, id)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
update(id, value, it)
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
if (it > 0) {
|
||||||
|
select {
|
||||||
|
selectById(this, id)
|
||||||
|
}.limit(1).firstOrNull() ?.asObject
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
|
||||||
|
onBeforeUpdate(listOf(id to value))
|
||||||
|
return updateWithoutNotification(id, value).also {
|
||||||
|
if (it != null) {
|
||||||
|
updateObjectsChannel.send(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType> {
|
||||||
|
onBeforeUpdate(values)
|
||||||
|
return (
|
||||||
|
transaction(db = database) {
|
||||||
|
values.map { (id, value) -> updateWithoutNotification(id, value) }
|
||||||
|
}.filter {
|
||||||
|
it != null
|
||||||
|
} as List<ObjectType>
|
||||||
|
).also {
|
||||||
|
it.forEach {
|
||||||
|
updateObjectsChannel.send(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected open suspend fun onBeforeDelete(ids: List<IdType>) {}
|
||||||
|
override suspend fun deleteById(ids: List<IdType>) {
|
||||||
|
onBeforeDelete(ids)
|
||||||
|
transaction(db = database) {
|
||||||
|
deleteWhere(null, null) {
|
||||||
|
selectByIds(ids)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
|
||||||
|
interface ExposedCRUDRepo<ObjectType, IdType> {
|
||||||
|
val database: Database
|
||||||
|
|
||||||
|
val ResultRow.asObject: ObjectType
|
||||||
|
val selectById: SqlExpressionBuilder.(IdType) -> Op<Boolean>
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
fun Table.initTable(database: Database) {
|
||||||
|
transaction(database) { SchemaUtils.createMissingTablesAndColumns(this@initTable) }
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed.keyvalue
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.utils.repos.StandardKeyValueRepo
|
||||||
|
import kotlinx.coroutines.channels.BroadcastChannel
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.asFlow
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
abstract class AbstractExposedKeyValueRepo<Key, Value>(
|
||||||
|
database: Database,
|
||||||
|
keyColumn: Column<Key>,
|
||||||
|
valueColumn: Column<Value>
|
||||||
|
) : StandardKeyValueRepo<Key, Value>, AbstractExposedReadKeyValueRepo<Key, Value>(
|
||||||
|
database,
|
||||||
|
keyColumn,
|
||||||
|
valueColumn
|
||||||
|
) {
|
||||||
|
private val onNewValueChannel = BroadcastChannel<Pair<Key, Value>>(Channel.BUFFERED)
|
||||||
|
private val onValueRemovedChannel = BroadcastChannel<Key>(Channel.BUFFERED)
|
||||||
|
|
||||||
|
override val onNewValue: Flow<Pair<Key, Value>> = onNewValueChannel.asFlow()
|
||||||
|
override val onValueRemoved: Flow<Key> = onValueRemovedChannel.asFlow()
|
||||||
|
|
||||||
|
override suspend fun set(k: Key, v: Value) {
|
||||||
|
transaction(db = database) {
|
||||||
|
if (select { keyColumn.eq(k) }.limit(1).any()) {
|
||||||
|
update({ keyColumn.eq(k) }) {
|
||||||
|
it[valueColumn] = v
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
insert {
|
||||||
|
it[keyColumn] = k
|
||||||
|
it[valueColumn] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onNewValueChannel.send(k to v)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun unset(k: Key) {
|
||||||
|
transaction(db = database) {
|
||||||
|
deleteWhere { keyColumn.eq(k) }
|
||||||
|
}
|
||||||
|
onValueRemovedChannel.send(k)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed.keyvalue
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
|
import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
abstract class AbstractExposedReadKeyValueRepo<Key, Value>(
|
||||||
|
protected val database: Database,
|
||||||
|
protected val keyColumn: Column<Key>,
|
||||||
|
protected val valueColumn: Column<Value>
|
||||||
|
) : StandardReadKeyValueRepo<Key, Value>, Table() {
|
||||||
|
override val primaryKey: PrimaryKey = PrimaryKey(keyColumn, valueColumn)
|
||||||
|
|
||||||
|
override suspend fun get(k: Key): Value? = transaction(db = database) {
|
||||||
|
select { keyColumn.eq(k) }.limit(1).firstOrNull() ?.getOrNull(valueColumn)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun contains(key: Key): Boolean = transaction(db = database) {
|
||||||
|
select { keyColumn.eq(key) }.limit(1).any()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun count(): Long = transaction(db = database) { selectAll().count() }
|
||||||
|
|
||||||
|
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = transaction(db = database) {
|
||||||
|
selectAll().paginate(pagination, keyColumn to if (reversed) SortOrder.DESC else SortOrder.ASC).map {
|
||||||
|
it[keyColumn]
|
||||||
|
}
|
||||||
|
}.createPaginationResult(pagination, count())
|
||||||
|
|
||||||
|
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> = transaction(db = database) {
|
||||||
|
selectAll().paginate(pagination, keyColumn to if (reversed) SortOrder.DESC else SortOrder.ASC).map {
|
||||||
|
it[valueColumn]
|
||||||
|
}
|
||||||
|
}.createPaginationResult(pagination, count())
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed.onetomany
|
||||||
|
|
||||||
|
import com.insanusmokrassar.budgetmanager.core.utils.repo.onetomany.AbstractOneToManyExposedReadKeyValueRepo
|
||||||
|
import com.insanusmokrassar.budgetmanager.core.utils.repo.onetomany.ColumnAllocator
|
||||||
|
import com.insanusmokrassar.postssystem.utils.repos.OneToManyKeyValueRepo
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
abstract class AbstractOneToManyExposedKeyValueRepo<Key, Value>(
|
||||||
|
keyColumnAllocator: ColumnAllocator<Key>,
|
||||||
|
valueColumnAllocator: ColumnAllocator<Value>,
|
||||||
|
database: Database
|
||||||
|
) : OneToManyKeyValueRepo<Key, Value>, AbstractOneToManyExposedReadKeyValueRepo<Key, Value>(
|
||||||
|
keyColumnAllocator,
|
||||||
|
valueColumnAllocator,
|
||||||
|
database
|
||||||
|
) {
|
||||||
|
override suspend fun add(k: Key, v: Value) {
|
||||||
|
transaction(db = database) {
|
||||||
|
insert {
|
||||||
|
it[keyColumn] = k
|
||||||
|
it[valueColumn] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun remove(k: Key, v: Value) {
|
||||||
|
transaction(db = database) { deleteWhere { keyColumn.eq(k).and(valueColumn.eq(v)) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun clear(k: Key) {
|
||||||
|
transaction(db = database) { deleteWhere { keyColumn.eq(k) } }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.exposed.onetomany
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
|
import com.insanusmokrassar.postssystem.utils.repos.OneToManyReadKeyValueRepo
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
typealias ColumnAllocator<T> = Table.() -> Column<T>
|
||||||
|
|
||||||
|
abstract class AbstractOneToManyExposedReadKeyValueRepo<Key, Value>(
|
||||||
|
keyColumnAllocator: ColumnAllocator<Key>,
|
||||||
|
valueColumnAllocator: ColumnAllocator<Value>,
|
||||||
|
protected val database: Database
|
||||||
|
) : OneToManyReadKeyValueRepo<Key, Value>, Table() {
|
||||||
|
protected val keyColumn: Column<Key> = keyColumnAllocator()
|
||||||
|
protected val valueColumn: Column<Value> = valueColumnAllocator()
|
||||||
|
|
||||||
|
override suspend fun count(k: Key): Long = transaction(db = database) { select { keyColumn.eq(k) }.count() }
|
||||||
|
|
||||||
|
override suspend fun count(): Long = transaction(db = database) { selectAll().count() }
|
||||||
|
|
||||||
|
override suspend fun get(
|
||||||
|
k: Key,
|
||||||
|
pagination: Pagination,
|
||||||
|
reversed: Boolean
|
||||||
|
): PaginationResult<Value> = transaction(db = database) {
|
||||||
|
select { keyColumn.eq(k) }.paginate(pagination, keyColumn, reversed).map { it[valueColumn] }
|
||||||
|
}.createPaginationResult(
|
||||||
|
pagination,
|
||||||
|
count(k)
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = transaction(db = database) {
|
||||||
|
selectAll().paginate(pagination, keyColumn, reversed).map { it[keyColumn] }
|
||||||
|
}.createPaginationResult(
|
||||||
|
pagination,
|
||||||
|
count()
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key): Boolean = transaction(db = database) {
|
||||||
|
select { keyColumn.eq(k) }.limit(1).any()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key, v: Value): Boolean = transaction(db = database) {
|
||||||
|
select { keyColumn.eq(k).and(valueColumn.eq(v)) }.limit(1).any()
|
||||||
|
}
|
||||||
|
}
|
17
repos/ktor/client/build.gradle
Normal file
17
repos/ktor/client/build.gradle
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
plugins {
|
||||||
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$mppProjectWithSerializationPresetPath"
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api internalProject("micro_utils.repos.ktor.common")
|
||||||
|
api "io.ktor:ktor-client:$ktor_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.crud
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.pagination.Pagination
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
class KtorReadStandardCrudRepo<ObjectType, IdType> (
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val client: HttpClient = HttpClient(),
|
||||||
|
private val objectsSerializer: KSerializer<ObjectType>,
|
||||||
|
private val objectsSerializerNullable: KSerializer<ObjectType?>,
|
||||||
|
private val idsSerializer: KSerializer<IdType>
|
||||||
|
) : ReadStandardCRUDRepo<ObjectType, IdType> {
|
||||||
|
private val paginationResultSerializer = PaginationResult.serializer(objectsSerializer)
|
||||||
|
|
||||||
|
override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = client.uniget(
|
||||||
|
buildStandardUrl(baseUrl, getByPaginationRouting, pagination.asUrlQueryParts),
|
||||||
|
paginationResultSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getById(id: IdType): ObjectType? = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
getByIdRouting,
|
||||||
|
mapOf(
|
||||||
|
"id" to idsSerializer.encodeUrlQueryValue(id)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
objectsSerializerNullable
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(id: IdType): Boolean = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
containsRouting,
|
||||||
|
mapOf(
|
||||||
|
"id" to idsSerializer.encodeUrlQueryValue(id)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Boolean.serializer()
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.crud
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
|
||||||
|
class KtorStandardCrudRepo<ObjectType, IdType, InputValue> (
|
||||||
|
baseUrl: String,
|
||||||
|
baseSubpart: String,
|
||||||
|
client: HttpClient,
|
||||||
|
objectsSerializer: KSerializer<ObjectType>,
|
||||||
|
objectsNullableSerializer: KSerializer<ObjectType?>,
|
||||||
|
inputsSerializer: KSerializer<InputValue>,
|
||||||
|
idsSerializer: KSerializer<IdType>
|
||||||
|
) : StandardCRUDRepo<ObjectType, IdType, InputValue>,
|
||||||
|
ReadStandardCRUDRepo<ObjectType, IdType> by KtorReadStandardCrudRepo(
|
||||||
|
"$baseUrl/$baseSubpart",
|
||||||
|
client,
|
||||||
|
objectsSerializer,
|
||||||
|
objectsNullableSerializer,
|
||||||
|
idsSerializer
|
||||||
|
),
|
||||||
|
WriteStandardCRUDRepo<ObjectType, IdType, InputValue> by KtorWriteStandardCrudRepo(
|
||||||
|
"$baseUrl/$baseSubpart",
|
||||||
|
client,
|
||||||
|
objectsSerializer,
|
||||||
|
objectsNullableSerializer,
|
||||||
|
inputsSerializer,
|
||||||
|
idsSerializer
|
||||||
|
)
|
@ -0,0 +1,65 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.crud
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.UpdatedValuePair
|
||||||
|
import dev.inmo.micro_utils.repos.WriteStandardCRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.*
|
||||||
|
|
||||||
|
class KtorWriteStandardCrudRepo<ObjectType, IdType, InputValue> (
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val client: HttpClient = HttpClient(),
|
||||||
|
private val objectsSerializer: KSerializer<ObjectType>,
|
||||||
|
private val objectsNullableSerializer: KSerializer<ObjectType?>,
|
||||||
|
private val inputsSerializer: KSerializer<InputValue>,
|
||||||
|
private val idsSerializer: KSerializer<IdType>
|
||||||
|
) : WriteStandardCRUDRepo<ObjectType, IdType, InputValue> {
|
||||||
|
private val listObjectsSerializer = ListSerializer(objectsSerializer)
|
||||||
|
private val listInputSerializer = ListSerializer(inputsSerializer)
|
||||||
|
private val listIdsSerializer = ListSerializer(idsSerializer)
|
||||||
|
private val inputUpdateSerializer = PairSerializer(
|
||||||
|
idsSerializer,
|
||||||
|
inputsSerializer
|
||||||
|
)
|
||||||
|
private val listInputUpdateSerializer = ListSerializer(inputUpdateSerializer)
|
||||||
|
|
||||||
|
override val newObjectsFlow: Flow<ObjectType> = client.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, newObjectsFlowRouting),
|
||||||
|
deserializer = objectsSerializer
|
||||||
|
)
|
||||||
|
override val updatedObjectsFlow: Flow<ObjectType> = client.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
|
||||||
|
deserializer = objectsSerializer
|
||||||
|
)
|
||||||
|
override val deletedObjectsIdsFlow: Flow<IdType> = client.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
|
||||||
|
deserializer = idsSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
override suspend fun create(values: List<InputValue>): List<ObjectType> = client.unipost(
|
||||||
|
buildStandardUrl(baseUrl, createRouting),
|
||||||
|
BodyPair(listInputSerializer, values),
|
||||||
|
listObjectsSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun update(id: IdType, value: InputValue): ObjectType? = client.unipost(
|
||||||
|
buildStandardUrl(baseUrl, updateRouting),
|
||||||
|
BodyPair(inputUpdateSerializer, id to value),
|
||||||
|
objectsNullableSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValue>>): List<ObjectType> = client.unipost(
|
||||||
|
buildStandardUrl(baseUrl, updateManyRouting),
|
||||||
|
BodyPair(listInputUpdateSerializer, values),
|
||||||
|
listObjectsSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun deleteById(ids: List<IdType>) = client.unipost(
|
||||||
|
buildStandardUrl(baseUrl, deleteByIdRouting),
|
||||||
|
BodyPair(listIdsSerializer, ids),
|
||||||
|
Unit.serializer()
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.key_value
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.StandardKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.StandardReadKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.StandardWriteKeyValueRepo
|
||||||
|
import io.ktor.client.*
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
|
||||||
|
class KtorStandartKeyValueRepo<K, V> (
|
||||||
|
baseUrl: String,
|
||||||
|
baseSubpart: String,
|
||||||
|
client: HttpClient = HttpClient(),
|
||||||
|
keySerializer: KSerializer<K>,
|
||||||
|
valueSerializer: KSerializer<V>,
|
||||||
|
valueNullableSerializer: KSerializer<V?>
|
||||||
|
) : StandardKeyValueRepo<K, V>,
|
||||||
|
StandardReadKeyValueRepo<K, V> by KtorStandartReadKeyValueRepo(
|
||||||
|
"$baseUrl/$baseSubpart",
|
||||||
|
client,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer,
|
||||||
|
valueNullableSerializer
|
||||||
|
),
|
||||||
|
StandardWriteKeyValueRepo<K, V> by KtorStandartWriteKeyValueRepo(
|
||||||
|
"$baseUrl/$baseSubpart",
|
||||||
|
client,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer
|
||||||
|
)
|
@ -0,0 +1,69 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.key_value
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.pagination.Pagination
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.repos.StandardReadKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
|
import io.ktor.client.*
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
class KtorStandartReadKeyValueRepo<Key, Value> (
|
||||||
|
private var baseUrl: String,
|
||||||
|
private var client: HttpClient = HttpClient(),
|
||||||
|
private var keySerializer: KSerializer<Key>,
|
||||||
|
private var valueSerializer: KSerializer<Value>,
|
||||||
|
private var valueNullableSerializer: KSerializer<Value?>,
|
||||||
|
) : StandardReadKeyValueRepo<Key, Value> {
|
||||||
|
override suspend fun get(k: Key): Value? = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
getRoute,
|
||||||
|
mapOf(
|
||||||
|
keyParameterName to keySerializer.encodeUrlQueryValue(k)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
valueNullableSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
valuesRoute,
|
||||||
|
mapOf(
|
||||||
|
reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed)
|
||||||
|
) + pagination.asUrlQueryParts
|
||||||
|
),
|
||||||
|
PaginationResult.serializer(valueSerializer)
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
keysRoute,
|
||||||
|
mapOf(
|
||||||
|
reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed)
|
||||||
|
) + pagination.asUrlQueryParts
|
||||||
|
),
|
||||||
|
PaginationResult.serializer(keySerializer)
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(key: Key): Boolean = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
containsRoute,
|
||||||
|
mapOf(
|
||||||
|
keyParameterName to keySerializer.encodeUrlQueryValue(key)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Boolean.serializer(),
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun count(): Long = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
countRoute,
|
||||||
|
),
|
||||||
|
Long.serializer()
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.key_value
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.StandardWriteKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
|
import io.ktor.client.*
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.PairSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
class KtorStandartWriteKeyValueRepo<K, V> (
|
||||||
|
private var baseUrl: String,
|
||||||
|
private var client: HttpClient = HttpClient(),
|
||||||
|
private var keySerializer: KSerializer<K>,
|
||||||
|
private var valueSerializer: KSerializer<V>,
|
||||||
|
) : StandardWriteKeyValueRepo<K, V> {
|
||||||
|
override val onNewValue: Flow<Pair<K, V>> = client.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, onNewValueRoute),
|
||||||
|
deserializer = PairSerializer(keySerializer, valueSerializer)
|
||||||
|
)
|
||||||
|
|
||||||
|
override val onValueRemoved: Flow<K> = client.createStandardWebsocketFlow(
|
||||||
|
buildStandardUrl(baseUrl, onValueRemovedRoute),
|
||||||
|
deserializer = keySerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun set(k: K, v: V) = client.unipost(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
setRoute
|
||||||
|
),
|
||||||
|
BodyPair(KeyValuePostObject.serializer(keySerializer, valueSerializer), KeyValuePostObject(k, v)),
|
||||||
|
Unit.serializer()
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun unset(k: K) = client.unipost(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
unsetRoute,
|
||||||
|
),
|
||||||
|
BodyPair(keySerializer, k),
|
||||||
|
Unit.serializer()
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyReadKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyWriteKeyValueRepo
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
|
||||||
|
class KtorOneToManyKeyValueRepo<Key, Value>(
|
||||||
|
baseUrl: String,
|
||||||
|
baseSubpart: String,
|
||||||
|
client: HttpClient,
|
||||||
|
keySerializer: KSerializer<Key>,
|
||||||
|
valueSerializer: KSerializer<Value>,
|
||||||
|
) : OneToManyKeyValueRepo<Key, Value>,
|
||||||
|
OneToManyReadKeyValueRepo<Key, Value> by KtorOneToManyReadKeyValueRepo<Key, Value> (
|
||||||
|
"$baseUrl/$baseSubpart",
|
||||||
|
client,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer,
|
||||||
|
),
|
||||||
|
OneToManyWriteKeyValueRepo<Key, Value> by KtorOneToManyWriteKeyValueRepo<Key, Value> (
|
||||||
|
"$baseUrl/$baseSubpart",
|
||||||
|
client,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer,
|
||||||
|
)
|
@ -0,0 +1,83 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.pagination.Pagination
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyReadKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
class KtorOneToManyReadKeyValueRepo<Key, Value> (
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val client: HttpClient = HttpClient(),
|
||||||
|
private val keySerializer: KSerializer<Key>,
|
||||||
|
private val valueSerializer: KSerializer<Value>,
|
||||||
|
) : OneToManyReadKeyValueRepo<Key, Value> {
|
||||||
|
private val paginationValueResultSerializer = PaginationResult.serializer(valueSerializer)
|
||||||
|
private val paginationKeyResultSerializer = PaginationResult.serializer(keySerializer)
|
||||||
|
|
||||||
|
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
getRoute,
|
||||||
|
mapOf(
|
||||||
|
keyParameterName to keySerializer.encodeUrlQueryValue(k),
|
||||||
|
reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed)
|
||||||
|
) + pagination.asUrlQueryParts
|
||||||
|
),
|
||||||
|
paginationValueResultSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
keysRoute,
|
||||||
|
mapOf(
|
||||||
|
reversedParameterName to Boolean.serializer().encodeUrlQueryValue(reversed)
|
||||||
|
) + pagination.asUrlQueryParts
|
||||||
|
),
|
||||||
|
paginationKeyResultSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key): Boolean = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
containsByKeyRoute,
|
||||||
|
mapOf(keyParameterName to keySerializer.encodeUrlQueryValue(k))
|
||||||
|
),
|
||||||
|
Boolean.serializer()
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key, v: Value): Boolean = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
containsByKeyValueRoute,
|
||||||
|
mapOf(
|
||||||
|
keyParameterName to keySerializer.encodeUrlQueryValue(k),
|
||||||
|
valueParameterName to valueSerializer.encodeUrlQueryValue(v),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Boolean.serializer()
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun count(k: Key): Long = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
countByKeyRoute,
|
||||||
|
mapOf(
|
||||||
|
keyParameterName to keySerializer.encodeUrlQueryValue(k)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Long.serializer()
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun count(): Long = client.uniget(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
countRoute,
|
||||||
|
),
|
||||||
|
Long.serializer()
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyWriteKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.PairSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
class KtorOneToManyWriteKeyValueRepo<Key, Value> (
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val client: HttpClient = HttpClient(),
|
||||||
|
private val keySerializer: KSerializer<Key>,
|
||||||
|
private val valueSerializer: KSerializer<Value>,
|
||||||
|
) : OneToManyWriteKeyValueRepo<Key, Value> {
|
||||||
|
private val keyValueSerializer = PairSerializer(keySerializer, valueSerializer)
|
||||||
|
|
||||||
|
override suspend fun add(k: Key, v: Value) = client.unipost(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
addRoute,
|
||||||
|
),
|
||||||
|
BodyPair(keyValueSerializer, k to v),
|
||||||
|
Unit.serializer(),
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun remove(k: Key, v: Value) = client.unipost(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
removeRoute,
|
||||||
|
),
|
||||||
|
BodyPair(keyValueSerializer, k to v),
|
||||||
|
Unit.serializer(),
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun clear(k: Key) = client.unipost(
|
||||||
|
buildStandardUrl(
|
||||||
|
baseUrl,
|
||||||
|
clearRoute,
|
||||||
|
),
|
||||||
|
BodyPair(keySerializer, k),
|
||||||
|
Unit.serializer(),
|
||||||
|
)
|
||||||
|
}
|
16
repos/ktor/common/build.gradle
Normal file
16
repos/ktor/common/build.gradle
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
plugins {
|
||||||
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$mppProjectWithSerializationPresetPath"
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api internalProject("micro_utils.repos.common")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common.crud
|
||||||
|
|
||||||
|
const val getByPaginationRouting = "getByPagination"
|
||||||
|
const val getByIdRouting = "getById"
|
||||||
|
const val containsRouting = "contains"
|
@ -0,0 +1,10 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common.crud
|
||||||
|
|
||||||
|
const val newObjectsFlowRouting = "newObjectsFlow"
|
||||||
|
const val updatedObjectsFlowRouting = "updatedObjectsFlow"
|
||||||
|
const val deletedObjectsIdsFlowRouting = "deletedObjectsIdsFlow"
|
||||||
|
|
||||||
|
const val createRouting = "create"
|
||||||
|
const val updateRouting = "update"
|
||||||
|
const val updateManyRouting = "updateMany"
|
||||||
|
const val deleteByIdRouting = "deleteById"
|
@ -0,0 +1,4 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common.key_value
|
||||||
|
|
||||||
|
const val keyParameterName = "key"
|
||||||
|
const val reversedParameterName = "reversed"
|
@ -0,0 +1,9 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common.key_value
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class KeyValuePostObject<K, V> (
|
||||||
|
val key: K,
|
||||||
|
val value: V,
|
||||||
|
)
|
@ -0,0 +1,12 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common.key_value
|
||||||
|
|
||||||
|
const val getRoute = "get"
|
||||||
|
const val valuesRoute = "values"
|
||||||
|
const val keysRoute = "keys"
|
||||||
|
const val containsRoute = "contains"
|
||||||
|
const val countRoute = "count"
|
||||||
|
|
||||||
|
const val onNewValueRoute = "onNewValue"
|
||||||
|
const val onValueRemovedRoute = "onValueRemoved"
|
||||||
|
const val setRoute = "set"
|
||||||
|
const val unsetRoute = "unset"
|
@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common.one_to_many
|
||||||
|
|
||||||
|
const val keyParameterName = "key"
|
||||||
|
const val valueParameterName = "value"
|
||||||
|
const val reversedParameterName = "reversed"
|
@ -0,0 +1,12 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.common.one_to_many
|
||||||
|
|
||||||
|
const val getRoute = "get"
|
||||||
|
const val keysRoute = "keys"
|
||||||
|
const val containsByKeyRoute = "containsByKey"
|
||||||
|
const val containsByKeyValueRoute = "containsByKeyValue"
|
||||||
|
const val countByKeyRoute = "countByKey"
|
||||||
|
const val countRoute = "count"
|
||||||
|
|
||||||
|
const val addRoute = "add"
|
||||||
|
const val removeRoute = "remove"
|
||||||
|
const val clearRoute = "clear"
|
23
repos/ktor/server/build.gradle
Normal file
23
repos/ktor/server/build.gradle
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
plugins {
|
||||||
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$mppJavaProjectPresetPath"
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api internalProject("micro_utils.repos.ktor.common")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jvmMain {
|
||||||
|
dependencies {
|
||||||
|
api "io.ktor:ktor-server:$ktor_version"
|
||||||
|
api "io.ktor:ktor-server-host-common:$ktor_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.crud
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.crud.containsRouting
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.crud.getByIdRouting
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.crud.getByPaginationRouting
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.repos.ReadStandardCRUDRepo
|
||||||
|
import io.ktor.application.call
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.get
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
fun <ObjectType, IdType> Route.configureReadStandardCrudRepoRoutes(
|
||||||
|
originalRepo: ReadStandardCRUDRepo<ObjectType, IdType>,
|
||||||
|
objectsSerializer: KSerializer<ObjectType>,
|
||||||
|
objectsNullableSerializer: KSerializer<ObjectType?>,
|
||||||
|
idsSerializer: KSerializer<IdType>
|
||||||
|
) {
|
||||||
|
val paginationResultSerializer = PaginationResult.serializer(objectsSerializer)
|
||||||
|
|
||||||
|
get(getByPaginationRouting) {
|
||||||
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
paginationResultSerializer,
|
||||||
|
originalRepo.getByPagination(pagination)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(getByIdRouting) {
|
||||||
|
val id = call.decodeUrlQueryValueOrSendError(
|
||||||
|
"id",
|
||||||
|
idsSerializer
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
objectsNullableSerializer,
|
||||||
|
originalRepo.getById(id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(containsRouting) {
|
||||||
|
val id = call.decodeUrlQueryValueOrSendError(
|
||||||
|
"id",
|
||||||
|
idsSerializer
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Boolean.serializer(),
|
||||||
|
originalRepo.contains(id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.crud
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.StandardCRUDRepo
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.route
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
|
||||||
|
fun <ObjectType, IdType, InputValue> Route.configureStandardCrudRepoRoutes(
|
||||||
|
baseSubpart: String,
|
||||||
|
originalRepo: StandardCRUDRepo<ObjectType, IdType, InputValue>,
|
||||||
|
objectsSerializer: KSerializer<ObjectType>,
|
||||||
|
objectsNullableSerializer: KSerializer<ObjectType?>,
|
||||||
|
inputsSerializer: KSerializer<InputValue>,
|
||||||
|
idsSerializer: KSerializer<IdType>
|
||||||
|
) {
|
||||||
|
route(baseSubpart) {
|
||||||
|
configureReadStandardCrudRepoRoutes(originalRepo, objectsSerializer, objectsNullableSerializer, idsSerializer)
|
||||||
|
configureWriteStandardCrudRepoRoutes(originalRepo, objectsSerializer, objectsNullableSerializer, inputsSerializer, idsSerializer)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.crud
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.WriteStandardCRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
||||||
|
import io.ktor.application.call
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.post
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.*
|
||||||
|
|
||||||
|
fun <ObjectType, IdType, InputValue> Route.configureWriteStandardCrudRepoRoutes(
|
||||||
|
originalRepo: WriteStandardCRUDRepo<ObjectType, IdType, InputValue>,
|
||||||
|
objectsSerializer: KSerializer<ObjectType>,
|
||||||
|
objectsNullableSerializer: KSerializer<ObjectType?>,
|
||||||
|
inputsSerializer: KSerializer<InputValue>,
|
||||||
|
idsSerializer: KSerializer<IdType>
|
||||||
|
) {
|
||||||
|
val listObjectsSerializer = ListSerializer(objectsSerializer)
|
||||||
|
val listInputSerializer = ListSerializer(inputsSerializer)
|
||||||
|
val listIdsSerializer = ListSerializer(idsSerializer)
|
||||||
|
val inputUpdateSerializer = PairSerializer(
|
||||||
|
idsSerializer,
|
||||||
|
inputsSerializer
|
||||||
|
)
|
||||||
|
val listInputUpdateSerializer = ListSerializer(inputUpdateSerializer)
|
||||||
|
|
||||||
|
includeWebsocketHandling(
|
||||||
|
newObjectsFlowRouting,
|
||||||
|
originalRepo.newObjectsFlow,
|
||||||
|
objectsSerializer
|
||||||
|
)
|
||||||
|
includeWebsocketHandling(
|
||||||
|
updatedObjectsFlowRouting,
|
||||||
|
originalRepo.updatedObjectsFlow,
|
||||||
|
objectsSerializer
|
||||||
|
)
|
||||||
|
includeWebsocketHandling(
|
||||||
|
deletedObjectsIdsFlowRouting,
|
||||||
|
originalRepo.deletedObjectsIdsFlow,
|
||||||
|
idsSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
post(createRouting) {
|
||||||
|
call.unianswer(
|
||||||
|
listObjectsSerializer,
|
||||||
|
originalRepo.create(
|
||||||
|
call.uniload(listInputSerializer)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(updateRouting) {
|
||||||
|
val (id, input) = call.uniload(inputUpdateSerializer)
|
||||||
|
call.unianswer(
|
||||||
|
objectsNullableSerializer,
|
||||||
|
originalRepo.update(
|
||||||
|
id, input
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(updateManyRouting) {
|
||||||
|
val updates = call.uniload(listInputUpdateSerializer)
|
||||||
|
call.unianswer(
|
||||||
|
listObjectsSerializer,
|
||||||
|
originalRepo.update(
|
||||||
|
updates
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(deleteByIdRouting) {
|
||||||
|
val ids = call.uniload(listIdsSerializer)
|
||||||
|
call.unianswer(
|
||||||
|
Unit.serializer(),
|
||||||
|
originalRepo.deleteById(
|
||||||
|
ids
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.key_value
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.StandardKeyValueRepo
|
||||||
|
import io.ktor.routing.*
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
|
||||||
|
fun <K, V> Route.configureStandartKeyValueRepoRoutes(
|
||||||
|
baseSubpart: String,
|
||||||
|
originalRepo: StandardKeyValueRepo<K, V>,
|
||||||
|
keySerializer: KSerializer<K>,
|
||||||
|
valueSerializer: KSerializer<V>,
|
||||||
|
valueNullableSerializer: KSerializer<V?>,
|
||||||
|
) {
|
||||||
|
route(baseSubpart) {
|
||||||
|
configureReadStandartKeyValueRepoRoutes(
|
||||||
|
originalRepo,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer,
|
||||||
|
valueNullableSerializer,
|
||||||
|
)
|
||||||
|
configureWriteStandartKeyValueRepoRoutes(
|
||||||
|
originalRepo,
|
||||||
|
keySerializer,
|
||||||
|
valueSerializer,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.key_value
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.StandardReadKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
|
import io.ktor.application.*
|
||||||
|
import io.ktor.routing.*
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
fun <K, V> Route.configureReadStandartKeyValueRepoRoutes (
|
||||||
|
originalRepo: StandardReadKeyValueRepo<K, V>,
|
||||||
|
keySerializer: KSerializer<K>,
|
||||||
|
valueSerializer: KSerializer<V>,
|
||||||
|
valueNullableSerializer: KSerializer<V?>,
|
||||||
|
) {
|
||||||
|
get(getRoute) {
|
||||||
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
|
keyParameterName,
|
||||||
|
keySerializer
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
valueNullableSerializer,
|
||||||
|
originalRepo.get(key)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(valuesRoute) {
|
||||||
|
val parination = call.request.queryParameters.extractPagination;
|
||||||
|
val reversed = call.decodeUrlQueryValueOrSendError(
|
||||||
|
reversedParameterName,
|
||||||
|
Boolean.serializer()
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
PaginationResult.serializer(valueSerializer),
|
||||||
|
originalRepo.values(parination, reversed)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(keysRoute) {
|
||||||
|
val parination = call.request.queryParameters.extractPagination;
|
||||||
|
val reversed = call.decodeUrlQueryValueOrSendError(
|
||||||
|
reversedParameterName,
|
||||||
|
Boolean.serializer()
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
PaginationResult.serializer(keySerializer),
|
||||||
|
originalRepo.keys(parination, reversed)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(containsRoute) {
|
||||||
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
|
keyParameterName,
|
||||||
|
keySerializer
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Boolean.serializer(),
|
||||||
|
originalRepo.contains(key)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(countRoute) {
|
||||||
|
call.unianswer(
|
||||||
|
Long.serializer(),
|
||||||
|
originalRepo.count()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.key_value
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.StandardWriteKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
||||||
|
import io.ktor.application.*
|
||||||
|
import io.ktor.routing.*
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.PairSerializer
|
||||||
|
|
||||||
|
fun <K, V> Route.configureWriteStandartKeyValueRepoRoutes (
|
||||||
|
originalRepo: StandardWriteKeyValueRepo<K, V>,
|
||||||
|
keySerializer: KSerializer<K>,
|
||||||
|
valueSerializer: KSerializer<V>,
|
||||||
|
) {
|
||||||
|
includeWebsocketHandling(
|
||||||
|
onNewValueRoute,
|
||||||
|
originalRepo.onNewValue,
|
||||||
|
PairSerializer(keySerializer, valueSerializer)
|
||||||
|
)
|
||||||
|
|
||||||
|
includeWebsocketHandling(
|
||||||
|
onValueRemovedRoute,
|
||||||
|
originalRepo.onValueRemoved,
|
||||||
|
keySerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
post(setRoute) {
|
||||||
|
val (key, value) = call.uniload(
|
||||||
|
KeyValuePostObject.serializer(keySerializer, valueSerializer)
|
||||||
|
)
|
||||||
|
|
||||||
|
originalRepo.set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(unsetRoute) {
|
||||||
|
val key = call.uniload(
|
||||||
|
keySerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
originalRepo.unset(key)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyKeyValueRepo
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.route
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
|
||||||
|
fun <Key, Value> Route.configureOneToManyKeyValueRepoRoutes(
|
||||||
|
baseSubpart: String,
|
||||||
|
originalRepo: OneToManyKeyValueRepo<Key, Value>,
|
||||||
|
keySerializer: KSerializer<Key>,
|
||||||
|
valueSealizer: KSerializer<Value>,
|
||||||
|
) {
|
||||||
|
route(baseSubpart) {
|
||||||
|
configureOneToManyReadKeyValueRepoRoutes(originalRepo, keySerializer, valueSealizer)
|
||||||
|
configureOneToManyWriteKeyValueRepoRoutes(originalRepo, keySerializer, valueSealizer)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyReadKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import io.ktor.application.call
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.get
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
fun <Key, Value> Route.configureOneToManyReadKeyValueRepoRoutes(
|
||||||
|
originalRepo: OneToManyReadKeyValueRepo<Key, Value>,
|
||||||
|
keySerializer: KSerializer<Key>,
|
||||||
|
valueSealizer: KSerializer<Value>,
|
||||||
|
) {
|
||||||
|
val paginationKeyResult = PaginationResult.serializer(keySerializer)
|
||||||
|
val paginationValueResult = PaginationResult.serializer(valueSealizer)
|
||||||
|
|
||||||
|
get(getRoute) {
|
||||||
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
|
keyParameterName,
|
||||||
|
keySerializer
|
||||||
|
) ?: return@get
|
||||||
|
val reversed = call.decodeUrlQueryValue(
|
||||||
|
reversedParameterName,
|
||||||
|
Boolean.serializer()
|
||||||
|
) ?: false
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
paginationValueResult,
|
||||||
|
originalRepo.get(key, pagination, reversed)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(keysRoute) {
|
||||||
|
val pagination = call.request.queryParameters.extractPagination
|
||||||
|
val reversed = call.decodeUrlQueryValue(
|
||||||
|
reversedParameterName,
|
||||||
|
Boolean.serializer()
|
||||||
|
) ?: false
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
paginationKeyResult,
|
||||||
|
originalRepo.keys(pagination, reversed)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(containsByKeyRoute) {
|
||||||
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
|
keyParameterName,
|
||||||
|
keySerializer
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Boolean.serializer(),
|
||||||
|
originalRepo.contains(key)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(containsByKeyValueRoute) {
|
||||||
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
|
keyParameterName,
|
||||||
|
keySerializer
|
||||||
|
) ?: return@get
|
||||||
|
val value = call.decodeUrlQueryValueOrSendError(
|
||||||
|
valueParameterName,
|
||||||
|
valueSealizer
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Boolean.serializer(),
|
||||||
|
originalRepo.contains(key, value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(countByKeyRoute) {
|
||||||
|
val key = call.decodeUrlQueryValueOrSendError(
|
||||||
|
keyParameterName,
|
||||||
|
keySerializer
|
||||||
|
) ?: return@get
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Long.serializer(),
|
||||||
|
originalRepo.count(key)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(countRoute) {
|
||||||
|
call.unianswer(
|
||||||
|
Long.serializer(),
|
||||||
|
originalRepo.count()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.ktor.server.one_to_many
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.OneToManyWriteKeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
||||||
|
import io.ktor.application.call
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import io.ktor.routing.post
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.builtins.PairSerializer
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
fun <Key, Value> Route.configureOneToManyWriteKeyValueRepoRoutes(
|
||||||
|
originalRepo: OneToManyWriteKeyValueRepo<Key, Value>,
|
||||||
|
keySerializer: KSerializer<Key>,
|
||||||
|
valueSealizer: KSerializer<Value>,
|
||||||
|
) {
|
||||||
|
val keyValueSerializer = PairSerializer(keySerializer, valueSealizer)
|
||||||
|
|
||||||
|
post(addRoute) {
|
||||||
|
val obj = call.uniload(
|
||||||
|
keyValueSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Unit.serializer(),
|
||||||
|
originalRepo.add(obj.first, obj.second)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(removeRoute) {
|
||||||
|
val obj = call.uniload(
|
||||||
|
keyValueSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Unit.serializer(),
|
||||||
|
originalRepo.remove(obj.first, obj.second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
post(clearRoute) {
|
||||||
|
val key = call.uniload(keySerializer)
|
||||||
|
|
||||||
|
call.unianswer(
|
||||||
|
Unit.serializer(),
|
||||||
|
originalRepo.clear(key),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,10 @@ String[] includes = [
|
|||||||
":pagination:ktor:common",
|
":pagination:ktor:common",
|
||||||
":pagination:ktor:server",
|
":pagination:ktor:server",
|
||||||
":repos:common",
|
":repos:common",
|
||||||
|
":repos:exposed",
|
||||||
|
":repos:ktor:client",
|
||||||
|
":repos:ktor:common",
|
||||||
|
":repos:ktor:server",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user