generate docs for a lot of API (test try)

This commit is contained in:
2026-02-24 18:18:10 +06:00
parent 3df90b1993
commit 4f270d9047
81 changed files with 2519 additions and 6 deletions

View File

@@ -4,10 +4,25 @@ import io.ktor.client.call.body
import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpStatusCode
/**
* Returns the response body as type [T] if the [statusFilter] condition is met, otherwise returns null.
* By default, the filter checks if the status code is [HttpStatusCode.OK].
*
* @param T The type to deserialize the response body to
* @param statusFilter A predicate to determine if the body should be retrieved. Defaults to checking for OK status
* @return The deserialized body of type [T], or null if the filter condition is not met
*/
suspend inline fun <reified T : Any> HttpResponse.bodyOrNull(
statusFilter: (HttpResponse) -> Boolean = { it.status == HttpStatusCode.OK }
) = takeIf(statusFilter) ?.body<T>()
/**
* Returns the response body as type [T] if the status code is not [HttpStatusCode.NoContent], otherwise returns null.
* This is useful for handling responses that may return 204 No Content.
*
* @param T The type to deserialize the response body to
* @return The deserialized body of type [T], or null if the status is No Content
*/
suspend inline fun <reified T : Any> HttpResponse.bodyOrNullOnNoContent() = bodyOrNull<T> {
it.status != HttpStatusCode.NoContent
}

View File

