Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/angular/cli/src/package-managers/package-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,12 @@ export class PackageManager {
try {
const { stdout } = await this.#run(this.descriptor.getPackageNameCommand);
if (stdout) {
return JSON.parse(stdout);
const name = JSON.parse(stdout);

// In a workspace member npm prints an object keyed by workspace name instead of a string.
if (typeof name === 'string') {
return name;
}
}
} catch {
// Fall back to reading file if command fails
Expand Down
51 changes: 51 additions & 0 deletions packages/angular/cli/src/package-managers/package-manager_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,57 @@ describe('PackageManager', () => {
});
});

describe('getCurrentPackageName', () => {
it('should return the name printed by the package manager', async () => {
const pm = new PackageManager(host, '/repo/app', descriptor);
runCommandSpy.and.resolveTo({ stdout: '"app"', stderr: '' });
const readFileSpy = spyOn(host, 'readFile');

expect(await pm.getCurrentPackageName()).toBe('app');
expect(readFileSpy).not.toHaveBeenCalled();
});

it('should read package.json when npm prints an object keyed by workspace', async () => {
const pm = new PackageManager(host, '/repo/apps/app', descriptor);
// Inside a workspace member, `npm pkg get name` prints `{ "app": "app" }` instead of `"app"`.
runCommandSpy.and.resolveTo({ stdout: '{\n "app": "app"\n}', stderr: '' });
const readFileSpy = spyOn(host, 'readFile').and.resolveTo('{"name": "app"}');

expect(await pm.getCurrentPackageName()).toBe('app');
expect(readFileSpy).toHaveBeenCalledWith(jasmine.stringMatching(/package\.json$/));
});
});

describe('getProjectDependencies', () => {
it('should list the dependencies of an npm workspace member', async () => {
const pm = new PackageManager(host, '/repo/apps/app', descriptor);
runCommandSpy.and.callFake((_binary: string, args: readonly string[]) =>
Promise.resolve({
stdout:
args[0] === 'pkg'
? '{\n "app": "app"\n}'
: JSON.stringify({
name: 'monorepo',
dependencies: {
app: {
version: '0.0.0',
resolved: 'file:../apps/app',
dependencies: { '@angular/core': { version: '22.0.0' } },
},
},
}),
stderr: '',
}),
);
spyOn(host, 'readFile').and.resolveTo('{"name": "app"}');

const dependencies = await pm.getProjectDependencies();

expect([...dependencies.keys()]).toEqual(['@angular/core']);
expect(dependencies.get('@angular/core')?.version).toBe('22.0.0');
});
});

describe('initializationError', () => {
it('should throw initializationError when running commands', async () => {
const error = new Error('Not installed');
Expand Down
Loading