use std::path::Path;
use anyhow::Result;
use colored::Colorize;
use crate::core::detection::package_json::PackageJson;
pub fn execute(path: &Path) -> Result<()> {
let path = if path.exists() && path.is_relative() {
std::env::current_dir()?.join(path)
} else {
path.to_path_buf()
};
let pkg_path = path.join("package.json");
if !pkg_path.exists() {
println!("{} No package.json found in {}", "⚠".yellow(), path.display());
return Ok(());
}
println!("Analyzing dependencies in {}...", pkg_path.display());
let pkg = match PackageJson::load(&pkg_path) {
Some(p) => p,
None => {
println!("{} Failed to parse package.json", "✖".red());
return Ok(());
}
};
let all_deps: std::collections::HashMap<&String, &String> = pkg
.dependencies
.iter()
.chain(pkg.dev_dependencies.iter())
.collect();
let mut deprecated = Vec::new();
let mut blockers = Vec::new();
let mut mismatches = Vec::new();
let deprecated_list = [
"tslint",
"request",
"@angular/http",
"moment",
"node-sass",
"phantomjs-prebuilt",
"bower",
"vue-resource",
"@babel/polyfill",
];
let blockers_list = [
"babel-core",
"gulp-util",
];
for (name, version) in &all_deps {
if deprecated_list.contains(&name.as_str()) {
deprecated.push(format!("{} ({})", name, version));
}
if blockers_list.contains(&name.as_str()) {
blockers.push(format!("{} ({})", name, version));
}
if name.as_str() == "webpack" && (version.starts_with('1') || version.starts_with('2') || version.starts_with('3') || version.starts_with("^1") || version.starts_with("^2") || version.starts_with("^3") || version.starts_with("~1") || version.starts_with("~2") || version.starts_with("~3")) {
blockers.push(format!("{} ({}) - too old", name, version));
}
}
if let (Some(react_ver), Some(react_dom_ver)) = (all_deps.get(&"react".to_string()), all_deps.get(&"react-dom".to_string())) {
if react_ver != react_dom_ver {
mismatches.push(format!("react ({}) vs react-dom ({})", react_ver, react_dom_ver));
}
}
if let (Some(core_ver), Some(cli_ver)) = (all_deps.get(&"@angular/core".to_string()), all_deps.get(&"@angular/cli".to_string())) {
let core_major = core_ver.split('.').next().unwrap_or("");
let cli_major = cli_ver.split('.').next().unwrap_or("");
if core_major != cli_major {
mismatches.push(format!("@angular/core ({}) vs @angular/cli ({})", core_ver, cli_ver));
}
}
println!("\n{}", "Dependency Analysis Summary:".bold());
println!(" Total dependencies: {}", pkg.dependencies.len());
println!(" Total devDependencies: {}", pkg.dev_dependencies.len());
if !deprecated.is_empty() {
println!("\n{} {}", "⚠".yellow(), "Deprecated Packages:".bold().yellow());
for item in &deprecated {
println!(" - {}", item);
}
}
if !blockers.is_empty() {
println!("\n{} {}", "✖".red(), "Migration Blockers:".bold().red());
for item in &blockers {
println!(" - {}", item);
}
}
if !mismatches.is_empty() {
println!("\n{} {}", "‼".red(), "Framework Version Mismatches:".bold().red());
for item in &mismatches {
println!(" - {}", item);
}
}
if deprecated.is_empty() && blockers.is_empty() && mismatches.is_empty() {
println!("\n{} {}", "✔".green(), "No major dependency issues found.".green());
}
Ok(())
}