add crud repo server and change a lot of different things
This commit is contained in:
core/ktor
client
src
commonMain
kotlin
com
insanusmokrassar
postssystem
core
ktor
client
server
src
main
kotlin
com
insanusmokrassar
postssystem
core
ktor
ktor
client
src
commonMain
kotlin
com
insanusmokrassar
postssystem
ktor
client
server
src
jvmMain
kotlin
com
insanusmokrassar
postssystem
tests
src
test
kotlin
com
insanusmokrassar
postssystem
ktor
tests
utils/repos
common
src
commonMain
kotlin
com
insanusmokrassar
postssystem
utils
repos
exposed
src
main
kotlin
com
insanusmokrassar
postssystem
utils
repos
ktor
client
src
commonMain
kotlin
com
insanusmokrassar
postssystem
utils
repos
ktor
server
@ -4,7 +4,6 @@ import com.insanusmokrassar.postssystem.core.content.*
|
||||
import com.insanusmokrassar.postssystem.core.content.api.WriteContentRepo
|
||||
import com.insanusmokrassar.postssystem.core.ktor.*
|
||||
import com.insanusmokrassar.postssystem.ktor.client.*
|
||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||
import io.ktor.client.HttpClient
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.serialization.builtins.nullable
|
||||
@ -15,16 +14,14 @@ class WriteContentRepoKtorClient(
|
||||
private val client: HttpClient = HttpClient()
|
||||
) : WriteContentRepo {
|
||||
override val contentCreatedFlow: Flow<RegisteredContent> = client.createStandardWebsocketFlow(
|
||||
"$baseUrl/$contentCreatedFlowRoute"
|
||||
) {
|
||||
standardKtorSerialFormat.decodeFromByteArray(RegisteredContent.serializer(), it)
|
||||
}
|
||||
"$baseUrl/$contentCreatedFlowRoute",
|
||||
deserializer = RegisteredContent.serializer()
|
||||
)
|
||||
|
||||
override val contentDeletedFlow: Flow<RegisteredContent> = client.createStandardWebsocketFlow(
|
||||
"$baseUrl/$contentDeletedFlowRoute"
|
||||
) {
|
||||
standardKtorSerialFormat.decodeFromByteArray(RegisteredContent.serializer(), it)
|
||||
}
|
||||
"$baseUrl/$contentDeletedFlowRoute",
|
||||
deserializer = RegisteredContent.serializer()
|
||||
)
|
||||
|
||||
override suspend fun registerContent(content: Content): RegisteredContent? = client.unipost(
|
||||
"$baseUrl/$registerContentRoute",
|
||||
|
@ -4,7 +4,6 @@ import com.insanusmokrassar.postssystem.core.ktor.*
|
||||
import com.insanusmokrassar.postssystem.core.post.*
|
||||
import com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo
|
||||
import com.insanusmokrassar.postssystem.ktor.client.*
|
||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.features.websocket.WebSockets
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@ -18,20 +17,17 @@ class WritePostsRepoKtorClient (
|
||||
}
|
||||
) : WritePostsRepo {
|
||||
override val postCreatedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
|
||||
"$baseUrl/$postCreatedFlowRoute"
|
||||
) {
|
||||
standardKtorSerialFormat.decodeFromByteArray(RegisteredPost.serializer(), it)
|
||||
}
|
||||
"$baseUrl/$postCreatedFlowRoute",
|
||||
deserializer = RegisteredPost.serializer()
|
||||
)
|
||||
override val postDeletedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
|
||||
"$baseUrl/$postDeletedFlowRoute"
|
||||
) {
|
||||
standardKtorSerialFormat.decodeFromByteArray(RegisteredPost.serializer(), it)
|
||||
}
|
||||
"$baseUrl/$postDeletedFlowRoute",
|
||||
deserializer = RegisteredPost.serializer()
|
||||
)
|
||||
override val postUpdatedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
|
||||
"$baseUrl/$postUpdatedFlowRoute"
|
||||
) {
|
||||
standardKtorSerialFormat.decodeFromByteArray(RegisteredPost.serializer(), it)
|
||||
}
|
||||
"$baseUrl/$postUpdatedFlowRoute",
|
||||
deserializer = RegisteredPost.serializer()
|
||||
)
|
||||
|
||||
override suspend fun createPost(post: Post): RegisteredPost? = client.unipost(
|
||||
"$baseUrl/$createPostRoute",
|
||||
|
@ -15,12 +15,8 @@ import kotlinx.serialization.builtins.serializer
|
||||
fun Route.configureWriteContentRepoRoutes(
|
||||
proxyTo: WriteContentRepo
|
||||
) {
|
||||
includeWebsocketHandling(contentCreatedFlowRoute, proxyTo.contentCreatedFlow) {
|
||||
standardKtorSerialFormat.encodeToByteArray(RegisteredContent.serializer(), it)
|
||||
}
|
||||
includeWebsocketHandling(contentDeletedFlowRoute, proxyTo.contentDeletedFlow) {
|
||||
standardKtorSerialFormat.encodeToByteArray(RegisteredContent.serializer(), it)
|
||||
}
|
||||
includeWebsocketHandling(contentCreatedFlowRoute, proxyTo.contentCreatedFlow, RegisteredContent.serializer())
|
||||
includeWebsocketHandling(contentDeletedFlowRoute, proxyTo.contentDeletedFlow, RegisteredContent.serializer())
|
||||
post(registerContentRoute) {
|
||||
val content = call.uniload(Content.serializer())
|
||||
val registered = proxyTo.registerContent(content)
|
||||
|
@ -15,15 +15,9 @@ import kotlinx.serialization.builtins.serializer
|
||||
fun Route.configureWritePostsRepoRoutes(
|
||||
proxyTo: WritePostsRepo
|
||||
) {
|
||||
includeWebsocketHandling(postCreatedFlowRoute, proxyTo.postCreatedFlow) {
|
||||
standardKtorSerialFormat.encodeToByteArray(RegisteredPost.serializer(), it)
|
||||
}
|
||||
includeWebsocketHandling(postDeletedFlowRoute, proxyTo.postDeletedFlow) {
|
||||
standardKtorSerialFormat.encodeToByteArray(RegisteredPost.serializer(), it)
|
||||
}
|
||||
includeWebsocketHandling(postUpdatedFlowRoute, proxyTo.postUpdatedFlow) {
|
||||
standardKtorSerialFormat.encodeToByteArray(RegisteredPost.serializer(), it)
|
||||
}
|
||||
includeWebsocketHandling(postCreatedFlowRoute, proxyTo.postCreatedFlow, RegisteredPost.serializer())
|
||||
includeWebsocketHandling(postDeletedFlowRoute, proxyTo.postDeletedFlow, RegisteredPost.serializer())
|
||||
includeWebsocketHandling(postUpdatedFlowRoute, proxyTo.postUpdatedFlow, RegisteredPost.serializer())
|
||||
|
||||
post(createPostRoute) {
|
||||
call.unianswer(
|
||||
|
18
ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/client/FlowsWebsockets.kt
18
ktor/client/src/commonMain/kotlin/com/insanusmokrassar/postssystem/ktor/client/FlowsWebsockets.kt
@ -1,6 +1,7 @@
|
||||
package com.insanusmokrassar.postssystem.ktor.client
|
||||
|
||||
import com.insanusmokrassar.postssystem.ktor.asCorrectWebSocketUrl
|
||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||
import com.insanusmokrassar.postssystem.utils.common.safely
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.features.websocket.ws
|
||||
@ -8,6 +9,7 @@ import io.ktor.http.cio.websocket.Frame
|
||||
import io.ktor.http.cio.websocket.readBytes
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
|
||||
/**
|
||||
* @param checkReconnection This lambda will be called when it is required to reconnect to websocket to establish
|
||||
@ -63,3 +65,19 @@ inline fun <T> HttpClient.createStandardWebsocketFlow(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param checkReconnection This lambda will be called when it is required to reconnect to websocket to establish
|
||||
* connection. Must return true in case if must be reconnected. By default always reconnecting
|
||||
*/
|
||||
inline fun <T> HttpClient.createStandardWebsocketFlow(
|
||||
url: String,
|
||||
crossinline checkReconnection: (Throwable?) -> Boolean = { true },
|
||||
deserializer: DeserializationStrategy<T>
|
||||
) = createStandardWebsocketFlow(
|
||||
url,
|
||||
checkReconnection
|
||||
) {
|
||||
standardKtorSerialFormat.decodeFromByteArray(deserializer, it)
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
package com.insanusmokrassar.postssystem.ktor.server
|
||||
|
||||
import com.insanusmokrassar.postssystem.ktor.CorrectCloseException
|
||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||
import com.insanusmokrassar.postssystem.utils.common.safely
|
||||
import io.ktor.http.cio.websocket.*
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.websocket.webSocket
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.SerializationStrategy
|
||||
|
||||
private suspend fun DefaultWebSocketSession.checkReceivedAndCloseIfExists() {
|
||||
if (incoming.poll() != null) {
|
||||
@ -29,3 +32,14 @@ fun <T> Route.includeWebsocketHandling(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Route.includeWebsocketHandling(
|
||||
suburl: String,
|
||||
flow: Flow<T>,
|
||||
serializer: SerializationStrategy<T>
|
||||
) = includeWebsocketHandling(
|
||||
suburl,
|
||||
flow
|
||||
) {
|
||||
standardKtorSerialFormat.encodeToByteArray(serializer, it)
|
||||
}
|
||||
|
@ -30,6 +30,14 @@ suspend fun ApplicationCall.getParameterOrSendError(
|
||||
field: String
|
||||
) = parameters[field].also {
|
||||
if (it == null) {
|
||||
respond(HttpStatusCode.BadRequest, "request must contains $field")
|
||||
respond(HttpStatusCode.BadRequest, "Request must contains $field")
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun ApplicationCall.getQueryParameterOrSendError(
|
||||
field: String
|
||||
) = request.queryParameters[field].also {
|
||||
if (it == null) {
|
||||
respond(HttpStatusCode.BadRequest, "Request query parametersmust contains $field")
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,7 @@ class WebsocketsTest {
|
||||
val server = createKtorServer(host = "127.0.0.1", port = port) {
|
||||
install(WebSockets)
|
||||
routing {
|
||||
includeWebsocketHandling(suburl, dataFlow) {
|
||||
standardKtorSerialFormat.encodeToByteArray(Int.serializer(), it)
|
||||
}
|
||||
includeWebsocketHandling(suburl, dataFlow, Int.serializer())
|
||||
}
|
||||
}.also {
|
||||
it.start(false)
|
||||
@ -42,10 +40,9 @@ class WebsocketsTest {
|
||||
}
|
||||
val incomingWebsocketFlow = client.createStandardWebsocketFlow(
|
||||
"$serverUrl/$suburl",
|
||||
{ false } // always skip reconnection
|
||||
) {
|
||||
standardKtorSerialFormat.decodeFromByteArray(Int.serializer(), it)
|
||||
}
|
||||
{ false }, // always skip reconnection
|
||||
deserializer = Int.serializer()
|
||||
)
|
||||
|
||||
var currentlyCheckingData: Int? = null
|
||||
incomingWebsocketFlow.onEach {
|
||||
|
@ -6,6 +6,7 @@ String[] includes = [
|
||||
':utils:repos:common',
|
||||
':utils:repos:ktor:common',
|
||||
':utils:repos:ktor:client',
|
||||
':utils:repos:ktor:server',
|
||||
':utils:repos:exposed',
|
||||
|
||||
':exposed:commons',
|
||||
|
@ -21,11 +21,21 @@ interface WriteStandardCRUDRepo<ObjectType, IdType, InputValueType> : Repo {
|
||||
val updatedObjectsFlow: Flow<ObjectType>
|
||||
val deletedObjectsIdsFlow: Flow<IdType>
|
||||
|
||||
suspend fun create(vararg values: InputValueType): List<ObjectType>
|
||||
suspend fun create(values: List<InputValueType>): List<ObjectType>
|
||||
suspend fun update(id: IdType, value: InputValueType): ObjectType?
|
||||
suspend fun update(vararg values: UpdatedValuePair<IdType, InputValueType>): List<ObjectType>
|
||||
suspend fun deleteById(vararg ids: IdType)
|
||||
suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType>
|
||||
suspend fun deleteById(ids: List<IdType>)
|
||||
}
|
||||
|
||||
suspend fun <ObjectType, IdType, InputValueType> WriteStandardCRUDRepo<ObjectType, IdType, InputValueType>.create(
|
||||
vararg values: InputValueType
|
||||
): List<ObjectType> = create(values.toList())
|
||||
suspend fun <ObjectType, IdType, InputValueType> WriteStandardCRUDRepo<ObjectType, IdType, InputValueType>.update(
|
||||
vararg values: UpdatedValuePair<IdType, InputValueType>
|
||||
): List<ObjectType> = update(values.toList())
|
||||
suspend fun <ObjectType, IdType, InputValueType> WriteStandardCRUDRepo<ObjectType, IdType, InputValueType>.deleteById(
|
||||
vararg ids: IdType
|
||||
) = deleteById(ids.toList())
|
||||
|
||||
interface StandardCRUDRepo<ObjectType, IdType, InputValueType> : ReadStandardCRUDRepo<ObjectType, IdType>,
|
||||
WriteStandardCRUDRepo<ObjectType, IdType, InputValueType>
|
||||
|
@ -27,20 +27,20 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
override val deletedObjectsIdsFlow: Flow<IdType> = deleteObjectsIdsChannel.asFlow()
|
||||
|
||||
abstract val InsertStatement<Number>.asObject: ObjectType
|
||||
abstract val selectByIds: SqlExpressionBuilder.(Array<out IdType>) -> Op<Boolean>
|
||||
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(vararg value: InputValueType) {}
|
||||
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(vararg values: InputValueType): List<ObjectType> {
|
||||
onBeforeCreate(*values)
|
||||
override suspend fun create(values: List<InputValueType>): List<ObjectType> {
|
||||
onBeforeCreate(values)
|
||||
return transaction(db = database) {
|
||||
values.map { value -> createWithoutNotification(value) }
|
||||
}.also {
|
||||
@ -50,7 +50,7 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
}
|
||||
}
|
||||
|
||||
protected open suspend fun onBeforeUpdate(vararg value: UpdatedValuePair<IdType, InputValueType>) {}
|
||||
protected open suspend fun onBeforeUpdate(value: List<UpdatedValuePair<IdType, InputValueType>>) {}
|
||||
private fun updateWithoutNotification(id: IdType, value: InputValueType): ObjectType? {
|
||||
return transaction(db = database) {
|
||||
update(
|
||||
@ -72,15 +72,15 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
}
|
||||
|
||||
override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
|
||||
onBeforeUpdate(id to value)
|
||||
onBeforeUpdate(listOf(id to value))
|
||||
return updateWithoutNotification(id, value).also {
|
||||
if (it != null) {
|
||||
updateObjectsChannel.send(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
override suspend fun update(vararg values: UpdatedValuePair<IdType, InputValueType>): List<ObjectType> {
|
||||
onBeforeUpdate(*values)
|
||||
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType> {
|
||||
onBeforeUpdate(values)
|
||||
return (
|
||||
transaction(db = database) {
|
||||
values.map { (id, value) -> updateWithoutNotification(id, value) }
|
||||
@ -93,9 +93,9 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
}
|
||||
}
|
||||
}
|
||||
protected open suspend fun onBeforeDelete(vararg ids: IdType) {}
|
||||
override suspend fun deleteById(vararg ids: IdType) {
|
||||
onBeforeDelete(*ids)
|
||||
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)
|
||||
|
@ -2,15 +2,12 @@ package com.insanusmokrassar.postssystem.utils.repos.ktor.client
|
||||
|
||||
import com.insanusmokrassar.postssystem.ktor.*
|
||||
import com.insanusmokrassar.postssystem.ktor.client.*
|
||||
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||
import com.insanusmokrassar.postssystem.utils.repos.*
|
||||
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.*
|
||||
import io.ktor.client.HttpClient
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.*
|
||||
import kotlinx.serialization.encodeToHexString
|
||||
|
||||
class KtorWriteStandardCrudRepo<ObjectType, IdType, InputValue> (
|
||||
private val baseUrl: String,
|
||||
@ -23,45 +20,47 @@ class KtorWriteStandardCrudRepo<ObjectType, IdType, InputValue> (
|
||||
private val listObjectsSerializer = ListSerializer(objectsSerializer)
|
||||
private val listInputSerializer = ListSerializer(inputsSerializer)
|
||||
private val listIdsSerializer = ListSerializer(idsSerializer)
|
||||
private val inputUpdateSerializer = TemporalInputObjectForUpdate.serializer(
|
||||
private val inputUpdateSerializer = PairSerializer(
|
||||
idsSerializer,
|
||||
inputsSerializer
|
||||
)
|
||||
private val listInputUpdateSerializer = ListSerializer(inputUpdateSerializer)
|
||||
|
||||
override val newObjectsFlow: Flow<ObjectType> = client.createStandardWebsocketFlow(
|
||||
buildStandardUrl(baseUrl, newObjectsFlowRouting)
|
||||
) { standardKtorSerialFormat.decodeFromByteArray(objectsSerializer, it) }
|
||||
buildStandardUrl(baseUrl, newObjectsFlowRouting),
|
||||
deserializer = objectsSerializer
|
||||
)
|
||||
override val updatedObjectsFlow: Flow<ObjectType> = client.createStandardWebsocketFlow(
|
||||
buildStandardUrl(baseUrl, updatedObjectsFlowRouting)
|
||||
) { standardKtorSerialFormat.decodeFromByteArray(objectsSerializer, it) }
|
||||
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
|
||||
deserializer = objectsSerializer
|
||||
)
|
||||
override val deletedObjectsIdsFlow: Flow<IdType> = client.createStandardWebsocketFlow(
|
||||
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting)
|
||||
) { standardKtorSerialFormat.decodeFromByteArray(idsSerializer, it) }
|
||||
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
|
||||
deserializer = idsSerializer
|
||||
)
|
||||
|
||||
|
||||
|
||||
override suspend fun create(vararg values: InputValue): List<ObjectType> = client.unipost(
|
||||
override suspend fun create(values: List<InputValue>): List<ObjectType> = client.unipost(
|
||||
buildStandardUrl(baseUrl, createRouting),
|
||||
BodyPair(listInputSerializer, values.toList()),
|
||||
BodyPair(listInputSerializer, values),
|
||||
listObjectsSerializer
|
||||
)
|
||||
|
||||
override suspend fun update(id: IdType, value: InputValue): ObjectType? = client.unipost(
|
||||
buildStandardUrl(baseUrl, updateRouting),
|
||||
BodyPair(inputUpdateSerializer, TemporalInputObjectForUpdate(id, value)),
|
||||
BodyPair(inputUpdateSerializer, id to value),
|
||||
objectsNullableSerializer
|
||||
)
|
||||
|
||||
override suspend fun update(vararg values: UpdatedValuePair<IdType, InputValue>): List<ObjectType> = client.unipost(
|
||||
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValue>>): List<ObjectType> = client.unipost(
|
||||
buildStandardUrl(baseUrl, updateManyRouting),
|
||||
BodyPair(listInputUpdateSerializer, values.map { TemporalInputObjectForUpdate(it.first, it.second) }),
|
||||
BodyPair(listInputUpdateSerializer, values),
|
||||
listObjectsSerializer
|
||||
)
|
||||
|
||||
override suspend fun deleteById(vararg ids: IdType) = client.unipost(
|
||||
override suspend fun deleteById(ids: List<IdType>) = client.unipost(
|
||||
buildStandardUrl(baseUrl, deleteByIdRouting),
|
||||
BodyPair(listIdsSerializer, ids.toList()),
|
||||
BodyPair(listIdsSerializer, ids),
|
||||
Unit.serializer()
|
||||
)
|
||||
}
|
||||
|
64
utils/repos/ktor/server/build.gradle
Normal file
64
utils/repos/ktor/server/build.gradle
Normal file
@ -0,0 +1,64 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
|
||||
}
|
||||
|
||||
project.version = "$core_version"
|
||||
project.group = "com.insanusmokrassar"
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://kotlin.bintray.com/kotlinx" }
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation kotlin('stdlib')
|
||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
|
||||
api projectByName("postssystem.utils.repos.ktor.common")
|
||||
api projectByName("postssystem.ktor.server")
|
||||
}
|
||||
}
|
||||
commonTest {
|
||||
dependencies {
|
||||
implementation kotlin('test-common')
|
||||
implementation kotlin('test-annotations-common')
|
||||
}
|
||||
}
|
||||
|
||||
jvmMain {
|
||||
dependencies {
|
||||
api "io.ktor:ktor-server:$ktor_version"
|
||||
api "io.ktor:ktor-server-host-common:$ktor_version"
|
||||
api "io.ktor:ktor-server-netty:$ktor_version"
|
||||
api "io.ktor:ktor-websockets:$ktor_version"
|
||||
}
|
||||
}
|
||||
jvmTest {
|
||||
dependencies {
|
||||
implementation kotlin('test-junit')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
55
utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/KtorReadStandardCrudRepo.kt
Normal file
55
utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/KtorReadStandardCrudRepo.kt
Normal file
@ -0,0 +1,55 @@
|
||||
package com.insanusmokrassar.postssystem.utils.repos.ktor.server
|
||||
|
||||
import com.insanusmokrassar.postssystem.ktor.server.*
|
||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
|
||||
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.*
|
||||
import io.ktor.application.call
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.routing.get
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.decodeFromHexString
|
||||
|
||||
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 = standardKtorSerialFormat.decodeFromHexString(
|
||||
idsSerializer,
|
||||
call.getQueryParameterOrSendError("id") ?: return@get
|
||||
)
|
||||
|
||||
call.unianswer(
|
||||
objectsNullableSerializer,
|
||||
originalRepo.getById(id)
|
||||
)
|
||||
}
|
||||
|
||||
get(containsRouting) {
|
||||
val id = standardKtorSerialFormat.decodeFromHexString(
|
||||
idsSerializer,
|
||||
call.getQueryParameterOrSendError("id") ?: return@get
|
||||
)
|
||||
|
||||
call.unianswer(
|
||||
Boolean.serializer(),
|
||||
originalRepo.contains(id)
|
||||
)
|
||||
}
|
||||
}
|
27
utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/KtorStandardCrudRepo.kt
Normal file
27
utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/KtorStandardCrudRepo.kt
Normal file
@ -0,0 +1,27 @@
|
||||
package com.insanusmokrassar.postssystem.utils.repos.ktor.server
|
||||
|
||||
import com.insanusmokrassar.postssystem.ktor.server.*
|
||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||
import com.insanusmokrassar.postssystem.utils.repos.*
|
||||
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.*
|
||||
import io.ktor.application.call
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.routing.get
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.*
|
||||
import kotlinx.serialization.decodeFromHexString
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
86
utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/KtorWriteStandardCrudRepo.kt
Normal file
86
utils/repos/ktor/server/src/jvmMain/kotlin/com/insanusmokrassar/postssystem/utils/repos/ktor/server/KtorWriteStandardCrudRepo.kt
Normal file
@ -0,0 +1,86 @@
|
||||
package com.insanusmokrassar.postssystem.utils.repos.ktor.server
|
||||
|
||||
import com.insanusmokrassar.postssystem.ktor.server.*
|
||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
|
||||
import com.insanusmokrassar.postssystem.utils.repos.WriteStandardCRUDRepo
|
||||
import com.insanusmokrassar.postssystem.utils.repos.ktor.common.*
|
||||
import io.ktor.application.call
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.routing.get
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.*
|
||||
import kotlinx.serialization.decodeFromHexString
|
||||
|
||||
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
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user