turbopack_bench/util/
npm.rs1use std::{
2 fs::{
3 File, {self},
4 },
5 io::{
6 Write, {self},
7 },
8 path::Path,
9};
10
11use anyhow::Result;
12use serde_json::json;
13
14use crate::util::command;
15
16pub struct NpmPackage<'a> {
17 pub name: &'a str,
18 pub version: &'a str,
19}
20
21impl<'a> NpmPackage<'a> {
22 pub fn new(name: &'a str, version: &'a str) -> Self {
23 NpmPackage { name, version }
24 }
25}
26
27impl std::fmt::Display for NpmPackage<'_> {
28 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
29 fmt.write_fmt(format_args!("{}@{}", self.name, self.version))
30 }
31}
32
33pub fn install(install_dir: &Path, packages: &[NpmPackage<'_>]) -> Result<()> {
34 if !fs::metadata(install_dir.join("package.json"))
35 .map(|metadata| metadata.is_file())
36 .unwrap_or(false)
37 {
38 let package_json = json!({
41 "private": true,
42 "version": "0.0.0",
43 });
44
45 File::create(install_dir.join("package.json"))?
46 .write_all(format!("{package_json:#}").as_bytes())?;
47 }
48
49 let mut args = vec![
50 "install".to_owned(),
51 "--force".to_owned(),
52 "--install-links".to_owned(),
55 "true".to_owned(),
56 ];
57 args.append(
58 &mut packages
59 .iter()
60 .map(|p| p.to_string())
61 .collect::<Vec<String>>(),
62 );
63
64 let npm = command("npm")
65 .args(args)
66 .current_dir(install_dir)
67 .output()?;
68
69 if !npm.status.success() {
70 io::stdout().write_all(&npm.stdout)?;
71 io::stderr().write_all(&npm.stderr)?;
72 anyhow::bail!("npm install failed. See above.")
73 }
74
75 Ok(())
76}