Skip to main content

dioxus_cloudflare/
error.rs

1//! Error bridge between `worker::Error` and Dioxus `ServerFnError`.
2//!
3//! Rust's orphan rule prevents implementing `From<worker::Error> for ServerFnError`
4//! directly since neither type is defined in this crate. The [`CfError`] newtype
5//! and [`CfResultExt`] trait provide an ergonomic workaround.
6
7use std::fmt;
8
9/// Newtype wrapper around [`worker::Error`] that implements conversion to
10/// `ServerFnError`.
11///
12/// Use the [`.cf()`](CfResultExt::cf) method on `worker::Result<T>` instead
13/// of constructing this directly.
14#[derive(Debug)]
15pub struct CfError(pub worker::Error);
16
17impl fmt::Display for CfError {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        write!(f, "Worker error: {}", self.0)
20    }
21}
22
23impl std::error::Error for CfError {}
24
25impl From<CfError> for crate::ServerFnError {
26    fn from(e: CfError) -> Self {
27        Self::new(e.to_string())
28    }
29}
30
31impl From<CfError> for worker::Error {
32    fn from(e: CfError) -> Self {
33        e.0
34    }
35}
36
37/// Extension trait for `worker::Result<T>` that converts errors into a type
38/// compatible with `ServerFnError` via the `?` operator.
39///
40/// # Example
41///
42/// ```rust,ignore
43/// use dioxus_cloudflare::prelude::*;
44///
45/// #[server]
46/// pub async fn get_count() -> Result<i64, ServerFnError> {
47///     let kv = cf::env().kv("COUNTS").cf()?;
48///     let val = kv.get("total").text().await.cf()?;
49///     Ok(val.unwrap_or_default().parse().unwrap_or(0))
50/// }
51/// ```
52pub trait CfResultExt<T> {
53    /// Convert a `worker::Result<T>` into `Result<T, CfError>`, which can
54    /// then be propagated with `?` into any function returning
55    /// `Result<_, ServerFnError>`.
56    fn cf(self) -> Result<T, CfError>;
57}
58
59impl<T> CfResultExt<T> for Result<T, worker::Error> {
60    fn cf(self) -> Result<T, CfError> {
61        self.map_err(CfError)
62    }
63}
64
65impl<T> CfResultExt<T> for Result<T, worker::kv::KvError> {
66    fn cf(self) -> Result<T, CfError> {
67        self.map_err(|e| CfError(e.into()))
68    }
69}