ts-node icon indicating copy to clipboard operation
ts-node copied to clipboard

[esm] Cannot import from external packages with an `exports` field that contains a wildcard and an extension

Open jmartinezmaes opened this issue 3 years ago • 6 comments

Search Terms

esm, external, exports, wildcard, extension

Expected Behavior

If a package defines an exports field

// foo_pkg/package.json

"exports": {
    "./*.js": "./dist/*.js"
}

And a consuming package imports:

// src/import_foo.ts

import { foo } from "foo_pkg/foo.js";

console.log(foo);

The program should compile and execute with ts-node-esm.

Actual Behavior

An ERR_PACKAGE_PATH_NOT_EXPORTED exception is raised.

Steps to reproduce the problem

I have made a branch on a repo to reproduce this issue.

Minimal reproduction

git clone --single-branch --branch ts_node_import_err https://github.com/jm4rtinez/ts_node_sandbox.git
npm install
npx ts-node-esm ./src/import_foo.ts

If the compiled form of the program is run with Node, no error occurs:

node ./dist/import_foo.js

Specifications

  • ts-node version: 10.9.1
  • node version: 19.2.0
  • TypeScript version: 4.9.4
  • tsconfig.json, if you're using one:
{
    "compilerOptions": {
        "target": "ES2022",
        "module": "ES2022",
        "moduleResolution": "NodeNext",
        "declaration": true,
        "declarationMap": true,
        "sourceMap": true,
        "strict": true,
        "outDir": "dist"
    },
    "include": ["src"]
}
  • package.json:
{
    "name": "ts-node-sandbox",
    "version": "1.0.0",
    "description": "",
    "type": "module",
    "scripts": {},
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "ts-node": "^10.9.1",
        "typescript": "~4.9"
    },
    "dependencies": {
        "foo_pkg": "file:foo_pkg-1.0.0.tgz"
    }
}
  • Operating system and version: Windows 10 Pro Version 10.0.19045 Build 19045
  • If Windows, are you using WSL or WSL2?: WSL2 Ubuntu 20.04.5 LTS

jmartinezmaes avatar Dec 29 '22 01:12 jmartinezmaes

I just ran in to this, as well. exports isn't that new 🙃

NullVoxPopuli avatar Jan 19 '23 22:01 NullVoxPopuli

turns out! I only had to change moduleResolution in my tsconfig.json to nodenext. yay

NullVoxPopuli avatar Jan 19 '23 22:01 NullVoxPopuli

Hitting this too and I have moduleResolution set to NodeNext.

Removing the extension worked though. So the exports field is now "./*": "./src/*" instead of "./*.js": "./src/*.js"

hitsthings avatar Jan 30 '23 20:01 hitsthings

The current implementation of the import resolution is from Node v15.3, and it basically assumes exports would either end with / or *. Export keys ending in an extension basically get ignored by the loop that tries to match them to the specifier to be resolved.

Since the file is a verbatim copy of Node's version I assume this matched the behaviour of Node at v15.3, but v16.9 updated it and all currently supported up to date Node versions now follow a different resolution logic.

As an example in some of my packages I like to enable folder paths to be resolved to index.js while still allow specific files to be imported too.

{
  "exports": {
    ".": "./build/index.js",
    "./*.js": "./build/*.js",
    "./*": "./build/*/index.js",
    "./*/": "./build/*/index.js"
  },
}

I'd expect import * from 'mypackage/some-path/some-file.js' to be resolved to mypackage/build/some-path/some-file.js, however ts-node tries to load mypackage/build/some-path/some-file.js/index.js instead, because it cannot understand the 2nd mapping and uses the 3rd instead.

This exports config works fine in node.js, when not used with ts-node.

BenceSzalai avatar Aug 17 '23 18:08 BenceSzalai

I've found the missing puzzle piece: https://github.com/nodejs/node/pull/39635

node-internal-modules-esm-resolve-v15.3.0.js should be updated to match at least Node v16.9's version, improved by the PR linked above. The feature was also backported to v14.19, but not v15. Using files from v15 seems to be an unfortunate choice, as LTS releases would have offered easier upgrade path for these files.

BenceSzalai avatar Aug 17 '23 20:08 BenceSzalai

face this issue too.

tianyingchun avatar Jan 26 '24 09:01 tianyingchun