Skip to content

Commit ed31134

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 b6d5789 commit ed31134

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
@@ -9,6 +9,7 @@
99
import {
1010
parseBunDependencies,
1111
parseNpmLikeError,
12+
parseYarnClassicDependencies,
1213
parseYarnClassicError,
1314
parseYarnModernDependencies,
1415
} from './parsers';
@@ -115,6 +116,38 @@ describe('parsers', () => {
115116
});
116117
});
117118

119+
describe('parseYarnClassicDependencies', () => {
120+
it('should parse yarn classic list output', () => {
121+
const stdout = JSON.stringify({
122+
type: 'tree',
123+
data: {
124+
trees: [{ name: '[email protected]', children: [] }],
125+
},
126+
});
127+
128+
const deps = parseYarnClassicDependencies(stdout);
129+
expect(deps.size).toBe(1);
130+
expect(deps.get('rxjs')).toEqual({ name: 'rxjs', version: '7.8.2' });
131+
});
132+
133+
it('should handle scoped packages', () => {
134+
const stdout = JSON.stringify({
135+
type: 'tree',
136+
data: {
137+
trees: [{ name: '@angular/[email protected]', children: [] }],
138+
},
139+
});
140+
141+
const deps = parseYarnClassicDependencies(stdout);
142+
expect(deps.size).toBe(1);
143+
expect(deps.get('@angular/core')).toEqual({ name: '@angular/core', version: '18.0.0' });
144+
});
145+
146+
it('should return empty map for empty stdout', () => {
147+
expect(parseYarnClassicDependencies('').size).toBe(0);
148+
});
149+
});
150+
118151
describe('parseBunDependencies', () => {
119152
it('should parse bun pm ls output', () => {
120153
const stdout = `

0 commit comments

Comments
 (0)