add all client realizations for core repos
This commit is contained in:
parent
336e169147
commit
3d3d184636
@ -1,9 +1,3 @@
|
|||||||
package com.insanusmokrassar.postssystem.core.content.api
|
package com.insanusmokrassar.postssystem.core.content.api
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
interface ContentRepo : ReadContentRepo, WriteContentRepo
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
interface ContentRepo : ReadContentRepo, WriteContentRepo {
|
|
||||||
val contentCreatedFlow: Flow<RegisteredContent>
|
|
||||||
val contentDeletedFlow: Flow<RegisteredContent>
|
|
||||||
}
|
|
||||||
|
@ -2,8 +2,8 @@ package com.insanusmokrassar.postssystem.core.content.api
|
|||||||
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.ContentId
|
import com.insanusmokrassar.postssystem.core.content.ContentId
|
||||||
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple read API by different properties of [com.insanusmokrassar.postssystem.core.content.Content].
|
* Simple read API by different properties of [com.insanusmokrassar.postssystem.core.content.Content].
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package com.insanusmokrassar.postssystem.core.content.api
|
package com.insanusmokrassar.postssystem.core.content.api
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.*
|
import com.insanusmokrassar.postssystem.core.content.*
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface WriteContentRepo {
|
interface WriteContentRepo {
|
||||||
|
val contentCreatedFlow: Flow<RegisteredContent>
|
||||||
|
val contentDeletedFlow: Flow<RegisteredContent>
|
||||||
|
|
||||||
suspend fun registerContent(content: Content): RegisteredContent?
|
suspend fun registerContent(content: Content): RegisteredContent?
|
||||||
suspend fun deleteContent(id: ContentId): Boolean
|
suspend fun deleteContent(id: ContentId): Boolean
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package com.insanusmokrassar.postssystem.core.post
|
package com.insanusmokrassar.postssystem.core.post
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.ContentId
|
import com.insanusmokrassar.postssystem.core.content.ContentId
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.UnixMillis
|
||||||
import com.soywiz.klock.DateTime
|
import com.soywiz.klock.DateTime
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
|
||||||
typealias PostId = String
|
typealias PostId = String
|
||||||
typealias ContentIds = List<ContentId>
|
typealias ContentIds = List<ContentId>
|
||||||
@ -9,35 +12,50 @@ typealias ContentIds = List<ContentId>
|
|||||||
/**
|
/**
|
||||||
* Base interface for creating of new post. Usually, it is just [SimplePost] instance
|
* Base interface for creating of new post. Usually, it is just [SimplePost] instance
|
||||||
*/
|
*/
|
||||||
interface Post {
|
@Serializable
|
||||||
val content: ContentIds
|
sealed class Post {
|
||||||
|
abstract val content: ContentIds
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root entity of whole system. Can be retrieved from [com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo] by
|
* Root entity of the whole system. Can be retrieved from [com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo]
|
||||||
* getting and created in [com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo] by inserting of [Post] instance
|
* by getting and created in [com.insanusmokrassar.postssystem.core.post.repo.WritePostsRepo] by inserting of [Post]
|
||||||
|
* instance
|
||||||
*/
|
*/
|
||||||
interface RegisteredPost : Post {
|
@Serializable
|
||||||
val id: PostId
|
sealed class RegisteredPost : Post() {
|
||||||
|
abstract val id: PostId
|
||||||
|
|
||||||
override val content: ContentIds
|
abstract override val content: ContentIds
|
||||||
|
|
||||||
val creationDate: DateTime
|
abstract val creationDate: DateTime
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base and currently (1st Nov 2019) single realisation of [Post]. There is [SimpleRegisteredPost] which is technically
|
* Base and currently (1st Nov 2019) single realisation of [Post]. There is [SimpleRegisteredPost] which is technically
|
||||||
* is [Post] too, but it is not direct [Post] realisation
|
* is [Post] too, but it is not direct [Post] realisation
|
||||||
*/
|
*/
|
||||||
|
@Serializable
|
||||||
data class SimplePost(
|
data class SimplePost(
|
||||||
override val content: ContentIds
|
override val content: ContentIds
|
||||||
) : Post
|
) : Post()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base and currently (1st Nov 2019) single realisation of [RegisteredPost]
|
* Base and currently (1st Nov 2019) single realisation of [RegisteredPost]
|
||||||
*/
|
*/
|
||||||
|
@Serializable
|
||||||
data class SimpleRegisteredPost(
|
data class SimpleRegisteredPost(
|
||||||
override val id: PostId,
|
override val id: PostId,
|
||||||
override val content: ContentIds,
|
override val content: ContentIds,
|
||||||
override val creationDate: DateTime = DateTime.now()
|
private val creationDateTimeMillis: UnixMillis
|
||||||
) : RegisteredPost
|
) : RegisteredPost() {
|
||||||
|
@Transient
|
||||||
|
override val creationDate: DateTime = DateTime(creationDateTimeMillis)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
fun RegisteredPost(
|
||||||
|
id: PostId,
|
||||||
|
content: ContentIds,
|
||||||
|
creationDate: DateTime
|
||||||
|
) = SimpleRegisteredPost(id, content, creationDate.unixMillis)
|
@ -5,8 +5,7 @@ import com.insanusmokrassar.postssystem.core.post.PostId
|
|||||||
import com.insanusmokrassar.postssystem.core.post.RegisteredPost
|
import com.insanusmokrassar.postssystem.core.post.RegisteredPost
|
||||||
import com.insanusmokrassar.postssystem.utils.common.MAX_DATE
|
import com.insanusmokrassar.postssystem.utils.common.MAX_DATE
|
||||||
import com.insanusmokrassar.postssystem.utils.common.MIN_DATE
|
import com.insanusmokrassar.postssystem.utils.common.MIN_DATE
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
|
|
||||||
import com.soywiz.klock.DateTime
|
import com.soywiz.klock.DateTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +30,11 @@ interface ReadPostsRepo {
|
|||||||
/**
|
/**
|
||||||
* @return all [RegisteredPost]s which was registered between [from] and [to]. Range will be used INCLUSIVE, line \[[from], [to]\]
|
* @return all [RegisteredPost]s which was registered between [from] and [to]. Range will be used INCLUSIVE, line \[[from], [to]\]
|
||||||
*/
|
*/
|
||||||
suspend fun getPostsByCreatingDates(from: DateTime = MIN_DATE, to: DateTime = MAX_DATE): List<RegisteredPost>
|
suspend fun getPostsByCreatingDates(
|
||||||
|
from: DateTime = MIN_DATE,
|
||||||
|
to: DateTime = MAX_DATE,
|
||||||
|
pagination: Pagination = FirstPagePagination()
|
||||||
|
): PaginationResult<RegisteredPost>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return all posts by pages basing on their creation date
|
* @return all posts by pages basing on their creation date
|
||||||
@ -41,8 +44,10 @@ interface ReadPostsRepo {
|
|||||||
|
|
||||||
suspend fun ReadPostsRepo.getPostsByCreatingDates(
|
suspend fun ReadPostsRepo.getPostsByCreatingDates(
|
||||||
from: DateTime? = null,
|
from: DateTime? = null,
|
||||||
to: DateTime? = null
|
to: DateTime? = null,
|
||||||
|
pagination: Pagination = FirstPagePagination()
|
||||||
) = getPostsByCreatingDates(
|
) = getPostsByCreatingDates(
|
||||||
from ?: MIN_DATE,
|
from ?: MIN_DATE,
|
||||||
to ?: MAX_DATE
|
to ?: MAX_DATE,
|
||||||
|
pagination
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,7 @@ import com.insanusmokrassar.postssystem.core.content.api.ContentRepo
|
|||||||
import com.insanusmokrassar.postssystem.core.exposed.content.*
|
import com.insanusmokrassar.postssystem.core.exposed.content.*
|
||||||
import com.insanusmokrassar.postssystem.core.generateContentId
|
import com.insanusmokrassar.postssystem.core.generateContentId
|
||||||
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import kotlinx.coroutines.channels.BroadcastChannel
|
import kotlinx.coroutines.channels.BroadcastChannel
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
@ -5,7 +5,7 @@ import com.insanusmokrassar.postssystem.core.generatePostId
|
|||||||
import com.insanusmokrassar.postssystem.core.post.*
|
import com.insanusmokrassar.postssystem.core.post.*
|
||||||
import com.insanusmokrassar.postssystem.core.post.repo.PostsRepo
|
import com.insanusmokrassar.postssystem.core.post.repo.PostsRepo
|
||||||
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import com.soywiz.klock.*
|
import com.soywiz.klock.*
|
||||||
import kotlinx.coroutines.channels.BroadcastChannel
|
import kotlinx.coroutines.channels.BroadcastChannel
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
@ -100,7 +100,7 @@ private class PostsRepoDatabaseTable(
|
|||||||
SimpleRegisteredPost(
|
SimpleRegisteredPost(
|
||||||
id,
|
id,
|
||||||
contentsTable.getPostContents(id),
|
contentsTable.getPostContents(id),
|
||||||
dateTimeFormat.parse(get(creationDateColumn)).local
|
dateTimeFormat.parse(get(creationDateColumn)).local.unixMillis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,11 +176,22 @@ private class PostsRepoDatabaseTable(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getPostsByCreatingDates(from: DateTime, to: DateTime): List<RegisteredPost> {
|
override suspend fun getPostsByCreatingDates(
|
||||||
|
from: DateTime,
|
||||||
|
to: DateTime,
|
||||||
|
pagination: Pagination
|
||||||
|
): PaginationResult<RegisteredPost> {
|
||||||
return transaction(
|
return transaction(
|
||||||
db = database
|
db = database
|
||||||
) {
|
) {
|
||||||
select { creationDateColumn.between(from, to) }.map { it.toRegisteredPost() }
|
select { creationDateColumn.between(from, to) }.paginate(
|
||||||
|
pagination
|
||||||
|
).map {
|
||||||
|
it.toRegisteredPost()
|
||||||
|
}.createPaginationResult(
|
||||||
|
pagination,
|
||||||
|
selectAll().count()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,18 @@
|
|||||||
package com.insanusmokrassar.postssystem.core.ktor.client.content
|
package com.insanusmokrassar.postssystem.core.ktor.client.content
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.api.*
|
import com.insanusmokrassar.postssystem.core.content.api.*
|
||||||
import com.insanusmokrassar.postssystem.core.ktor.contentCreatedFlowRoute
|
|
||||||
import com.insanusmokrassar.postssystem.core.ktor.contentDeletedFlowRoute
|
|
||||||
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
|
|
||||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerializer
|
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import kotlinx.coroutines.flow.Flow
|
import io.ktor.client.features.websocket.WebSockets
|
||||||
|
|
||||||
class ContentRepoKtorClient(
|
class ContentRepoKtorClient(
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
client: HttpClient = HttpClient()
|
client: HttpClient = HttpClient {
|
||||||
) : ContentRepo,
|
install(WebSockets)
|
||||||
ReadContentRepo by ReadContentRepoKtorClient(
|
}
|
||||||
|
) : ContentRepo, ReadContentRepo by ReadContentRepoKtorClient(
|
||||||
baseUrl,
|
baseUrl,
|
||||||
client
|
client
|
||||||
),
|
), WriteContentRepo by WriteContentRepoKtorClient(
|
||||||
WriteContentRepo by WriteContentRepoKtorClient(
|
|
||||||
baseUrl,
|
baseUrl,
|
||||||
client
|
client
|
||||||
) {
|
)
|
||||||
|
|
||||||
override val contentCreatedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
|
|
||||||
client,
|
|
||||||
"$baseUrl/$contentCreatedFlowRoute"
|
|
||||||
) {
|
|
||||||
standardKtorSerializer.load(RegisteredContent.serializer(), it)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val contentDeletedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
|
|
||||||
client,
|
|
||||||
"$baseUrl/$contentDeletedFlowRoute"
|
|
||||||
) {
|
|
||||||
standardKtorSerializer.load(RegisteredContent.serializer(), it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,9 +4,9 @@ import com.insanusmokrassar.postssystem.core.content.ContentId
|
|||||||
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
||||||
import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo
|
import com.insanusmokrassar.postssystem.core.content.api.ReadContentRepo
|
||||||
import com.insanusmokrassar.postssystem.core.ktor.*
|
import com.insanusmokrassar.postssystem.core.ktor.*
|
||||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerializer
|
import com.insanusmokrassar.postssystem.ktor.*
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import kotlinx.serialization.builtins.nullable
|
import kotlinx.serialization.builtins.nullable
|
||||||
@ -18,18 +18,20 @@ class ReadContentRepoKtorClient(
|
|||||||
override suspend fun getContentsIds(): Set<ContentId> = client.get<ByteArray>(
|
override suspend fun getContentsIds(): Set<ContentId> = client.get<ByteArray>(
|
||||||
"$baseUrl/$getContentsIdsRoute"
|
"$baseUrl/$getContentsIdsRoute"
|
||||||
).let {
|
).let {
|
||||||
standardKtorSerializer.load(contentIdsSerializer, it)
|
standardKtorSerialFormat.load(contentIdsSerializer, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getContentById(id: ContentId): RegisteredContent? = client.get<ByteArray>(
|
override suspend fun getContentById(id: ContentId): RegisteredContent? = client.get<ByteArray>(
|
||||||
"$baseUrl/$getContentByIdRoute"
|
"$baseUrl/$getContentByIdRoute/$id"
|
||||||
).let {
|
).let {
|
||||||
standardKtorSerializer.load(RegisteredContent.serializer().nullable, it)
|
standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<out RegisteredContent> = client.get<ByteArray>(
|
override suspend fun getContentByPagination(pagination: Pagination): PaginationResult<out RegisteredContent> = client.get<ByteArray>(
|
||||||
"$baseUrl/$getContentByPaginationRoute"
|
"$baseUrl/$getContentByPaginationRoute".includeQueryParams(
|
||||||
|
pagination.asUrlQueryParts
|
||||||
|
)
|
||||||
).let {
|
).let {
|
||||||
standardKtorSerializer.load(registeredContentPaginationResultSerializer, it)
|
standardKtorSerialFormat.load(registeredContentPaginationResultSerializer, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,12 +2,13 @@ package com.insanusmokrassar.postssystem.core.ktor.client.content
|
|||||||
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.*
|
import com.insanusmokrassar.postssystem.core.content.*
|
||||||
import com.insanusmokrassar.postssystem.core.content.api.WriteContentRepo
|
import com.insanusmokrassar.postssystem.core.content.api.WriteContentRepo
|
||||||
import com.insanusmokrassar.postssystem.core.ktor.deleteContentRoute
|
import com.insanusmokrassar.postssystem.core.ktor.*
|
||||||
import com.insanusmokrassar.postssystem.core.ktor.registerContentRoute
|
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
|
||||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerializer
|
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.request.post
|
import io.ktor.client.request.post
|
||||||
import io.ktor.client.request.url
|
import io.ktor.client.request.url
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.serialization.builtins.nullable
|
import kotlinx.serialization.builtins.nullable
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
@ -15,17 +16,31 @@ class WriteContentRepoKtorClient(
|
|||||||
private val baseUrl: String,
|
private val baseUrl: String,
|
||||||
private val client: HttpClient = HttpClient()
|
private val client: HttpClient = HttpClient()
|
||||||
) : WriteContentRepo {
|
) : WriteContentRepo {
|
||||||
|
override val contentCreatedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
|
||||||
|
client,
|
||||||
|
"$baseUrl/$contentCreatedFlowRoute"
|
||||||
|
) {
|
||||||
|
standardKtorSerialFormat.load(RegisteredContent.serializer(), it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val contentDeletedFlow: Flow<RegisteredContent> = createStandardWebsocketFlow(
|
||||||
|
client,
|
||||||
|
"$baseUrl/$contentDeletedFlowRoute"
|
||||||
|
) {
|
||||||
|
standardKtorSerialFormat.load(RegisteredContent.serializer(), it)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun registerContent(content: Content): RegisteredContent? = client.post<ByteArray> {
|
override suspend fun registerContent(content: Content): RegisteredContent? = client.post<ByteArray> {
|
||||||
url("$baseUrl/$registerContentRoute")
|
url("$baseUrl/$registerContentRoute")
|
||||||
body = standardKtorSerializer.dump(Content.serializer(), content)
|
body = standardKtorSerialFormat.dump(Content.serializer(), content)
|
||||||
}.let {
|
}.let {
|
||||||
standardKtorSerializer.load(RegisteredContent.serializer().nullable, it)
|
standardKtorSerialFormat.load(RegisteredContent.serializer().nullable, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteContent(id: ContentId): Boolean = client.post<ByteArray> {
|
override suspend fun deleteContent(id: ContentId): Boolean = client.post<ByteArray> {
|
||||||
url("$baseUrl/$deleteContentRoute")
|
url("$baseUrl/$deleteContentRoute")
|
||||||
body = standardKtorSerializer.dump(ContentId.serializer(), id)
|
body = standardKtorSerialFormat.dump(ContentId.serializer(), id)
|
||||||
}.let {
|
}.let {
|
||||||
standardKtorSerializer.load(Boolean.serializer(), it)
|
standardKtorSerialFormat.load(Boolean.serializer(), it)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.core.ktor.client.post
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.core.post.repo.*
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.features.websocket.WebSockets
|
||||||
|
|
||||||
|
class PostsRepoKtorClient(
|
||||||
|
baseUrl: String,
|
||||||
|
client: HttpClient = HttpClient {
|
||||||
|
install(WebSockets)
|
||||||
|
}
|
||||||
|
) : PostsRepo, ReadPostsRepo by ReadPostsRepoKtorClient(
|
||||||
|
baseUrl,
|
||||||
|
client
|
||||||
|
), WritePostsRepo by WritePostsRepoKtorClient(
|
||||||
|
baseUrl,
|
||||||
|
client
|
||||||
|
)
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.core.ktor.client.post
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.core.content.ContentId
|
||||||
|
import com.insanusmokrassar.postssystem.core.ktor.*
|
||||||
|
import com.insanusmokrassar.postssystem.core.post.PostId
|
||||||
|
import com.insanusmokrassar.postssystem.core.post.RegisteredPost
|
||||||
|
import com.insanusmokrassar.postssystem.core.post.repo.ReadPostsRepo
|
||||||
|
import com.insanusmokrassar.postssystem.ktor.*
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
|
import com.soywiz.klock.DateTime
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import kotlinx.serialization.builtins.nullable
|
||||||
|
|
||||||
|
class ReadPostsRepoKtorClient(
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val client: HttpClient = HttpClient()
|
||||||
|
) : ReadPostsRepo {
|
||||||
|
override suspend fun getPostsIds(): Set<PostId> = client.get<ByteArray>(
|
||||||
|
"$baseUrl/$getPostsIdsRoute"
|
||||||
|
).let {
|
||||||
|
standardKtorSerialFormat.load(postIdsSerializer, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPostById(id: PostId): RegisteredPost? = client.get<ByteArray>(
|
||||||
|
"$baseUrl/$getPostByIdRoute/$id"
|
||||||
|
).let {
|
||||||
|
standardKtorSerialFormat.load(RegisteredPost.serializer().nullable, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPostsByContent(id: ContentId): List<RegisteredPost> = client.get<ByteArray>(
|
||||||
|
"$baseUrl/$getPostsByContentRoute/$id"
|
||||||
|
).let {
|
||||||
|
standardKtorSerialFormat.load(registeredPostsListSerializer, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPostsByCreatingDates(
|
||||||
|
from: DateTime,
|
||||||
|
to: DateTime,
|
||||||
|
pagination: Pagination
|
||||||
|
): PaginationResult<RegisteredPost> = client.get<ByteArray>(
|
||||||
|
"$baseUrl/$getPostsByCreatingDatesRoute".includeQueryParams(
|
||||||
|
(from to to).asFromToUrlPart + pagination.asUrlQueryParts
|
||||||
|
)
|
||||||
|
).let {
|
||||||
|
standardKtorSerialFormat.load(registeredPostsPaginationResultSerializer, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPostsByPagination(pagination: Pagination): PaginationResult<RegisteredPost> = client.get<ByteArray>(
|
||||||
|
"$baseUrl/$getPostsByPaginationRoute".includeQueryParams(
|
||||||
|
pagination.asUrlQueryParts
|
||||||
|
)
|
||||||
|
).let {
|
||||||
|
standardKtorSerialFormat.load(registeredPostsPaginationResultSerializer, it)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.core.ktor.client.post
|
||||||
|
|
||||||
|
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.createStandardWebsocketFlow
|
||||||
|
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.features.websocket.WebSockets
|
||||||
|
import io.ktor.client.request.post
|
||||||
|
import io.ktor.client.request.url
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.serialization.builtins.nullable
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
class WritePostsRepoKtorClient (
|
||||||
|
private val baseUrl: String,
|
||||||
|
private val client: HttpClient = HttpClient {
|
||||||
|
install(WebSockets)
|
||||||
|
}
|
||||||
|
) : WritePostsRepo {
|
||||||
|
override val postCreatedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
|
||||||
|
"$baseUrl/$postCreatedFlowRoute"
|
||||||
|
) {
|
||||||
|
standardKtorSerialFormat.load(RegisteredPost.serializer(), it)
|
||||||
|
}
|
||||||
|
override val postDeletedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
|
||||||
|
"$baseUrl/$postDeletedFlowRoute"
|
||||||
|
) {
|
||||||
|
standardKtorSerialFormat.load(RegisteredPost.serializer(), it)
|
||||||
|
}
|
||||||
|
override val postUpdatedFlow: Flow<RegisteredPost> = client.createStandardWebsocketFlow(
|
||||||
|
"$baseUrl/$postUpdatedFlowRoute"
|
||||||
|
) {
|
||||||
|
standardKtorSerialFormat.load(RegisteredPost.serializer(), it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun createPost(post: Post): RegisteredPost? = client.post<ByteArray> {
|
||||||
|
url("$baseUrl/$createPostRoute")
|
||||||
|
body = standardKtorSerialFormat.dump(Post.serializer(), post)
|
||||||
|
}.let {
|
||||||
|
standardKtorSerialFormat.load(RegisteredPost.serializer().nullable, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deletePost(id: PostId): Boolean = client.post<ByteArray> {
|
||||||
|
url("$baseUrl/$createPostRoute")
|
||||||
|
body = standardKtorSerialFormat.dump(PostId.serializer(), id)
|
||||||
|
}.let {
|
||||||
|
standardKtorSerialFormat.load(Boolean.serializer(), it)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun updatePostContent(postId: PostId, post: Post): Boolean = client.post<ByteArray> {
|
||||||
|
url("$baseUrl/$createPostRoute")
|
||||||
|
body = standardKtorSerialFormat.dump(UpdatePostObject.serializer(), UpdatePostObject(postId, post))
|
||||||
|
}.let {
|
||||||
|
standardKtorSerialFormat.load(Boolean.serializer(), it)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.core.ktor
|
||||||
|
|
||||||
|
const val getPostsIdsRoute = "getPostsIds"
|
||||||
|
const val getPostByIdRoute = "getPostById"
|
||||||
|
const val getPostsByContentRoute = "getPostsByContent"
|
||||||
|
const val getPostsByCreatingDatesRoute = "getPostsByCreatingDates"
|
||||||
|
const val getPostsByPaginationRoute = "getPostsByPagination"
|
||||||
|
|
||||||
|
const val postCreatedFlowRoute = "postCreatedFlow"
|
||||||
|
const val postDeletedFlowRoute = "postDeletedFlow"
|
||||||
|
const val postUpdatedFlowRoute = "postUpdatedFlow"
|
||||||
|
const val createPostRoute = "createPost"
|
||||||
|
const val deletePostRoute = "deletePost"
|
||||||
|
const val updatePostContentRoute = "updatePostContent"
|
@ -1,8 +1,13 @@
|
|||||||
package com.insanusmokrassar.postssystem.core.ktor
|
package com.insanusmokrassar.postssystem.core.ktor
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
import com.insanusmokrassar.postssystem.core.content.RegisteredContent
|
||||||
|
import com.insanusmokrassar.postssystem.core.post.RegisteredPost
|
||||||
import com.insanusmokrassar.postssystem.ktor.setIdsSerializer
|
import com.insanusmokrassar.postssystem.ktor.setIdsSerializer
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
|
|
||||||
val contentIdsSerializer = setIdsSerializer
|
val contentIdsSerializer = setIdsSerializer
|
||||||
|
val postIdsSerializer = setIdsSerializer
|
||||||
|
val registeredPostsListSerializer = ListSerializer(RegisteredPost.serializer())
|
||||||
|
val registeredPostsPaginationResultSerializer = PaginationResult.serializer(RegisteredPost.serializer())
|
||||||
val registeredContentPaginationResultSerializer = PaginationResult.serializer(RegisteredContent.serializer())
|
val registeredContentPaginationResultSerializer = PaginationResult.serializer(RegisteredContent.serializer())
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.core.ktor
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.core.post.Post
|
||||||
|
import com.insanusmokrassar.postssystem.core.post.PostId
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class UpdatePostObject(
|
||||||
|
val postId: PostId,
|
||||||
|
val post: Post
|
||||||
|
)
|
@ -1,6 +1,6 @@
|
|||||||
package com.insanusmokrassar.postssystem.exposed.commons
|
package com.insanusmokrassar.postssystem.exposed.commons
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
|
|
||||||
fun Query.paginate(with: Pagination, orderBy: Pair<Expression<*>, SortOrder>? = null) = limit(
|
fun Query.paginate(with: Pagination, orderBy: Pair<Expression<*>, SortOrder>? = null) = limit(
|
||||||
|
@ -62,3 +62,8 @@ inline fun <reified T> createStandardWebsocketFlow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> HttpClient.createStandardWebsocketFlow(
|
||||||
|
url: String,
|
||||||
|
crossinline conversation: suspend (ByteArray) -> T
|
||||||
|
) = createStandardWebsocketFlow(this, url, conversation)
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.ktor
|
||||||
|
|
||||||
|
import com.soywiz.klock.DateTime
|
||||||
|
|
||||||
|
typealias FromToDateTime = Pair<DateTime?, DateTime?>
|
||||||
|
|
||||||
|
val FromToDateTime.asFromToUrlPart: QueryParams
|
||||||
|
get() = mapOf(
|
||||||
|
"from" to first ?.unixMillis ?.toString(),
|
||||||
|
"to" to second ?.unixMillis ?.toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
val QueryParams.extractFromToDateTime: FromToDateTime
|
||||||
|
get() = FromToDateTime(
|
||||||
|
get("from") ?.toDoubleOrNull() ?.let { DateTime(it) },
|
||||||
|
get("to") ?.toDoubleOrNull() ?.let { DateTime(it) }
|
||||||
|
)
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.ktor
|
||||||
|
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
|
|
||||||
|
private val numberRegex = Regex("[\\d]{1,10}")
|
||||||
|
private val pageRegex = Regex("page=${numberRegex.pattern}")
|
||||||
|
private val sizeRegex = Regex("size=${numberRegex.pattern}")
|
||||||
|
|
||||||
|
val Pagination.asUrlQueryParts
|
||||||
|
get() = mapOf(
|
||||||
|
"page" to page.toString(),
|
||||||
|
"size" to size.toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
val Map<String, String?>.extractPagination: Pagination
|
||||||
|
get() = SimplePagination(
|
||||||
|
get("page") ?.toIntOrNull() ?: 0,
|
||||||
|
get("size") ?.toIntOrNull() ?: defaultMediumPageSize
|
||||||
|
)
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.ktor
|
||||||
|
|
||||||
|
typealias QueryParams = Map<String, String?>
|
||||||
|
|
||||||
|
val QueryParams.asUrlQuery: String
|
||||||
|
get() = keys.joinToString("&") { "${it}${get(it) ?.let { value -> "=$value" }}" }
|
||||||
|
fun String.includeQueryParams(
|
||||||
|
queryParams: QueryParams
|
||||||
|
): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}"
|
||||||
|
|
||||||
|
val String.parseUrlQuery: QueryParams
|
||||||
|
get() = split("&").map {
|
||||||
|
it.split("=").let { pair ->
|
||||||
|
pair.first() to pair.getOrNull(1)
|
||||||
|
}
|
||||||
|
}.toMap()
|
@ -2,4 +2,4 @@ package com.insanusmokrassar.postssystem.ktor
|
|||||||
|
|
||||||
import kotlinx.serialization.cbor.Cbor
|
import kotlinx.serialization.cbor.Cbor
|
||||||
|
|
||||||
val standardKtorSerializer = Cbor
|
val standardKtorSerialFormat = Cbor
|
||||||
|
@ -3,13 +3,9 @@ package com.insanusmokrassar.postssystem.ktor.tests
|
|||||||
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
|
import com.insanusmokrassar.postssystem.ktor.client.createStandardWebsocketFlow
|
||||||
import com.insanusmokrassar.postssystem.ktor.server.createKtorServer
|
import com.insanusmokrassar.postssystem.ktor.server.createKtorServer
|
||||||
import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling
|
import com.insanusmokrassar.postssystem.ktor.server.includeWebsocketHandling
|
||||||
import com.insanusmokrassar.postssystem.ktor.standardKtorSerializer
|
import com.insanusmokrassar.postssystem.ktor.standardKtorSerialFormat
|
||||||
import io.ktor.application.install
|
import io.ktor.application.install
|
||||||
import io.ktor.application.log
|
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.http.cio.websocket.pingPeriod
|
|
||||||
import io.ktor.http.cio.websocket.timeout
|
|
||||||
import io.ktor.routing.route
|
|
||||||
import io.ktor.routing.routing
|
import io.ktor.routing.routing
|
||||||
import io.ktor.websocket.WebSockets
|
import io.ktor.websocket.WebSockets
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@ -17,7 +13,6 @@ import kotlinx.coroutines.channels.Channel
|
|||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.time.Duration
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
@ -33,7 +28,7 @@ class WebsocketsTest {
|
|||||||
install(WebSockets)
|
install(WebSockets)
|
||||||
routing {
|
routing {
|
||||||
includeWebsocketHandling(suburl, dataFlow) {
|
includeWebsocketHandling(suburl, dataFlow) {
|
||||||
standardKtorSerializer.dump(Int.serializer(), it)
|
standardKtorSerialFormat.dump(Int.serializer(), it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
@ -50,7 +45,7 @@ class WebsocketsTest {
|
|||||||
"$serverUrl/$suburl",
|
"$serverUrl/$suburl",
|
||||||
{ false } // always skip reconnection
|
{ false } // always skip reconnection
|
||||||
) {
|
) {
|
||||||
standardKtorSerializer.load(Int.serializer(), it)
|
standardKtorSerialFormat.load(Int.serializer(), it)
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentlyCheckingData: Int? = null
|
var currentlyCheckingData: Int? = null
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.insanusmokrassar.postssystem.markups.core
|
package com.insanusmokrassar.postssystem.markups.core
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.markups.core.utils.*
|
import com.insanusmokrassar.postssystem.markups.core.utils.*
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
|
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
abstract class MarkupsSystem(
|
abstract class MarkupsSystem(
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
package com.insanusmokrassar.postssystem.utils.common
|
||||||
|
|
||||||
|
typealias UnixMillis = Double
|
@ -1,4 +1,4 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos.pagination
|
package com.insanusmokrassar.postssystem.utils.common.pagination
|
||||||
|
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos.pagination
|
package com.insanusmokrassar.postssystem.utils.common.pagination
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos.pagination
|
package com.insanusmokrassar.postssystem.utils.common.pagination
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos
|
package com.insanusmokrassar.postssystem.utils.repos
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
|
|
||||||
interface OneToManyReadKeyValueRepo<Key, Value> : Repo {
|
interface OneToManyReadKeyValueRepo<Key, Value> : Repo {
|
||||||
suspend fun get(k: Key, pagination: Pagination, reversed: Boolean = false): PaginationResult<Value>
|
suspend fun get(k: Key, pagination: Pagination, reversed: Boolean = false): PaginationResult<Value>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos
|
package com.insanusmokrassar.postssystem.utils.repos
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface ReadStandardCRUDRepo<ObjectType, IdType> : Repo {
|
interface ReadStandardCRUDRepo<ObjectType, IdType> : Repo {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos
|
package com.insanusmokrassar.postssystem.utils.repos
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.Pagination
|
import com.insanusmokrassar.postssystem.utils.common.pagination.Pagination
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.PaginationResult
|
import com.insanusmokrassar.postssystem.utils.common.pagination.PaginationResult
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface StandardReadKeyValueRepo<Key, Value> : Repo {
|
interface StandardReadKeyValueRepo<Key, Value> : Repo {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos.exposed
|
package com.insanusmokrassar.postssystem.utils.repos.exposed
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
|
import com.insanusmokrassar.postssystem.utils.repos.ReadStandardCRUDRepo
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
|
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.insanusmokrassar.postssystem.utils.repos.exposed.keyvalue
|
package com.insanusmokrassar.postssystem.utils.repos.exposed.keyvalue
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo
|
import com.insanusmokrassar.postssystem.utils.repos.StandardReadKeyValueRepo
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
|
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.insanusmokrassar.budgetmanager.core.utils.repo.onetomany
|
package com.insanusmokrassar.budgetmanager.core.utils.repo.onetomany
|
||||||
|
|
||||||
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
import com.insanusmokrassar.postssystem.exposed.commons.paginate
|
||||||
|
import com.insanusmokrassar.postssystem.utils.common.pagination.*
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.OneToManyReadKeyValueRepo
|
import com.insanusmokrassar.postssystem.utils.repos.OneToManyReadKeyValueRepo
|
||||||
import com.insanusmokrassar.postssystem.utils.repos.pagination.*
|
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user