paulmillr / micro-key-producer

Produces secure keys and passwords. Supports SSH, PGP, BLS, OTP and many other formats
MIT License
34 stars 9 forks source link

commonjs imports doesn't work with typescript #20

Closed killroy192 closed 3 weeks ago

killroy192 commented 3 weeks ago

The context: .ts application with a "module": "commonjs"

The issue:

Screenshot 2024-06-26 at 15 58 24

I guess the problem is that package.json exports in micro-key-producer explicitly force to use /lib/esm folder when importing the module using the "import" word.

paulmillr commented 3 weeks ago

use moduleResolution ndoe16, nodenext or bundler - as it says

killroy192 commented 3 weeks ago

use moduleResolution ndoe16, nodenext or bundler - as it says

This will require migrate the project to esm, which is not an option. Any chance to add commonJS support for TS?

paulmillr commented 3 weeks ago

No, that's false. It would simply make your module resolution proper even with commonjs.

killroy192 commented 3 weeks ago

@paulmillr please consider mr https://github.com/paulmillr/micro-key-producer/pull/22

killroy192 commented 3 weeks ago

No, that's false. It would simply make your module resolution proper even with commonjs.

sure, keeping commonjs will require importing esm with await import() which makes the code unnecessarily complex. I'd rather use the ts possibilities to generate cjs and esm.

The repo I play with: https://github.com/dgma/mono-helpers

paulmillr commented 3 weeks ago

@killroy192 why would I consider pull request that degrades developer experience?

We have perfectly fine modules which work in BOTH commonjs AND esm today, using /slip10.js. There is no need to write /esm/slip10.js or so.

sure, keeping commonjs will require importing esm with await import()

I don't understand what you're talking about. Commonjs can't import ESM.

paulmillr commented 3 weeks ago

Facts:

  1. The repo supports both esm and commonjs
  2. moduleResolution is independent from module commonjs/esm
  3. Modern moduleResolution must be used even with commonjs
killroy192 commented 3 weeks ago

facts:

  1. comminJS can use esm modules with dynamic imports: https://sliceofdev.com/posts/commonjs-and-esm-modules-interoperability-in-nodejs. Also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.

  2. Setting moduleResolution to 'node16', 'nodenext' or whatever will break commonjs imports.

    Screenshot 2024-06-26 at 10 52 15 PM
  3. I did refactoring in the proposed MR, so anyone can easily import either esm or cjs modules. And they works. I really appreciate your 'wtf' in the comments, hahaha hilarious.

killroy192 commented 3 weeks ago

Thanks for support, will use my fork with 'degraded developer experience' that at least works in TS enviroment.

paulmillr commented 3 weeks ago

This module was obviously created for typescript, so it works in typescript. If it doesn't work in your env, then your env is probably wrong.

package.json exports field is utilized, which maps ONE path to TWO different versions (ESM and CJS). This is effective and recommended by community. I am also using it in 10 different packages without issues.

I have just tested common.js support and it compiles fine on my machine:

a.ts

const slip = require('micro-key-producer/slip10.js');
console.log(slip);

tsconfig.json

{
  "compilerOptions": {
    "baseUrl": ".",
    "outDir": "out",
    "module": "Node16",
    "moduleResolution": "Node16"
  },
  "include": [
    "a.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

Produced output is common.js:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const slip = require('micro-key-producer/slip10.js');
console.log(slip);

Then i've tested ESM module resolution and it also works fine. "ESM can be imported in CJS" is a new feature exclusively available in node v22 and higher. You are trying to use brand new nodejs version with very old module resolution (commonjs / node10), which doesn't support package.json exports. Upgrade to something modern.

Is asking users to do two different things based on their module choice degraded?

const slip = require('micro-key-producer/cjs/slip10.js'); // cjs
import * as slip from 'micro-key-producer/esm/slip10.js'); // esm

Yes, it is, because export maps are used to make it the same.

killroy192 commented 3 weeks ago

When I chage moduleResolution to node16, micro-key-produce modules resolves fine, while the others such as https://github.com/bitcoinjs/tiny-secp256k1 don't. It seems the others modules are broken or supports only 'classic' moduleResolution. That why I tried to update micro-key-produce, so it can be used with legacy tsconfigs.