Skip to content

package.json and tsconfig.json module values conflict #324

@spacebear21

Description

@spacebear21

Disclaimer: I am not a JS expert and used Claude liberally to troubleshoot and explain things to me.

I am using this library to generate WASM + JS bindings that can run in Node.js (payjoin/rust-payjoin#1190). I've got it mostly working by just setting target: nodejs in the ubrn.config.yaml. However, there was an issue with module imports resulting in the error below when executing the generated code:

❯ npm run test

> [email protected] test
> node test.js

file:///Users/spacebear/Projects/rust-payjoin/payjoin-ffi/javascript/dist/generated/bitcoin.js:7
import { AbstractFfiConverterByteArray, FfiConverterArray, FfiConverterArrayBuffer, FfiConverterBool, FfiConverterFloat64, FfiConverterInt32, FfiConverterObject, FfiConverterUInt32, FfiConverterUInt64, FfiConverterUInt8, UniffiAbstractObject, UniffiError, UniffiInternalError, UniffiRustCaller, destructorGuardSymbol, pointerLiteralSymbol, uniffiCreateFfiConverterString, uniffiCreateRecord, uniffiTypeNameSymbol, } from "uniffi-bindgen-react-native";
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: The requested module 'uniffi-bindgen-react-native' does not provide an export named 'AbstractFfiConverterByteArray'
    at #_instantiate (node:internal/modules/esm/module_job:254:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:369:5)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:691:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)

Node.js v24.11.0

This seems to be caused by a conflict between package.json which specifies "type": "module", and tsconfig.json which sets "module": "commonjs". The package declares itself as ESM but compiles to CommonJS.

I found a note in the TS documentation which states:

Node.js’s rules for module format detection and interoperability make it incorrect to specify module as esnext or commonjs for projects that run in Node.js, even if all files emitted by tsc are ESM or CJS, respectively. The only correct module settings for projects that intend to run in Node.js are node16 and nodenext. While the emitted JavaScript for an all-ESM Node.js project might look identical between compilations using esnext and nodenext, the type checking can differ. See the reference section on nodenext for more details.

I was able to get around this issue with a fork that changes the tsconfig module value to nodenext and updates the imports accordingly, but it would be nice to upstream a fix into the next official release. I'm not sure whether my solution is compatible with other JS settings e.g. React Native and web, as I only validated it in Node, but will open a draft PR for consideration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions