Repository: ergoplatform/sigma-rust (language: rust)

Issue:
Issue running `ergo-lib-wasm-browser` in Node environments
Although it may seem weird to run `ergo-lib-wasm-browser` in Node environments (as we have `ergo-lib-wasm-node`), it makes sense when we consider writing tests for apps that use `ergo-lib-wasm-browser` using tools running in Node. It's not possible to write tests using Jest or Vitest, for example, if we add this package to an app dependencies.

The issue is not directly related to `sigma-rust`, however; Unfortunately, `wasm-pack` output `package.json` only contains a `module` field. There are no `type: module`, `main` or `exports` fields available so that Node can handle the package as expected. There is [an open pull request](https://github.com/rustwasm/wasm-pack/pull/1061) in `wasm-pack` repo to fix the issue, but it's not merged yet.

Meanwhile, we can wait for `wasm-pack` to fix their issue and use tools such as `patch-package` to bypass the problem, or we can apply some minor modifications to the output of `wasm-pack` and add required fields to the generated `package.json`.


Discussion / hints:
Thanks for bringing this up! 
I have no high hopes that the wasm-pack PR will be merged anytime soon. We have a few scripts already that modify package.json after the build (see https://github.com/ergoplatform/sigma-rust/tree/develop/bindings/ergo-lib-wasm/scripts). Could you please add a new one for this matter?

Sure.

I can add the official Node standard `exports` field, or I can just remove the `module` field in favor of `main` and `type: module`, like the open pull request in `wasm-pack`, so that we remove the script later IF the pull request gets merged. We can also just add new fields and leave the old ones as-is.

Which one do you think is better to implement?
Thanks for picking it up! I don't know that much about the ecosystem so I leave it up to you. I'm not sure if wasm-pack PR gets merged at all. I'd prefer the method that does not affect/brake the browser workflow. 
Ok.

I work on it and create a PR asap.
Another possible option could be using the node package in tests and the browser package in browser - since `wasm-pack` is targeting a different environment I wouldn't be surprised if there were other env related issues aside from imports.

I've done something like this in the past, and I think I've seen some other projects do something like this too:

```ts
export const initErgo = async (): Promise<Ergo> => {
  if (!ergo) {
    // Tests are ran using jest (nodejs) otherwise we should be in the browser
    ergo = await (process.env.NODE_ENV === 'test'
      ? import('ergo-lib-wasm-nodejs')
      : import('ergo-lib-wasm-browser'));
  }

  return ergo;
};
```
@ross-weir
In my opinion, different JS environments are getting closer to each other. ESM support is a good example. I don't know if we get other env related issues in the future. In my own use case, that didn't happen, but it may happen for others.

Anyway, using the node version of the package instead of the browser version for tests is a kind of mocking. Although it works, I really prefer not to mock the whole package in favor of another package. Considering they both get generated from the same rust code, there still may be some differences in the generated code that we lose by mocking.  

Mocking is a code smell. I think in our case, we can provide the better solution of fixing `package.json` and let the possible users facing other env related issues (if any) mock the package using the node output.

Fix patch:
diff --git a/bindings/ergo-lib-wasm/package.json b/bindings/ergo-lib-wasm/package.json
index 81572f24e..2aa8daccd 100644
--- a/bindings/ergo-lib-wasm/package.json
+++ b/bindings/ergo-lib-wasm/package.json
@@ -10,8 +10,8 @@
         "doc": "jsdoc -c jsdoc.json pkg/ergo_wallet_wasm.js README.md -d docs",
         "build-nodejs": "rm -rf ./pkg-nodejs && wasm-pack build --target nodejs --out-dir pkg-nodejs && cd pkg-nodejs && node ../scripts/publish_helper -nodejs",
         "build-nodejs-alpha": "rm -rf ./pkg-nodejs && wasm-pack build --target nodejs --out-dir pkg-nodejs && cd pkg-nodejs && node ../scripts/publish_helper -nodejs && npm version minor && node ../scripts/set_alpha_version -nodejs $(git rev-parse --short HEAD)",
-        "build-browser": "rm -rf ./pkg-browser && wasm-pack build --target browser --out-dir pkg-browser --features rest && cd pkg-browser && node ../scripts/publish_helper -browser",
-        "build-browser-alpha": "rm -rf ./pkg-browser && wasm-pack build --target browser --out-dir pkg-browser --features rest && cd pkg-browser && node ../scripts/publish_helper -browser && npm version minor && node ../scripts/set_alpha_version -browser $(git rev-parse --short HEAD)",
+        "build-browser": "rm -rf ./pkg-browser && wasm-pack build --target browser --out-dir pkg-browser --features rest && cd pkg-browser && node ../scripts/publish_helper -browser && node ../scripts/set_exports",
+        "build-browser-alpha": "rm -rf ./pkg-browser && wasm-pack build --target browser --out-dir pkg-browser --features rest && cd pkg-browser && node ../scripts/publish_helper -browser && node ../scripts/set_exports && npm version minor && node ../scripts/set_alpha_version -browser $(git rev-parse --short HEAD)",
         "publish-nodejs": "npm run build-nodejs &&  cd pkg-nodejs && npm publish",
         "publish-browser": "npm run build-browser && cd pkg-browser && npm publish"
     },
diff --git a/bindings/ergo-lib-wasm/scripts/set_exports.js b/bindings/ergo-lib-wasm/scripts/set_exports.js
new file mode 100644
index 000000000..9aa5b1362
--- /dev/null
+++ b/bindings/ergo-lib-wasm/scripts/set_exports.js
@@ -0,0 +1,19 @@
+const fs = require("fs");
+
+// Remove "module" from the generated (old) {package.json}
+const {
+  module: unusedModule,
+  ...oldPackageJson
+} = require(`../pkg-browser/package.json`);
+
+const newPackageJson = {
+  ...oldPackageJson,
+  type: "module",
+  exports: {
+    ".": "./ergo_lib_wasm",
+  },
+};
+
+console.log(newPackageJson);
+
+fs.writeFileSync("./package.json", JSON.stringify(newPackageJson, null, 2));


Test patch: