syncable_cli/analyzer/tool_management/installers/
javascript.rs1use super::common::InstallationUtils;
2use crate::analyzer::tool_management::ToolDetector;
3use crate::error::{AnalysisError, IaCGeneratorError, Result};
4use log::{info, warn};
5use std::collections::HashMap;
6use std::process::Command;
7
8pub fn ensure_npm(
10 tool_detector: &mut ToolDetector,
11 _installed_tools: &mut HashMap<String, bool>,
12) -> Result<()> {
13 if tool_detector.detect_tool("npm").available {
14 return Ok(());
15 }
16
17 warn!("📦 npm not found. Please install Node.js from https://nodejs.org/");
18 warn!(" npm audit is required for JavaScript/TypeScript vulnerability scanning");
19
20 Ok(()) }
22
23pub fn install_bun(
25 tool_detector: &mut ToolDetector,
26 installed_tools: &mut HashMap<String, bool>,
27) -> Result<()> {
28 if tool_detector.detect_tool("bun").available {
29 return Ok(());
30 }
31
32 info!("🔧 Installing bun runtime and package manager...");
33
34 let install_result = if cfg!(target_os = "windows") {
35 install_bun_windows()
36 } else {
37 install_bun_unix()
38 };
39
40 match install_result {
41 Ok(()) => {
42 info!("✅ Bun installed successfully");
43 tool_detector.clear_cache();
44 installed_tools.insert("bun".to_string(), true);
45 Ok(())
46 }
47 Err(e) => {
48 warn!("❌ Failed to install bun: {}", e);
49 warn!("📦 Please install bun manually from https://bun.sh/");
50 warn!(" Falling back to npm for JavaScript/TypeScript vulnerability scanning");
51 ensure_npm(tool_detector, installed_tools)
52 }
53 }
54}
55
56fn install_bun_windows() -> Result<()> {
58 info!("💻 Installing bun on Windows using PowerShell...");
59
60 let success = InstallationUtils::execute_command(
61 "powershell",
62 &["-Command", "irm bun.sh/install.ps1 | iex"],
63 )?;
64
65 if success {
66 info!("✅ Bun installed successfully via PowerShell");
67 Ok(())
68 } else {
69 Err(IaCGeneratorError::Analysis(
70 AnalysisError::DependencyParsing {
71 file: "bun installation".to_string(),
72 reason: "PowerShell installation failed".to_string(),
73 },
74 ))
75 }
76}
77
78fn install_bun_unix() -> Result<()> {
80 info!("🐧 Installing bun on Unix using curl...");
81
82 let output = Command::new("curl")
83 .args(["-fsSL", "https://bun.sh/install"])
84 .stdout(std::process::Stdio::piped())
85 .spawn()
86 .and_then(|curl_process| {
87 Command::new("bash")
88 .stdin(curl_process.stdout.unwrap())
89 .output()
90 })
91 .map_err(|e| {
92 IaCGeneratorError::Analysis(AnalysisError::DependencyParsing {
93 file: "bun installation".to_string(),
94 reason: format!("Failed to execute curl | bash installer: {}", e),
95 })
96 })?;
97
98 if output.status.success() {
99 info!("✅ Bun installed successfully via curl");
100 info!(
101 "💡 Note: You may need to restart your terminal or run 'source ~/.bashrc' to use bun"
102 );
103 Ok(())
104 } else {
105 let stderr = String::from_utf8_lossy(&output.stderr);
106 Err(IaCGeneratorError::Analysis(
107 AnalysisError::DependencyParsing {
108 file: "bun installation".to_string(),
109 reason: format!("curl installation failed: {}", stderr),
110 },
111 ))
112 }
113}
114
115pub fn ensure_yarn(
117 tool_detector: &mut ToolDetector,
118 installed_tools: &mut HashMap<String, bool>,
119) -> Result<()> {
120 if tool_detector.detect_tool("yarn").available {
121 return Ok(());
122 }
123
124 info!("🔧 Installing yarn package manager...");
125
126 let success = InstallationUtils::execute_command("npm", &["install", "-g", "yarn"])?;
127
128 if success {
129 info!("✅ yarn installed successfully");
130 installed_tools.insert("yarn".to_string(), true);
131 tool_detector.clear_cache();
132 } else {
133 warn!("❌ Failed to install yarn via npm");
134 warn!("📦 Please install yarn manually: https://yarnpkg.com/");
135 }
136
137 Ok(())
138}
139
140pub fn ensure_pnpm(
142 tool_detector: &mut ToolDetector,
143 installed_tools: &mut HashMap<String, bool>,
144) -> Result<()> {
145 if tool_detector.detect_tool("pnpm").available {
146 return Ok(());
147 }
148
149 info!("🔧 Installing pnpm package manager...");
150
151 let success = InstallationUtils::execute_command("npm", &["install", "-g", "pnpm"])?;
152
153 if success {
154 info!("✅ pnpm installed successfully");
155 installed_tools.insert("pnpm".to_string(), true);
156 tool_detector.clear_cache();
157 } else {
158 warn!("❌ Failed to install pnpm via npm");
159 warn!("📦 Please install pnpm manually: https://pnpm.io/");
160 }
161
162 Ok(())
163}