From ea4df6c0010af26b34305569eaf23483b25dc214 Mon Sep 17 00:00:00 2001 From: Robert Jaros Date: Sat, 2 Nov 2019 11:50:39 +0100 Subject: New set of methods returning Response object in RestClient (#100) --- .../kotlin/pl/treksoft/kvision/rest/RestClient.kt | 322 +++++++++++++++++++-- 1 file changed, 290 insertions(+), 32 deletions(-) (limited to 'src/main/kotlin/pl/treksoft') diff --git a/src/main/kotlin/pl/treksoft/kvision/rest/RestClient.kt b/src/main/kotlin/pl/treksoft/kvision/rest/RestClient.kt index 9ccfc38f..49222298 100644 --- a/src/main/kotlin/pl/treksoft/kvision/rest/RestClient.kt +++ b/src/main/kotlin/pl/treksoft/kvision/rest/RestClient.kt @@ -32,8 +32,6 @@ import pl.treksoft.jquery.jQuery import pl.treksoft.kvision.utils.JSON.toObj import pl.treksoft.kvision.utils.obj import kotlin.js.Promise -import kotlin.js.then -import kotlin.js.undefined import kotlin.js.JSON as NativeJSON enum class HttpMethod { @@ -44,6 +42,11 @@ enum class HttpMethod { OPTIONS } +/** + * A response wrapper + */ +data class Response(val data: T, val textStatus: String, val jqXHR: JQueryXHR) + /** * HTTP status unauthorized (401). */ @@ -54,8 +57,6 @@ const val HTTP_UNAUTHORIZED = 401 */ open class RestClient { - private var counter = 1 - /** * Makes a remote call to the remote server. * @param url an URL address @@ -73,34 +74,7 @@ open class RestClient { contentType: String = "application/json", beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null ): Promise { - return Promise { resolve, reject -> - jQuery.ajax(url, obj { - this.contentType = if (contentType != "multipart/form-data") contentType else false - this.data = data - this.method = method.name - this.processData = if (contentType != "multipart/form-data") undefined else false - this.success = - { data: dynamic, _: Any, _: Any -> - resolve(data) - } - this.error = - { xhr: JQueryXHR, _: String, errorText: String -> - val message = if (xhr.responseJSON != null && xhr.responseJSON != undefined) { - NativeJSON.stringify(xhr.responseJSON) - } else if (xhr.responseText != undefined) { - xhr.responseText - } else { - errorText - } - if (xhr.status.toInt() == HTTP_UNAUTHORIZED) { - reject(SecurityException(message)) - } else { - reject(Exception(message)) - } - } - this.beforeSend = beforeSend - }) - } + return remoteRequest(url, data, method, contentType, beforeSend).then { it.data } } /** @@ -332,4 +306,288 @@ open class RestClient { transform ) } + + /** + * Makes a remote call to the remote server. + * @param url an URL address + * @param data data to be sent + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @return a promise of the response + */ + @Suppress("UnsafeCastFromDynamic", "ComplexMethod") + fun remoteRequest( + url: String, + data: dynamic = null, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null + ): Promise> { + return Promise { resolve, reject -> + jQuery.ajax(url, obj { + this.contentType = if (contentType != "multipart/form-data") contentType else false + this.data = data + this.method = method.name + this.processData = if (contentType != "multipart/form-data") undefined else false + this.success = + { data: dynamic, textStatus: String, jqXHR: JQueryXHR -> + resolve(Response(data, textStatus, jqXHR)) + } + this.error = + { xhr: JQueryXHR, _: String, errorText: String -> + val message = if (xhr.responseJSON != null && xhr.responseJSON != undefined) { + NativeJSON.stringify(xhr.responseJSON) + } else if (xhr.responseText != undefined) { + xhr.responseText + } else { + errorText + } + if (xhr.status.toInt() == HTTP_UNAUTHORIZED) { + reject(SecurityException(message)) + } else { + reject(Exception(message)) + } + } + this.beforeSend = beforeSend + }) + } + } + + + /** + * Makes a remote call to the remote server. + * @param url an URL address + * @param data data to be sent + * @param deserializer a deserializer for the result value + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @param transform a function to transform the result of the call + * @return a promise of the response + */ + fun remoteRequest( + url: String, + data: dynamic = null, + deserializer: DeserializationStrategy, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null, + transform: ((dynamic) -> dynamic)? = null + ): Promise> { + return remoteRequest(url, data, method, contentType, beforeSend).then { result: Response -> + val transformed = if (transform != null) { + transform(result.data) + } else { + result.data + } + Response(DynamicObjectParser().parse(transformed, deserializer), result.textStatus, result.jqXHR) + } + } + + /** + * Makes a remote call to the remote server. + * @param url an URL address + * @param serializer for the data + * @param data data to be sent + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @return a promise of the response + */ + fun remoteRequest( + url: String, + serializer: SerializationStrategy, + data: V, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null + ): Promise> { + return remoteRequest(url, data.toObj(serializer), method, contentType, beforeSend) + } + + + /** + * Makes a remote call to the remote server. + * @param url an URL address + * @param serializer for the data + * @param data data to be sent + * @param deserializer a deserializer for the result value + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @param transform a function to transform the result of the call + * @return a promise of the response + */ + fun remoteRequest( + url: String, + serializer: SerializationStrategy, + data: V, + deserializer: DeserializationStrategy, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null, + transform: ((dynamic) -> dynamic)? = null + ): Promise> { + return remoteRequest( + url, + data.toObj(serializer), + method, + contentType, + beforeSend + ).then { result: Response -> + val transformed = if (transform != null) { + transform(result.data) + } else { + result.data + } + Response(DynamicObjectParser().parse(transformed, deserializer), result.textStatus, result.jqXHR) + } + } + + /** + * Helper inline function to automatically get deserializer for the result value with dynamic data. + * @param url an URL address + * @param data data to be sent + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @param transform a function to transform the result of the call + * @return a promise of the response + */ + @UseExperimental(ImplicitReflectionSerializer::class) + inline fun request( + url: String, + data: dynamic = null, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + noinline beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null, + noinline transform: ((dynamic) -> dynamic)? = null + ): Promise> { + return remoteRequest(url, data, T::class.serializer(), method, contentType, beforeSend, transform) + } + + /** + * Helper inline function to automatically get serializer for the data. + * @param url an URL address + * @param data data to be sent + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @return a promise of the response + */ + @UseExperimental(ImplicitReflectionSerializer::class) + inline fun request( + url: String, + data: V, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + noinline beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null + ): Promise> { + return remoteRequest( + url, + V::class.serializer(), + data, + method, + contentType, + beforeSend + ) + } + + /** + * Helper inline function to automatically get serializer for the data. + * @param url an URL address + * @param data data to be sent + * @param deserializer a deserializer for the result value + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @param transform a function to transform the result of the call + * @return a promise of the response + */ + @UseExperimental(ImplicitReflectionSerializer::class) + inline fun request( + url: String, + data: V, + deserializer: DeserializationStrategy, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + noinline beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null, + noinline transform: ((dynamic) -> dynamic)? = null + ): Promise> { + return remoteRequest( + url, + V::class.serializer(), + data, + deserializer, + method, + contentType, + beforeSend, + transform + ) + } + + /** + * Helper inline function to automatically deserializer for the result value with typed data. + * @param url an URL address + * @param serializer for the data + * @param data data to be sent + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @param transform a function to transform the result of the call + * @return a promise of the response + */ + @UseExperimental(ImplicitReflectionSerializer::class) + inline fun request( + url: String, + serializer: SerializationStrategy, + data: V, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + noinline beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null, + noinline transform: ((dynamic) -> dynamic)? = null + ): Promise> { + return remoteRequest( + url, + serializer, + data, + T::class.serializer(), + method, + contentType, + beforeSend, + transform + ) + } + + /** + * Helper inline function to automatically get serializer for the data and deserializer for the result value. + * @param url an URL address + * @param data data to be sent + * @param method a HTTP method + * @param contentType a content type of the request + * @param beforeSend a content type of the request + * @param transform a function to transform the result of the call + * @return a promise of the response + */ + @UseExperimental(ImplicitReflectionSerializer::class) + inline fun request( + url: String, + data: V, + method: HttpMethod = HttpMethod.GET, + contentType: String = "application/json", + noinline beforeSend: ((JQueryXHR, JQueryAjaxSettings) -> Boolean)? = null, + noinline transform: ((dynamic) -> dynamic)? = null + ): Promise> { + return remoteRequest( + url, + V::class.serializer(), + data, + T::class.serializer(), + method, + contentType, + beforeSend, + transform + ) + } } -- cgit