syncable_cli/analyzer/tool_management/installers/
javascript.rs1use crate::analyzer::tool_management::ToolDetector;
2use crate::error::{AnalysisError, IaCGeneratorError, Result};
3use super::common::InstallationUtils;
4use std::collections::HashMap;
5use std::process::Command;
6use log::{info, warn};
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("powershell", &[
61 "-Command",
62 "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(AnalysisError::DependencyParsing {
70 file: "bun installation".to_string(),
71 reason: "PowerShell installation failed".to_string(),
72 }))
73 }
74}
75
76fn install_bun_unix() -> Result<()> {
78 info!("🐧 Installing bun on Unix using curl...");
79
80 let output = Command::new("curl")
81 .args(&["-fsSL", "https://bun.sh/install"])
82 .stdout(std::process::Stdio::piped())
83 .spawn()
84 .and_then(|curl_process| {
85 Command::new("bash")
86 .stdin(curl_process.stdout.unwrap())
87 .output()
88 })
89 .map_err(|e| IaCGeneratorError::Analysis(AnalysisError::DependencyParsing {
90 file: "bun installation".to_string(),
91 reason: format!("Failed to execute curl | bash installer: {}", e),
92 }))?;
93
94 if output.status.success() {
95 info!("✅ Bun installed successfully via curl");
96 info!("💡 Note: You may need to restart your terminal or run 'source ~/.bashrc' to use bun");
97 Ok(())
98 } else {
99 let stderr = String::from_utf8_lossy(&output.stderr);
100 Err(IaCGeneratorError::Analysis(AnalysisError::DependencyParsing {
101 file: "bun installation".to_string(),
102 reason: format!("curl installation failed: {}", stderr),
103 }))
104 }
105}
106
107pub fn ensure_yarn(
109 tool_detector: &mut ToolDetector,
110 installed_tools: &mut HashMap<String, bool>,
111) -> Result<()> {
112 if tool_detector.detect_tool("yarn").available {
113 return Ok(());
114 }
115
116 info!("🔧 Installing yarn package manager...");
117
118 let success = InstallationUtils::execute_command("npm", &["install", "-g", "yarn"])?;
119
120 if success {
121 info!("✅ yarn installed successfully");
122 installed_tools.insert("yarn".to_string(), true);
123 tool_detector.clear_cache();
124 } else {
125 warn!("❌ Failed to install yarn via npm");
126 warn!("📦 Please install yarn manually: https://yarnpkg.com/");
127 }
128
129 Ok(())
130}
131
132pub fn ensure_pnpm(
134 tool_detector: &mut ToolDetector,
135 installed_tools: &mut HashMap<String, bool>,
136) -> Result<()> {
137 if tool_detector.detect_tool("pnpm").available {
138 return Ok(());
139 }
140
141 info!("🔧 Installing pnpm package manager...");
142
143 let success = InstallationUtils::execute_command("npm", &["install", "-g", "pnpm"])?;
144
145 if success {
146 info!("✅ pnpm installed successfully");
147 installed_tools.insert("pnpm".to_string(), true);
148 tool_detector.clear_cache();
149 } else {
150 warn!("❌ Failed to install pnpm via npm");
151 warn!("📦 Please install pnpm manually: https://pnpm.io/");
152 }
153
154 Ok(())
155}