mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2026-03-11 12:52:23 +00:00
generate docs for a lot of API (test try)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) },
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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?
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user