use clap::{Arg, ArgMatches, Command};
use std::{io::Write, vec::Vec};
use crate::{
command_add::{
add_cargo_deps_to_toml::add_cargo_dep_to_toml,
fetch_index_json::fetch_index_content,
get_path_from_toml::get_base_path_from_Components_toml,
models::MyComponent,
print_tree::print_dependency_tree,
resolve_registry_dependencies::{
all_tree_resolved, get_all_resolved_cargo_dependencies, get_all_resolved_components,
get_all_resolved_parent_dirs,
},
},
constants::{commands::COMMAND_ADD, urls::BASE_URL},
};
use super::fetch_from_registry_and_write::fetch_from_registry_component_name_json_and_write_to_file;
pub fn command_add() -> Command {
Command::new(COMMAND_ADD)
.about("Add components and dependencies to your project")
.arg(
Arg::new("components")
.help("The components to add (space-separated)")
.required(false)
.num_args(1..), )
}
pub async fn process_add(matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
let user_components: Vec<String> = matches
.get_many::<String>("components")
.unwrap_or_default()
.cloned()
.collect();
let index_content_from_url = fetch_index_content(BASE_URL).await?;
let vec_components_from_index: Vec<MyComponent> = serde_json::from_str(&index_content_from_url).unwrap();
let all_tree_resolved = all_tree_resolved(user_components, &vec_components_from_index);
print_dependency_tree(&all_tree_resolved);
let all_resolved_components = get_all_resolved_components(&all_tree_resolved);
let all_resolved_parent_dirs = get_all_resolved_parent_dirs(&all_tree_resolved);
let all_resolved_cargo_dependencies = get_all_resolved_cargo_dependencies(&all_tree_resolved);
let user_config_path_toml = get_base_path_from_Components_toml().unwrap_or_default();
create_components_mod_if_not_exists_with_pub_mods(user_config_path_toml, all_resolved_parent_dirs.clone());
for component_to_add in all_resolved_components {
fetch_from_registry_component_name_json_and_write_to_file(component_to_add).await;
}
if !all_resolved_cargo_dependencies.is_empty() {
add_cargo_dep_to_toml(&all_resolved_cargo_dependencies)?;
}
Ok(())
}
fn create_components_mod_if_not_exists_with_pub_mods(user_config_path: String, parent_dirs: Vec<String>) {
let components_mod_path = format!("{}/mod.rs", user_config_path);
let dir = std::path::Path::new(&components_mod_path)
.parent()
.expect("Failed to get parent directory");
std::fs::create_dir_all(dir).expect("Failed to create directories");
let mut mod_content = String::new();
if std::path::Path::new(&components_mod_path).exists() {
mod_content = std::fs::read_to_string(&components_mod_path).expect("Failed to read mod.rs");
}
let mut mod_rs_file = std::fs::OpenOptions::new()
.write(true)
.append(true)
.create(true)
.open(components_mod_path)
.expect("Failed to open mod.rs");
for parent_dir in parent_dirs {
if !mod_content.contains(&format!("pub mod {};", parent_dir)) {
writeln!(mod_rs_file, "pub mod {};", parent_dir).expect("Failed to write to mod.rs");
println!("Added pub mod {}; to components/mod.rs", parent_dir);
}
}
}