Skip to content

fix: match wildcard imports keys with a trailer - #57

Merged
pi0 merged 1 commit into
mainfrom
fix/pkg-import
Jul 27, 2026
Merged

fix: match wildcard imports keys with a trailer#57
pi0 merged 1 commit into
mainfrom
fix/pkg-import

Conversation

@pi0x

@pi0x pi0x commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Fixes #56.

Problem

packageImportsResolve computed the wildcard pattern base as key.slice(0, -1) instead of key.slice(0, patternIndex). For a key like #*.js this tested name.startsWith("#*."), which never matches, so the key was skipped.

Usually that meant resolution threw — but when a less specific key also matched, it silently resolved the wrong file. Given #feat*.js and #feat*, patternKeyCompare should pick the former for #featx.js; instead the former was skipped and the latter won by default.

Keys without a trailer (#/*) were unaffected — slice(0, -1) and slice(0, patternIndex) coincide there — which is why this went unnoticed. packageExportsResolve already used the correct base, so exports and imports disagreed within the same file.

Changes

  • src/internal/resolve.ts — one-line fix, aligning with the Node.js upstream implementation.
  • test/resolve-imports-exports.test.ts — regression tests for a bare wildcard-with-trailer key, a nested one, and the wrong-winner case above (both targets exist on disk, so it pins key selection rather than mere existence), plus a negative test that #.js still does not match #*.js.

The three positive tests fail on the parent commit and pass with the fix. Because key.slice(0, patternIndex) is always a prefix of key.slice(0, -1), the new predicate is a strict superset of the old one — it can only add matches, never remove them.

Verification

Full suite passes (84 passed, 1 skipped), as do tsc --noEmit, oxlint, and oxfmt --check.

The fixture in test/fixture/imports-pkg was also checked against real Node (createRequire().resolve, v24.18.0) to confirm the expectations are Node's actual answers and that the added keys don't disturb the pre-existing cases:

specifier Node
#internal/marker.js runtime/internal/marker.js
#lib/deep/thing.js lib/deep/thing.js
#featx.js feat-js/x.js
#.js ERR_PACKAGE_IMPORT_NOT_DEFINED
#/util.js src/util.js (unchanged)
#internal internal.js (unchanged)

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The imports resolver now matches wildcard keys using the actual * position. Fixtures add runtime and library mappings, and regression tests verify direct and nested trailer-pattern imports resolve to existing files.

Changes

Wildcard imports resolution

Layer / File(s) Summary
Correct wildcard prefix matching
src/internal/resolve.ts, test/fixture/imports-pkg/package.json
packageImportsResolve now slices imports keys through the wildcard position, supporting mappings such as #*.js and #lib/*.js.
Validate trailer-pattern resolution
test/fixture/imports-pkg/runtime/internal/marker.js, test/fixture/imports-pkg/lib/deep/thing.js, test/resolve-imports-exports.test.ts
Fixture exports and regression tests cover direct and nested wildcard imports, including resolved URL and filesystem existence checks.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • unjs/exsolve#49: Both changes update wildcard or internal imports matching in src/internal/resolve.ts.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The resolver fix and regression tests address the trailer-pattern imports bug, including nested paths.
Out of Scope Changes check ✅ Passed The added fixtures and tests directly support the resolver fix; no unrelated changes are evident.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: fixing wildcard imports keys that include a trailer.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pkg-import

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.61%. Comparing base (a55eb05) to head (c5c10be).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #57      +/-   ##
==========================================
+ Coverage   65.26%   65.61%   +0.34%     
==========================================
  Files           6        6              
  Lines         858      858              
  Branches      305      305              
==========================================
+ Hits          560      563       +3     
  Misses        236      236              
+ Partials       62       59       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

`packageImportsResolve` computed the pattern base as `key.slice(0, -1)`
instead of `key.slice(0, patternIndex)`. For a key like `#*.js` this
tested `name.startsWith("#*.")`, which never matches, so the key was
skipped.

Usually that meant resolution threw, but when a less specific key also
matched the specifier it silently resolved the wrong file: given
`#feat*.js` and `#feat*`, `#featx.js` should pick the former, yet the
former was skipped and the latter won by default.

Keys without a trailer (`#/*`) were unaffected, which hid the bug, and
`packageExportsResolve` already used the correct base.

Aligns with the Node.js upstream implementation.

Fixes #56

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pi0x
pi0x force-pushed the fix/pkg-import branch from 84678f7 to c5c10be Compare July 27, 2026 16:41
@pi0
pi0 merged commit 6858b1c into main Jul 27, 2026
7 checks passed
@pi0
pi0 deleted the fix/pkg-import branch July 27, 2026 16:46
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.

packageImportsResolve: wildcard imports keys with a trailer (#*.js) never match

2 participants