185 lines
7.8 KiB
Rust
185 lines
7.8 KiB
Rust
use colored::*;
|
|
|
|
pub fn handle_api_error(err: anyhow::Error, api_url: &str) -> ! {
|
|
eprintln!("{}", format_error_message(&err, api_url));
|
|
std::process::exit(1);
|
|
}
|
|
|
|
fn format_error_message(err: &anyhow::Error, api_url: &str) -> String {
|
|
let err_str = err.to_string();
|
|
|
|
// Connection refused
|
|
if err_str.contains("Connection refused") || err_str.contains("tcp connect error") || err_str.contains("error sending request") {
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n • {}\n\n{}\n {}",
|
|
"✗".bright_red().bold(),
|
|
"Cannot connect to Hindsight API".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"Possible causes:".bright_yellow(),
|
|
"The Hindsight API server is not running".bright_white(),
|
|
format!("The server is running on a different address than {}", api_url).bright_white(),
|
|
"A firewall is blocking the connection".bright_white(),
|
|
"Try:".bright_green(),
|
|
"Start the Hindsight API server and ensure it's accessible".bright_white()
|
|
);
|
|
}
|
|
|
|
// Timeout
|
|
if err_str.contains("timeout") || err_str.contains("Timeout") {
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n\n{}\n • {}\n • {}",
|
|
"✗".bright_red().bold(),
|
|
"Request timed out".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"Possible causes:".bright_yellow(),
|
|
"The API server is slow to respond".bright_white(),
|
|
"Network latency is too high".bright_white(),
|
|
"Try:".bright_green(),
|
|
"Check if the API server is healthy".bright_white(),
|
|
"Try again with a better network connection".bright_white()
|
|
);
|
|
}
|
|
|
|
// DNS/Host resolution
|
|
if err_str.contains("dns") || err_str.contains("DNS") || err_str.contains("failed to lookup") {
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n\n{}\n {}",
|
|
"✗".bright_red().bold(),
|
|
"Cannot resolve API hostname".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"Possible causes:".bright_yellow(),
|
|
"The hostname in the API URL is incorrect".bright_white(),
|
|
"DNS server is not responding".bright_white(),
|
|
"Try:".bright_green(),
|
|
"Check the HINDSIGHT_API_URL environment variable".bright_white()
|
|
);
|
|
}
|
|
|
|
// 404 Not Found
|
|
if err_str.contains("404") {
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n\n{}\n {}",
|
|
"✗".bright_red().bold(),
|
|
"API endpoint not found (404)".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"Possible causes:".bright_yellow(),
|
|
"The API endpoint path has changed".bright_white(),
|
|
"You're using an incompatible API version".bright_white(),
|
|
"Try:".bright_green(),
|
|
"Check that you're using the correct Hindsight API version".bright_white()
|
|
);
|
|
}
|
|
|
|
// 401/403 Authentication
|
|
if err_str.contains("401") || err_str.contains("403") {
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n\n{}\n {}",
|
|
"✗".bright_red().bold(),
|
|
"Authentication failed".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"Possible causes:".bright_yellow(),
|
|
"API requires authentication".bright_white(),
|
|
"Invalid or missing credentials".bright_white(),
|
|
"Try:".bright_green(),
|
|
"Check if the API requires an API key or token".bright_white()
|
|
);
|
|
}
|
|
|
|
// 500 Server Error
|
|
if err_str.contains("500") || err_str.contains("502") || err_str.contains("503") {
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n\n{}\n • {}\n • {}",
|
|
"✗".bright_red().bold(),
|
|
"API server error".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"The server encountered an error:".bright_yellow(),
|
|
"Internal server error (500)".bright_white(),
|
|
"Service temporarily unavailable".bright_white(),
|
|
"Try:".bright_green(),
|
|
"Check the API server logs for details".bright_white(),
|
|
"Try again in a few moments".bright_white()
|
|
);
|
|
}
|
|
|
|
// Invalid URL
|
|
if err_str.contains("invalid URL") || err_str.contains("InvalidUri") {
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n {}\n\n{}\n {}",
|
|
"✗".bright_red().bold(),
|
|
"Invalid API URL".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"The API URL format is invalid.".bright_yellow(),
|
|
"Ensure it starts with http:// or https://".bright_white(),
|
|
"Example:".bright_green(),
|
|
"export HINDSIGHT_API_URL=http://localhost:8888".bright_white()
|
|
);
|
|
}
|
|
|
|
// JSON parsing error - show actual response
|
|
if err_str.contains("Failed to parse") || err_str.contains("error decoding") {
|
|
// Extract the actual response if available
|
|
let response_hint = if err_str.contains("Response was:") {
|
|
let parts: Vec<&str> = err_str.split("Response was:").collect();
|
|
if parts.len() > 1 {
|
|
format!("\n{}\n{}", "Actual response:".bright_yellow(), parts[1].trim().bright_white())
|
|
} else {
|
|
String::new()
|
|
}
|
|
} else {
|
|
String::new()
|
|
};
|
|
|
|
return format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n • {}{}\n\n{}\n • {}\n • {}",
|
|
"✗".bright_red().bold(),
|
|
"Invalid API response format".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"Possible causes:".bright_yellow(),
|
|
"The API returned an unexpected response format".bright_white(),
|
|
"Version mismatch between CLI and API".bright_white(),
|
|
"The API endpoint doesn't exist or returned HTML instead of JSON".bright_white(),
|
|
response_hint,
|
|
"Try:".bright_green(),
|
|
"Run with --verbose flag to see the full request/response".bright_white(),
|
|
"Ensure you're using a compatible Hindsight API version".bright_white()
|
|
);
|
|
}
|
|
|
|
// Generic error with the full error message
|
|
format!(
|
|
"{} {}\n\n{}\n {}\n\n{}\n {}\n\n{}\n • {}\n • {}\n • {}",
|
|
"✗".bright_red().bold(),
|
|
"API request failed".bright_red().bold(),
|
|
"API URL:".bright_yellow(),
|
|
api_url.bright_white(),
|
|
"Error:".bright_yellow(),
|
|
err_str.bright_white(),
|
|
"Suggestions:".bright_green(),
|
|
"Check that HINDSIGHT_API_URL is set correctly".bright_white(),
|
|
"Ensure the Hindsight API server is running".bright_white(),
|
|
"Verify network connectivity to the API server".bright_white()
|
|
)
|
|
}
|
|
|
|
pub fn print_config_help() {
|
|
println!("\n{}", "Configuration:".bright_cyan().bold());
|
|
println!(" Run the configure command to set the API URL:");
|
|
println!(" {}", "hindsight configure".bright_white());
|
|
println!();
|
|
println!(" Or set it directly:");
|
|
println!(" {}", "hindsight configure --api-url http://your-api:8888".bright_white());
|
|
println!();
|
|
println!(" {}", "Configuration priority:".bright_yellow());
|
|
println!(" 1. Environment variable (HINDSIGHT_API_URL) - highest priority");
|
|
println!(" 2. Config file (~/.hindsight/config)");
|
|
println!(" 3. Default (http://localhost:8888)");
|
|
println!();
|
|
}
|