add paging request #2

Open
chinyeewen wants to merge 5 commits from feat/paging-request into main
5 changed files with 89 additions and 5 deletions

View File

@@ -3,7 +3,7 @@ plugins {
}
group = "ai.neuon.utility"
version = "0.1.0"
version = "0.3.1"
repositories {
mavenCentral()

View File

@@ -13,7 +13,8 @@ repositories {
dependencies {
implementation(libs.kotlinx.serialization.json)
testImplementation(kotlin("test"))
implementation(libs.bundles.ktor.server)
implementation(libs.bundles.slf4j)
}
tasks.test {

View File

@@ -26,7 +26,7 @@ import kotlin.math.roundToLong
* ## buildPagingJsonObject
* - Serializes the pagination metadata into JSON format:
* - "config" → Contains the current page index and page size.
* - "page" → Can include the total number of pages if totalItemsCount is set.
* - "page" → Includes "totalItems" and "totalPages" when totalItemsCount is set.
*/
data class PagingData<T>(
val i: Int, val pageSize: Int, val totalItemsCount: Long? = null,
@@ -52,13 +52,14 @@ data class PagingData<T>(
put("size", JsonPrimitive(pageSize))
}
putJsonObject("page") {
totalItemsCount?.also { itemCount ->
max(
totalItemsCount?.let { itemCount ->
val totalPages = max(
1, ceil(
itemCount.toFloat()
.div(pageSize)
).roundToLong()
)
put("count", JsonPrimitive(totalPages))
}
}
}

View File

@@ -0,0 +1,50 @@
package ai.neuon.utility.paging
import io.ktor.server.request.ApplicationRequest
import kotlin.math.max
sealed class PagingRequest {
companion object {
fun from(request: ApplicationRequest): PagingRequest {
val params = request.queryParameters
val pagingType = params["paging"]?.let {
Type.from(it)
} ?: Type.OFFSET
return when (pagingType) {
Type.NONE -> None
Type.OFFSET -> {
val i = params["page"]?.toInt()
?.let { max(0, it) } ?: 0
val limit = params["pageSize"]?.toInt()
?.let { max(1, it) } ?: 10
Offset(index = i, limit = limit)
}
}
}
}
data object None : PagingRequest()
data class Offset(val index: Int, val limit: Int) : PagingRequest() {
val skip: Int
get() = index * limit
}
enum class Type(val key: String) {
NONE(key = "none"), OFFSET(key = "offset");
companion object {
/**
* @throws IllegalArgumentException
*/
fun from(type: String): Type {
return when (type) {
"none" -> NONE
"offset" -> OFFSET
else -> throw IllegalArgumentException("Unsupported pagination type, $type")
}
}
}
}
}

View File

@@ -2,12 +2,44 @@
dokka = "2.0.0"
kotlin = "2.2.0"
kotlinx-serialization-json = "1.9.0"
ktor = "3.4.1"
logback = "1.5.32"
slf4j = "2.0.17"
[libraries]
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }
ktor-server-caching-headers = { module = "io.ktor:ktor-server-caching-headers", version.ref = "ktor" }
ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }
ktor-server-config-yaml = { module = "io.ktor:ktor-server-config-yaml", version.ref = "ktor" }
ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" }
ktor-server-core = { module = "io.ktor:ktor-server-core-jvm", version.ref = "ktor" }
ktor-server-di = { module = "io.ktor:ktor-server-di", version.ref = "ktor" }
ktor-server-status-pages = { module = "io.ktor:ktor-server-status-pages", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
[bundles]
ktor-server = [
"ktor-server-cio",
"ktor-server-caching-headers",
"ktor-server-core",
"ktor-server-config-yaml",
"ktor-server-content-negotiation",
"ktor-server-di",
"ktor-server-status-pages",
"ktor-serialization-kotlinx-json",
"logback",
]
slf4j = ["slf4j-api", "logback"]
[plugins]
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }