Skip to content

fix: Respect package.json exports when adding extensions to package imports - #212

Merged
bennycode merged 1 commit into
mainfrom
fix/package-exports
Sep 29, 2026
Merged

bennycode merged 1 commit into
mainfrom
fix/package-exports

Conversation

@bennycode

Copy link
Copy Markdown
Owner

Fixes #128

Package imports got a file extension whenever a matching file existed on disk. The package's exports field was never read. For a package that exports ./sub and also ships sub.js, modern/sub became modern/sub.js, and Node.js rejects that with ERR_PACKAGE_PATH_NOT_EXPORTED. The firebase example in the issue only worked because that package happens not to have a file at v1/https.js.

Package imports are now checked with TypeScript's module resolver in NodeNext ESM mode, as suggested in #123:

  • An import that resolves as written stays untouched (firebase-functions/v1/https, @playwright/test).
  • Otherwise .js or /index.js is added if that makes it resolve (lodash/omit becomes lodash/omit.js).
  • If neither resolves, the import is left alone.

An earlier attempt used the project's own compiler options. Those are CommonJS before the migration, so lodash/omit resolved without an extension. Resolving in ESM mode gives the answer Node.js will give after the migration.

This also covers package roots from #81, so isNodeModuleRoot and its special case are removed.

The new fixture ships a few fake packages in node_modules, so .gitignore gets an exception for fixture node_modules folders.

…mports

Package imports got a file extension whenever a matching file existed on
disk, without looking at the package's "exports" field. For a package
that exports "./sub" and also ships sub.js, "pkg/sub" became "pkg/sub.js",
which Node.js rejects with ERR_PACKAGE_PATH_NOT_EXPORTED.

Package imports are now checked with TypeScript's module resolver in
NodeNext ESM mode. An import that resolves as written stays untouched,
and an extension is only added when the import doesn't resolve without
it but does with it. This also covers package roots like
"@playwright/test" (#81), so the isNodeModuleRoot special case is gone.
@bennycode
bennycode merged commit 5b06cd4 into main Sep 29, 2026
2 checks passed
@bennycode
bennycode deleted the fix/package-exports branch September 29, 2026 14:18
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

Successfully merging this pull request may close these issues.

Handling exports in package.json from 3rd party packages

1 participant