Skip to content

Commit d9cd609

Browse files
committed
fix(@angular/cli): correctly parse scoped packages in yarn classic list output
The `parseYarnClassicDependencies` function incorrectly parsed scoped packages (e.g., `@angular/[email protected]`) by splitting at the first `@`, resulting in an empty name. This commit updates the logic to split at the last `@`, ensuring scoped package names are correctly identified.
1 parent a457377 commit d9cd609

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

packages/angular/cli/src/package-managers/parsers.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,10 @@ export function parseYarnClassicDependencies(
155155
for (const json of parseJsonLines(stdout, logger)) {
156156
if (json.type === 'tree' && json.data?.trees) {
157157
for (const info of json.data.trees) {
158-
const name = info.name.split('@')[0];
159-
const version = info.name.split('@').pop();
158+
const lastAtIndex = info.name.lastIndexOf('@');
159+
const name = info.name.slice(0, lastAtIndex);
160+
const version = info.name.slice(lastAtIndex + 1);
161+
160162
dependencies.set(name, {
161163
name,
162164
version,

packages/angular/cli/src/package-managers/parsers_spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
parseBunDependencies,
1111
parseNpmLikeError,
1212
parseNpmLikeManifest,
13+
parseYarnClassicDependencies,
1314
parseYarnClassicError,
1415
parseYarnModernDependencies,
1516
} from './parsers';
@@ -135,6 +136,38 @@ describe('parsers', () => {
135136
});
136137
});
137138

139+
describe('parseYarnClassicDependencies', () => {
140+
it('should parse yarn classic list output', () => {
141+
const stdout = JSON.stringify({
142+
type: 'tree',
143+
data: {
144+
trees: [{ name: '[email protected]', children: [] }],
145+
},
146+
});
147+
148+
const deps = parseYarnClassicDependencies(stdout);
149+
expect(deps.size).toBe(1);
150+
expect(deps.get('rxjs')).toEqual({ name: 'rxjs', version: '7.8.2' });
151+
});
152+
153+
it('should handle scoped packages', () => {
154+
const stdout = JSON.stringify({
155+
type: 'tree',
156+
data: {
157+
trees: [{ name: '@angular/[email protected]', children: [] }],
158+
},
159+
});
160+
161+
const deps = parseYarnClassicDependencies(stdout);
162+
expect(deps.size).toBe(1);
163+
expect(deps.get('@angular/core')).toEqual({ name: '@angular/core', version: '18.0.0' });
164+
});
165+
166+
it('should return empty map for empty stdout', () => {
167+
expect(parseYarnClassicDependencies('').size).toBe(0);
168+
});
169+
});
170+
138171
describe('parseBunDependencies', () => {
139172
it('should parse bun pm ls output', () => {
140173
const stdout = `

0 commit comments

Comments
 (0)