use std::sync::OnceLock;
#[derive(Clone, Copy, Debug)]
pub struct Embedder {
pub name: &'static str,
pub display_name: &'static str,
pub vendor: Option<&'static str>,
pub version: &'static str,
pub user_agent: &'static str,
pub self_names: &'static [&'static str],
pub compatible_names: &'static [&'static str],
pub lockfile_basename: &'static str,
pub workspace_yaml: Option<&'static str>,
pub manifest_namespace: &'static str,
pub env_prefix: Option<&'static str>,
pub cache_namespace: &'static str,
pub data_namespace: &'static str,
pub canonical_lockfile_always_wins: bool,
pub runtime_switching: bool,
pub self_engines_check: bool,
pub self_update_enabled: bool,
}
pub const AUBE: Embedder = Embedder {
name: "aube",
display_name: "aube",
vendor: Some("by jdx.dev"),
version: env!("CARGO_PKG_VERSION"),
user_agent: concat!("aube/", env!("CARGO_PKG_VERSION")),
self_names: &["aube"],
compatible_names: &["pnpm"],
lockfile_basename: "aube-lock.yaml",
workspace_yaml: Some("aube-workspace.yaml"),
manifest_namespace: "aube",
env_prefix: Some("AUBE"),
cache_namespace: "aube",
data_namespace: "aube",
canonical_lockfile_always_wins: true,
runtime_switching: true,
self_engines_check: true,
self_update_enabled: true,
};
static ACTIVE: OnceLock<&'static Embedder> = OnceLock::new();
pub fn set_embedder(embedder: &'static Embedder) {
debug_assert!(
embedder.lockfile_basename.contains('.'),
"embedder lockfile_basename {:?} must contain a `.` (stem/extension split is load-bearing)",
embedder.lockfile_basename,
);
debug_assert!(
!FOREIGN_LOCKFILE_NAMES.contains(&embedder.lockfile_basename),
"embedder lockfile_basename {:?} aliases a foreign package manager's lockfile; \
pick a distinct name so aube's lockfile stays distinguishable in the candidate set",
embedder.lockfile_basename,
);
let _ = ACTIVE.set(embedder);
}
const FOREIGN_LOCKFILE_NAMES: &[&str] = &[
"pnpm-lock.yaml",
"package-lock.json",
"bun.lock",
"yarn.lock",
"npm-shrinkwrap.json",
];
pub fn embedder() -> &'static Embedder {
ACTIVE.get().copied().unwrap_or(&AUBE)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn embedder_unset_is_aube() {
let id = embedder();
assert_eq!(id.name, "aube");
assert_eq!(id.display_name, "aube");
assert_eq!(id.vendor, Some("by jdx.dev"));
assert_eq!(id.version, env!("CARGO_PKG_VERSION"));
assert_eq!(id.user_agent, concat!("aube/", env!("CARGO_PKG_VERSION")));
assert_eq!(id.self_names, &["aube"]);
assert_eq!(id.compatible_names, &["pnpm"]);
assert_eq!(id.lockfile_basename, "aube-lock.yaml");
assert_eq!(id.workspace_yaml, Some("aube-workspace.yaml"));
assert_eq!(id.manifest_namespace, "aube");
assert_eq!(id.env_prefix, Some("AUBE"));
assert_eq!(id.cache_namespace, "aube");
assert_eq!(id.data_namespace, "aube");
assert!(id.canonical_lockfile_always_wins);
assert!(id.runtime_switching);
assert!(id.self_engines_check);
assert!(id.self_update_enabled);
}
}