Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 37 additions & 7 deletions src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
)]

use anyhow::{anyhow, bail, Context, Result};
use log::debug;
mod npm;

use std::path::Path;
Expand Down Expand Up @@ -625,16 +626,44 @@ impl CrateData {
target: Target,
) -> Result<()> {
let pkg_file_path = out_dir.join("package.json");
// Check if a `package.json` was already generated by wasm-bindgen, if so

// Check if a `package.json` was already generated by wasm-bindgen, if so,
// we merge the NPM dependencies already specified in it.
let existing_deps = if pkg_file_path.exists() {
// It's just a map of dependency names to versions
Some(serde_json::from_str::<HashMap<String, String>>(
&fs::read_to_string(&pkg_file_path)?,
)?)
let package_json_content = fs::read_to_string(&pkg_file_path)?;
debug!("Input package.json path: {:?} content:\n{}", pkg_file_path, package_json_content);

// NOTE: The previous logic failed because it attempted to parse the entire package.json
// as a simple HashMap<String, String>. We now use a two-step parsing process:

// 1. Parse the entire file content into a generic serde_json::Value.
debug!("Starting full JSON parse.");
let full_json: serde_json::Value = serde_json::from_str(&package_json_content)?;
debug!("Finished full JSON parse.");

// 2. Extract the value associated with the "dependencies" key.
if let Some(deps_value) = full_json.get("dependencies") {
// The value must be a JSON object (a map).
if deps_value.is_object() {
// Deserialize the dependency map (Value::Object) back into the
// expected target type: HashMap<String, String>. This handles
// the dependency merging downstream.
debug!("Attempting to deserialize dependencies into HashMap<String, String>.");
let map: HashMap<String, String> = serde_json::from_value(deps_value.clone())?;
debug!("Successfully deserialized dependencies.");
Some(map)
} else {
// If "dependencies" key exists but its value is not an object, skip merging.
None
}
} else {
// If the "dependencies" key does not exist, skip merging.
None
}
} else {
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),
Expand All @@ -643,9 +672,10 @@ impl CrateData {
// Deno does not need package.json
Target::Deno => return Ok(()),
};

let npm_json = serde_json::to_string_pretty(&npm_data)?;

debug!("Output package.json path: {:?} content:\n{}", pkg_file_path, npm_json);

fs::write(&pkg_file_path, npm_json)
.with_context(|| anyhow!("failed to write: {}", pkg_file_path.display()))?;
Ok(())
Expand Down
Loading