Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
jmartinezmaes opened this issue Dec 29, 2022 · 6 comments

Comments

@jmartinezmaes
Copy link

jmartinezmaes commented Dec 29, 2022

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
@NullVoxPopuli
Copy link

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

@NullVoxPopuli
Copy link

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

@hitsthings
Copy link

hitsthings commented Jan 30, 2023

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"

@BenceSzalai
Copy link

BenceSzalai commented Aug 17, 2023

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
Copy link

BenceSzalai commented Aug 17, 2023

I've found the missing puzzle piece: nodejs/node#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.

teidesu added a commit to mtcute/mtcute that referenced this issue Dec 2, 2023
@tianyingchun
Copy link

face this issue too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants