dioxus_use_js/
build.rs

1use std::env::current_dir;
2use std::path::PathBuf;
3use std::process::Command;
4
5use bon::Builder;
6
7#[cfg_attr(docsrs, doc(cfg(feature = "build")))]
8#[derive(Builder)]
9pub struct BunBuild {
10    /// Files to build from
11    src_files: Vec<PathBuf>,
12    /// The output directory
13    output_dir: PathBuf,
14    /// If set the output will be a single file
15    output_file: Option<String>,
16    #[builder(default = true)]
17    minify: bool,
18    /// Extra bun build flags
19    extra_flags: Option<Vec<String>>,
20    /// If true, the normal `bun build ...` command will not execute if bun is not installed, but will instead print a warning.
21    /// This may be useful in CI environment where bun is not installed (and is not needed), since the output was created during
22    /// development and is already in source.
23    #[builder(default = false)]
24    skip_if_no_bun: bool,
25}
26
27impl BunBuild {
28    pub fn run(&self) {
29        fn bun_exists() -> bool {
30            Command::new("bun")
31                .arg("--version")
32                .output()
33                .map(|o| o.status.success())
34                .unwrap_or(false)
35        }
36        if self.skip_if_no_bun && !bun_exists() {
37            println!("cargo:warning=Bun does not exist and configuration allows this, skipping bun build.");
38            return;
39        }
40
41        let src_files = self
42            .src_files
43            .iter()
44            .map(|e| {
45                e.to_str()
46                    .expect("a src file is not a valid utf-8 string")
47                    .to_owned()
48            })
49            .collect::<Vec<_>>();
50        let output_dir = self
51            .output_dir
52            .to_str()
53            .expect("The output file is not a valid utf-8 string")
54            .to_owned();
55
56        let mut args = Vec::new();
57        args.push("build".to_owned());
58        args.extend(src_files);
59
60        if let Some(output_file) = &self.output_file {
61            args.extend([
62                "--outfile".to_owned(),
63                self.output_dir
64                    .join(output_file)
65                    .to_str()
66                    .unwrap()
67                    .to_owned(),
68            ])
69        } else {
70            args.extend(["--outdir".to_owned(), output_dir]);
71        }
72        if self.minify {
73            args.push("--minify".to_owned());
74        }
75        args.push("--target=browser".to_owned());
76        args.extend(self.extra_flags.iter().flatten().cloned());
77
78        // Run bun build
79        let output = Command::new("bun")
80            .args(&args)
81            .output()
82            .expect("Failed to execute bun build");
83        if !output.status.success() {
84            panic!(
85                "bun build failed.\nArgs: `{}`\nCurrent Directory: `{}`\nStderr:\n{}",
86                args.join(" "),
87                current_dir().unwrap().display(),
88                String::from_utf8_lossy(&output.stderr)
89            );
90        }
91    }
92}