Compare commits

...

19 Commits

Author SHA1 Message Date
121e513fdd fixes in tempUpload of js part 2022-06-22 22:36:06 +06:00
9cf01ab54f improve compose list state creation 2022-06-22 16:56:51 +06:00
c655107681 renames in compose states creation 2022-06-22 16:52:19 +06:00
91a5af6a9a fix of changelog 2022-06-22 16:10:58 +06:00
86e74c0a6f add extension toMutableListState 2022-06-22 16:09:52 +06:00
d8f01f21a0 start 0.11.4 2022-06-22 16:09:35 +06:00
9fb8626d8c Rewrite crud.yml 2022-06-16 15:51:22 +06:00
1c52e04cdb Merge pull request #164 from InsanusMokrassar/0.11.3
0.11.3
2022-06-14 23:59:49 +06:00
798128256e fixes in websockets 2022-06-14 23:48:10 +06:00
72c2df47fd start 0.11.3 2022-06-14 19:35:17 +06:00
c9c6d4c0c1 Merge pull request #163 from InsanusMokrassar/0.11.2
0.11.2
2022-06-13 23:21:14 +06:00
2f4f9f3003 fixes 2022-06-13 23:20:25 +06:00
22e8f8e5d6 start 0.11.2 2022-06-13 22:19:33 +06:00
04cf8c3d9a Merge pull request #162 from InsanusMokrassar/0.11.1
0.11.1
2022-06-12 16:32:05 +06:00
52198be543 fixes in tempupload 2022-06-12 14:26:41 +06:00
80fd5a489b add pagination type info in crud read repo client 2022-06-11 22:37:32 +06:00
b187043ee1 fixes in kv and kvs of ktor repos 2022-06-10 22:25:16 +06:00
8965752055 start 0.11.1 2022-06-10 22:23:45 +06:00
b796620267 Merge pull request #161 from InsanusMokrassar/0.11.0
0.11.0
2022-06-05 02:54:05 +06:00
16 changed files with 420 additions and 279 deletions

View File

@@ -1,5 +1,30 @@
# Changelog
## 0.11.4
* `Coroutines`:
* `Compose`:
* Add extension `StateFlow#asMutableComposeListState` and `StateFlow#asComposeList`
* Add extension `StateFlow#asMutableComposeState`/`StateFlow#asComposeState`
## 0.11.3
* `Ktor`:
* Support of `WebSockets` has been improved
* `Client`:
* New extensions: `HttpClient#openBaseWebSocketFlow`, `HttpClient#openWebSocketFlow`, `HttpClient#openSecureWebSocketFlow`
## 0.11.2
* `Ktor`:
* Support of `WebSockets` has been improved and added fixes inside of clients
## 0.11.1
* `Repos`
* `Ktor`
* In `configureReadKeyValueRepoRoutes` and `configureReadKeyValuesRepoRoutes` configurators fixed requiring of `reversed` property
## 0.11.0
* `Versions`

View File

@@ -0,0 +1,26 @@
package dev.inmo.micro_utils.coroutines.compose
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import dev.inmo.micro_utils.common.applyDiff
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
@Suppress("NOTHING_TO_INLINE")
inline fun <reified T> Flow<List<T>>.asMutableComposeListState(
scope: CoroutineScope
): SnapshotStateList<T> {
val state = mutableStateListOf<T>()
subscribeSafelyWithoutExceptions(scope) {
state.applyDiff(it)
}
return state
}
@Suppress("NOTHING_TO_INLINE")
inline fun <reified T> Flow<List<T>>.asComposeList(
scope: CoroutineScope
): List<T> = asMutableComposeListState(scope)

View File

