pixeluvw_supabase 0.1.0

A production-ready, high-performance Supabase SDK for Rust with middleware, retry logic, and Arc<Inner> architecture
Documentation
use crate::core::Session;
use crate::error::Result;
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};

/// Trait for persisting sessions.
pub trait SessionStore: Send + Sync {
    /// Save the session.
    fn save(&self, session: &Session) -> Result<()>;
    /// Load the session.
    fn load(&self) -> Result<Option<Session>>;
    /// Delete the session.
    fn delete(&self) -> Result<()>;
}

/// A simple file-based session store.
///
/// Saves the session as JSON to a specified path.
#[derive(Debug)]
pub struct FileSessionStore {
    path: PathBuf,
}

impl FileSessionStore {
    pub fn new<P: AsRef<Path>>(path: P) -> Self {
        Self {
            path: path.as_ref().to_path_buf(),
        }
    }
}

impl SessionStore for FileSessionStore {
    fn save(&self, session: &Session) -> Result<()> {
        let json = serde_json::to_string(session).map_err(|e| crate::SupaError::ClientError {
            message: format!("Failed to serialize session: {}", e),
        })?;

        if let Some(parent) = self.path.parent() {
            fs::create_dir_all(parent).map_err(|e| crate::SupaError::ClientError {
                message: format!("Failed to create session dir: {}", e),
            })?;
        }

        fs::write(&self.path, json).map_err(|e| crate::SupaError::ClientError {
            message: format!("Failed to write session file: {}", e),
        })?;
        Ok(())
    }

    fn load(&self) -> Result<Option<Session>> {
        if !self.path.exists() {
            return Ok(None);
        }

        let json = fs::read_to_string(&self.path).map_err(|e| crate::SupaError::ClientError {
            message: format!("Failed to read session file: {}", e),
        })?;

        let session: Session =
            serde_json::from_str(&json).map_err(|e| crate::SupaError::ClientError {
                message: format!("Failed to deserialize session: {}", e),
            })?;

        Ok(Some(session))
    }

    fn delete(&self) -> Result<()> {
        if self.path.exists() {
            fs::remove_file(&self.path).map_err(|e| crate::SupaError::ClientError {
                message: format!("Failed to delete session file: {}", e),
            })?;
        }
        Ok(())
    }
}

/// A thread-safe in-memory session store (mostly for testing).
#[derive(Debug, Default)]
pub struct MemorySessionStore {
    session: Arc<Mutex<Option<Session>>>,
}

impl MemorySessionStore {
    pub fn new() -> Self {
        Self {
            session: Arc::new(Mutex::new(None)),
        }
    }
}

impl SessionStore for MemorySessionStore {
    fn save(&self, session: &Session) -> Result<()> {
        let mut lock = self.session.lock().unwrap();
        *lock = Some(session.clone());
        Ok(())
    }

    fn load(&self) -> Result<Option<Session>> {
        let lock = self.session.lock().unwrap();
        Ok(lock.clone())
    }

    fn delete(&self) -> Result<()> {
        let mut lock = self.session.lock().unwrap();
        *lock = None;
        Ok(())
    }
}