Skip to content

Commit 562614d

Browse files
committed
feat(pm): add pm command group
1 parent f727103 commit 562614d

4 files changed

Lines changed: 2151 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod add;
22
mod install;
3+
pub mod pm;
34
pub mod remove;
45
pub mod update;
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
use std::{collections::HashMap, process::ExitStatus};
2+
3+
use vite_error::Error;
4+
use vite_path::AbsolutePath;
5+
6+
use crate::package_manager::{
7+
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
8+
};
9+
10+
impl PackageManager {
11+
/// Run a pm subcommand with pass-through arguments.
12+
#[must_use]
13+
pub async fn run_pm_command(
14+
&self,
15+
subcommand: &str,
16+
args: &[String],
17+
cwd: impl AsRef<AbsolutePath>,
18+
) -> Result<ExitStatus, Error> {
19+
let resolve_command = self.resolve_pm_command(subcommand, args);
20+
run_command(&resolve_command.bin_path, &resolve_command.args, &resolve_command.envs, cwd)
21+
.await
22+
}
23+
24+
/// Resolve pm command with minimal processing.
25+
/// Most arguments are passed through directly to the package manager.
26+
#[must_use]
27+
pub fn resolve_pm_command(&self, subcommand: &str, args: &[String]) -> ResolveCommandResult {
28+
let bin_name: String;
29+
let envs = HashMap::from([("PATH".to_string(), format_path_env(self.get_bin_prefix()))]);
30+
let mut cmd_args: Vec<String> = Vec::new();
31+
32+
match self.client {
33+
PackageManagerType::Pnpm => {
34+
bin_name = "pnpm".into();
35+
36+
// Map vite pm commands to pnpm commands
37+
match subcommand {
38+
"prune" => cmd_args.push("prune".into()),
39+
"pack" => cmd_args.push("pack".into()),
40+
"list" | "ls" => cmd_args.push("list".into()),
41+
"view" => cmd_args.push("view".into()),
42+
"publish" => cmd_args.push("publish".into()),
43+
"owner" => cmd_args.push("owner".into()),
44+
"cache" => {
45+
// Map cache subcommands
46+
if !args.is_empty() {
47+
match args[0].as_str() {
48+
"dir" | "path" => {
49+
cmd_args.push("store".into());
50+
cmd_args.push("path".into());
51+
return ResolveCommandResult {
52+
bin_path: bin_name,
53+
args: cmd_args,
54+
envs,
55+
};
56+
}
57+
"clean" | "clear" => {
58+
cmd_args.push("store".into());
59+
cmd_args.push("prune".into());
60+
// Skip the subcommand arg, pass through the rest
61+
cmd_args.extend_from_slice(&args[1..]);
62+
return ResolveCommandResult {
63+
bin_path: bin_name,
64+
args: cmd_args,
65+
envs,
66+
};
67+
}
68+
"list" => {
69+
cmd_args.push("store".into());
70+
cmd_args.push("list".into());
71+
// Skip the subcommand arg, pass through the rest
72+
cmd_args.extend_from_slice(&args[1..]);
73+
return ResolveCommandResult {
74+
bin_path: bin_name,
75+
args: cmd_args,
76+
envs,
77+
};
78+
}
79+
"verify" => {
80+
eprintln!("Warning: pnpm does not support 'cache verify'");
81+
return ResolveCommandResult {
82+
bin_path: "echo".into(),
83+
args: vec!["pnpm does not support cache verify".into()],
84+
envs,
85+
};
86+
}
87+
_ => cmd_args.push("store".into()),
88+
}
89+
} else {
90+
cmd_args.push("store".into());
91+
cmd_args.push("path".into());
92+
return ResolveCommandResult {
93+
bin_path: bin_name,
94+
args: cmd_args,
95+
envs,
96+
};
97+
}
98+
}
99+
"config" => cmd_args.push("config".into()),
100+
_ => cmd_args.push(subcommand.into()),
101+
}
102+
}
103+
PackageManagerType::Npm => {
104+
bin_name = "npm".into();
105+
106+
match subcommand {
107+
"prune" => {
108+
eprintln!(
109+
"Warning: npm removed 'prune' command in v6. Use 'vite install --prod' instead."
110+
);
111+
return ResolveCommandResult {
112+
bin_path: "echo".into(),
113+
args: vec!["npm prune is deprecated".into()],
114+
envs,
115+
};
116+
}
117+
"pack" => cmd_args.push("pack".into()),
118+
"list" | "ls" => cmd_args.push("list".into()),
119+
"view" => cmd_args.push("view".into()),
120+
"publish" => cmd_args.push("publish".into()),
121+
"owner" => cmd_args.push("owner".into()),
122+
"cache" => {
123+
cmd_args.push("cache".into());
124+
if !args.is_empty() {
125+
match args[0].as_str() {
126+
"path" => {
127+
// npm uses 'dir' not 'path'
128+
cmd_args.push("dir".into());
129+
// Skip the subcommand arg, pass through the rest
130+
cmd_args.extend_from_slice(&args[1..]);
131+
return ResolveCommandResult {
132+
bin_path: bin_name,
133+
args: cmd_args,
134+
envs,
135+
};
136+
}
137+
"clear" => {
138+
// npm uses 'clean' not 'clear'
139+
cmd_args.push("clean".into());
140+
// Skip the subcommand arg, pass through the rest
141+
cmd_args.extend_from_slice(&args[1..]);
142+
return ResolveCommandResult {
143+
bin_path: bin_name,
144+
args: cmd_args,
145+
envs,
146+
};
147+
}
148+
"list" => {
149+
eprintln!("Warning: npm does not support 'cache list'");
150+
return ResolveCommandResult {
151+
bin_path: "echo".into(),
152+
args: vec!["npm does not support cache list".into()],
153+
envs,
154+
};
155+
}
156+
_ => {}
157+
}
158+
}
159+
}
160+
"config" => cmd_args.push("config".into()),
161+
_ => cmd_args.push(subcommand.into()),
162+
}
163+
}
164+
PackageManagerType::Yarn => {
165+
bin_name = "yarn".into();
166+
167+
match subcommand {
168+
"prune" => {
169+
if self.version.starts_with("1.") {
170+
cmd_args.push("prune".into());
171+
} else {
172+
eprintln!("Warning: yarn@2+ does not have 'prune' command");
173+
return ResolveCommandResult {
174+
bin_path: "echo".into(),
175+
args: vec!["yarn@2+ does not support prune".into()],
176+
envs,
177+
};
178+
}
179+
}
180+
"pack" => cmd_args.push("pack".into()),
181+
"list" | "ls" => cmd_args.push("list".into()),
182+
"view" => {
183+
// yarn uses 'info' instead of 'view'
184+
cmd_args.push("info".into());
185+
}
186+
"publish" => {
187+
if self.version.starts_with("1.") {
188+
cmd_args.push("publish".into());
189+
} else {
190+
cmd_args.push("npm".into());
191+
cmd_args.push("publish".into());
192+
}
193+
}
194+
"owner" => {
195+
if self.version.starts_with("1.") {
196+
cmd_args.push("owner".into());
197+
} else {
198+
cmd_args.push("npm".into());
199+
cmd_args.push("owner".into());
200+
}
201+
}
202+
"cache" => {
203+
cmd_args.push("cache".into());
204+
if !args.is_empty() {
205+
match args[0].as_str() {
206+
"path" => {
207+
// yarn uses 'dir' not 'path'
208+
cmd_args.push("dir".into());
209+
// Skip the subcommand arg, pass through the rest
210+
cmd_args.extend_from_slice(&args[1..]);
211+
return ResolveCommandResult {
212+
bin_path: bin_name,
213+
args: cmd_args,
214+
envs,
215+
};
216+
}
217+
"clear" => {
218+
// yarn uses 'clean' not 'clear'
219+
cmd_args.push("clean".into());
220+
// Skip the subcommand arg, pass through the rest
221+
cmd_args.extend_from_slice(&args[1..]);
222+
return ResolveCommandResult {
223+
bin_path: bin_name,
224+
args: cmd_args,
225+
envs,
226+
};
227+
}
228+
"verify" => {
229+
eprintln!("Warning: yarn does not support 'cache verify'");
230+
return ResolveCommandResult {
231+
bin_path: "echo".into(),
232+
args: vec!["yarn does not support cache verify".into()],
233+
envs,
234+
};
235+
}
236+
_ => {}
237+
}
238+
}
239+
}
240+
"config" => {
241+
cmd_args.push("config".into());
242+
// yarn@2+ uses different config commands
243+
if !self.version.starts_with("1.")
244+
&& !args.is_empty()
245+
&& args[0] == "delete"
246+
{
247+
cmd_args.push("unset".into());
248+
cmd_args.extend_from_slice(&args[1..]);
249+
return ResolveCommandResult {
250+
bin_path: bin_name,
251+
args: cmd_args,
252+
envs,
253+
};
254+
}
255+
}
256+
_ => cmd_args.push(subcommand.into()),
257+
}
258+
}
259+
}
260+
261+
// Pass through all remaining arguments
262+
cmd_args.extend_from_slice(args);
263+
264+
ResolveCommandResult { bin_path: bin_name, args: cmd_args, envs }
265+
}
266+
}

0 commit comments

Comments
 (0)