Repository: rustwasm/wasm-pack (rust)

Issue:
Missing wasm-bindgen file in package.json
Hey team! I'm hitting an issue with the packing step of `wasm-pack`. I think I'm missing a file in my `package.json`'s files section. It's affecting module resolution after I `npm install` the output from `wasm-pack pack`.

Consider the test fixture `js-hello-world`. After `wasm-pack init -t nodejs`, `wasm-bindgen` generates a typescript file, two javascript files, and one WASM file:

```bash 
$ ls -al pkg 
total 624
drwxr-xr-x  9 mciantyre  staff     288 Jul  6 17:08 .
drwxr-xr-x  9 mciantyre  staff     288 Jul  6 17:33 ..
-rw-r--r--  1 mciantyre  staff      51 Jul  6 17:57 README.md
-rw-r--r--  1 mciantyre  staff   74708 Jul  6 17:08 js-hello-world-0.1.0.tgz
-rw-r--r--  1 mciantyre  staff      65 Jul  6 17:58 js_hello_world.d.ts
-rw-r--r--  1 mciantyre  staff    4294 Jul  6 17:58 js_hello_world.js
-rw-r--r--  1 mciantyre  staff     423 Jul  6 17:58 js_hello_world_bg.js
-rw-r--r--  1 mciantyre  staff  216481 Jul  6 17:58 js_hello_world_bg.wasm
-rw-r--r--  1 mciantyre  staff     437 Jul  6 17:57 package.json
```

But the `package.json` is missing `js_hello_world_bg.js`:

```json
  "files": [
    "js_hello_world_bg.wasm",
    "js_hello_world.d.ts"
  ],
```

It seems that if that third file isn't provided, `wasm-pack pack` doesn't include it in the output tar. Then, after I `npm install` the tar and require the package, node throws a module resolution error.

As a minimum example, from the `tests/fixtures/js-hello-world` example:

```bash
$ wasm-pack init -t nodejs
$ mkdir example && cd example
$ npm init -y
$ npm install ../pkg/js-hello-world-0.1.0.tgz
$ cat << EOF > index.js
  var lib = require('js-hello-world');
  EOF
$ node index.js

internal/modules/cjs/loader.js:583
    throw err;
    ^

Error: Cannot find module './js_hello_world_bg'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object.<anonymous> (/Users/mciantyre/Projects/wasm-pack/tests/fixtures/js-hello-world/example/node_modules/js-hello-world/js_hello_world.js:178:8)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)

```

If I go back to `pkg/package.json` to make it look like

```javascript
  "files": [
    "js_hello_world_bg.wasm",
    "js_hello_world.d.ts",
    "js_hello_world_bg.js" // new file here
  ],
```

re-pack with `wasm-pack pack`, and re-install the tar with `npm install`, everything is good.

Sorry if this is already a known issue. If it's more helpful to have another example, let me know and I can put something together.

I have what I believe to be a fix for `wasm-pack`. My patch worked on this example and my other use-case. Say the word, and I'll open a PR!

Versions of all the things:

- wasm-pack 0.4.0
- node v10.6.0
- npm 6.1.0
- rustc 1.28.0-nightly (e3bf634e0 2018-06-28)
- MacOS 10.13.5


Pull request description:
fix files behavior on node, and generally remove redundancy in the files key
fixes #199 (FOR REAL THIS TIME)

this PR does several things:
- passes the value of the target flag to the `write_package_json` method
- optionally includes a `_bg.js` file in the `files` key if the `target` is `nodejs`
- updates `files` key to NOT include the file in `main` (it is unecessary)
- adds a test to ensure correct behavior on node
- cleans up tests to test for correct `files` key