@@ -0,0 +1,35 @@
package dev.inmo.micro_utils.coroutines.compose
import androidx.compose.runtime.*
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
fun <T> Flow<T>.asMutableComposeState(
initial: T,
scope: CoroutineScope
): MutableState<T> {
val state = mutableStateOf(initial)
subscribeSafelyWithoutExceptions(scope) { state.value = it }
return state
}
@Suppress("NOTHING_TO_INLINE")
inline fun <T> StateFlow<T>.asMutableComposeState(
scope: CoroutineScope
): MutableState<T> = asMutableComposeState(value, scope)
fun <T> Flow<T>.asComposeState(
initial: T,
scope: CoroutineScope
): State<T> {
val state = asMutableComposeState(initial, scope)
return derivedStateOf { state.value }
}
@Suppress("NOTHING_TO_INLINE")
inline fun <T> StateFlow<T>.asComposeState(
scope: CoroutineScope
): State<T> = asComposeState(value, scope)

View File

@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
# Project data
group=dev.inmo
version=0.11.0
android_code_version=124
version=0.11.4
android_code_version=128

View File

@@ -1,5 +1,6 @@
package dev.inmo.micro_utils.ktor.client
import dev.inmo.micro_utils.common.Warning
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.ktor.common.*
@@ -7,35 +8,25 @@ import io.ktor.client.HttpClient
import io.ktor.client.plugins.pluginOrNull
import io.ktor.client.plugins.websocket.*
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.websocket.Frame
import io.ktor.websocket.readBytes
import io.ktor.websocket.serialization.sendSerializedBase
import io.ktor.http.URLProtocol
import kotlinx.coroutines.channels.SendChannel
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
*/
inline fun <reified T> HttpClient.createStandardWebsocketFlow(
url: String,
@Warning("This feature is internal and should not be used directly. It is can be changed without any notification and warranty on compile-time or other guaranties")
inline fun <reified T : Any> openBaseWebSocketFlow(
noinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
noinline requestBuilder: HttpRequestBuilder.() -> Unit = {}
noinline webSocketSessionRequest: suspend SendChannel<T>.() -> Unit
): 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) {
sendSerialized(received.data)
}
}
webSocketSessionRequest()
checkReconnection(null)
}.getOrElse { e ->
checkReconnection(e).also {
@@ -53,3 +44,60 @@ inline fun <reified T> HttpClient.createStandardWebsocketFlow(
}
}
}
/**
* @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
*/
inline fun <reified T : Any> HttpClient.openWebSocketFlow(
url: String,
useSecureConnection: Boolean,
noinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
noinline requestBuilder: HttpRequestBuilder.() -> Unit = {}
): Flow<T> {
pluginOrNull(WebSockets) ?: error("Plugin $WebSockets must be installed for using createStandardWebsocketFlow")
return openBaseWebSocketFlow<T>(checkReconnection) {
val block: suspend DefaultClientWebSocketSession.() -> Unit = {
while (isActive) {
send(receiveDeserialized<T>())
}
}
if (useSecureConnection) {
wss(url, requestBuilder, block)
} else {
ws(url, requestBuilder, block)
}
}
}
/**
* @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
*/
inline fun <reified T : Any> HttpClient.openWebSocketFlow(
url: String,
noinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
noinline requestBuilder: HttpRequestBuilder.() -> Unit = {}
): Flow<T> = openWebSocketFlow(url, false, checkReconnection, requestBuilder)
/**
* @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
*/
inline fun <reified T : Any> HttpClient.openSecureWebSocketFlow(
url: String,
noinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
noinline requestBuilder: HttpRequestBuilder.() -> Unit = {}
): Flow<T> = openWebSocketFlow(url, true, checkReconnection, requestBuilder)
/**
* @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
*/
inline fun <reified T : Any> HttpClient.createStandardWebsocketFlow(
url: String,
noinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
noinline requestBuilder: HttpRequestBuilder.() -> Unit = {}
): Flow<T> = openWebSocketFlow(url, checkReconnection, requestBuilder)

View File

