mod build;
mod bun;
mod cache;
pub mod command;
pub mod detect;
pub mod error;
mod export;
mod interactive;
pub mod kicad;
pub mod output;
mod process;
#[cfg(test)]
mod tests;
use std::path::{Path, PathBuf};
pub use bun::bun_path;
pub use command::{
add_command, build_command, dev_command, export_command, install_command, search_command,
};
pub use detect::detect_runner;
pub use error::RunnerError;
pub use kicad::convert_kicad;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RunnerKind {
Local(PathBuf),
Global(PathBuf),
Bun(PathBuf),
}
impl RunnerKind {
pub fn description(&self) -> String {
match self {
Self::Local(p) => format!("local executable ({})", p.display()),
Self::Global(p) => format!("global executable ({})", p.display()),
Self::Bun(p) => format!("bun x tsci via {}", p.display()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Runner {
kind: RunnerKind,
}
pub fn detect() -> Result<Runner, RunnerError> {
Runner::detect()
}
impl Runner {
pub fn new(kind: RunnerKind) -> Self {
Self { kind }
}
pub fn detect() -> Result<Self, RunnerError> {
let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
let path_var = std::env::var_os("PATH");
detect_runner(¤t_dir, path_var.as_deref())
}
pub fn kind(&self) -> &RunnerKind {
&self.kind
}
}
fn resolve_hardware_context(file: &Path) -> (Option<PathBuf>, PathBuf) {
if let Some(parent) = file.parent() {
if !parent.as_os_str().is_empty() && parent.join("package.json").is_file() {
let filename = file
.file_name()
.map(PathBuf::from)
.unwrap_or_else(|| file.to_path_buf());
return (Some(parent.to_path_buf()), filename);
}
}
if Path::new("hardware").join("package.json").is_file() {
if let Ok(rel) = file.strip_prefix("hardware") {
return (Some(PathBuf::from("hardware")), rel.to_path_buf());
}
}
(None, file.to_path_buf())
}