Skip to content

fix: link aliased dependencies to their real package#2214

Open
thealxlabs wants to merge 4 commits intonpmx-dev:mainfrom
thealxlabs:fix/aliased-dependency-links
Open

fix: link aliased dependencies to their real package#2214
thealxlabs wants to merge 4 commits intonpmx-dev:mainfrom
thealxlabs:fix/aliased-dependency-links

Conversation

@thealxlabs
Copy link

🔗 Linked issue

resolves #2010

🧭 Context

When a package uses npm alias syntax (e.g. "my-react": "npm:react@^18.0.0"), the dependencies list linked to the alias name my-react rather than to the real package react. This made aliased dependencies unlinkable and gave a confusing user experience.

📚 Description

  • Added parseNpmAlias(version) which parses the npm:real-pkg@range alias syntax, handling both regular and scoped packages.
  • Extracted the function to a dedicated utility file app/utils/npm/alias.ts for testability and reuse.
  • Updated Package/Dependencies.vue to import from the utility and use parseNpmAlias(version)?.name ?? dep when constructing package route links, so aliased dependencies route to the real package.

Unit tests in test/unit/app/utils/npm/alias.spec.ts cover:

  • Regular semver range returns null (not an alias)
  • npm:real-pkg@^1.0.0{ name: 'real-pkg', range: '^1.0.0' }
  • npm:@scope/pkg@^1.0.0{ name: '@scope/pkg', range: '^1.0.0' }
  • npm:real-pkg (no version) → { name: 'real-pkg', range: '' }

@vercel
Copy link

vercel bot commented Mar 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Mar 22, 2026 7:08pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Mar 22, 2026 7:08pm
npmx-lunaria Ignored Ignored Mar 22, 2026 7:08pm

Request Review

@vercel
Copy link

vercel bot commented Mar 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
npmx-lunaria Ignored Ignored Mar 22, 2026 7:04pm

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 22, 2026

📝 Walkthrough

Walkthrough

A new utility function parseNpmAlias was added to parse npm alias syntax (format: npm:package-name@version-range). The function extracts the actual package name and version range from aliased dependency strings, returning null for non-aliased inputs. The Dependencies component was updated to use this utility when constructing dependency links, ensuring links route to the actual package rather than the alias name. Unit tests were added to validate the parsing logic across various input formats including scoped packages, version ranges, and non-alias strings.

Suggested reviewers

  • danielroe
  • ghostdevv
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description clearly relates to the changeset, describing the addition of parseNpmAlias utility and its integration into Dependencies.vue to fix aliased dependency links.
Linked Issues check ✅ Passed The pull request successfully addresses issue #2010 by implementing parseNpmAlias to correctly parse npm alias syntax and updating Dependencies.vue to route aliased dependencies to their real package names.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing aliased dependency links: the new parseNpmAlias utility, its integration in Dependencies.vue, and corresponding unit tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
test/unit/app/utils/npm/alias.spec.ts (1)

4-62: Please add one component-level regression around the rendered links.

These assertions lock the parser down well, but the bug fixed by this PR lives in Dependencies.vue. A small Vitest component test that renders an aliased dependency and checks the generated to target would protect the actual navigation users click on.

As per coding guidelines **/*.{test,spec}.{ts,tsx}: Write unit tests for core functionality using vitest.

app/components/Package/Dependencies.vue (1)

118-123: Pull the alias route resolution out of the template.

The same parseNpmAlias(spec)?.name ?? ... / parseNpmAlias(spec)?.range ?? ... branching is repeated across direct, peer, and optional dependency links. A tiny helper or precomputed row shape would keep the routing rules in one place, avoid reparsing the same spec several times per row, and make future link changes much harder to miss.

♻️ One possible shape
+function getDependencyPackageName(depName: string, spec: string) {
+  return parseNpmAlias(spec)?.name ?? depName
+}
+
+function getDependencyVersion(spec: string) {
+  const alias = parseNpmAlias(spec)
+  return alias ? (alias.range || undefined) : spec
+}

Then the bindings can call packageRoute(getDependencyPackageName(dep, version), getDependencyVersion(version)).

Also applies to: 177-182, 240-244, 252-257, 310-314, 318-323


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cfc0ff95-cbe8-45f2-900a-0b0a1ceeb0be

📥 Commits

Reviewing files that changed from the base of the PR and between 7f2fc1a and 96f2bbd.

📒 Files selected for processing (3)
  • app/components/Package/Dependencies.vue
  • app/utils/npm/alias.ts
  • test/unit/app/utils/npm/alias.spec.ts

Comment on lines +11 to +17
export function parseNpmAlias(version: string): { name: string; range: string } | null {
if (!version.startsWith('npm:')) return null
const spec = version.slice(4) // strip 'npm:'
// Handle scoped packages like @scope/pkg@1.0.0 — find @ after position 0
const atIdx = spec.startsWith('@') ? spec.indexOf('@', 1) : spec.indexOf('@')
if (atIdx === -1) return { name: spec, range: '' }
return { name: spec.slice(0, atIdx), range: spec.slice(atIdx + 1) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Return null for empty alias targets.

npm: currently parses to { name: '', range: '' }, which would send callers such as Dependencies.vue down the alias path with an empty package name instead of letting them fall back cleanly. Please treat blank specs as invalid and add a regression case for it.

🩹 Suggested guard
 export function parseNpmAlias(version: string): { name: string; range: string } | null {
   if (!version.startsWith('npm:')) return null
   const spec = version.slice(4) // strip 'npm:'
+  if (!spec.trim()) return null
   // Handle scoped packages like `@scope/pkg`@1.0.0 — find @ after position 0
   const atIdx = spec.startsWith('@') ? spec.indexOf('@', 1) : spec.indexOf('@')
   if (atIdx === -1) return { name: spec, range: '' }
   return { name: spec.slice(0, atIdx), range: spec.slice(atIdx + 1) }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function parseNpmAlias(version: string): { name: string; range: string } | null {
if (!version.startsWith('npm:')) return null
const spec = version.slice(4) // strip 'npm:'
// Handle scoped packages like @scope/pkg@1.0.0 — find @ after position 0
const atIdx = spec.startsWith('@') ? spec.indexOf('@', 1) : spec.indexOf('@')
if (atIdx === -1) return { name: spec, range: '' }
return { name: spec.slice(0, atIdx), range: spec.slice(atIdx + 1) }
export function parseNpmAlias(version: string): { name: string; range: string } | null {
if (!version.startsWith('npm:')) return null
const spec = version.slice(4) // strip 'npm:'
if (!spec.trim()) return null
// Handle scoped packages like `@scope/pkg`@1.0.0 — find @ after position 0
const atIdx = spec.startsWith('@') ? spec.indexOf('@', 1) : spec.indexOf('@')
if (atIdx === -1) return { name: spec, range: '' }
return { name: spec.slice(0, atIdx), range: spec.slice(atIdx + 1) }
}

@codecov
Copy link

codecov bot commented Mar 22, 2026

Codecov Report

❌ Patch coverage is 55.55556% with 4 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/utils/npm/alias.ts 50.00% 2 Missing and 1 partial ⚠️
app/components/Package/Dependencies.vue 66.66% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

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.

Aliased dependencies are not linked correctly

1 participant