mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-11-04 06:00:22 +00:00 
			
		
		
		
	deprecations removing
This commit is contained in:
		@@ -2,6 +2,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## 0.13.0
 | 
					## 0.13.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**ALL DEPRECATIONS HAVE BEEN REMOVED**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* `Repos`:
 | 
					* `Repos`:
 | 
				
			||||||
  * `Exposed`:
 | 
					  * `Exposed`:
 | 
				
			||||||
    * `AbstractExposedWriteCRUDRepo` got two new methods: `update` with `it` as `UpdateBuilder<Int>` and `createAndInsertId`
 | 
					    * `AbstractExposedWriteCRUDRepo` got two new methods: `update` with `it` as `UpdateBuilder<Int>` and `createAndInsertId`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,82 +0,0 @@
 | 
				
			|||||||
package dev.inmo.micro_utils.ktor.client
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.coroutines.safely
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.ktor.common.*
 | 
					 | 
				
			||||||
import io.ktor.client.HttpClient
 | 
					 | 
				
			||||||
import io.ktor.client.plugins.pluginOrNull
 | 
					 | 
				
			||||||
import io.ktor.client.plugins.websocket.WebSockets
 | 
					 | 
				
			||||||
import io.ktor.client.plugins.websocket.ws
 | 
					 | 
				
			||||||
import io.ktor.client.request.HttpRequestBuilder
 | 
					 | 
				
			||||||
import io.ktor.websocket.Frame
 | 
					 | 
				
			||||||
import io.ktor.websocket.readBytes
 | 
					 | 
				
			||||||
import kotlinx.coroutines.flow.Flow
 | 
					 | 
				
			||||||
import kotlinx.coroutines.flow.channelFlow
 | 
					 | 
				
			||||||
import kotlinx.coroutines.isActive
 | 
					 | 
				
			||||||
