fluxor_cli/
lib.rs

1pub mod hello_world;
2
3pub use clap::Parser;
4use regex::Regex;
5use std::fs;
6use std::path::Path;
7use std::process::Command as ProcessCommand;
8
9#[derive(Parser, Debug)]
10#[clap(author, version, about, long_about = None)]
11pub struct Args {
12    #[clap(subcommand)]
13    pub command: Commands,
14}
15
16#[derive(Parser, Debug)]
17pub enum Commands {
18    New {
19        name: String,
20        #[clap(short, long, default_value = "latest")]
21        version: String,
22        #[clap(short, long, default_value = "helloworld")]
23        example: String,
24    },
25}
26
27pub fn fetch_latest_version(crate_name: &str) -> Result<String, Box<dyn std::error::Error>> {
28    let output = ProcessCommand::new("cargo")
29        .arg("search")
30        .arg(crate_name)
31        .output()?;
32
33    if !output.status.success() {
34        return Err(format!(
35            "Failed to fetch latest version of {}: {}",
36            crate_name,
37            String::from_utf8_lossy(&output.stderr)
38        )
39        .into());
40    }
41
42    let stdout = String::from_utf8_lossy(&output.stdout);
43    println!("Cargo search output: {}", stdout); // Debug print
44
45    // Use a regex to extract the version number
46    let re = Regex::new(r#"(\d+\.\d+\.\d+)"#).unwrap();
47    let version = stdout
48        .lines()
49        .find(|line| line.contains(crate_name))
50        .and_then(|line| re.find(line))
51        .map(|version| version.as_str())
52        .ok_or_else(|| format!("Crate '{}' not found", crate_name))?;
53
54    println!("Parsed version: {}", version); // Debug print
55
56    Ok(version.to_string())
57}
58
59pub fn create_fluxor_web_project(name: &str, version: &str, example: &str) {
60    let project_path = Path::new(name);
61
62    // Check if project directory already exists
63    if project_path.exists() {
64        eprintln!("Project directory already exists.");
65        return;
66    }
67
68    // Create project directory
69    fs::create_dir_all(&project_path).expect("Failed to create project directory");
70
71    // Fetch fluxor version if "latest" is specified
72    let fluxor_version = if version == "latest" {
73        fetch_latest_version("fluxor").expect("Failed to fetch latest version of fluxor")
74    } else {
75        version.to_string()
76    };
77
78    // Create .gitignore file
79    let gitignore = r#"/target
80    "#;
81       
82    fs::write(project_path.join(".gitignore"), gitignore)
83        .expect("Failed to create .gitignore");
84
85    // Create .gitignore file
86    let readme = format!(r#"# {}
87
88This project has been initialized with the assistance of the [Fluxor CLI](https://crates.io/crates/fluxor_cli), a command-line tool that allows developers to quickly and efficiently create project starters for the [Fluxor web framework](https://crates.io/crates/fluxor)."
89"#, name);
90        
91    fs::write(project_path.join("README.md"), readme)
92        .expect("Failed to create readme file");
93
94    // Create Cargo.toml specific for the example
95    let cargo_toml = match example {
96        // Hello World Examples
97        "helloworld" => hello_world::hello_world_cargo_toml(name, &fluxor_version),
98        "helloworld-api" => hello_world::hello_world_cargo_toml(name, &fluxor_version),
99        "helloworld-api-server" => hello_world::hello_world_api_server_cargo_toml(name, &fluxor_version),
100        _ => {
101            eprintln!("Unknown example specified: {}", example);
102            return;
103        }
104    };
105
106    fs::write(project_path.join("Cargo.toml"), cargo_toml)
107        .expect("Failed to create Cargo.toml");
108
109    // Create src directory under the project
110    let src_path = project_path.join("src");
111    fs::create_dir_all(&src_path).expect("Failed to create src directory");
112
113    // Create main.rs based on the specified example
114    match example {
115        "helloworld" => {
116            hello_world::hello_world_template(&src_path);
117        }
118        "helloworld-api" => {
119            hello_world::hello_world_api_template(&src_path);
120        }
121        "helloworld-api-server" => {
122            hello_world::hello_world_api_server_template(&src_path);
123        }
124        _ => {
125            eprintln!("Unknown example specified: {}", example);
126            return;
127        }
128    }
129
130    println!("Fluxor project '{}' created successfully using the '{}' example.", name, example);
131}