@@ -4,7 +4,10 @@ import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.micro_utils.ktor.common.TemporalFileId
import io.ktor.client.HttpClient
import kotlinx.coroutines.*
import org.w3c.dom.mediasource.ENDED
import org.w3c.dom.mediasource.ReadyState
import org.w3c.xhr.*
import org.w3c.xhr.XMLHttpRequest.Companion.DONE
suspend fun tempUpload(
fullTempUploadDraftPath: String,
@@ -12,7 +15,7 @@ suspend fun tempUpload(
onUpload: (Long, Long) -> Unit
): TemporalFileId {
val formData = FormData()
val answer = CompletableDeferred<TemporalFileId>()
val answer = CompletableDeferred<TemporalFileId>(currentCoroutineContext().job)
formData.append(
"data",
@@ -37,17 +40,15 @@ suspend fun tempUpload(
request.open("POST", fullTempUploadDraftPath, true)
request.send(formData)
val handle = currentCoroutineContext().job.invokeOnCompletion {
answer.invokeOnCompletion {
runCatching {
request.abort()
if (request.readyState != DONE) {
request.abort()
}
}
}
return runCatching {
answer.await()
}.also {
handle.dispose()
}.getOrThrow()
return answer.await()
}

View File

@@ -12,6 +12,7 @@ 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>,

View File

@@ -15,7 +15,8 @@ import kotlinx.serialization.SerializationStrategy
inline fun <reified T : Any> Route.includeWebsocketHandling(
suburl: String,
flow: Flow<T>,
protocol: URLProtocol? = null
protocol: URLProtocol? = null,
noinline dataMapper: suspend WebSocketServerSession.(T) -> T? = { it }
) {
application.apply {
pluginOrNull(WebSockets) ?: install(WebSockets)
@@ -23,7 +24,7 @@ inline fun <reified T : Any> Route.includeWebsocketHandling(
webSocket(suburl, protocol ?.name) {
safely {
flow.collect {
sendSerialized(it)
sendSerialized(dataMapper(it) ?: return@collect)
}
}
}

View File

@@ -13,6 +13,7 @@ import io.ktor.http.content.streamProvider
import io.ktor.server.application.call
import io.ktor.server.request.receiveMultipart
import io.ktor.server.response.respond
import io.ktor.server.response.respondText
import io.ktor.server.routing.Route
import io.ktor.server.routing.post
import kotlinx.coroutines.*
@@ -111,7 +112,7 @@ class TemporalFilesRoutingConfigurator(
temporalFilesMutex.withLock {
temporalFilesMap[fileId] = file
}
call.respond(fileId.string)
call.respondText(fileId.string)
launchSafelyWithoutExceptions { filesFlow.emit(fileId) }
} ?: call.respond(HttpStatusCode.BadRequest)
}

View File

@@ -1,6 +1,7 @@
package dev.inmo.micro_utils.repos.ktor.client.crud
import dev.inmo.micro_utils.ktor.common.*
import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.*
import io.ktor.client.HttpClient
import io.ktor.http.ContentType
@@ -19,14 +20,14 @@ class KtorCRUDRepoClient<ObjectType, IdType, InputValue> (
inline operator fun <reified ObjectType, reified IdType, reified InputValue> invoke(
baseUrl: String,
httpClient: HttpClient,
objectTypeInfo: TypeInfo,
contentType: ContentType,
noinline idSerializer: suspend (IdType) -> String
) = KtorCRUDRepoClient(
KtorReadCRUDRepoClient(
baseUrl,
httpClient,
objectTypeInfo,
typeInfo<ObjectType>(),
typeInfo<PaginationResult<ObjectType>>(),
contentType,
idSerializer
),
@@ -41,33 +42,17 @@ class KtorCRUDRepoClient<ObjectType, IdType, InputValue> (
baseUrl: String,
subpart: String,
httpClient: HttpClient,
objectTypeInfo: TypeInfo,
contentType: ContentType,
noinline idSerializer: suspend (IdType) -> String
) = KtorCRUDRepoClient<ObjectType, IdType, InputValue>(
buildStandardUrl(baseUrl, subpart),
httpClient,
objectTypeInfo,
contentType,
idSerializer
)
}
}
inline fun <reified ObjectType, reified IdType, reified InputValue> KtorCRUDRepoClient(
baseUrl: String,
httpClient: HttpClient,
contentType: ContentType,
noinline idSerializer: suspend (IdType) -> String
) = KtorCRUDRepoClient<ObjectType, IdType, InputValue>(
baseUrl,
httpClient,
typeInfo<ObjectType>(),
contentType,
idSerializer
)
inline fun <reified ObjectType, reified IdType, reified InputValue> KtorCRUDRepoClient(
baseUrl: String,
httpClient: HttpClient,

View File

@@ -18,6 +18,7 @@ class KtorReadCRUDRepoClient<ObjectType, IdType> (
private val baseUrl: String,
private val httpClient: HttpClient,
private val objectType: TypeInfo,
private val paginationObjectType: TypeInfo,
private val contentType: ContentType,
private val idSerializer: suspend (IdType) -> String
) : ReadCRUDRepo<ObjectType, IdType> {
@@ -25,7 +26,7 @@ class KtorReadCRUDRepoClient<ObjectType, IdType> (
buildStandardUrl(baseUrl, getByPaginationRouting, pagination.asUrlQueryParts)
) {
contentType(contentType)
}.body()
}.body(paginationObjectType)
override suspend fun getById(id: IdType): ObjectType? = httpClient.get(
buildStandardUrl(
@@ -70,6 +71,7 @@ inline fun <reified ObjectType, IdType> KtorReadCRUDRepoClient(
baseUrl,
httpClient,
typeInfo<ObjectType>(),
typeInfo<PaginationResult<ObjectType>>(),
contentType,
idSerializer
)

View File

@@ -1,7 +1,7 @@
swagger: "2.0"
openapi: "3.0.0"
info:
description: "This is a template for the CRUD repositories from [microutils](https://github.com/InsanusMokrassar/MicroUtils/tree/master/repos/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/ktor/server/crud)"
version: "0.11.0"
version: "0.11.3"
title: "CRUD Repo"
contact:
email: "ovsyannikov.alexey95@gmail.com"
@@ -11,91 +11,61 @@ tags:
- name: "Write"
description: "Operations with `post` request in most cases"
parameters:
IdInQuery:
in: "query"
name: "id"
allOf:
- $ref: "#/definitions/Key"
IdsInBody:
in: "body"
name: "body"
type: array
items:
$ref: "#/definitions/Key"
NewValuesInBody:
in: "body"
name: "body"
type: array
allOf:
- $ref: "#/definitions/NewValues"
NewValuesWithIdsInBody:
in: "body"
name: "body"
type: array
items:
allOf:
- $ref: "#/definitions/Pair"
- properties:
first:
$ref: "#/definitions/Key"
second:
$ref: "#/definitions/NewValue"
PaginationInQueryPage:
in: "query"
type: integer
name: "ppage"
description: "Page of pagination"
required: false
PaginationInQuerySize:
in: "query"
type: integer
name: "psize"
description: "Size of each page in pagination"
required: false
components:
parameters:
IdInQuery:
in: "query"
name: "id"
schema:
$ref: "#/components/schemas/Key"
PaginationInQueryPage:
in: "query"
name: "ppage"
description: "Page of pagination"
schema:
type: integer
required: false
PaginationInQuerySize:
in: "query"
name: "psize"
description: "Size of each page in pagination"
schema:
type: integer
required: false
schemas:
definitions:
Key:
type: integer
description: "REWRITE THIS TYPE AS KEY IN SWAGGER FILE"
Value:
type: integer
description: "REWRITE THIS TYPE AS VALUE IN SWAGGER FILE"
Values:
type: array
items:
$ref: "#/definitions/Value"
NewValue:
type: integer
description: "REWRITE THIS TYPE AS NEW VALUE IN SWAGGER FILE"
Pair:
type: object
description: "Pair of objects"
properties:
first:
second:
NewValues:
type: array
items:
$ref: "#/definitions/NewValue"
PaginationResult:
type: object
properties:
page:
type: integer
description: "Page of pagination"
pagesNumber:
type: integer
description: "Count of pages with the size from this pagination"
size:
type: integer
description: "Size of each page in pagination"
results:
type: array
description: "Array of all elements on that page. Size of pagination and size of array can be different and it can be interpreted like current page is the last one"
items:
type: object
Key:
type: integer
description: "REWRITE THIS TYPE AS KEY IN SWAGGER FILE"
Value:
type: integer
description: "REWRITE THIS TYPE AS VALUE IN SWAGGER FILE"
NewValue:
type: integer
description: "REWRITE THIS TYPE AS NEW VALUE IN SWAGGER FILE"
Pair:
type: object
description: "Pair of objects"
properties:
first:
second:
PaginationResult:
type: object
properties:
page:
type: integer
description: "Page of pagination"
pagesNumber:
type: integer
description: "Count of pages with the size from this pagination"
size:
type: integer
description: "Size of each page in pagination"
results:
type: array
description: "Array of all elements on that page. Size of pagination and size of array can be different and it can be interpreted like current page is the last one"
items:
type: object
paths:
/getByPagination:
@@ -103,30 +73,34 @@ paths:
tags:
- "Read"
parameters:
- $ref: "#/parameters/PaginationInQueryPage"
- $ref: "#/parameters/PaginationInQuerySize"
- $ref: "#/components/parameters/PaginationInQueryPage"
- $ref: "#/components/parameters/PaginationInQuerySize"
responses:
"200":
description: "Pagination with elements"
schema:
allOf:
- $ref: "#/definitions/PaginationResult"
- properties:
results:
items:
$ref: "#/definitions/Value"
content:
application/json:
schema:
allOf:
- $ref: "#/components/schemas/PaginationResult"
- properties:
results:
items:
$ref: "#/components/schemas/Value"
/getById:
get:
tags:
- "Read"
parameters:
- $ref: "#/parameters/IdInQuery"
- $ref: "#/components/parameters/IdInQuery"
required: true
responses:
"200":
description: "Result object"
schema:
$ref: "#/definitions/Value"
content:
application/json:
schema:
$ref: "#/components/schemas/Value"
"204":
description: "No value by id"
/contains:
@@ -134,13 +108,15 @@ paths:
tags:
- "Read"
parameters:
- $ref: "#/parameters/IdInQuery"
- $ref: "#/components/parameters/IdInQuery"
required: true
responses:
"200":
description: "Object with id availability in repo"
schema:
type: boolean
content:
application/json:
schema:
type: boolean
/count:
get:
tags:
@@ -148,40 +124,75 @@ paths:
responses:
"200":
description: "Amount of objects in repo"
schema:
type: integer
content:
application/json:
schema:
type: integer
/create:
post:
tags:
- "Write"
parameters:
- $ref: "#/parameters/NewValuesInBody"
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/NewValue"
responses:
"200":
description: "Objects has been created and saved"
schema:
$ref: "#/definitions/Values"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Value"
/update:
post:
tags:
- "Write"
parameters:
- $ref: "#/parameters/NewValuesWithIdsInBody"
requestBody:
content:
application/json:
schema:
type: array
items:
allOf:
- $ref: "#/components/schemas/Pair"
- properties:
first:
$ref: "#/components/schemas/Key"
second:
$ref: "#/components/schemas/NewValue"
responses:
"200":
description: "Objects has been updated"
schema:
$ref: "#/definitions/Values"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Value"
/deleteById:
post:
tags:
- "Write"
parameters:
- $ref: "#/parameters/IdsInBody"
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Key"
responses:
"200":
description: "Objects has been updated"
schema:
$ref: "#/definitions/Values"
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Value"

View File

@@ -1,7 +1,7 @@
swagger: "2.0"
openapi: "3.0.0"
info:
description: "This is a template for the KeyValue repositories from [microutils](https://github.com/InsanusMokrassar/MicroUtils/tree/master/repos/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/ktor/server/key/value)"
version: "0.11.0"
version: "0.11.1"
title: "KeyValue Repo"
contact:
email: "ovsyannikov.alexey95@gmail.com"
@@ -11,81 +11,63 @@ tags:
- name: "Write"
description: "Operations with `post` request in most cases"
parameters:
KeyInQuery:
in: "query"
name: "key"
allOf:
- $ref: "#/definitions/Key"
KeysInBody:
in: "body"
name: "body"
type: array
items:
$ref: "#/definitions/Key"
ValuesInBody:
in: "body"
name: "body"
type: array
items:
$ref: "#/definitions/Value"
PaginationInQueryPage:
in: "query"
type: integer
name: "ppage"
description: "Page of pagination"
required: false
PaginationInQuerySize:
in: "query"
type: integer
name: "psize"
description: "Size of each page in pagination"
required: false
ReversedInQuery:
in: "query"
type: boolean
name: "reversed"
description: "If passed, will tell to reverse the result pages"
required: false
ValueInQuery:
in: "query"
name: "value"
allOf:
- $ref: "#/definitions/Value"
MapInBody:
in: "body"
name: "body"
allOf:
- $ref: "#/definitions/Map"
definitions:
Key:
type: integer
description: "REWRITE THIS TYPE AS KEY IN SWAGGER FILE"
Value:
type: integer
description: "REWRITE THIS TYPE AS VALUE IN SWAGGER FILE"
Map:
type: object
description: "Map of objects"
PaginationResult:
type: object
properties:
page:
components:
parameters:
KeyInQuery:
in: "query"
name: "key"
schema:
$ref: "#/components/schemas/Key"
PaginationInQueryPage:
in: "query"
name: "ppage"
description: "Page of pagination"
schema:
type: integer
description: "Page of pagination"
pagesNumber:
required: false
PaginationInQuerySize:
in: "query"
name: "psize"
description: "Size of each page in pagination"
schema:
type: integer
description: "Count of pages with the size from this pagination"
size:
type: integer
description: "Size of each page in pagination"
results:
type: array
description: "Array of all elements on that page. Size of pagination and size of array can be different and it can be interpreted like current page is the last one"
items:
type: object
required: false
ReversedInQuery:
in: "query"
name: "reversed"
description: "If passed, will tell to reverse the result pages"
schema:
type: boolean
required: false
ValueInQuery:
in: "query"
name: "value"
schema:
$ref: "#/components/schemas/Value"
schemas:
Key:
type: integer
description: "REWRITE THIS TYPE AS KEY IN SWAGGER FILE"
Value:
type: integer
description: "REWRITE THIS TYPE AS VALUE IN SWAGGER FILE"
PaginationResult:
type: object
properties:
page:
type: integer
description: "Page of pagination"
pagesNumber:
type: integer
description: "Count of pages with the size from this pagination"
size:
type: integer
description: "Size of each page in pagination"
results:
type: array
description: "Array of all elements on that page. Size of pagination and size of array can be different and it can be interpreted like current page is the last one"
items:
type: object
paths:
/get:
@@ -93,13 +75,16 @@ paths:
tags:
- "Read"
parameters:
- $ref: "#/parameters/KeyInQuery"
required: true
- allOf:
- $ref: "#/components/parameters/KeyInQuery"
- required: true
responses:
"200":
description: "Element by key"
schema:
$ref: "#/definitions/Value"
content:
"*/*":
schema:
$ref: "#/components/schemas/Value"
"204":
description: "No value by id"
/values:
@@ -107,51 +92,57 @@ paths:
tags:
- "Read"
parameters:
- $ref: "#/parameters/PaginationInQueryPage"
- $ref: "#/parameters/PaginationInQuerySize"
- $ref: "#/parameters/ReversedInQuery"
- $ref: "#/components/parameters/PaginationInQueryPage"
- $ref: "#/components/parameters/PaginationInQuerySize"
- $ref: "#/components/parameters/ReversedInQuery"
responses:
"200":
description: "Pagination with elements"
schema:
allOf:
- $ref: "#/definitions/PaginationResult"
- properties:
results:
items:
$ref: "#/definitions/Value"
content:
"*/*":
schema:
allOf:
- $ref: "#/components/schemas/PaginationResult"
- properties:
results:
items:
$ref: "#/components/schemas/Value"
/keys:
get:
tags:
- "Read"
parameters:
- $ref: "#/parameters/PaginationInQueryPage"
- $ref: "#/parameters/PaginationInQuerySize"
- $ref: "#/parameters/ReversedInQuery"
- $ref: "#/parameters/ValueInQuery"
- $ref: "#/components/parameters/PaginationInQueryPage"
- $ref: "#/components/parameters/PaginationInQuerySize"
- $ref: "#/components/parameters/ReversedInQuery"
- $ref: "#/components/parameters/ValueInQuery"
required: false
responses:
"200":
description: "Pagination with elements"
schema:
allOf:
- $ref: "#/definitions/PaginationResult"
- properties:
results:
items:
$ref: "#/definitions/Key"
content:
"*/*":
schema:
allOf:
- $ref: "#/components/schemas/PaginationResult"
- properties:
results:
items:
$ref: "#/components/schemas/Key"
/contains:
get:
tags:
- "Read"
parameters:
- $ref: "#/parameters/KeyInQuery"
- $ref: "#/components/parameters/KeyInQuery"
required: true
responses:
"200":
description: "Object with id availability in repo"
schema:
type: boolean
content:
"*/*":
schema:
type: boolean
/count:
get:
tags:
@@ -159,19 +150,23 @@ paths:
responses:
"200":
description: "Amount of objects in repo"
schema:
type: integer
content:
"*/*":
schema:
type: integer
/set:
post:
tags:
- "Write"
parameters:
- allOf:
- $ref: "#/parameters/MapInBody"
- additionalProperties:
$ref: "#/definitions/Value"
requestBody:
content:
"*/*":
schema:
type: object
additionalProperties:
$ref: "#/components/schemas/Value"
description: "Map with new elements to set. Use keys as a keys of this map"
responses:
"200":
@@ -180,8 +175,13 @@ paths:
post:
tags:
- "Write"
parameters:
- $ref: "#/parameters/KeysInBody"
requestBody:
content:
"*/*":
schema:
type: array
items:
$ref: "#/components/schemas/Key"
responses:
"200":
description: "Objects with keys from body has been unset"
@@ -189,8 +189,13 @@ paths:
post:
tags:
- "Write"
parameters:
- $ref: "#/parameters/ValuesInBody"
requestBody:
content:
"*/*":
schema:
type: array
items:
$ref: "#/components/schemas/Value"
responses:
"200":
description: "Objects with values from body has been unset"

View File

@@ -51,7 +51,7 @@ inline fun <reified Key, reified Value> Route.configureReadKeyValueRepoRoutes (
get(keysRoute) {
val pagination = call.request.queryParameters.extractPagination
val reversed = call.getQueryParameterOrSendError(reversedParameterName) ?.toBoolean() ?: false
val reversed = call.getQueryParameter(reversedParameterName) ?.toBoolean() ?: false
val value = call.getQueryParameter(valueParameterName) ?.let {
valueDeserializer(it)
}

View File

@@ -42,7 +42,7 @@ inline fun <reified Key, reified Value> Route.configureReadKeyValuesRepoRoutes (
get(keysRoute) {
val pagination = call.request.queryParameters.extractPagination
val reversed = call.getQueryParameterOrSendError(reversedParameterName) ?.toBoolean() ?: false
val reversed = call.getQueryParameter(reversedParameterName) ?.toBoolean() ?: false
val value = call.getQueryParameter(valueParameterName) ?.let {
valueDeserializer(it)
}