use crate::config::CliConfig; use crate::util::prelude::*; use anyhow::Result; use sd_core::client::CoreClient; use std::path::PathBuf; use uuid::Uuid; #[derive(Debug, Clone, Copy, clap::ValueEnum)] pub enum OutputFormat { Human, Json, } #[derive(Clone)] pub struct Context { pub core: CoreClient, pub format: OutputFormat, pub data_dir: PathBuf, pub socket_path: PathBuf, pub library_id: Option, pub cli_config: CliConfig, } impl Context { pub fn new( core: CoreClient, format: OutputFormat, data_dir: PathBuf, socket_path: PathBuf, ) -> Result { let cli_config = CliConfig::load(&data_dir)?; let library_id = cli_config.current_library_id; Ok(Self { core, format, data_dir, socket_path, library_id, cli_config, }) } pub fn with_library_id(mut self, library_id: Uuid) -> Self { self.library_id = Some(library_id); self } pub fn set_library_id(&mut self, library_id: Uuid) -> Result<()> { self.library_id = Some(library_id); self.cli_config .set_current_library(library_id, &self.data_dir) } /// Get the current library ID pub fn get_current_library_id(&self) -> Option { self.library_id } /// Set the current library by ID pub fn set_current_library(&mut self, library_id: Uuid) -> Result<()> { self.library_id = Some(library_id); self.cli_config .set_current_library(library_id, &self.data_dir) } /// Clear the current library pub fn clear_current_library(&mut self) -> Result<()> { self.library_id = None; self.cli_config.clear_current_library(&self.data_dir) } /// Switch to a library by ID pub fn switch_to_library(&mut self, library_id: Uuid) -> Result<()> { self.library_id = Some(library_id); self.cli_config .set_current_library(library_id, &self.data_dir) } /// Switch to a library by name pub async fn switch_to_library_named(&mut self, name: &str) -> Result<()> { let libs: Vec = execute_core_query!( self, sd_core::ops::libraries::list::query::ListLibrariesInput { include_stats: false } ); if let Some(lib) = libs.iter().find(|lib| lib.name == name) { self.library_id = Some(lib.id); self.cli_config .set_current_library(lib.id, &self.data_dir)?; Ok(()) } else { anyhow::bail!("Library '{}' not found", name) } } /// Get current library info pub async fn get_current_library_info( &self, ) -> Result> { if let Some(_library_id) = self.library_id { let input = sd_core::ops::libraries::info::query::LibraryInfoQueryInput {}; let info: sd_core::ops::libraries::info::output::LibraryInfoOutput = execute_query!(self, input); Ok(Some(info)) } else { Ok(None) } } /// Require a current library (error if none set) pub fn require_current_library(&self) -> Result { self.library_id.ok_or_else(|| { anyhow::anyhow!("No library selected. Use 'sd library switch' to select a library.") }) } /// Get current library ID or throw error pub fn get_current_library_id_or_throw(&self) -> Result { self.require_current_library() } /// Create a new library and optionally switch to it pub async fn create_and_switch_to_library( &mut self, name: String, path: PathBuf, set_as_current: bool, ) -> Result { let input = sd_core::ops::libraries::create::input::LibraryCreateInput { name: name.clone(), path: Some(path), }; let output: sd_core::ops::libraries::create::output::LibraryCreateOutput = execute_action!(self, input); if set_as_current { self.library_id = Some(output.library_id); } Ok(output.library_id) } /// Get current library jobs with optional status filter pub async fn get_current_library_jobs( &self, status: Option, ) -> Result> { let library_id = self.require_current_library()?; let input = sd_core::ops::jobs::list::query::JobListInput { status }; let output: sd_core::ops::jobs::list::output::JobListOutput = execute_query!(self, input); Ok(output.jobs) } /// Get current library status pub async fn get_current_library_status( &self, ) -> Result> { self.get_current_library_info().await } /// Check if there's an active library pub fn has_active_library(&self) -> bool { self.library_id.is_some() } /// List all available libraries pub async fn list_libraries( &self, ) -> Result> { let input = sd_core::ops::libraries::list::query::ListLibrariesInput { include_stats: false, }; let output: Vec = execute_core_query!(self, input); Ok(output) } }