From 436188c75ddfe72ef833afc76fdfd47305f74bef Mon Sep 17 00:00:00 2001 From: nbransby Date: Thu, 28 Sep 2023 17:05:40 +0700 Subject: [PATCH] add code to FirebaseFunctionsException --- .../gitlive/firebase/functions/functions.kt | 5 ++ .../gitlive/firebase/functions/functions.kt | 23 +++++++ .../gitlive/firebase/functions/functions.kt | 65 ++++++++++++++++--- .../gitlive/firebase/functions/functions.kt | 56 +++++++++++++++- 4 files changed, 136 insertions(+), 13 deletions(-) diff --git a/firebase-functions/src/androidMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/androidMain/kotlin/dev/gitlive/firebase/functions/functions.kt index 16acdc7a1..3a44f3ed0 100644 --- a/firebase-functions/src/androidMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/androidMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -52,3 +52,8 @@ actual class HttpsCallableResult constructor(val android: com.google.firebase.fu } actual typealias FirebaseFunctionsException = com.google.firebase.functions.FirebaseFunctionsException + +actual val FirebaseFunctionsException.code: FunctionsExceptionCode get() = code + +actual typealias FunctionsExceptionCode = com.google.firebase.functions.FirebaseFunctionsException.Code + diff --git a/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt index f1f3a225a..6b8878d7f 100644 --- a/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -39,3 +39,26 @@ expect fun Firebase.functions(app: FirebaseApp): FirebaseFunctions expect fun Firebase.functions(app: FirebaseApp, region: String): FirebaseFunctions expect class FirebaseFunctionsException: FirebaseException + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +expect val FirebaseFunctionsException.code: FunctionsExceptionCode + +expect enum class FunctionsExceptionCode { + OK, + CANCELLED, + UNKNOWN, + INVALID_ARGUMENT, + DEADLINE_EXCEEDED, + NOT_FOUND, + ALREADY_EXISTS, + PERMISSION_DENIED, + RESOURCE_EXHAUSTED, + FAILED_PRECONDITION, + ABORTED, + OUT_OF_RANGE, + UNIMPLEMENTED, + INTERNAL, + UNAVAILABLE, + DATA_LOSS, + UNAUTHENTICATED +} diff --git a/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt index e705ca9ab..179741de3 100644 --- a/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/iosMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -4,16 +4,14 @@ package dev.gitlive.firebase.functions -import cocoapods.FirebaseFunctions.* -import dev.gitlive.firebase.Firebase -import dev.gitlive.firebase.FirebaseApp -import dev.gitlive.firebase.FirebaseException -import dev.gitlive.firebase.decode -import dev.gitlive.firebase.encode +import cocoapods.FirebaseFunctions.FIRFunctions +import cocoapods.FirebaseFunctions.FIRHTTPSCallable +import cocoapods.FirebaseFunctions.FIRHTTPSCallableResult +import dev.gitlive.firebase.* import kotlinx.coroutines.CompletableDeferred import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy -import platform.Foundation.* +import platform.Foundation.NSError actual val Firebase.functions get() = FirebaseFunctions(FIRFunctions.functions()) @@ -58,7 +56,54 @@ actual class HttpsCallableResult constructor(val ios: FIRHTTPSCallableResult) { decode(strategy, ios.data()) } -actual class FirebaseFunctionsException(message: String): FirebaseException(message) +actual class FirebaseFunctionsException(message: String, val code: FunctionsExceptionCode) : FirebaseException(message) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +actual val FirebaseFunctionsException.code: FunctionsExceptionCode get() = code + +actual enum class FunctionsExceptionCode { + OK, + CANCELLED, + UNKNOWN, + INVALID_ARGUMENT, + DEADLINE_EXCEEDED, + NOT_FOUND, + ALREADY_EXISTS, + PERMISSION_DENIED, + RESOURCE_EXHAUSTED, + FAILED_PRECONDITION, + ABORTED, + OUT_OF_RANGE, + UNIMPLEMENTED, + INTERNAL, + UNAVAILABLE, + DATA_LOSS, + UNAUTHENTICATED +} +//todo uncomment once https://github.com/firebase/firebase-ios-sdk/issues/11862 fixed +fun NSError.toException() = when(domain) { +// FIRFunctionsErrorDomain -> when(code) { +// FIRFunctionsErrorCodeOK -> FunctionsExceptionCode.OK +// FIRFunctionsErrorCodeCancelled -> FunctionsExceptionCode.CANCELLED +// FIRFunctionsErrorCodeUnknown -> FunctionsExceptionCode.UNKNOWN +// FIRFunctionsErrorCodeInvalidArgument -> FunctionsExceptionCode.INVALID_ARGUMENT +// FIRFunctionsErrorCodeDeadlineExceeded -> FunctionsExceptionCode.DEADLINE_EXCEEDED +// FIRFunctionsErrorCodeNotFound -> FunctionsExceptionCode.NOT_FOUND +// FIRFunctionsErrorCodeAlreadyExists -> FunctionsExceptionCode.ALREADY_EXISTS +// FIRFunctionsErrorCodePermissionDenied -> FunctionsExceptionCode.PERMISSION_DENIED +// FIRFunctionsErrorCodeResourceExhausted -> FunctionsExceptionCode.RESOURCE_EXHAUSTED +// FIRFunctionsErrorCodeFailedPrecondition -> FunctionsExceptionCode.FAILED_PRECONDITION +// FIRFunctionsErrorCodeAborted -> FunctionsExceptionCode.ABORTED +// FIRFunctionsErrorCodeOutOfRange -> FunctionsExceptionCode.OUT_OF_RANGE +// FIRFunctionsErrorCodeUnimplemented -> FunctionsExceptionCode.UNIMPLEMENTED +// FIRFunctionsErrorCodeInternal -> FunctionsExceptionCode.INTERNAL +// FIRFunctionsErrorCodeUnavailable -> FunctionsExceptionCode.UNAVAILABLE +// FIRFunctionsErrorCodeDataLoss -> FunctionsExceptionCode.DATA_LOSS +// FIRFunctionsErrorCodeUnauthenticated -> FunctionsExceptionCode.UNAUTHENTICATED +// else -> FunctionsExceptionCode.UNKNOWN +// } + else -> FunctionsExceptionCode.UNKNOWN +}.let { FirebaseFunctionsException(description!!, it) } suspend inline fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { val job = CompletableDeferred() @@ -66,7 +111,7 @@ suspend inline fun T.await(function: T.(callback: (NSError?) -> Unit) -> Uni if(error == null) { job.complete(Unit) } else { - job.completeExceptionally(FirebaseFunctionsException(error.localizedDescription)) + job.completeExceptionally(error.toException()) } } job.await() @@ -78,7 +123,7 @@ suspend inline fun T.awaitResult(function: T.(callback: (R?, NSEr if(error == null) { job.complete(result) } else { - job.completeExceptionally(FirebaseFunctionsException(error.localizedDescription)) + job.completeExceptionally(error.toException()) } } return job.await() as R diff --git a/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt index 419deb7ce..e6aba296d 100644 --- a/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -9,7 +9,6 @@ import dev.gitlive.firebase.functions.externals.* import kotlinx.coroutines.await import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy -import org.w3c.dom.url.URL import kotlin.js.json import dev.gitlive.firebase.functions.externals.HttpsCallableResult as JsHttpsCallableResult @@ -55,7 +54,30 @@ actual class HttpsCallableResult constructor(val js: JsHttpsCallableResult) { } -actual open class FirebaseFunctionsException(code: String?, cause: Throwable): FirebaseException(code, cause) +actual class FirebaseFunctionsException(cause: Throwable, val code: FunctionsExceptionCode) : FirebaseException(code.toString(), cause) + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +actual val FirebaseFunctionsException.code: FunctionsExceptionCode get() = code + +actual enum class FunctionsExceptionCode { + OK, + CANCELLED, + UNKNOWN, + INVALID_ARGUMENT, + DEADLINE_EXCEEDED, + NOT_FOUND, + ALREADY_EXISTS, + PERMISSION_DENIED, + RESOURCE_EXHAUSTED, + FAILED_PRECONDITION, + ABORTED, + OUT_OF_RANGE, + UNIMPLEMENTED, + INTERNAL, + UNAVAILABLE, + DATA_LOSS, + UNAUTHENTICATED +} inline fun T.rethrow(function: T.() -> R): R = dev.gitlive.firebase.functions.rethrow { function() } @@ -65,6 +87,34 @@ inline fun rethrow(function: () -> R): R { } catch (e: Exception) { throw e } catch(e: dynamic) { - throw FirebaseFunctionsException(e.code as String?, e) + throw errorToException(e) } } + +fun errorToException(e: dynamic) = (e?.code ?: e?.message ?: "") + .toString() + .lowercase() + .let { + when { + "cancelled" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.CANCELLED) + "invalid-argument" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.INVALID_ARGUMENT) + "deadline-exceeded" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.DEADLINE_EXCEEDED) + "not-found" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.NOT_FOUND) + "already-exists" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.ALREADY_EXISTS) + "permission-denied" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.PERMISSION_DENIED) + "resource-exhausted" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.RESOURCE_EXHAUSTED) + "failed-precondition" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.FAILED_PRECONDITION) + "aborted" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.ABORTED) + "out-of-range" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.OUT_OF_RANGE) + "unimplemented" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.UNIMPLEMENTED) + "internal" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.INTERNAL) + "unavailable" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.UNAVAILABLE) + "data-loss" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.DATA_LOSS) + "unauthenticated" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.UNAUTHENTICATED) + "unknown" in it -> FirebaseFunctionsException(e, FunctionsExceptionCode.UNKNOWN) + else -> { + println("Unknown error code in ${JSON.stringify(e)}") + FirebaseFunctionsException(e, FunctionsExceptionCode.UNKNOWN) + } + } + }