1use std::path::PathBuf;
7use vx_installer::{InstallConfig, InstallMethod};
8use vx_tool_standard::{StandardToolConfig, StandardUrlBuilder, ToolDependency};
9
10pub struct Config;
12
13pub struct PnpmUrlBuilder;
15
16impl StandardUrlBuilder for PnpmUrlBuilder {
17 fn download_url(version: &str) -> Option<String> {
19 let _platform = Self::get_platform_string();
20 let filename = Self::get_filename(version);
21
22 Some(format!(
23 "https://github.com/pnpm/pnpm/releases/download/v{}/{}",
24 version, filename
25 ))
26 }
27
28 fn get_filename(version: &str) -> String {
30 let platform = Self::get_platform_string();
31 if cfg!(windows) {
32 format!("pnpm-{}-{}.exe", platform, version)
33 } else {
34 format!("pnpm-{}-{}", platform, version)
35 }
36 }
37
38 fn get_platform_string() -> String {
40 match (std::env::consts::OS, std::env::consts::ARCH) {
41 ("windows", "x86_64") => "win-x64".to_string(),
42 ("windows", "aarch64") => "win-arm64".to_string(),
43 ("macos", "x86_64") => "macos-x64".to_string(),
44 ("macos", "aarch64") => "macos-arm64".to_string(),
45 ("linux", "x86_64") => "linux-x64".to_string(),
46 ("linux", "aarch64") => "linux-arm64".to_string(),
47 _ => "linux-x64".to_string(), }
49 }
50}
51
52impl StandardToolConfig for Config {
54 fn tool_name() -> &'static str {
55 "pnpm"
56 }
57
58 fn create_install_config(version: &str, install_dir: PathBuf) -> InstallConfig {
59 create_install_config(version, install_dir)
60 }
61
62 fn get_install_methods() -> Vec<String> {
63 get_install_methods()
64 }
65
66 fn supports_auto_install() -> bool {
67 true
68 }
69
70 fn get_manual_instructions() -> String {
71 get_manual_instructions()
72 }
73
74 fn get_dependencies() -> Vec<ToolDependency> {
75 vec![
76 ToolDependency::required("node", "PNPM requires Node.js runtime")
77 .with_version(">=16.14.0"),
78 ]
79 }
80
81 fn get_default_version() -> &'static str {
82 "latest"
83 }
84}
85
86pub fn create_install_config(version: &str, install_dir: PathBuf) -> InstallConfig {
88 let actual_version = if version == "latest" {
89 "8.15.0" } else {
91 version
92 };
93
94 let download_url = PnpmUrlBuilder::download_url(actual_version);
95 let install_method = InstallMethod::Binary;
96
97 InstallConfig::builder()
98 .tool_name("pnpm")
99 .version(version.to_string())
100 .install_method(install_method)
101 .download_url(download_url.unwrap_or_default())
102 .install_dir(install_dir)
103 .build()
104}
105
106pub fn get_install_methods() -> Vec<String> {
108 vec![
109 "GitHub releases (recommended)".to_string(),
110 "NPM global install".to_string(),
111 if cfg!(target_os = "macos") {
112 "Homebrew".to_string()
113 } else {
114 "Package manager".to_string()
115 },
116 ]
117}
118
119pub fn supports_auto_install() -> bool {
121 true
122}
123
124pub fn get_manual_instructions() -> String {
126 "To install PNPM manually:\n\
127 • npm install -g pnpm\n\
128 • Or visit: https://pnpm.io/installation\n\
129 • Requires Node.js >=16.14.0"
130 .to_string()
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_pnpm_dependencies() {
139 let deps = Config::get_dependencies();
140 assert_eq!(deps.len(), 1);
141 assert_eq!(deps[0].tool_name, "node");
142 assert!(deps[0].required);
143 assert_eq!(deps[0].version_requirement, Some(">=16.14.0".to_string()));
144 }
145
146 #[test]
147 fn test_pnpm_config() {
148 assert_eq!(Config::tool_name(), "pnpm");
149 assert!(Config::supports_auto_install());
150 assert_eq!(Config::get_default_version(), "latest");
151 }
152
153 #[test]
154 fn test_pnpm_url_builder() {
155 let url = PnpmUrlBuilder::download_url("8.15.0");
156 assert!(url.is_some());
157 assert!(url.unwrap().contains("github.com/pnpm/pnpm"));
158 }
159
160 #[test]
161 fn test_create_install_config() {
162 let config = create_install_config("latest", PathBuf::from("/tmp/pnpm"));
163 assert_eq!(config.tool_name, "pnpm");
164 assert_eq!(config.version, "latest");
165 }
166}