gitdataai/libs/frontend/build.rs

91 lines
2.9 KiB
Rust

use md5::compute as md5_hash;
use std::{env, fs, path::PathBuf, process::Command};
fn run_pnpm(args: &[&str], cwd: &str) {
let mut cmd = if cfg!(target_os = "windows") {
let mut c = Command::new("cmd");
c.args(["/C", "pnpm"]);
c
} else {
Command::new("pnpm")
};
let status = cmd
.args(args)
.current_dir(cwd)
.status()
.expect("failed to run pnpm");
if !status.success() {
panic!("pnpm command failed: {:?}", args);
}
}
fn find_all_file(path: PathBuf) -> Vec<PathBuf> {
let mut files = vec![];
for entry in fs::read_dir(path).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
if path.is_file() {
files.push(path);
} else if path.is_dir() {
files.extend(find_all_file(path));
}
}
files
}
fn main() {
println!("cargo:rerun-if-changed=../../package.json");
println!("cargo:rerun-if-changed=../../pnpm-lock.yaml");
println!("cargo:rerun-if-changed=../../tsconfig.json");
println!("cargo:rerun-if-changed=../../src/");
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let project_root = manifest_dir.parent().unwrap().parent().unwrap();
let node_modules = project_root.join("node_modules");
let _cache_file = node_modules.join(".cache_hash");
// Build frontend using pnpm in project root
println!("cargo:warning=Building frontend...");
run_pnpm(&["run", "build"], project_root.to_str().unwrap());
// Embed dist/ into OUT_DIR as blob files + generated .rs
let dist = project_root.join("dist");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let blob_dir = out_dir.join("dist_blobs");
fs::create_dir_all(&blob_dir).unwrap();
let mut strs = vec![];
for file in find_all_file(dist.clone()) {
let key = file.strip_prefix(&dist).unwrap()
.components()
.collect::<PathBuf>()
.to_string_lossy()
.replace('\\', "/");
let safe_name = key.replace('/', "_").replace('\\', "_");
let blob_path = blob_dir.join(&safe_name);
fs::copy(&file, &blob_path).unwrap();
// Compute ETag (MD5 hex of content) at build time
let content = fs::read(&file).unwrap();
let hash = md5_hash(&content);
let etag_literal = format!("\"{:x}\"", hash);
let key_literal = format!("\"{}\"", key.replace('"', "\\\""));
strs.push(format!(
" ({}, include_bytes!(\"dist_blobs/{}\"), {}),",
key_literal, safe_name, etag_literal
));
}
let out_file = out_dir.join("frontend.rs");
let generated = format!(
"lazy_static::lazy_static! {{\n pub static ref FRONTEND: Vec<(&'static str, &'static [u8], &'static str)> = vec![\n{} ];\n}}\n",
strs.join("\n")
);
fs::write(&out_file, generated).unwrap();
println!("cargo:include={}", out_file.display());
}