Patch:
diff --git a/src/command/init.rs b/src/command/init.rs
index b65c7e3..d35cf95 100644
--- a/src/command/init.rs
+++ b/src/command/init.rs
@@ -161,7 +161,13 @@ impl Init {
 
     fn step_create_json(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
         info!(&log, "Writing a package.json...");
-        manifest::write_package_json(&self.crate_path, &self.scope, self.disable_dts, step)?;
+        manifest::write_package_json(
+            &self.crate_path,
+            &self.scope,
+            self.disable_dts,
+            &self.target,
+            step,
+        )?;
         #[cfg(not(target_os = "windows"))]
         info!(
             &log,
diff --git a/src/manifest.rs b/src/manifest.rs
index 7addfb5..e545a1a 100644
--- a/src/manifest.rs
+++ b/src/manifest.rs
@@ -68,16 +68,23 @@ fn read_cargo_toml(path: &str) -> Result<CargoManifest, Error> {
 }
 
 impl CargoManifest {
-    fn into_npm(mut self, scope: &Option<String>, disable_dts: bool) -> NpmPackage {
+    fn into_npm(mut self, scope: &Option<String>, disable_dts: bool, target: &str) -> NpmPackage {
         let filename = self.package.name.replace("-", "_");
         let wasm_file = format!("{}_bg.wasm", filename);
         let js_file = format!("{}.js", filename);
+
         let dts_file = if disable_dts == true {
             None
         } else {
             Some(format!("{}.d.ts", filename))
         };
 
+        let js_bg_file = if target == "nodejs" {
+            Some(format!("{}_bg.js", filename))
+        } else {
+            None
+        };
+
         if let Some(s) = scope {
             self.package.name = format!("@{}/{}", s, self.package.name);
         }
@@ -90,6 +97,13 @@ impl CargoManifest {
             None => {}
         }
 
+        match js_bg_file {
+            Some(ref js_bg_file) => {
+                files.push(js_bg_file.to_string());
+            }
+            None => {}
+        }
+
         NpmPackage {
             name: self.package.name,
             collaborators: self.package.authors,
@@ -112,6 +126,7 @@ pub fn write_package_json(
     path: &str,
     scope: &Option<String>,
     disable_dts: bool,
+    target: &str,
     step: &Step,
 ) -> Result<(), Error> {
     let msg = format!("{}Writing a package.json...", emoji::MEMO);
@@ -127,7 +142,7 @@ pub fn write_package_json(
     let pkg_file_path = format!("{}/pkg/package.json", path);
     let mut pkg_file = File::create(pkg_file_path)?;
     let crate_data = read_cargo_toml(path)?;
-    let npm_data = crate_data.into_npm(scope, disable_dts);
+    let npm_data = crate_data.into_npm(scope, disable_dts, target);
 
     if npm_data.description.is_none() {
         PBAR.warn(&warn_fmt("description"));


Test patch:
diff --git a/tests/manifest/main.rs b/tests/manifest/main.rs
index 6f2b039..cf66196 100644
--- a/tests/manifest/main.rs
+++ b/tests/manifest/main.rs
@@ -6,6 +6,7 @@ extern crate wasm_pack;
 
 mod utils;
 
+use std::collections::HashSet;
 use std::fs;
 
 use wasm_pack::manifest;
@@ -48,7 +49,7 @@ fn it_creates_a_package_json_default_path() {
     let step = wasm_pack::progressbar::Step::new(1);
     let path = ".".to_string();
     wasm_pack::command::init::create_pkg_dir(&path, &step).unwrap();
-    assert!(manifest::write_package_json(&path, &None, false, &step).is_ok());
+    assert!(manifest::write_package_json(&path, &None, false, "", &step).is_ok());
     let package_json_path = format!("{}/pkg/package.json", &path);
     assert!(fs::metadata(package_json_path).is_ok());
     assert!(utils::read_package_json(&path).is_ok());
@@ -59,10 +60,16 @@ fn it_creates_a_package_json_default_path() {
         pkg.repository.url,
         "https://github.com/ashleygwilliams/wasm-pack.git"
     );
-    assert_eq!(pkg.files, ["wasm_pack_bg.wasm", "wasm_pack.d.ts"]);
     assert_eq!(pkg.main, "wasm_pack.js");
     let types = pkg.types.unwrap_or_default();
     assert_eq!(types, "wasm_pack.d.ts");
+
+    let actual_files: HashSet<String> = pkg.files.into_iter().collect();
+    let expected_files: HashSet<String> = ["wasm_pack_bg.wasm", "wasm_pack.d.ts"]
+        .iter()
+        .map(|&s| String::from(s))
+        .collect();
+    assert_eq!(actual_files, expected_files);
 }
 
 #[test]
@@ -70,12 +77,20 @@ fn it_creates_a_package_json_provided_path() {
     let step = wasm_pack::progressbar::Step::new(1);
     let path = "tests/fixtures/js-hello-world".to_string();
     wasm_pack::command::init::create_pkg_dir(&path, &step).unwrap();
-    assert!(manifest::write_package_json(&path, &None, false, &step).is_ok());
+    assert!(manifest::write_package_json(&path, &None, false, "", &step).is_ok());
     let package_json_path = format!("{}/pkg/package.json", &path);
     assert!(fs::metadata(package_json_path).is_ok());
     assert!(utils::read_package_json(&path).is_ok());
     let pkg = utils::read_package_json(&path).unwrap();
     assert_eq!(pkg.name, "js-hello-world");
+    assert_eq!(pkg.main, "js_hello_world.js");
+
+    let actual_files: HashSet<String> = pkg.files.into_iter().collect();
+    let expected_files: HashSet<String> = ["js_hello_world_bg.wasm", "js_hello_world.d.ts"]
+        .iter()
+        .map(|&s| String::from(s))
+        .collect();
+    assert_eq!(actual_files, expected_files);
 }
 
 #[test]
@@ -83,12 +98,77 @@ fn it_creates_a_package_json_provided_path_with_scope() {
     let step = wasm_pack::progressbar::Step::new(1);
     let path = "tests/fixtures/scopes".to_string();
     wasm_pack::command::init::create_pkg_dir(&path, &step).unwrap();
-    assert!(manifest::write_package_json(&path, &Some("test".to_string()), false, &step).is_ok());
+    assert!(
+        manifest::write_package_json(&path, &Some("test".to_string()), false, "", &step).is_ok()
+    );
     let package_json_path = format!("{}/pkg/package.json", &path);
     assert!(fs::metadata(package_json_path).is_ok());
     assert!(utils::read_package_json(&path).is_ok());
     let pkg = utils::read_package_json(&path).unwrap();
     assert_eq!(pkg.name, "@test/scopes-hello-world");
+    assert_eq!(pkg.main, "scopes_hello_world.js");
+
+    let actual_files: HashSet<String> = pkg.files.into_iter().collect();
+    let expected_files: HashSet<String> = ["scopes_hello_world_bg.wasm", "scopes_hello_world.d.ts"]
+        .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 step = wasm_pack::progressbar::Step::new(1);
+    let path = ".".to_string();
+    wasm_pack::command::init::create_pkg_dir(&path, &step).unwrap();
+    assert!(manifest::write_package_json(&path, &None, false, "nodejs", &step).is_ok());
+    let package_json_path = format!("{}/pkg/package.json", &path);
+    assert!(fs::metadata(package_json_path).is_ok());
+    assert!(utils::read_package_json(&path).is_ok());
+    let pkg = utils::read_package_json(&path).unwrap();
+    assert_eq!(pkg.name, "wasm-pack");
+    assert_eq!(pkg.repository.ty, "git");
+    assert_eq!(
+        pkg.repository.url,
+        "https://github.com/ashleygwilliams/wasm-pack.git"
+    );
+    assert_eq!(pkg.main, "wasm_pack.js");
+    let types = pkg.types.unwrap_or_default();
+    assert_eq!(types, "wasm_pack.d.ts");
+
+    let actual_files: HashSet<String> = pkg.files.into_iter().collect();
+    let expected_files: HashSet<String> =
+        ["wasm_pack_bg.wasm", "wasm_pack_bg.js", "wasm_pack.d.ts"]
+            .iter()
+            .map(|&s| String::from(s))
+            .collect();
+    assert_eq!(actual_files, expected_files);
+}
+
+#[test]
+fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
+    let step = wasm_pack::progressbar::Step::new(1);
+    let path = ".".to_string();
+    wasm_pack::command::init::create_pkg_dir(&path, &step).unwrap();
+    assert!(manifest::write_package_json(&path, &None, true, "", &step).is_ok());
+    let package_json_path = format!("{}/pkg/package.json", &path);
+    assert!(fs::metadata(package_json_path).is_ok());
+    assert!(utils::read_package_json(&path).is_ok());
+    let pkg = utils::read_package_json(&path).unwrap();
+    assert_eq!(pkg.name, "wasm-pack");
+    assert_eq!(pkg.repository.ty, "git");
+    assert_eq!(
+        pkg.repository.url,
+        "https://github.com/ashleygwilliams/wasm-pack.git"
+    );
+    assert_eq!(pkg.main, "wasm_pack.js");
+
+    let actual_files: HashSet<String> = pkg.files.into_iter().collect();
+    let expected_files: HashSet<String> = ["wasm_pack_bg.wasm"]
+        .iter()
+        .map(|&s| String::from(s))
+        .collect();
+    assert_eq!(actual_files, expected_files);
 }
 
 #[test]