All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.ferhatwi.supabase.database.Utils.kt Maven / Gradle / Ivy

Go to download

Some experiments on Kotlin client for Supabase Database, currently in development phase.

There is a newer version: 0.4.0
Show newest version
package io.github.ferhatwi.supabase.database

import io.github.ferhatwi.supabase.Supabase
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.cio.*
import io.ktor.client.features.*
import io.ktor.client.features.json.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.client.utils.*
import io.ktor.http.*

internal fun databaseURL() = "https://${Supabase.PROJECT_ID}.supabase.co/rest/v1"

internal fun getClient(): HttpClient {
    return HttpClient(CIO) {
        install(JsonFeature) {
            serializer = GsonSerializer()
        }
    }
}


internal suspend inline fun  HttpClient.request(
    schema: String,
    url: String,
    method: HttpMethod,
    range: Pair? = null,
    count: Count? = null,
    body: Any = EmptyContent,
    merge: Boolean = false,
    noinline headers: HeadersBuilder.() -> Unit = {}
): T {
    return request(url) {
        this.method = method
        this.body = body
        headers {
            profile(method, schema)
            apiKey()
            authorize()
            range(range)
            preference(count, url.contains("select"), merge)
            headers()
        }
    }
}

internal fun HttpRequestBuilder.profile(httpMethod: HttpMethod, name: String) {
    if (name != "public") headers.append(
        if (httpMethod == HttpMethod.Get || httpMethod == HttpMethod.Head) "Accept-Profile" else "Content-Profile",
        name
    )
}

internal fun HttpRequestBuilder.apiKey() {
    headers.append("apikey", Supabase.API_KEY)
}

internal fun HttpRequestBuilder.authorize() {
    headers.append(HttpHeaders.Authorization, "Bearer ${Supabase.AUTHORIZATION}")
}

internal fun HttpRequestBuilder.range(range: Pair?) {
    if (range != null) headers.append(HttpHeaders.Range, "${range.first}-${range.second}")
}

internal fun HttpRequestBuilder.preference(count: Count?, representation: Boolean, merge: Boolean) {
    val array = mutableListOf()
    if (count != null) {
        array.add("count=$count")
    }
    if (representation) {
        array.add("return=representation")
    }
    if (merge) {
        array.add("resolution=merge-duplicates")
    }
    headers.append(HttpHeaders.Prefer, array.joinToString(separator = ","))
}

internal fun HeadersBuilder.applicationJson() {
    append(HttpHeaders.ContentType, "application/json")
}


internal suspend inline fun  runCatching(
    block: () -> HttpResponse,
    onSuccess: (T) -> Unit,
    defaultValueForNoTransformation: T,
    head: Boolean = false
) = runCatching {
    if (head) {
        block()
        onSuccess(defaultValueForNoTransformation)
    } else onSuccess(block().receive())
}.getOrElse {
    when (it) {
        is ResponseException -> {
            val map: Map = it.response.receive()
            val message = map["message"] as String?
            val code = map["code"] as String?
            val statusCode = it.response
            throw SupabaseDatabaseException("$message $code, $statusCode")
        }
        is NoTransformationFoundException -> onSuccess(defaultValueForNoTransformation)
        else -> throw it
    }
}


@JvmName("asQueryStringSelect")
internal fun List.asQueryString() = if (isEmpty()) {
    ""
} else {
    "select=${joinToString(separator = "&")}"
}


@JvmName("asQueryStringFilter")
internal fun MutableList.asQueryString() = if (isEmpty()) {
    ""
} else {
    joinToString("&") {
        it.toString()
    }
}


@JvmName("asQueryStringOrder")
internal fun MutableList.asQueryString() = if (isEmpty()) {
    ""
} else {
    joinToString("&") {
        it.toString()
    }
}

internal fun limitToString(limit: Int?) = if (limit == null) "" else "limit=$limit"

internal fun appendQueryString(vararg queryStrings: String) = queryStrings.toMutableList().apply {
    removeIf {
        it.isEmpty()
    }
}.joinToString(separator = "&")




© 2015 - 2025 Weber Informatics LLC | Privacy Policy