use std::path::PathBuf;
use tracing::info;
use crate::compile::{CargoDriver, Compiler};
use crate::error::{Error, Result};
use crate::npm::Assembler;
use crate::project::{Overrides, Project};
use crate::target::TargetResolver;
pub const DEFAULT_MANIFEST_PATH: &str = "Cargo.toml";
pub const DEFAULT_OUT: &str = "dist/npm";
pub const DEFAULT_DRIVER: &str = "cargo";
const TAG_PREFIX: &str = "v";
#[derive(Debug)]
pub struct Generator {
manifest_path: PathBuf,
out: PathBuf,
tag: Option<String>,
no_build: bool,
driver: String,
targets: Vec<String>,
overrides: Overrides,
}
impl Generator {
pub fn builder() -> GeneratorBuilder {
GeneratorBuilder::default()
}
pub fn run(&self) -> Result<()> {
let project = Project::load(&self.manifest_path, &self.overrides)?;
if let Some(tag) = &self.tag {
let expected = format!("{TAG_PREFIX}{}", project.version);
if tag != &expected {
return Err(Error::TagMismatch {
tag: tag.clone(),
expected,
});
}
}
let targets =
TargetResolver::new(&project.config, &project.workspace_root).resolve(&self.targets)?;
if !self.no_build {
let driver = CargoDriver::new(&self.driver);
Compiler::new(&driver).compile_all(&project, &targets)?;
}
Assembler::new(&project, &targets, &self.out).assemble()?;
info!(
package = %project.package_name(),
version = %project.version,
targets = targets.len(),
out = %self.out.display(),
"generated npm publish tree",
);
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct GeneratorBuilder {
manifest_path: PathBuf,
out: PathBuf,
tag: Option<String>,
no_build: bool,
driver: String,
targets: Vec<String>,
overrides: Overrides,
}
impl Default for GeneratorBuilder {
fn default() -> Self {
Self {
manifest_path: PathBuf::from(DEFAULT_MANIFEST_PATH),
out: PathBuf::from(DEFAULT_OUT),
tag: None,
no_build: false,
driver: DEFAULT_DRIVER.to_owned(),
targets: Vec::new(),
overrides: Overrides::default(),
}
}
}
impl GeneratorBuilder {
pub fn manifest_path(mut self, path: impl Into<PathBuf>) -> Self {
self.manifest_path = path.into();
self
}
pub fn out(mut self, out: impl Into<PathBuf>) -> Self {
self.out = out.into();
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.tag = Some(tag.into());
self
}
pub fn no_build(mut self, no_build: bool) -> Self {
self.no_build = no_build;
self
}
pub fn driver(mut self, driver: impl Into<String>) -> Self {
self.driver = driver.into();
self
}
pub fn targets(mut self, targets: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.targets = targets.into_iter().map(Into::into).collect();
self
}
pub fn overrides(mut self, overrides: Overrides) -> Self {
self.overrides = overrides;
self
}
pub fn package(mut self, package: impl Into<String>) -> Self {
self.overrides.package = Some(package.into());
self
}
pub fn bin(mut self, bin: impl Into<String>) -> Self {
self.overrides.bin = Some(bin.into());
self
}
pub fn version(mut self, version: impl Into<String>) -> Self {
self.overrides.version = Some(version.into());
self
}
pub fn build(self) -> Generator {
Generator {
manifest_path: self.manifest_path,
out: self.out,
tag: self.tag,
no_build: self.no_build,
driver: self.driver,
targets: self.targets,
overrides: self.overrides,
}
}
}