use anyhow::{Context, Result};
use std::fs;
use crate::build::run_build;
use crate::cli::{BuildArgs, BuildLibraryArgs};
use crate::utils::copy_dir_recursive;
pub fn run_build_library(args: BuildLibraryArgs) -> Result<()> {
println!("pleme-linker build-library: Building TypeScript library");
println!(" Source: {}", args.src.display());
println!(" Output: {}", args.output.display());
println!(" Manifest: {}", args.manifest.display());
println!();
fs::create_dir_all(&args.output)?;
println!("Stage 1: Building node_modules...");
let node_modules_build = args.output.join("node_modules_build");
run_build(BuildArgs {
manifest: args.manifest.clone(),
output: node_modules_build.clone(),
node_bin: args.node_bin.clone(),
})?;
println!();
println!("Stage 2: Setting up build environment...");
let build_dir = args.output.join("build_workspace");
fs::create_dir_all(&build_dir)?;
copy_dir_recursive(&args.src, &build_dir)?;
let build_node_modules = build_dir.join("node_modules");
if build_node_modules.exists() {
fs::remove_dir_all(&build_node_modules)?;
}
std::os::unix::fs::symlink(
node_modules_build.join("node_modules"),
&build_node_modules,
)?;
println!(" Build directory ready");
println!();
println!("Stage 3: Running tsdown...");
let tsdown_bin = build_node_modules.join(".bin/tsdown");
if !tsdown_bin.exists() {
anyhow::bail!(
"tsdown not found in node_modules/.bin. Ensure it's in devDependencies.\n\
Expected at: {}",
tsdown_bin.display()
);
}
let status = std::process::Command::new(&tsdown_bin)
.current_dir(&build_dir)
.env("NODE_ENV", "production")
.env("PATH", args.node_bin.parent().unwrap_or(&args.node_bin))
.status()
.with_context(|| "Failed to run tsdown")?;
if !status.success() {
anyhow::bail!("tsdown failed with exit code: {:?}", status.code());
}
println!(" tsdown completed successfully");
println!();
println!("Stage 4: Copying build output...");
let dist_dir = build_dir.join("dist");
if !dist_dir.exists() {
anyhow::bail!(
"dist/ directory not found after tsdown build.\n\
Expected at: {}\n\
Check tsdown.config.ts for output configuration.",
dist_dir.display()
);
}
let output_dist = args.output.join("dist");
copy_dir_recursive(&dist_dir, &output_dist)?;
let package_json_src = build_dir.join("package.json");
if package_json_src.exists() {
fs::copy(&package_json_src, args.output.join("package.json"))?;
}
for file in &["README.md", "tsconfig.json", "tsconfig.build.json"] {
let src_file = build_dir.join(file);
if src_file.exists() {
fs::copy(&src_file, args.output.join(file))?;
}
}
println!();
println!("Stage 5: Cleaning up...");
fs::remove_dir_all(&build_dir)?;
fs::remove_dir_all(&node_modules_build)?;
println!();
println!("Done!");
println!(" Output: {}", args.output.display());
println!(" dist/: {}", output_dist.display());
Ok(())
}