import kotlinx.serialization.DeserializationStrategy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @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
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
inline fun <T> HttpClient.createStandardWebsocketFlow(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    crossinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
 | 
					 | 
				
			||||||
    noinline requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    crossinline conversation: suspend (StandardKtorSerialInputData) -> T
 | 
					 | 
				
			||||||
): Flow<T> {
 | 
					 | 
				
			||||||
    pluginOrNull(WebSockets) ?: error("Plugin $WebSockets must be installed for using createStandardWebsocketFlow")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    val correctedUrl = url.asCorrectWebSocketUrl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return channelFlow {
 | 
					 | 
				
			||||||
        do {
 | 
					 | 
				
			||||||
            val reconnect = runCatchingSafely {
 | 
					 | 
				
			||||||
                ws(correctedUrl, requestBuilder) {
 | 
					 | 
				
			||||||
                    for (received in incoming) {
 | 
					 | 
				
			||||||
                        when (received) {
 | 
					 | 
				
			||||||
                            is Frame.Binary -> send(conversation(received.data))
 | 
					 | 
				
			||||||
                            else -> {
 | 
					 | 
				
			||||||
                                close()
 | 
					 | 
				
			||||||
                                return@ws
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                checkReconnection(null)
 | 
					 | 
				
			||||||
            }.getOrElse { e ->
 | 
					 | 
				
			||||||
                checkReconnection(e).also {
 | 
					 | 
				
			||||||
                    if (!it) {
 | 
					 | 
				
			||||||
                        close(e)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } while (reconnect && isActive)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (isActive) {
 | 
					 | 
				
			||||||
            safely {
 | 
					 | 
				
			||||||
                close()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @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
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
inline fun <T> HttpClient.createStandardWebsocketFlow(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    deserializer: DeserializationStrategy<T>,
 | 
					 | 
				
			||||||
    crossinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat,
 | 
					 | 
				
			||||||
    noinline requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
) = createStandardWebsocketFlow(
 | 
					 | 
				
			||||||
    url,
 | 
					 | 
				
			||||||
    checkReconnection,
 | 
					 | 
				
			||||||
    requestBuilder
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    serialFormat.decodeDefault(deserializer, it)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,260 +0,0 @@
 | 
				
			|||||||
package dev.inmo.micro_utils.ktor.client
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.common.MPPFile
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.common.filename
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.ktor.common.*
 | 
					 | 
				
			||||||
import io.ktor.client.HttpClient
 | 
					 | 
				
			||||||
import io.ktor.client.call.body
 | 
					 | 
				
			||||||
import io.ktor.client.request.*
 | 
					 | 
				
			||||||
import io.ktor.client.request.forms.*
 | 
					 | 
				
			||||||
import io.ktor.client.statement.readBytes
 | 
					 | 
				
			||||||
import io.ktor.http.*
 | 
					 | 
				
			||||||
import io.ktor.utils.io.core.ByteReadPacket
 | 
					 | 
				
			||||||
import kotlinx.serialization.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This class will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
class UnifiedRequester(
 | 
					 | 
				
			||||||
    val client: HttpClient = HttpClient(),
 | 
					 | 
				
			||||||
    val serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    suspend fun <ResultType> uniget(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        resultDeserializer: DeserializationStrategy<ResultType>
 | 
					 | 
				
			||||||
    ): ResultType = client.uniget(url, resultDeserializer, serialFormat)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun <T> encodeUrlQueryValue(
 | 
					 | 
				
			||||||
        serializationStrategy: SerializationStrategy<T>,
 | 
					 | 
				
			||||||
        value: T
 | 
					 | 
				
			||||||
    ) = serializationStrategy.encodeUrlQueryValue(
 | 
					 | 
				
			||||||
        value,
 | 
					 | 
				
			||||||
        serialFormat
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <BodyType, ResultType> unipost(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        bodyInfo: Pair<SerializationStrategy<BodyType>, BodyType>,
 | 
					 | 
				
			||||||
        resultDeserializer: DeserializationStrategy<ResultType>
 | 
					 | 
				
			||||||
    ) = client.unipost(url, bodyInfo, resultDeserializer, serialFormat)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <ResultType> unimultipart(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        filename: String,
 | 
					 | 
				
			||||||
        inputProvider: InputProvider,
 | 
					 | 
				
			||||||
        resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
        mimetype: String = "*/*",
 | 
					 | 
				
			||||||
        additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    ): ResultType = client.unimultipart(url, filename, inputProvider, resultDeserializer, mimetype, additionalParametersBuilder, dataHeadersBuilder, requestBuilder, serialFormat)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <BodyType, ResultType> unimultipart(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        filename: String,
 | 
					 | 
				
			||||||
        inputProvider: InputProvider,
 | 
					 | 
				
			||||||
        otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
 | 
					 | 
				
			||||||
        resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
        mimetype: String = "*/*",
 | 
					 | 
				
			||||||
        additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    ): ResultType = client.unimultipart(url, filename, otherData, inputProvider, resultDeserializer, mimetype, additionalParametersBuilder, dataHeadersBuilder, requestBuilder, serialFormat)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <ResultType> unimultipart(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        mppFile: MPPFile,
 | 
					 | 
				
			||||||
        resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
        mimetype: String = "*/*",
 | 
					 | 
				
			||||||
        additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        requestBuilder: HttpRequestBuilder.() -> Unit = {}
 | 
					 | 
				
			||||||
    ): ResultType = client.unimultipart(
 | 
					 | 
				
			||||||
        url, mppFile, resultDeserializer, mimetype, additionalParametersBuilder, dataHeadersBuilder, requestBuilder, serialFormat
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <BodyType, ResultType> unimultipart(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        mppFile: MPPFile,
 | 
					 | 
				
			||||||
        otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
 | 
					 | 
				
			||||||
        resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
        mimetype: String = "*/*",
 | 
					 | 
				
			||||||
        additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
        requestBuilder: HttpRequestBuilder.() -> Unit = {}
 | 
					 | 
				
			||||||
    ): ResultType = client.unimultipart(
 | 
					 | 
				
			||||||
        url, mppFile, otherData, resultDeserializer, mimetype, additionalParametersBuilder, dataHeadersBuilder, requestBuilder, serialFormat
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun <T> createStandardWebsocketFlow(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        checkReconnection: suspend (Throwable?) -> Boolean,
 | 
					 | 
				
			||||||
        deserializer: DeserializationStrategy<T>,
 | 
					 | 
				
			||||||
        requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    ) = client.createStandardWebsocketFlow(url, deserializer, checkReconnection, serialFormat, requestBuilder)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun <T> createStandardWebsocketFlow(
 | 
					 | 
				
			||||||
        url: String,
 | 
					 | 
				
			||||||
        deserializer: DeserializationStrategy<T>,
 | 
					 | 
				
			||||||
        requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    ) = createStandardWebsocketFlow(url, { true }, deserializer, requestBuilder)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This property will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
val defaultRequester = UnifiedRequester()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <ResultType> HttpClient.uniget(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
) = get(url).let {
 | 
					 | 
				
			||||||
    serialFormat.decodeDefault(resultDeserializer, it.body<StandardKtorSerialInputData>())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
fun <T> SerializationStrategy<T>.encodeUrlQueryValue(
 | 
					 | 
				
			||||||
    value: T,
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
) = serialFormat.encodeHex(
 | 
					 | 
				
			||||||
    this,
 | 
					 | 
				
			||||||
    value
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <BodyType, ResultType> HttpClient.unipost(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    bodyInfo: Pair<SerializationStrategy<BodyType>, BodyType>,
 | 
					 | 
				
			||||||
    resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
) = post(url) {
 | 
					 | 
				
			||||||
    setBody(
 | 
					 | 
				
			||||||
        serialFormat.encodeDefault(bodyInfo.first, bodyInfo.second)
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}.let {
 | 
					 | 
				
			||||||
    serialFormat.decodeDefault(resultDeserializer, it.body<StandardKtorSerialInputData>())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <ResultType> HttpClient.unimultipart(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    filename: String,
 | 
					 | 
				
			||||||
    inputProvider: InputProvider,
 | 
					 | 
				
			||||||
    resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
    mimetype: String = "*/*",
 | 
					 | 
				
			||||||
    additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
): ResultType = submitFormWithBinaryData(
 | 
					 | 
				
			||||||
    url,
 | 
					 | 
				
			||||||
    formData = formData {
 | 
					 | 
				
			||||||
        append(
 | 
					 | 
				
			||||||
            "bytes",
 | 
					 | 
				
			||||||
            inputProvider,
 | 
					 | 
				
			||||||
            Headers.build {
 | 
					 | 
				
			||||||
                append(HttpHeaders.ContentType, mimetype)
 | 
					 | 
				
			||||||
                append(HttpHeaders.ContentDisposition, "filename=\"$filename\"")
 | 
					 | 
				
			||||||
                dataHeadersBuilder()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        additionalParametersBuilder()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    requestBuilder()
 | 
					 | 
				
			||||||
}.let { serialFormat.decodeDefault(resultDeserializer, it.body<StandardKtorSerialInputData>()) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <BodyType, ResultType> HttpClient.unimultipart(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    filename: String,
 | 
					 | 
				
			||||||
    otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
 | 
					 | 
				
			||||||
    inputProvider: InputProvider,
 | 
					 | 
				
			||||||
    resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
    mimetype: String = "*/*",
 | 
					 | 
				
			||||||
    additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
): ResultType = unimultipart(
 | 
					 | 
				
			||||||
    url,
 | 
					 | 
				
			||||||
    filename,
 | 
					 | 
				
			||||||
    inputProvider,
 | 
					 | 
				
			||||||
    resultDeserializer,
 | 
					 | 
				
			||||||
    mimetype,
 | 
					 | 
				
			||||||
    additionalParametersBuilder = {
 | 
					 | 
				
			||||||
        val serialized = serialFormat.encodeDefault(otherData.first, otherData.second)
 | 
					 | 
				
			||||||
        append(
 | 
					 | 
				
			||||||
            "data",
 | 
					 | 
				
			||||||
            InputProvider(serialized.size.toLong()) {
 | 
					 | 
				
			||||||
                ByteReadPacket(serialized)
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            Headers.build {
 | 
					 | 
				
			||||||
                append(HttpHeaders.ContentType, ContentType.Application.Cbor.contentType)
 | 
					 | 
				
			||||||
                append(HttpHeaders.ContentDisposition, "filename=data.bytes")
 | 
					 | 
				
			||||||
                dataHeadersBuilder()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        additionalParametersBuilder()
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    dataHeadersBuilder,
 | 
					 | 
				
			||||||
    requestBuilder,
 | 
					 | 
				
			||||||
    serialFormat
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <ResultType> HttpClient.unimultipart(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    mppFile: MPPFile,
 | 
					 | 
				
			||||||
    resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
    mimetype: String = "*/*",
 | 
					 | 
				
			||||||
    additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
): ResultType = unimultipart(
 | 
					 | 
				
			||||||
    url,
 | 
					 | 
				
			||||||
    mppFile.filename.string,
 | 
					 | 
				
			||||||
    mppFile.inputProvider(),
 | 
					 | 
				
			||||||
    resultDeserializer,
 | 
					 | 
				
			||||||
    mimetype,
 | 
					 | 
				
			||||||
    additionalParametersBuilder,
 | 
					 | 
				
			||||||
    dataHeadersBuilder,
 | 
					 | 
				
			||||||
    requestBuilder,
 | 
					 | 
				
			||||||
    serialFormat
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <BodyType, ResultType> HttpClient.unimultipart(
 | 
					 | 
				
			||||||
    url: String,
 | 
					 | 
				
			||||||
    mppFile: MPPFile,
 | 
					 | 
				
			||||||
    otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
 | 
					 | 
				
			||||||
    resultDeserializer: DeserializationStrategy<ResultType>,
 | 
					 | 
				
			||||||
    mimetype: String = "*/*",
 | 
					 | 
				
			||||||
    additionalParametersBuilder: FormBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    dataHeadersBuilder: HeadersBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    requestBuilder: HttpRequestBuilder.() -> Unit = {},
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
 | 
					 | 
				
			||||||
): ResultType = unimultipart(
 | 
					 | 
				
			||||||
    url,
 | 
					 | 
				
			||||||
    mppFile,
 | 
					 | 
				
			||||||
    resultDeserializer,
 | 
					 | 
				
			||||||
    mimetype,
 | 
					 | 
				
			||||||
    additionalParametersBuilder = {
 | 
					 | 
				
			||||||
        val serialized = serialFormat.encodeDefault(otherData.first, otherData.second)
 | 
					 | 
				
			||||||
        append(
 | 
					 | 
				
			||||||
            "data",
 | 
					 | 
				
			||||||
            InputProvider(serialized.size.toLong()) {
 | 
					 | 
				
			||||||
                ByteReadPacket(serialized)
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            Headers.build {
 | 
					 | 
				
			||||||
                append(HttpHeaders.ContentType, ContentType.Application.Cbor.contentType)
 | 
					 | 
				
			||||||
                append(HttpHeaders.ContentDisposition, "filename=data.bytes")
 | 
					 | 
				
			||||||
                dataHeadersBuilder()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        additionalParametersBuilder()
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    dataHeadersBuilder,
 | 
					 | 
				
			||||||
    requestBuilder,
 | 
					 | 
				
			||||||
    serialFormat
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@@ -1,61 +0,0 @@
 | 
				
			|||||||
package dev.inmo.micro_utils.ktor.server
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.coroutines.safely
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.ktor.common.*
 | 
					 | 
				
			||||||
import io.ktor.http.URLProtocol
 | 
					 | 
				
			||||||
import io.ktor.server.application.install
 | 
					 | 
				
			||||||
import io.ktor.server.application.pluginOrNull
 | 
					 | 
				
			||||||
import io.ktor.server.routing.Route
 | 
					 | 
				
			||||||
import io.ktor.server.routing.application
 | 
					 | 
				
			||||||
import io.ktor.server.websocket.*
 | 
					 | 
				
			||||||
import io.ktor.websocket.send
 | 
					 | 
				
			||||||
import kotlinx.coroutines.flow.Flow
 | 
					 | 
				
			||||||
import kotlinx.serialization.SerializationStrategy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon")
 | 
					 | 
				
			||||||
fun <T> Route.includeWebsocketHandling(
 | 
					 | 
				
			||||||
    suburl: String,
 | 
					 | 
				
			||||||
    flow: Flow<T>,
 | 
					 | 
				
			||||||
    protocol: URLProtocol? = null,
 | 
					 | 
				
			||||||
    converter: suspend WebSocketServerSession.(T) -> StandardKtorSerialInputData?
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    application.apply {
 | 
					 | 
				
			||||||
        pluginOrNull(WebSockets) ?: install(WebSockets)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    webSocket(suburl, protocol ?.name) {
 | 
					 | 
				
			||||||
        safely {
 | 
					 | 
				
			||||||
            flow.collect {
 | 
					 | 
				
			||||||
                converter(it) ?.let { data ->
 | 
					 | 
				
			||||||
                    send(data)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon")
 | 
					 | 
				
			||||||
fun <T> Route.includeWebsocketHandling(
 | 
					 | 
				
			||||||
    suburl: String,
 | 
					 | 
				
			||||||
    flow: Flow<T>,
 | 
					 | 
				
			||||||
    serializer: SerializationStrategy<T>,
 | 
					 | 
				
			||||||
    serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat,
 | 
					 | 
				
			||||||
    protocol: URLProtocol? = null,
 | 
					 | 
				
			||||||
    filter: (suspend WebSocketServerSession.(T) -> Boolean)? = null
 | 
					 | 
				
			||||||
) = includeWebsocketHandling(
 | 
					 | 
				
			||||||
    suburl,
 | 
					 | 
				
			||||||
    flow,
 | 
					 | 
				
			||||||
    protocol,
 | 
					 | 
				
			||||||
    converter = if (filter == null) {
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            serialFormat.encodeDefault(serializer, it)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (filter(it)) {
 | 
					 | 
				
			||||||
                serialFormat.encodeDefault(serializer, it)
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                null
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@@ -19,106 +19,6 @@ import kotlinx.coroutines.flow.Flow
 | 
				
			|||||||
import kotlinx.serialization.DeserializationStrategy
 | 
					import kotlinx.serialization.DeserializationStrategy
 | 
				
			||||||
import kotlinx.serialization.SerializationStrategy
 | 
					import kotlinx.serialization.SerializationStrategy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Deprecated("This class method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
class UnifiedRouter(
 | 
					 | 
				
			||||||
    val serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat,
 | 
					 | 
				
			||||||
    val serialFormatContentType: ContentType = standardKtorSerialFormatContentType
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    fun <T> Route.includeWebsocketHandling(
 | 
					 | 
				
			||||||
        suburl: String,
 | 
					 | 
				
			||||||
        flow: Flow<T>,
 | 
					 | 
				
			||||||
        serializer: SerializationStrategy<T>,
 | 
					 | 
				
			||||||
        protocol: URLProtocol? = null,
 | 
					 | 
				
			||||||
        filter: (suspend WebSocketServerSession.(T) -> Boolean)? = null
 | 
					 | 
				
			||||||
    ) = includeWebsocketHandling(suburl, flow, serializer, serialFormat, protocol, filter)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <T> PipelineContext<*, ApplicationCall>.unianswer(
 | 
					 | 
				
			||||||
        answerSerializer: SerializationStrategy<T>,
 | 
					 | 
				
			||||||
        answer: T
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        call.respondBytes (
 | 
					 | 
				
			||||||
            serialFormat.encodeDefault(answerSerializer, answer),
 | 
					 | 
				
			||||||
            serialFormatContentType
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <T> PipelineContext<*, ApplicationCall>.uniload(
 | 
					 | 
				
			||||||
        deserializer: DeserializationStrategy<T>
 | 
					 | 
				
			||||||
    ) = safely {
 | 
					 | 
				
			||||||
        serialFormat.decodeDefault(
 | 
					 | 
				
			||||||
            deserializer,
 | 
					 | 
				
			||||||
            call.receive()
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun PipelineContext<*, ApplicationCall>.getParameterOrSendError(
 | 
					 | 
				
			||||||
        field: String
 | 
					 | 
				
			||||||
    ) = call.parameters[field].also {
 | 
					 | 
				
			||||||
        if (it == null) {
 | 
					 | 
				
			||||||
            call.respond(HttpStatusCode.BadRequest, "Request must contains $field")
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun PipelineContext<*, ApplicationCall>.getQueryParameter(
 | 
					 | 
				
			||||||
        field: String
 | 
					 | 
				
			||||||
    ) = call.request.queryParameters[field]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun PipelineContext<*, ApplicationCall>.getQueryParameterOrSendError(
 | 
					 | 
				
			||||||
        field: String
 | 
					 | 
				
			||||||
    ) = getQueryParameter(field).also {
 | 
					 | 
				
			||||||
        if (it == null) {
 | 
					 | 
				
			||||||
            call.respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun <T> PipelineContext<*, ApplicationCall>.decodeUrlQueryValue(
 | 
					 | 
				
			||||||
        field: String,
 | 
					 | 
				
			||||||
        deserializer: DeserializationStrategy<T>
 | 
					 | 
				
			||||||
    ) = getQueryParameter(field) ?.let {
 | 
					 | 
				
			||||||
        serialFormat.decodeHex(
 | 
					 | 
				
			||||||
            deserializer,
 | 
					 | 
				
			||||||
            it
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suspend fun <T> PipelineContext<*, ApplicationCall>.decodeUrlQueryValueOrSendError(
 | 
					 | 
				
			||||||
        field: String,
 | 
					 | 
				
			||||||
        deserializer: DeserializationStrategy<T>
 | 
					 | 
				
			||||||
    ) = decodeUrlQueryValue(field, deserializer).also {
 | 
					 | 
				
			||||||
        if (it == null) {
 | 
					 | 
				
			||||||
            call.respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    companion object {
 | 
					 | 
				
			||||||
        val default
 | 
					 | 
				
			||||||
            get() = defaultUnifiedRouter
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
val defaultUnifiedRouter = UnifiedRouter()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <T> ApplicationCall.unianswer(
 | 
					 | 
				
			||||||
    answerSerializer: SerializationStrategy<T>,
 | 
					 | 
				
			||||||
    answer: T
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
    respondBytes (
 | 
					 | 
				
			||||||
        standardKtorSerialFormat.encodeDefault(answerSerializer, answer),
 | 
					 | 
				
			||||||
        standardKtorSerialFormatContentType
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <T> ApplicationCall.uniload(
 | 
					 | 
				
			||||||
    deserializer: DeserializationStrategy<T>
 | 
					 | 
				
			||||||
) = safely {
 | 
					 | 
				
			||||||
    standardKtorSerialFormat.decodeDefault(
 | 
					 | 
				
			||||||
        deserializer,
 | 
					 | 
				
			||||||
        receive()
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
suspend fun ApplicationCall.uniloadMultipart(
 | 
					suspend fun ApplicationCall.uniloadMultipart(
 | 
				
			||||||
    onFormItem: (PartData.FormItem) -> Unit = {},
 | 
					    onFormItem: (PartData.FormItem) -> Unit = {},
 | 
				
			||||||
    onCustomFileItem: (PartData.FileItem) -> Unit = {},
 | 
					    onCustomFileItem: (PartData.FileItem) -> Unit = {},
 | 
				
			||||||
@@ -146,82 +46,6 @@ suspend fun ApplicationCall.uniloadMultipart(
 | 
				
			|||||||
    resultInput ?: error("Bytes has not been received")
 | 
					    resultInput ?: error("Bytes has not been received")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <T> ApplicationCall.uniloadMultipart(
 | 
					 | 
				
			||||||
    deserializer: DeserializationStrategy<T>,
 | 
					 | 
				
			||||||
    onFormItem: (PartData.FormItem) -> Unit = {},
 | 
					 | 
				
			||||||
    onCustomFileItem: (PartData.FileItem) -> Unit = {},
 | 
					 | 
				
			||||||
    onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
 | 
					 | 
				
			||||||
    onBinaryContent: (PartData.BinaryItem) -> Unit = {}
 | 
					 | 
				
			||||||
): Pair<Input, T> {
 | 
					 | 
				
			||||||
    var data: Optional<T>? = null
 | 
					 | 
				
			||||||
    val resultInput = uniloadMultipart(
 | 
					 | 
				
			||||||
        onFormItem,
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (it.name == "data") {
 | 
					 | 
				
			||||||
                data = standardKtorSerialFormat.decodeDefault(deserializer, it.provider().readBytes()).optional
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                onCustomFileItem(it)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onBinaryChannelItem,
 | 
					 | 
				
			||||||
        onBinaryContent
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    val completeData = data ?: error("Data has not been received")
 | 
					 | 
				
			||||||
    return resultInput to (completeData.dataOrNull().let { it as T })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <T> ApplicationCall.uniloadMultipartFile(
 | 
					 | 
				
			||||||
    deserializer: DeserializationStrategy<T>,
 | 
					 | 
				
			||||||
    onFormItem: (PartData.FormItem) -> Unit = {},
 | 
					 | 
				
			||||||
    onCustomFileItem: (PartData.FileItem) -> Unit = {},
 | 
					 | 
				
			||||||
    onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
 | 
					 | 
				
			||||||
    onBinaryContent: (PartData.BinaryItem) -> Unit = {},
 | 
					 | 
				
			||||||
) = safely {
 | 
					 | 
				
			||||||
    val multipartData = receiveMultipart()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var resultInput: MPPFile? = null
 | 
					 | 
				
			||||||
    var data: Optional<T>? = null
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    multipartData.forEachPart {
 | 
					 | 
				
			||||||
        when (it) {
 | 
					 | 
				
			||||||
            is PartData.FormItem -> onFormItem(it)
 | 
					 | 
				
			||||||
            is PartData.FileItem -> {
 | 
					 | 
				
			||||||
                when (it.name) {
 | 
					 | 
				
			||||||
                    "bytes" -> {
 | 
					 | 
				
			||||||
                        val name = FileName(it.originalFileName ?: error("File name is unknown for default part"))
 | 
					 | 
				
			||||||
                        resultInput = MPPFile.createTempFile(
 | 
					 | 
				
			||||||
                            name.nameWithoutExtension.let {
 | 
					 | 
				
			||||||
                                var resultName = it
 | 
					 | 
				
			||||||
                                while (resultName.length < 3) {
 | 
					 | 
				
			||||||
                                    resultName += "_"
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                                resultName
 | 
					 | 
				
			||||||
                            },
 | 
					 | 
				
			||||||
                            ".${name.extension}"
 | 
					 | 
				
			||||||
                        ).apply {
 | 
					 | 
				
			||||||
                            outputStream().use { fileStream ->
 | 
					 | 
				
			||||||
                                it.streamProvider().use {
 | 
					 | 
				
			||||||
                                    it.copyTo(fileStream)
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    "data" -> data = standardKtorSerialFormat.decodeDefault(deserializer, it.provider().readBytes()).optional
 | 
					 | 
				
			||||||
                    else -> onCustomFileItem(it)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            is PartData.BinaryItem -> onBinaryContent(it)
 | 
					 | 
				
			||||||
            is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    val completeData = data ?: error("Data has not been received")
 | 
					 | 
				
			||||||
    (resultInput ?: error("Bytes has not been received")) to (completeData.dataOrNull().let { it as T })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
suspend fun ApplicationCall.uniloadMultipartFile(
 | 
					suspend fun ApplicationCall.uniloadMultipartFile(
 | 
				
			||||||
    onFormItem: (PartData.FormItem) -> Unit = {},
 | 
					    onFormItem: (PartData.FormItem) -> Unit = {},
 | 
				
			||||||
    onCustomFileItem: (PartData.FileItem) -> Unit = {},
 | 
					    onCustomFileItem: (PartData.FileItem) -> Unit = {},
 | 
				
			||||||
@@ -285,24 +109,3 @@ suspend fun ApplicationCall.getQueryParameterOrSendError(
 | 
				
			|||||||
        respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
 | 
					        respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
fun <T> ApplicationCall.decodeUrlQueryValue(
 | 
					 | 
				
			||||||
    field: String,
 | 
					 | 
				
			||||||
    deserializer: DeserializationStrategy<T>
 | 
					 | 
				
			||||||
) = getQueryParameter(field) ?.let {
 | 
					 | 
				
			||||||
    standardKtorSerialFormat.decodeHex(
 | 
					 | 
				
			||||||
        deserializer,
 | 
					 | 
				
			||||||
        it
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
 | 
					 | 
				
			||||||
suspend fun <T> ApplicationCall.decodeUrlQueryValueOrSendError(
 | 
					 | 
				
			||||||
    field: String,
 | 
					 | 
				
			||||||
    deserializer: DeserializationStrategy<T>
 | 
					 | 
				
			||||||
) = decodeUrlQueryValue(field, deserializer).also {
 | 
					 | 
				
			||||||
    if (it == null) {
 | 
					 | 
				
			||||||
        respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,18 +33,6 @@ data class PaginationResult<T>(
 | 
				
			|||||||
        results,
 | 
					        results,
 | 
				
			||||||
        (pagesNumber * size).toLong()
 | 
					        (pagesNumber * size).toLong()
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    @Deprecated("Replace with The other order of incoming parameters or objectsCount parameter")
 | 
					 | 
				
			||||||
    constructor(
 | 
					 | 
				
			||||||
        page: Int,
 | 
					 | 
				
			||||||
        pagesNumber: Int,
 | 
					 | 
				
			||||||
        results: List<T>,
 | 
					 | 
				
			||||||
        size: Int
 | 
					 | 
				
			||||||
    ) : this(
 | 
					 | 
				
			||||||
        page,
 | 
					 | 
				
			||||||
        results,
 | 
					 | 
				
			||||||
        pagesNumber,
 | 
					 | 
				
			||||||
        size
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun <T> emptyPaginationResult() = PaginationResult<T>(0, 0, emptyList(), 0L)
 | 
					fun <T> emptyPaginationResult() = PaginationResult<T>(0, 0, emptyList(), 0L)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user