rust_supabase_sdk 0.2.17

An SDK kit for SupaBase so that Rust lovers can use SupaBase with the low level abstracted away. If you want new features tell me and I'll add them.
Documentation
use std::time::Duration;

use reqwest::{Client, StatusCode};
use serde_json::Value;
use crate::SupabaseClient;



pub enum HttpMethod {
    Get,
    Post,
    Put,
    Patch,
    Delete,
}

impl SupabaseClient {
    pub async fn request(
        &self,
        path: &str,
        method: HttpMethod,
        payload: Option<Value>,
        upsert: bool,
    ) -> Result<Value, String> {
        let client = Client::new();
        let max_retries = 5;

        for attempt in 0..=max_retries {
            let req_url = format!("{}{}", self.url, path);
            let mut req = match method {
                HttpMethod::Get => client.get(&req_url),
                HttpMethod::Post => client.post(&req_url),
                HttpMethod::Put => client.put(&req_url),
                HttpMethod::Patch => client.patch(&req_url),
                HttpMethod::Delete => client.delete(&req_url),
            }
            .bearer_auth(&self.api_key)
            .header("apikey", &self.api_key);

            if upsert {
                req = req.header("Prefer", "resolution=merge-duplicates");
            }

            if let Some(ref data) = payload {
                req = req.json(data);
            }

            match req.send().await {
                Ok(resp) => {
                    let status = resp.status();

                    if status == StatusCode::TOO_MANY_REQUESTS && attempt < max_retries {
                        tokio::time::sleep(Duration::from_millis(50 * 2_u64.pow(attempt))).await;
                        continue;
                    }

                    if !status.is_success() {
                        let body = resp.text().await.unwrap_or_else(|_| "".into());
                        return Err(format!(
                            "HTTP error {} on path {}\nPayload: {:#?}\nBody: {}",
                            status, path, payload, body
                        ));
                    }

                    let text = resp
                        .text()
                        .await
                        .map_err(|e| format!("Failed to read response: {:?}", e))?;

                    return if text.is_empty() {
                        Ok(Value::Null)
                    } else {
                        serde_json::from_str(&text)
                            .map_err(|e| format!("JSON parse error: {:?}", e))
                    };
                }

                Err(e) => return Err(format!("Request error: {:?}", e)),
            }
        }

        Err("Exceeded max retries".into())
    }
}