From eda96852438f2008567fa4376ce7abadf6dc56a0 Mon Sep 17 00:00:00 2001 From: Stevie Gayet Date: Sun, 30 Mar 2025 16:51:20 +0200 Subject: [PATCH] feat(build): add optional `package_name` parameter This commit adds optional `package_name` parameter, which defaults to Rust crate name. --- docs/src/commands/build.md | 14 ++++++++ src/command/build.rs | 8 +++++ src/manifest/mod.rs | 37 ++++++++++++++------ tests/all/manifest.rs | 70 ++++++++++++++++++++++++++++++-------- 4 files changed, 104 insertions(+), 25 deletions(-) diff --git a/docs/src/commands/build.md b/docs/src/commands/build.md index 9b12922e..627d3af6 100644 --- a/docs/src/commands/build.md +++ b/docs/src/commands/build.md @@ -115,6 +115,20 @@ the npm documentation [here][npm-scope-documentation]. [npm-scope-documentation]: https://docs.npmjs.com/misc/scope +## Name + +The `build` command also accepts an optional `--package-name` argument. This will override package name, which defaults to crate name. For example: + +``` +wasm-pack build examples/js-hello-world --package-name hello-world +``` + +This command would create a `package.json` file for a package called +`hello-world`. For more information about scoping, you can refer to +the npm documentation [here][npm-name-documentation]. + +[npm-name-documentation]: https://docs.npmjs.com/cli/v11/configuring-npm/package-json#name + ## Mode The `build` command accepts an optional `--mode` argument. diff --git a/src/command/build.rs b/src/command/build.rs index 11d3ab98..f1558c6a 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -28,6 +28,7 @@ pub struct Build { pub crate_path: PathBuf, pub crate_data: manifest::CrateData, pub scope: Option, + pub package_name: Option, pub disable_dts: bool, pub weak_refs: bool, pub reference_types: bool, @@ -124,6 +125,10 @@ pub struct BuildOptions { #[clap(long = "scope", short = 's')] pub scope: Option, + /// The npm package name to use in package.json, if any. + #[clap(long = "package-name", short = 'p')] + pub package_name: Option, + #[clap(long = "mode", short = 'm', default_value = "normal")] /// Sets steps to be run. [possible values: no-install, normal, force] pub mode: InstallMode, @@ -191,6 +196,7 @@ impl Default for BuildOptions { Self { path: None, scope: None, + package_name: None, mode: InstallMode::default(), disable_dts: false, weak_refs: false, @@ -247,6 +253,7 @@ impl Build { crate_path, crate_data, scope: build_opts.scope, + package_name: build_opts.package_name, disable_dts: build_opts.disable_dts, weak_refs: build_opts.weak_refs, reference_types: build_opts.reference_types, @@ -392,6 +399,7 @@ impl Build { self.crate_data.write_package_json( &self.out_dir, &self.scope, + &self.package_name, self.disable_dts, self.target, )?; diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index bf715a81..71a1b7d2 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -16,6 +16,7 @@ use self::npm::{ repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage, }; use crate::command::build::{BuildProfile, Target}; +use crate::emoji::PACKAGE; use crate::PBAR; use cargo_metadata::Metadata; use chrono::offset; @@ -621,6 +622,7 @@ impl CrateData { &self, out_dir: &Path, scope: &Option, + package_name: &Option, disable_dts: bool, target: Target, ) -> Result<()> { @@ -636,10 +638,16 @@ impl CrateData { None }; let npm_data = match target { - Target::Nodejs => self.to_commonjs(scope, disable_dts, existing_deps, out_dir), - Target::NoModules => self.to_nomodules(scope, disable_dts, existing_deps, out_dir), - Target::Bundler => self.to_esmodules(scope, disable_dts, existing_deps, out_dir), - Target::Web => self.to_web(scope, disable_dts, existing_deps, out_dir), + Target::Nodejs => { + self.to_commonjs(scope, package_name, disable_dts, existing_deps, out_dir) + } + Target::NoModules => { + self.to_nomodules(scope, package_name, disable_dts, existing_deps, out_dir) + } + Target::Bundler => { + self.to_esmodules(scope, package_name, disable_dts, existing_deps, out_dir) + } + Target::Web => self.to_web(scope, package_name, disable_dts, existing_deps, out_dir), // Deno does not need package.json Target::Deno => return Ok(()), }; @@ -654,6 +662,7 @@ impl CrateData { fn npm_data( &self, scope: &Option, + package_name: &Option, add_js_bg_to_package_json: bool, disable_dts: bool, out_dir: &Path, @@ -670,9 +679,11 @@ impl CrateData { } let pkg = &self.data.packages[self.current_idx]; - let npm_name = match scope { - Some(s) => format!("@{}/{}", s, pkg.name), - None => pkg.name.clone(), + let npm_name = match (scope, package_name) { + (Some(s), Some(name)) => format!("@{}/{}", s, name), + (Some(s), None) => format!("@{}/{}", s, pkg.name.clone()), + (None, Some(name)) => name.clone(), + (None, None) => pkg.name.clone(), }; let dts_file = if !disable_dts { @@ -723,11 +734,12 @@ impl CrateData { fn to_commonjs( &self, scope: &Option, + package_name: &Option, disable_dts: bool, dependencies: Option>, out_dir: &Path, ) -> NpmPackage { - let data = self.npm_data(scope, false, disable_dts, out_dir); + let data = self.npm_data(scope, package_name, false, disable_dts, out_dir); let pkg = &self.data.packages[self.current_idx]; self.check_optional_fields(); @@ -754,11 +766,12 @@ impl CrateData { fn to_esmodules( &self, scope: &Option, + package_name: &Option, disable_dts: bool, dependencies: Option>, out_dir: &Path, ) -> NpmPackage { - let data = self.npm_data(scope, true, disable_dts, out_dir); + let data = self.npm_data(scope, package_name, true, disable_dts, out_dir); let pkg = &self.data.packages[self.current_idx]; self.check_optional_fields(); @@ -787,11 +800,12 @@ impl CrateData { fn to_web( &self, scope: &Option, + package_name: &Option, disable_dts: bool, dependencies: Option>, out_dir: &Path, ) -> NpmPackage { - let data = self.npm_data(scope, false, disable_dts, out_dir); + let data = self.npm_data(scope, package_name, false, disable_dts, out_dir); let pkg = &self.data.packages[self.current_idx]; self.check_optional_fields(); @@ -820,11 +834,12 @@ impl CrateData { fn to_nomodules( &self, scope: &Option, + package_name: &Option, disable_dts: bool, dependencies: Option>, out_dir: &Path, ) -> NpmPackage { - let data = self.npm_data(scope, false, disable_dts, out_dir); + let data = self.npm_data(scope, package_name, false, disable_dts, out_dir); let pkg = &self.data.packages[self.current_idx]; self.check_optional_fields(); diff --git a/tests/all/manifest.rs b/tests/all/manifest.rs index 8d4af2df..27b66192 100644 --- a/tests/all/manifest.rs +++ b/tests/all/manifest.rs @@ -79,7 +79,7 @@ fn it_creates_a_package_json_default_path() { let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, false, Target::Bundler) + .write_package_json(&out_dir, &None, &None, false, Target::Bundler) .is_ok()); let package_json_path = &fixture.path.join("pkg").join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -119,7 +119,7 @@ fn it_creates_a_package_json_provided_path() { let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, false, Target::Bundler) + .write_package_json(&out_dir, &None, &None, false, Target::Bundler) .is_ok()); let package_json_path = &fixture.path.join("pkg").join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -149,7 +149,13 @@ fn it_creates_a_package_json_provided_path_with_scope() { let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &Some("test".to_string()), false, Target::Bundler,) + .write_package_json( + &out_dir, + &Some("test".to_string()), + &None, + false, + Target::Bundler, + ) .is_ok()); let package_json_path = &fixture.path.join("pkg").join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -172,6 +178,42 @@ fn it_creates_a_package_json_provided_path_with_scope() { assert_eq!(actual_files, expected_files); } +#[test] +fn it_creates_a_package_json_provided_path_with_package_name() { + let fixture = fixture::js_hello_world(); + let out_dir = fixture.path.join("pkg"); + let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); + assert!(crate_data + .write_package_json( + &out_dir, + &None, + &Some("hello-world".to_string()), + false, + Target::Bundler, + ) + .is_ok()); + let package_json_path = &fixture.path.join("pkg").join("package.json"); + fs::metadata(package_json_path).unwrap(); + utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); + let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); + assert_eq!(pkg.name, "hello-world"); + assert_eq!(pkg.ty, "module"); + assert_eq!(pkg.main, "js_hello_world.js"); + + let actual_files: HashSet = pkg.files.into_iter().collect(); + let expected_files: HashSet = [ + "js_hello_world.d.ts", + "js_hello_world_bg.js", + "js_hello_world_bg.wasm", + "js_hello_world.js", + ] + .iter() + .map(|&s| String::from(s)) + .collect(); + assert_eq!(actual_files, expected_files); +} + #[test] fn it_creates_a_pkg_json_with_correct_files_on_node() { let fixture = fixture::js_hello_world(); @@ -179,7 +221,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() { let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, false, Target::Nodejs) + .write_package_json(&out_dir, &None, &None, false, Target::Nodejs) .is_ok()); let package_json_path = &out_dir.join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -213,7 +255,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_nomodules() { let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, false, Target::NoModules) + .write_package_json(&out_dir, &None, &None, false, Target::NoModules) .is_ok()); let package_json_path = &out_dir.join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -247,7 +289,7 @@ fn it_creates_a_package_json_with_correct_files_when_out_name_is_provided() { let crate_data = manifest::CrateData::new(&fixture.path, Some("index".to_owned())).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, false, Target::Bundler) + .write_package_json(&out_dir, &None, &None, false, Target::Bundler) .is_ok()); let package_json_path = &fixture.path.join("pkg").join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -280,7 +322,7 @@ fn it_creates_a_pkg_json_in_out_dir() { let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, false, Target::Bundler) + .write_package_json(&out_dir, &None, &None, false, Target::Bundler) .is_ok()); let package_json_path = &fixture.path.join(&out_dir).join("package.json"); @@ -295,7 +337,7 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() { let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, true, Target::Bundler) + .write_package_json(&out_dir, &None, &None, true, Target::Bundler) .is_ok()); let package_json_path = &out_dir.join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -337,7 +379,7 @@ fn it_creates_a_package_json_with_npm_dependencies_provided_by_wasm_bindgen() { ) .unwrap(); assert!(crate_data - .write_package_json(&out_dir, &None, true, Target::Bundler) + .write_package_json(&out_dir, &None, &None, true, Target::Bundler) .is_ok()); let package_json_path = &out_dir.join("package.json"); fs::metadata(package_json_path).unwrap(); @@ -409,7 +451,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() { wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); crate_data - .write_package_json(&out_dir, &None, true, Target::Bundler) + .write_package_json(&out_dir, &None, &None, true, Target::Bundler) .unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); @@ -425,7 +467,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() { wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); crate_data - .write_package_json(&out_dir, &None, true, Target::Bundler) + .write_package_json(&out_dir, &None, &None, true, Target::Bundler) .unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); @@ -464,7 +506,7 @@ fn it_sets_keywords_field_if_available_in_cargo_toml() { wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); crate_data - .write_package_json(&out_dir, &None, true, Target::Bundler) + .write_package_json(&out_dir, &None, &None, true, Target::Bundler) .unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); @@ -482,7 +524,7 @@ fn it_sets_keywords_field_if_available_in_cargo_toml() { wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); crate_data - .write_package_json(&out_dir, &None, true, Target::Bundler) + .write_package_json(&out_dir, &None, &None, true, Target::Bundler) .unwrap(); let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap(); @@ -581,7 +623,7 @@ fn it_lists_license_files_in_files_field_of_package_json() { wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); license::copy_from_crate(&crate_data, &fixture.path, &out_dir).unwrap(); crate_data - .write_package_json(&out_dir, &None, false, Target::Bundler) + .write_package_json(&out_dir, &None, &None, false, Target::Bundler) .unwrap(); let package_json_path = &fixture.path.join("pkg").join("package.json");