@@ -4,6 +4,13 @@ import io.ktor.client.plugins.ClientRequestException
import io.ktor.client.statement.HttpResponse
import io.ktor.http.isSuccess
/**
* Throws a [ClientRequestException] if this [HttpResponse] does not have a successful status code.
* A status code is considered successful if it's in the 2xx range.
*
* @param unsuccessMessage A lambda that provides the error message to use if the response is unsuccessful
* @throws ClientRequestException if the response status is not successful
*/
inline fun HttpResponse.throwOnUnsuccess(
unsuccessMessage: () -> String
) {

View File

@@ -5,6 +5,12 @@ import dev.inmo.micro_utils.common.filesize
import dev.inmo.micro_utils.ktor.common.input
import io.ktor.client.request.forms.InputProvider
/**
* Creates a Ktor [InputProvider] from this multiplatform file for use in HTTP client requests.
* The input provider knows the file size and can create input streams on demand.
*
* @return An [InputProvider] for reading this file in HTTP requests
*/
fun MPPFile.inputProvider(): InputProvider = InputProvider(filesize) {
input()
}

View File

@@ -1,3 +1,9 @@
package dev.inmo.micro_utils.ktor.client
/**
* A callback function type for tracking upload progress.
*
* @param uploaded The number of bytes uploaded so far
* @param count The total number of bytes to be uploaded
*/
typealias OnUploadCallback = suspend (uploaded: Long, count: Long) -> Unit

View File

@@ -5,6 +5,15 @@ import dev.inmo.micro_utils.ktor.common.*
import io.ktor.client.HttpClient
import io.ktor.client.content.*
/**
* Uploads a file to a temporary storage on the server.
* The server should provide an endpoint that accepts multipart uploads and returns a [TemporalFileId].
*
* @param fullTempUploadDraftPath The full URL path to the temporary upload endpoint
* @param file The file to upload
* @param onUpload Progress callback invoked during upload
* @return A [TemporalFileId] that can be used to reference the uploaded file
*/
expect suspend fun HttpClient.tempUpload(
fullTempUploadDraftPath: String,
file: MPPFile,

View File

@@ -10,6 +10,14 @@ import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.StringFormat
import kotlinx.serialization.json.Json
/**
* Information about a file to upload in a multipart request.
* This allows uploading from custom sources beyond regular files.
*
* @param fileName The name of the file
* @param mimeType The MIME type of the file
* @param inputAllocator A lambda that provides input streams for reading the file data
*/
data class UniUploadFileInfo(
val fileName: FileName,
val mimeType: String,

View File

@@ -1,5 +1,14 @@
package dev.inmo.micro_utils.ktor.common
/**
* Builds a standard URL by combining a base part, subpart, and optional query parameters.
* The base and subpart are joined with a '/', and query parameters are appended.
*
* @param basePart The base part of the URL (e.g., "https://example.com/api")
* @param subpart The subpart of the URL (e.g., "users")
* @param parameters Query parameters as a map. Defaults to an empty map
* @return The complete URL string with query parameters
*/
fun buildStandardUrl(
basePart: String,
subpart: String,
@@ -8,6 +17,15 @@ fun buildStandardUrl(
parameters
)
/**
* Builds a standard URL by combining a base part, subpart, and query parameters as a list.
* The base and subpart are joined with a '/', and query parameters are appended.
*
* @param basePart The base part of the URL (e.g., "https://example.com/api")
* @param subpart The subpart of the URL (e.g., "users")
* @param parameters Query parameters as a list of key-value pairs
* @return The complete URL string with query parameters
*/
fun buildStandardUrl(
basePart: String,
subpart: String,
@@ -16,6 +34,15 @@ fun buildStandardUrl(
parameters
)
/**
* Builds a standard URL by combining a base part, subpart, and vararg query parameters.
* The base and subpart are joined with a '/', and query parameters are appended.
*
* @param basePart The base part of the URL (e.g., "https://example.com/api")
* @param subpart The subpart of the URL (e.g., "users")
* @param parameters Query parameters as vararg key-value pairs
* @return The complete URL string with query parameters
*/
fun buildStandardUrl(
basePart: String,
subpart: String,

View File

@@ -1,3 +1,8 @@
package dev.inmo.micro_utils.ktor.common
/**
* An exception used to indicate a correct/normal closure of a connection or stream.
* This is typically used in WebSocket or network communication scenarios where a
* clean shutdown needs to be distinguished from error conditions.
*/
object CorrectCloseException : Exception()

View File

@@ -2,6 +2,14 @@ package dev.inmo.micro_utils.ktor.common
private val schemaRegex = Regex("^[^:]*://")
/**
* Converts this string to a correct WebSocket URL by ensuring it starts with "ws://" scheme.
* If the URL already starts with "ws", it is returned unchanged.
* If the URL contains a scheme (e.g., "http://"), it is replaced with "ws://".
* If the URL has no scheme, "ws://" is prepended.
*
* @return A properly formatted WebSocket URL
*/
val String.asCorrectWebSocketUrl: String
get() = if (startsWith("ws")) {
this

View File

@@ -2,14 +2,30 @@ package dev.inmo.micro_utils.ktor.common
import korlibs.time.DateTime
/**
* Type alias representing a date-time range with optional start and end times.
* First element is the "from" date-time, second is the "to" date-time.
*/
typealias FromToDateTime = Pair<DateTime?, DateTime?>
/**
* Converts this [FromToDateTime] range to URL query parameters.
* Creates "from" and "to" query parameters with Unix millisecond timestamps.
*
* @return A map of query parameters representing the date-time range
*/
val FromToDateTime.asFromToUrlPart: QueryParams
get() = mapOf(
"from" to first ?.unixMillis ?.toString(),
"to" to second ?.unixMillis ?.toString()
)
/**
* Extracts a [FromToDateTime] range from URL query parameters.
* Looks for "from" and "to" parameters containing Unix millisecond timestamps.
*
* @return A [FromToDateTime] pair extracted from the query parameters
*/
val QueryParams.extractFromToDateTime: FromToDateTime
get() = FromToDateTime(
get("from") ?.toDoubleOrNull() ?.let { DateTime(it) },

View File

@@ -2,4 +2,8 @@ package dev.inmo.micro_utils.ktor.common
import io.ktor.utils.io.core.Input
/**
* A function type that provides an [Input] instance.
* This is useful for lazy or deferred input creation in Ktor operations.
*/
typealias LambdaInputProvider = () -> Input

View File

@@ -3,4 +3,10 @@ package dev.inmo.micro_utils.ktor.common
import dev.inmo.micro_utils.common.MPPFile
import io.ktor.utils.io.core.Input
/**
* Creates a Ktor [Input] from this multiplatform file.
* Platform-specific implementations handle file reading for each supported platform.
*
* @return An [Input] stream for reading this file
*/
expect fun MPPFile.input(): Input

View File

@@ -29,6 +29,13 @@ fun String.includeQueryParams(
queryParams: List<QueryParam>
): String = "$this${if (contains("?")) "&" else "?"}${queryParams.asUrlQuery}"
/**
* Parses this URL query string into a [QueryParams] map.
* Splits on '&' to separate parameters and '=' to separate keys from values.
* Parameters without values will have null as their value.
*
* @return A map of query parameter keys to their values (or null if no value)
*/
val String.parseUrlQuery: QueryParams
get() = split("&").map {
it.split("=").let { pair ->

View File

@@ -5,27 +5,73 @@ package dev.inmo.micro_utils.ktor.common
import kotlinx.serialization.*
import kotlinx.serialization.cbor.Cbor
/**
* Type alias for the standard serialization format used in Ktor utilities, which is [BinaryFormat].
*/
typealias StandardKtorSerialFormat = BinaryFormat
/**
* Type alias for the standard serialization input data type, which is [ByteArray].
*/
typealias StandardKtorSerialInputData = ByteArray
/**
* The standard Ktor serialization format instance, configured as CBOR.
*/
val standardKtorSerialFormat: StandardKtorSerialFormat = Cbor { }
/**
* Decodes data from [StandardKtorSerialInputData] using the standard format.
*
* @param T The type to decode to
* @param deserializationStrategy The deserialization strategy for type [T]
* @param input The byte array input data to decode
* @return The decoded value of type [T]
*/
inline fun <T> StandardKtorSerialFormat.decodeDefault(
deserializationStrategy: DeserializationStrategy<T>,
input: StandardKtorSerialInputData
): T = decodeFromByteArray(deserializationStrategy, input)
/**
* Encodes data to [StandardKtorSerialInputData] using the standard format.
*
* @param T The type to encode
* @param serializationStrategy The serialization strategy for type [T]
* @param data The data to encode
* @return The encoded byte array
*/
inline fun <T> StandardKtorSerialFormat.encodeDefault(
serializationStrategy: SerializationStrategy<T>,
data: T
): StandardKtorSerialInputData = encodeToByteArray(serializationStrategy, data)
/**
* A CBOR instance for serialization operations.
*/
val cbor = Cbor {}
/**
* Decodes data from a hex string using the standard binary format.
*
* @param T The type to decode to
* @param deserializationStrategy The deserialization strategy for type [T]
* @param input The hex string to decode
* @return The decoded value of type [T]
*/
inline fun <T> StandardKtorSerialFormat.decodeHex(
deserializationStrategy: DeserializationStrategy<T>,
input: String
): T = decodeFromHexString(deserializationStrategy, input)
/**
* Encodes data to a hex string using the standard binary format.
*
* @param T The type to encode
* @param serializationStrategy The serialization strategy for type [T]
* @param data The data to encode
* @return The encoded hex string
*/
inline fun <T> StandardKtorSerialFormat.encodeHex(
serializationStrategy: SerializationStrategy<T>,
data: T

View File

@@ -3,8 +3,17 @@ package dev.inmo.micro_utils.ktor.common
import kotlin.jvm.JvmInline
import kotlinx.serialization.Serializable
/**
* The default subdirectory path for storing temporal files during upload operations.
*/
const val DefaultTemporalFilesSubPath = "temp_upload"
/**
* A value class representing a unique identifier for a temporal file.
* Temporal files are typically used for temporary storage during file upload/processing operations.
*
* @param string The string representation of the temporal file ID
*/
@Serializable
@JvmInline
value class TemporalFileId(val string: String)

View File

@@ -4,6 +4,12 @@ import korlibs.time.DateTime
import dev.inmo.micro_utils.ktor.common.FromToDateTime
import io.ktor.http.Parameters
/**
* Extracts a [FromToDateTime] range from Ktor server [Parameters].
* Looks for "from" and "to" parameters containing Unix millisecond timestamps.
*
* @return A [FromToDateTime] pair extracted from the parameters
*/
val Parameters.extractFromToDateTime: FromToDateTime
get() = FromToDateTime(
get("from") ?.toDoubleOrNull() ?.let { DateTime(it) },

View File

@@ -4,6 +4,13 @@ import io.ktor.http.HttpStatusCode
import io.ktor.server.application.ApplicationCall
import io.ktor.server.response.respond
/**
* Retrieves a parameter value by [field] name from the request parameters.
* If the parameter is not present, responds with [HttpStatusCode.BadRequest] (400) and an error message.
*
* @param field The name of the parameter to retrieve
* @return The parameter value, or null if not found (after sending error response)
*/
suspend fun ApplicationCall.getParameterOrSendError(
field: String
) = parameters[field].also {
@@ -12,6 +19,13 @@ suspend fun ApplicationCall.getParameterOrSendError(
}
}
/**
* Retrieves all parameter values by [field] name from the request parameters.
* If the parameter is not present, responds with [HttpStatusCode.BadRequest] (400) and an error message.
*
* @param field The name of the parameter to retrieve
* @return A list of parameter values, or null if not found (after sending error response)
*/
suspend fun ApplicationCall.getParametersOrSendError(
field: String
) = parameters.getAll(field).also {
@@ -20,14 +34,33 @@ suspend fun ApplicationCall.getParametersOrSendError(
}
}
/**
* Retrieves a query parameter value by [field] name from the request.
*
* @param field The name of the query parameter to retrieve
* @return The query parameter value, or null if not found
*/
fun ApplicationCall.getQueryParameter(
field: String
) = request.queryParameters[field]
/**
* Retrieves all query parameter values by [field] name from the request.
*
* @param field The name of the query parameter to retrieve
* @return A list of query parameter values, or null if not found
*/
fun ApplicationCall.getQueryParameters(
field: String
) = request.queryParameters.getAll(field)
/**
* Retrieves a query parameter value by [field] name from the request.
* If the parameter is not present, responds with [HttpStatusCode.BadRequest] (400) and an error message.
*
* @param field The name of the query parameter to retrieve
* @return The query parameter value, or null if not found (after sending error response)
*/
suspend fun ApplicationCall.getQueryParameterOrSendError(
field: String
) = getQueryParameter(field).also {
@@ -36,6 +69,13 @@ suspend fun ApplicationCall.getQueryParameterOrSendError(
}
}
/**
* Retrieves all query parameter values by [field] name from the request.
* If the parameter is not present, responds with [HttpStatusCode.BadRequest] (400) and an error message.
*
* @param field The name of the query parameter to retrieve
* @return A list of query parameter values, or null if not found (after sending error response)
*/
suspend fun ApplicationCall.getQueryParametersOrSendError(
field: String
) = getQueryParameters(field).also {

View File

@@ -4,6 +4,13 @@ import io.ktor.http.HttpStatusCode
import io.ktor.server.application.ApplicationCall
import io.ktor.server.response.respond
/**
* Responds with the given [data] if it's not null, or responds with [HttpStatusCode.NoContent] (204) if it's null.
* This is useful for API endpoints that may return empty results.
*
* @param T The type of data to respond with
* @param data The data to respond with, or null to respond with No Content
*/
suspend inline fun <reified T : Any> ApplicationCall.respondOrNoContent(
data: T?
) {