use std::path::PathBuf;
use tracing::info;
use crate::compile::{CargoDriver, Compiler};
use crate::error::{Error, Result};
use crate::npm::Assembler;
use crate::project::Project;
use crate::target::TargetResolver;
pub const DEFAULT_OUT: &str = "dist/npm";
pub const DEFAULT_DRIVER: &str = "cargo";
const TAG_PREFIX: &str = "v";
#[derive(Debug)]
pub struct Generator<'a> {
project: &'a Project,
out: PathBuf,
tag: Option<String>,
no_build: bool,
driver: String,
targets: Vec<String>,
}
impl<'a> Generator<'a> {
pub fn new(project: &'a Project) -> Self {
Self {
project,
out: PathBuf::from(DEFAULT_OUT),
tag: None,
no_build: false,
driver: DEFAULT_DRIVER.to_owned(),
targets: Vec::new(),
}
}
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 run(&self) -> Result<()> {
let project = self.project;
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(())
}
}