pupoxide 0.2.0

A high-performance, memory-safe, declarative configuration management tool inspired by Puppet.
use crate::domain::{
    Transaction,
    error::{DomainError, Result},
};
use std::fs;
use std::path::PathBuf;

pub struct StateStore {
    root: PathBuf,
}

impl StateStore {
    pub fn new(root: PathBuf) -> Self {
        Self { root }
    }

    pub fn save_transaction(&self, transaction: &Transaction) -> Result<()> {
        let path = self.get_transaction_path(&transaction.id);
        if let Some(parent) = path.parent() {
            fs::create_dir_all(parent)
                .map_err(|e| DomainError::Internal(format!("Failed to create state dir: {}", e)))?;
        }
        let json = serde_json::to_string_pretty(transaction).map_err(|e| {
            DomainError::Internal(format!("Failed to serialize transaction: {}", e))
        })?;
        fs::write(path, json)
            .map_err(|e| DomainError::Internal(format!("Failed to write transaction: {}", e)))?;

        // Update 'latest' pointer
        let latest_path = self.root.join("latest_transaction");
        fs::write(latest_path, &transaction.id).map_err(|e| {
            DomainError::Internal(format!("Failed to update latest transaction: {}", e))
        })?;

        Ok(())
    }

    pub fn load_transaction(&self, id: &str) -> Result<Transaction> {
        let path = self.get_transaction_path(id);
        let json = fs::read_to_string(path).map_err(|e| {
            DomainError::Internal(format!("Failed to read transaction {}: {}", id, e))
        })?;
        serde_json::from_str(&json)
            .map_err(|e| DomainError::Internal(format!("Failed to deserialize transaction: {}", e)))
    }

    pub fn load_latest_transaction(&self) -> Result<Transaction> {
        let latest_path = self.root.join("latest_transaction");
        let id = fs::read_to_string(latest_path)
            .map_err(|e| DomainError::Internal(format!("No previous transaction found: {}", e)))?;
        self.load_transaction(id.trim())
    }

    fn get_transaction_path(&self, id: &str) -> PathBuf {
        self.root.join("transactions").join(format!("{}.json", id))
    }
}