gitdataai/libs/frontend/build.rs
ZhenYi 7e42139989
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
feat(frontend): embed SPA assets into app binary at compile time
- Add libs/frontend crate: build.rs runs pnpm build, copies dist/ to
  OUT_DIR/dist_blobs/, generates frontend.rs with lazy_static! map
- libs/api/dist.rs serves embedded assets via serve_frontend handler
- Register /{path:.*} SPA fallback in route.rs (after /api/*)
- Remove frontend container from deploy: docker/frontend.Dockerfile,
  deploy/templates/frontend-*.yaml, values.yaml frontend section
- Update ingress: gitdata.ai root now routes to app service
- Update scripts: build.js removes frontend step, deploy.js removes frontend
2026-04-17 12:04:34 +08:00

81 lines
2.7 KiB
Rust

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();
let key_literal = format!("\"{}\"", key.replace('"', "\\\""));
strs.push(format!(" ({}, include_bytes!(\"dist_blobs/{}\")),", key_literal, safe_name));
}
let out_file = out_dir.join("frontend.rs");
let content = format!(
"lazy_static::lazy_static! {{\n pub static ref FRONTEND: Vec<(&'static str, &'static [u8])> = vec![\n{} ];\n}}\n",
strs.join("\n")
);
fs::write(&out_file, content).unwrap();
println!("cargo:include={}", out_file.display());
}