Skip to content

Commit 46cba36

Browse files
authored
feat: add pnpm support for package installation (#2040)
1 parent 69a467a commit 46cba36

File tree

10 files changed

+40
-3
lines changed

10 files changed

+40
-3
lines changed

packages/webpack-cli/lib/utils/__tests__/get-package-manager.test.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ describe('packageUtils', () => {
2222
describe('getPackageManager', () => {
2323
const testYarnLockPath = path.resolve(__dirname, 'test-yarn-lock');
2424
const testNpmLockPath = path.resolve(__dirname, 'test-npm-lock');
25-
const testBothPath = path.resolve(__dirname, 'test-both');
25+
const testPnpmLockPath = path.resolve(__dirname, 'test-pnpm-lock');
26+
const testNpmAndPnpmPath = path.resolve(__dirname, 'test-npm-and-pnpm');
27+
const testAllPath = path.resolve(__dirname, 'test-all-lock');
2628

2729
const cwdSpy = jest.spyOn(process, 'cwd');
2830

@@ -33,7 +35,8 @@ describe('packageUtils', () => {
3335
fs.mkdirSync(testNpmLockPath);
3436
}
3537
fs.writeFileSync(path.resolve(testNpmLockPath, 'package-lock.json'), '');
36-
fs.writeFileSync(path.resolve(testBothPath, 'package-lock.json'), '');
38+
fs.writeFileSync(path.resolve(testNpmAndPnpmPath, 'package-lock.json'), '');
39+
fs.writeFileSync(path.resolve(testAllPath, 'package-lock.json'), '');
3740
});
3841

3942
beforeEach(() => {
@@ -52,8 +55,20 @@ describe('packageUtils', () => {
5255
expect(syncMock.mock.calls.length).toEqual(0);
5356
});
5457

58+
it('should find pnpm-lock.yaml', () => {
59+
cwdSpy.mockReturnValue(testPnpmLockPath);
60+
expect(getPackageManager()).toEqual('pnpm');
61+
expect(syncMock.mock.calls.length).toEqual(0);
62+
});
63+
64+
it('should prioritize npm over pnpm', () => {
65+
cwdSpy.mockReturnValue(testNpmAndPnpmPath);
66+
expect(getPackageManager()).toEqual('npm');
67+
expect(syncMock.mock.calls.length).toEqual(0);
68+
});
69+
5570
it('should prioritize yarn with many lock files', () => {
56-
cwdSpy.mockReturnValue(testBothPath);
71+
cwdSpy.mockReturnValue(testAllPath);
5772
expect(getPackageManager()).toEqual('yarn');
5873
expect(syncMock.mock.calls.length).toEqual(0);
5974
});

packages/webpack-cli/lib/utils/__tests__/prompt-installation.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@ describe('promptInstallation', () => {
6060
expect(runCommand.mock.calls[0][0]).toEqual('yarn add -D test-package');
6161
});
6262

63+
it('should prompt to install using pnpm if pnpm is package manager', async () => {
64+
prompt.mockReturnValue({
65+
installConfirm: true,
66+
});
67+
getPackageManager.mockReturnValue('pnpm');
68+
const preMessage = jest.fn();
69+
const promptResult = await promptInstallation('test-package', preMessage);
70+
expect(promptResult).toBeTruthy();
71+
expect(preMessage.mock.calls.length).toEqual(1);
72+
expect(prompt.mock.calls.length).toEqual(1);
73+
expect(runCommand.mock.calls.length).toEqual(1);
74+
expect(prompt.mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/);
75+
// install the package using npm
76+
expect(runCommand.mock.calls[0][0]).toEqual('pnpm install -D test-package');
77+
});
78+
6379
it('should not install if install is not confirmed', async () => {
6480
prompt.mockReturnValue({
6581
installConfirm: false,

packages/webpack-cli/lib/utils/__tests__/test-both/package-lock.json renamed to packages/webpack-cli/lib/utils/__tests__/test-all-lock/package-lock.json

File renamed without changes.

packages/webpack-cli/lib/utils/__tests__/test-both/yarn.lock renamed to packages/webpack-cli/lib/utils/__tests__/test-all-lock/pnpm-lock.yaml

File renamed without changes.

packages/webpack-cli/lib/utils/__tests__/test-all-lock/yarn.lock

Whitespace-only changes.

packages/webpack-cli/lib/utils/__tests__/test-npm-and-pnpm/package-lock.json

Whitespace-only changes.

packages/webpack-cli/lib/utils/__tests__/test-npm-and-pnpm/pnpm-lock.yaml

Whitespace-only changes.

packages/webpack-cli/lib/utils/__tests__/test-pnpm-lock/pnpm-lock.yaml

Whitespace-only changes.

packages/webpack-cli/lib/utils/get-package-manager.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@ const { sync } = require('execa');
1212
function getPackageManager() {
1313
const hasLocalYarn = fs.existsSync(path.resolve(process.cwd(), 'yarn.lock'));
1414
const hasLocalNpm = fs.existsSync(path.resolve(process.cwd(), 'package-lock.json'));
15+
const hasLocalPnpm = fs.existsSync(path.resolve(process.cwd(), 'pnpm-lock.yaml'));
16+
1517
if (hasLocalYarn) {
1618
return 'yarn';
1719
} else if (hasLocalNpm) {
1820
return 'npm';
21+
} else if (hasLocalPnpm) {
22+
return 'pnpm';
1923
}
24+
2025
try {
2126
// if the sync function below fails because yarn is not installed,
2227
// an error will be thrown

packages/webpack-cli/lib/utils/prompt-installation.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const packageExists = require('./package-exists');
1111
*/
1212
async function promptInstallation(packageName, preMessage) {
1313
const packageManager = getPackageManager();
14+
// yarn uses 'add' command, rest npm and pnpm both use 'install'
1415
const options = [packageManager === 'yarn' ? 'add' : 'install', '-D', packageName];
1516

1617
const commandToBeRun = `${packageManager} ${options.join(' ')}`;

0 commit comments

Comments
 (0)