bun_cli/
cli.rs

1use crate::error::Result;
2use crate::generator::{ProjectConfig, ProjectGenerator};
3use std::io;
4
5/// CLI interface for the bun-cli tool
6pub struct Cli;
7
8impl Cli {
9    /// Run the CLI application
10    pub fn run() -> Result<()> {
11        println!("šŸ¦€ Bun CLI Generator");
12        println!("A Cool name for your Bun project šŸ˜Ž:");
13
14        let project_name = Self::read_project_name()?;
15
16        let config = ProjectConfig {
17            name: project_name.clone(),
18            ..Default::default()
19        };
20
21        let generator = ProjectGenerator::new(config);
22        
23        // Try to generate directly
24        if let Err(e) = generator.generate() {
25            // check specifically for BunNotInstalled error
26            if let crate::error::BunCliError::BunNotInstalled = e {
27                println!("\nāŒ Bun is not installed.");
28                println!("Would you like to install it now? (Y/n)");
29                
30                let mut response = String::new();
31                io::stdin().read_line(&mut response)?;
32                let response = response.trim().to_lowercase();
33                
34                if response == "y" || response == "yes" || response == "" {
35                     ProjectGenerator::install_bun()?;
36                     
37                     // Update PATH for the current process to include the new bun binary
38                     // This is needed so the next command can find 'bun'
39                     let home = std::env::var("HOME").unwrap_or_default();
40                     let bun_bin = format!("{home}/.bun/bin");
41                     let current_path = std::env::var("PATH").unwrap_or_default();
42                     std::env::set_var("PATH", format!("{bun_bin}:{current_path}"));
43                     
44                     // Verify installation
45                     if ProjectGenerator::check_bun_installed().is_ok() {
46                         println!("Retrying project creation...");
47                         generator.generate()?;
48                     } else {
49                         return Err(crate::error::BunCliError::BunNotInstalled);
50                     }
51                } else {
52                    return Err(e);
53                }
54            } else {
55                return Err(e);
56            }
57        }
58
59        println!("\n🄳 All done! Your project is ready to use.");
60        println!("Run 'cd {project_name}' to get started!");
61
62        Ok(())
63    }
64
65    /// Read project name from stdin
66    fn read_project_name() -> Result<String> {
67        let mut project_name = String::new();
68        io::stdin().read_line(&mut project_name)?;
69        Ok(project_name.trim().to_string())
70    }
71
72    /// Display an error message
73    pub fn display_error(error: &dyn std::error::Error) {
74        eprintln!("\nāŒ Error: {error}");
75        
76        // Display the chain of errors if available
77        let mut source = error.source();
78        while let Some(err) = source {
79            eprintln!("  Caused by: {err}");
80            source = err.source();
81        }
82    }
83}