use std::env::current_dir;
use std::path::PathBuf;
use std::process::Command;
use bon::Builder;
#[cfg_attr(docsrs, doc(cfg(feature = "build")))]
#[derive(Builder)]
pub struct BunBuild {
src_files: Vec<PathBuf>,
output_dir: PathBuf,
output_file: Option<String>,
#[builder(default = true)]
minify: bool,
extra_flags: Option<Vec<String>>,
#[builder(default = false)]
skip_if_no_bun: bool,
}
impl BunBuild {
pub fn run(&self) {
fn bun_exists() -> bool {
Command::new("bun")
.arg("--version")
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
if self.skip_if_no_bun && !bun_exists() {
println!("cargo:warning=Bun does not exist and configuration allows this, skipping bun build.");
return;
}
let src_files = self
.src_files
.iter()
.map(|e| {
e.to_str()
.expect("a src file is not a valid utf-8 string")
.to_owned()
})
.collect::<Vec<_>>();
let output_dir = self
.output_dir
.to_str()
.expect("The output file is not a valid utf-8 string")
.to_owned();
let mut args = Vec::new();
args.push("build".to_owned());
args.extend(src_files);
if let Some(output_file) = &self.output_file {
args.extend([
"--outfile".to_owned(),
self.output_dir
.join(output_file)
.to_str()
.unwrap()
.to_owned(),
])
} else {
args.extend(["--outdir".to_owned(), output_dir]);
}
if self.minify {
args.push("--minify".to_owned());
}
args.push("--target=browser".to_owned());
args.extend(self.extra_flags.iter().flatten().cloned());
let output = Command::new("bun")
.args(&args)
.output()
.expect("Failed to execute bun build");
if !output.status.success() {
panic!(
"bun build failed.\nArgs: `{}`\nCurrent Directory: `{}`\nStderr:\n{}",
args.join(" "),
current_dir().unwrap().display(),
String::from_utf8_lossy(&output.stderr)
);
}
}
}