fix(purl): handle literal @ in scoped package shorthand#50
Conversation
Version extraction used indexOf("@") which grabbed the scope marker
in inputs like pkg:npm/@vue/core, treating @vue/core as the version.
Use lastIndexOf("@") guarded by position after the last "/" so the
scope @ is left alone and only a real version separator gets picked up.
Closes #25
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (7)test/**/*.test.ts📄 CodeRabbit inference engine (test/AGENTS.md)
Files:
test/unit/**/*.test.ts📄 CodeRabbit inference engine (test/AGENTS.md)
Files:
test/unit/purl.test.ts📄 CodeRabbit inference engine (test/AGENTS.md)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
src/**/*.ts📄 CodeRabbit inference engine (src/AGENTS.md)
Files:
src/**/!(client).ts📄 CodeRabbit inference engine (src/AGENTS.md)
Files:
src/core/**/*.ts📄 CodeRabbit inference engine (src/core/AGENTS.md)
Files:
🧠 Learnings (12)📓 Common learnings📚 Learning: 2026-03-10T07:36:54.862ZApplied to files:
📚 Learning: 2026-03-10T07:36:38.679ZApplied to files:
📚 Learning: 2026-03-10T07:36:29.354ZApplied to files:
📚 Learning: 2026-03-10T07:36:29.354ZApplied to files:
📚 Learning: 2026-03-10T07:36:12.605ZApplied to files:
📚 Learning: 2026-03-10T07:36:54.862ZApplied to files:
📚 Learning: 2026-03-13T19:49:05.270ZApplied to files:
📚 Learning: 2026-03-10T07:36:12.605ZApplied to files:
📚 Learning: 2026-03-10T07:36:54.862ZApplied to files:
📚 Learning: 2026-03-13T19:49:05.270ZApplied to files:
📚 Learning: 2026-03-17T10:54:06.865ZApplied to files:
🧬 Code graph analysis (1)test/unit/purl.test.ts (1)
🔇 Additional comments (3)
📝 WalkthroughWalkthroughFixed PURL parsing for npm scoped packages by refining version extraction to find the last Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
✨ Simplify code
📝 Coding Plan
Comment |
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Requires human review: This PR modifies core parsing logic in a core utility. Changes to business logic or string parsing in core paths require human review to prevent regressions.
Architecture diagram
sequenceDiagram
participant Client as CLI (info/deps/versions)
participant Parser as parsePURL()
participant Decoder as decodePURLComponent()
Note over Client,Parser: User provides PURL (e.g., "pkg:npm/@vue/core@3.4.0")
Client->>Parser: parsePURL(purlStr)
Note over Parser: Step 1: Strip 'pkg:' prefix
rect fontcolor:#ffffff,fill:#172554
Note over Parser: NEW: Version Extraction Logic
Parser->>Parser: Find last '/' position
Parser->>Parser: Find last '@' position
alt last '@' exists AND last '@' > last '/'
Parser->>Decoder: decodePURLComponent(versionPart)
Decoder-->>Parser: decoded version
else last '@' is before '/' or missing
Note over Parser: Treat '@' as part of scope/name
Parser->>Parser: version = ""
end
end
Parser->>Parser: Extract package type (e.g., 'npm')
Parser->>Parser: Extract namespace (e.g., '@vue') and name ('core')
alt Parsing Successful
Parser-->>Client: Return ParsedPURL object
else Parsing Failed (Invalid format)
Parser-->>Client: Throw InvalidPURLError
end
Note over Client: Command proceeds with parsed metadata
Version extraction in
parsePURLusedindexOf("@")on the full remainder, sopkg:npm/@vue/corehit the scope@first and treated@vue/coreas the version string. Every CLI command (info,versions,deps,maintainers) threwInvalidPURLErroron scoped shorthand that wasn't percent-encoded.Switched to
lastIndexOf("@")with a positional guard - the@only counts as a version separator if it sits after the last/. Scoped@always comes before a/, so it's left alone now.Existing tests still pass (percent-encoded scopes were fine before). Two new tests cover the literal
@path:pkg:npm/@vue/corewithout version andpkg:npm/@vue/core@3.4.0with one.Closes #25