diff --git a/src/bindgen.rs b/src/bindgen.rs index 3bc2946d..d48887f2 100644 --- a/src/bindgen.rs +++ b/src/bindgen.rs @@ -189,6 +189,7 @@ pub fn wasm_bindgen_build( }; let out_dir = out_dir.to_str().unwrap(); + let out_name = &[data.crate_name(), target.to_owned()].join("_"); let wasm_path = data .target_directory() @@ -212,6 +213,8 @@ pub fn wasm_bindgen_build( cmd.arg(&wasm_path) .arg("--out-dir") .arg(out_dir) + .arg("--out-name") + .arg(out_name) .arg(dts_arg) .arg(target_arg); diff --git a/src/command/build.rs b/src/command/build.rs index c6bad240..c1d79321 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -25,7 +25,7 @@ pub struct Build { pub crate_data: manifest::CrateData, pub scope: Option, pub disable_dts: bool, - pub target: String, + pub targets: Vec, pub profile: BuildProfile, pub mode: BuildMode, pub out_dir: PathBuf, @@ -99,7 +99,7 @@ pub struct BuildOptions { #[structopt(long = "target", short = "t", default_value = "browser")] /// Sets the target environment. [possible values: browser, nodejs, no-modules] - pub target: String, + pub target: Vec, #[structopt(long = "debug")] /// Deprecated. Renamed to `--dev`. @@ -134,7 +134,7 @@ impl Default for BuildOptions { scope: None, mode: BuildMode::Normal, disable_dts: false, - target: String::new(), + target: vec![], debug: false, dev: false, release: false, @@ -166,8 +166,10 @@ impl Build { // `possible_values` in clap isn't supported by `structopt` let possible_targets = ["browser", "nodejs", "no-modules"]; - if !possible_targets.contains(&build_opts.target.as_str()) { - bail!("Supported targets: browser, nodejs, no-modules"); + for target in &build_opts.target { + if !possible_targets.contains(&target.as_str()) { + bail!("Supported targets: browser, nodejs, no-modules"); + } } Ok(Build { @@ -175,7 +177,7 @@ impl Build { crate_data, scope: build_opts.scope, disable_dts: build_opts.disable_dts, - target: build_opts.target, + targets: build_opts.target, profile, mode: build_opts.mode, out_dir, @@ -315,7 +317,7 @@ impl Build { &self.out_dir, &self.scope, self.disable_dts, - &self.target, + &self.targets.iter().map(|n| n.as_ref()).collect::>(), step, )?; info!( @@ -358,15 +360,17 @@ impl Build { fn step_run_wasm_bindgen(&mut self, step: &Step) -> Result<(), Error> { info!("Building the wasm bindings..."); - bindgen::wasm_bindgen_build( - &self.crate_data, - self.bindgen.as_ref().unwrap(), - &self.out_dir, - self.disable_dts, - &self.target, - self.profile, - step, - )?; + for target in &self.targets { + bindgen::wasm_bindgen_build( + &self.crate_data, + self.bindgen.as_ref().unwrap(), + &self.out_dir, + self.disable_dts, + target, + self.profile, + step, + )?; + } info!("wasm bindings were built at {:#?}.", &self.out_dir); Ok(()) } diff --git a/src/command/publish/mod.rs b/src/command/publish/mod.rs index 568104b4..5e16b1f8 100644 --- a/src/command/publish/mod.rs +++ b/src/command/publish/mod.rs @@ -47,7 +47,7 @@ pub fn publish( .to_string(); let build_opts = BuildOptions { path: Some(crate_path.clone()), - target, + target: vec![target], out_dir: out_dir.clone(), ..Default::default() }; diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 92f03cd4..ea9a0c56 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -5,9 +5,7 @@ mod npm; use std::fs; use std::path::Path; -use self::npm::{ - repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage, -}; +use self::npm::NpmPackage; use cargo_metadata::Metadata; use command::build::BuildProfile; use emoji; @@ -366,22 +364,32 @@ impl CrateData { out_dir: &Path, scope: &Option, disable_dts: bool, - target: &str, + targets: &[&str], step: &Step, ) -> Result<(), Error> { let msg = format!("{}Writing a package.json...", emoji::MEMO); PBAR.step(step, &msg); let pkg_file_path = out_dir.join("package.json"); - let npm_data = if target == "nodejs" { - self.to_commonjs(scope, disable_dts) - } else if target == "no-modules" { - self.to_nomodules(scope, disable_dts) - } else { - self.to_esmodules(scope, disable_dts) - }; + let mut npm_package = self.to_base_package(scope, disable_dts, targets[0]); + for target in targets { + if target == &"nodejs" { + let mut npm_data = self.npm_data(scope, false, disable_dts, target); + npm_package.main = Some(npm_data.main); + npm_package.files.append(&mut npm_data.files); + } else if target == &"no-modules" { + let mut npm_data = self.npm_data(scope, false, disable_dts, target); + npm_package.browser = Some(npm_data.main.clone()); + npm_package.files.append(&mut npm_data.files); + } else { + let mut npm_data = self.npm_data(scope, false, disable_dts, target); + npm_package.module = Some(npm_data.main.clone()); + npm_package.side_effects = Some("false".to_string()); + npm_package.files.append(&mut npm_data.files); + } + } - let npm_json = serde_json::to_string_pretty(&npm_data)?; + let npm_json = serde_json::to_string_pretty(&npm_package)?; fs::write(&pkg_file_path, npm_json) .with_context(|_| format!("failed to write: {}", pkg_file_path.display()))?; Ok(()) @@ -392,15 +400,16 @@ impl CrateData { scope: &Option, include_commonjs_shim: bool, disable_dts: bool, + target: &str, ) -> NpmData { let crate_name = self.crate_name(); - let wasm_file = format!("{}_bg.wasm", crate_name); - let js_file = format!("{}.js", crate_name); + let wasm_file = format!("{}_{}_bg.wasm", crate_name, target); + let js_file = format!("{}_{}.js", crate_name, target); let mut files = vec![wasm_file]; files.push(js_file.clone()); if include_commonjs_shim { - let js_bg_file = format!("{}_bg.js", crate_name); + let js_bg_file = format!("{}_{}_bg.js", crate_name, target); files.push(js_bg_file.to_string()); } @@ -411,7 +420,7 @@ impl CrateData { }; let dts_file = if !disable_dts { - let file = format!("{}.d.ts", crate_name); + let file = format!("{}_{}.d.ts", crate_name, target); files.push(file.to_string()); Some(file) } else { @@ -425,86 +434,18 @@ impl CrateData { } } - fn to_commonjs(&self, scope: &Option, disable_dts: bool) -> NpmPackage { - let data = self.npm_data(scope, true, disable_dts); - let pkg = &self.data.packages[self.current_idx]; - - self.check_optional_fields(); - - NpmPackage::CommonJSPackage(CommonJSPackage { - name: data.name, - collaborators: pkg.authors.clone(), - description: self.manifest.package.description.clone(), - version: pkg.version.clone(), - license: self.manifest.package.license.clone(), - repository: self - .manifest - .package - .repository - .clone() - .map(|repo_url| Repository { - ty: "git".to_string(), - url: repo_url, - }), - files: data.files, - main: data.main, - types: data.dts_file, - }) - } - - fn to_esmodules(&self, scope: &Option, disable_dts: bool) -> NpmPackage { - let data = self.npm_data(scope, false, disable_dts); - let pkg = &self.data.packages[self.current_idx]; - - self.check_optional_fields(); - - NpmPackage::ESModulesPackage(ESModulesPackage { - name: data.name, - collaborators: pkg.authors.clone(), - description: self.manifest.package.description.clone(), - version: pkg.version.clone(), - license: self.manifest.package.license.clone(), - repository: self - .manifest - .package - .repository - .clone() - .map(|repo_url| Repository { - ty: "git".to_string(), - url: repo_url, - }), - files: data.files, - module: data.main, - types: data.dts_file, - side_effects: "false".to_string(), - }) - } - - fn to_nomodules(&self, scope: &Option, disable_dts: bool) -> NpmPackage { - let data = self.npm_data(scope, false, disable_dts); + fn to_base_package( + &self, + scope: &Option, + disable_dts: bool, + target: &str, + ) -> NpmPackage { + let data = self.npm_data(scope, false, disable_dts, target); let pkg = &self.data.packages[self.current_idx]; self.check_optional_fields(); - NpmPackage::NoModulesPackage(NoModulesPackage { - name: data.name, - collaborators: pkg.authors.clone(), - description: self.manifest.package.description.clone(), - version: pkg.version.clone(), - license: self.manifest.package.license.clone(), - repository: self - .manifest - .package - .repository - .clone() - .map(|repo_url| Repository { - ty: "git".to_string(), - url: repo_url, - }), - files: data.files, - browser: data.main, - types: data.dts_file, - }) + NpmPackage::base(data, &pkg, &self.manifest) } fn check_optional_fields(&self) { diff --git a/src/manifest/npm/commonjs.rs b/src/manifest/npm/commonjs.rs deleted file mode 100644 index ed8b8f99..00000000 --- a/src/manifest/npm/commonjs.rs +++ /dev/null @@ -1,20 +0,0 @@ -use manifest::npm::repository::Repository; - -#[derive(Serialize)] -pub struct CommonJSPackage { - pub name: String, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub collaborators: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - pub version: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub license: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub repository: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub files: Vec, - pub main: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub types: Option, -} diff --git a/src/manifest/npm/esmodules.rs b/src/manifest/npm/esmodules.rs deleted file mode 100644 index df73964e..00000000 --- a/src/manifest/npm/esmodules.rs +++ /dev/null @@ -1,22 +0,0 @@ -use manifest::npm::repository::Repository; - -#[derive(Serialize)] -pub struct ESModulesPackage { - pub name: String, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub collaborators: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - pub version: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub license: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub repository: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub files: Vec, - pub module: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub types: Option, - #[serde(rename = "sideEffects")] - pub side_effects: String, -} diff --git a/src/manifest/npm/mod.rs b/src/manifest/npm/mod.rs index c8d65821..82251dfa 100644 --- a/src/manifest/npm/mod.rs +++ b/src/manifest/npm/mod.rs @@ -1,16 +1,77 @@ -mod commonjs; -mod esmodules; -mod nomodules; pub mod repository; -pub use self::commonjs::CommonJSPackage; -pub use self::esmodules::ESModulesPackage; -pub use self::nomodules::NoModulesPackage; +use self::repository::Repository; +use super::{CargoManifest, NpmData}; #[derive(Serialize)] -#[serde(untagged)] -pub enum NpmPackage { - CommonJSPackage(CommonJSPackage), - ESModulesPackage(ESModulesPackage), - NoModulesPackage(NoModulesPackage), +pub struct NpmPackage { + pub name: String, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub collaborators: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + pub version: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub license: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub files: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub browser: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub main: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub module: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub types: Option, + #[serde(rename = "sideEffects")] + #[serde(skip_serializing_if = "Option::is_none")] + pub side_effects: Option, +} + +impl NpmPackage { + pub(super) fn base( + data: NpmData, + pkg: &cargo_metadata::Package, + manifest: &CargoManifest, + ) -> Self { + Self { + name: data.name, + collaborators: pkg.authors.clone(), + description: manifest.package.description.clone(), + version: pkg.version.clone(), + license: manifest.package.license.clone(), + repository: manifest + .package + .repository + .clone() + .map(|repo_url| Repository { + ty: "git".to_string(), + url: repo_url, + }), + files: vec![], + types: data.dts_file, + ..Self::default() + } + } +} + +impl Default for NpmPackage { + fn default() -> Self { + Self { + name: "".to_owned(), + collaborators: vec![], + description: None, + version: "".to_owned(), + license: None, + repository: None, + files: vec![], + browser: None, + main: None, + module: None, + types: None, + side_effects: None, + } + } } diff --git a/src/manifest/npm/nomodules.rs b/src/manifest/npm/nomodules.rs deleted file mode 100644 index 696a74b0..00000000 --- a/src/manifest/npm/nomodules.rs +++ /dev/null @@ -1,20 +0,0 @@ -use manifest::npm::repository::Repository; - -#[derive(Serialize)] -pub struct NoModulesPackage { - pub name: String, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub collaborators: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - pub version: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub license: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub repository: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub files: Vec, - pub browser: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub types: Option, -}