mod prompts;
mod templates;
mod validation;
mod wizard;
pub use templates::{ConfigTemplate, TemplateRegistry};
pub use wizard::{SetupMode, SetupResult, apply_template, run_setup_wizard};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum OnboardingError {
#[error("User cancelled setup")]
Cancelled,
#[error("Template not found: {0}")]
TemplateNotFound(String),
#[error("Validation failed: {0}")]
Validation(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error(
"Not a TTY - interactive mode requires a terminal. Use --template for non-interactive mode."
)]
#[allow(dead_code)]
NotATty,
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("Path does not exist: {0}")]
PathNotFound(String),
#[error("User navigated back")]
NavigateBack,
#[error("Prompt error: {0}")]
Prompt(String),
}
impl From<dialoguer::Error> for OnboardingError {
fn from(err: dialoguer::Error) -> Self {
if err.to_string().contains("interrupted") {
OnboardingError::Cancelled
} else {
OnboardingError::Prompt(err.to_string())
}
}
}
pub fn list_templates() -> Vec<ConfigTemplate> {
TemplateRegistry::new().list().to_vec()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_list_templates_returns_templates() {
let templates = list_templates();
assert!(!templates.is_empty(), "Should have at least one template");
}
#[test]
fn test_onboarding_error_display() {
let err = OnboardingError::Cancelled;
assert_eq!(err.to_string(), "User cancelled setup");
let err = OnboardingError::TemplateNotFound("foo".into());
assert_eq!(err.to_string(), "Template not found: foo");
}
}