From e53f1645c729c3bbcb27ffd41c999ed321f86f9d Mon Sep 17 00:00:00 2001 From: James George Date: Wed, 9 Jun 2021 21:54:06 +0530 Subject: [PATCH] feat(init-generator): add ability to specify a package manager of choice (#2769) * feat: add ability to specify a package manager of choice * chore: choose default installer based on the lock file presence * test: update test suite --- packages/generators/src/init-generator.ts | 13 ++++++++-- .../lib/utils/get-available-installers.js | 25 +++++++++++++++++++ packages/webpack-cli/lib/utils/index.js | 4 +++ test/init/init.test.js | 17 +++++++++---- 4 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 packages/webpack-cli/lib/utils/get-available-installers.js diff --git a/packages/generators/src/init-generator.ts b/packages/generators/src/init-generator.ts index 1006e2aeb5a..d8868052102 100644 --- a/packages/generators/src/init-generator.ts +++ b/packages/generators/src/init-generator.ts @@ -99,8 +99,17 @@ export default class InitGenerator extends CustomGenerator { } } - public installPlugins(): void { - const packager = this.utils.getPackageManager(); + public async installPlugins(): Promise { + // Prompt for the package manager of choice + const defaultPackager = this.utils.getPackageManager(); + const { packager } = await Question.List( + this, + "packager", + "Pick a package manager:", + this.utils.getAvailableInstallers(), + defaultPackager, + this.force, + ); const opts: { dev?: boolean; "save-dev"?: boolean; diff --git a/packages/webpack-cli/lib/utils/get-available-installers.js b/packages/webpack-cli/lib/utils/get-available-installers.js new file mode 100644 index 00000000000..d2ee92414c5 --- /dev/null +++ b/packages/webpack-cli/lib/utils/get-available-installers.js @@ -0,0 +1,25 @@ +const { sync } = require("execa"); + +const utils = require("./"); + +function hasPmInstalled(packageManager) { + try { + sync(packageManager, ["--version"]); + return packageManager; + } catch (err) { + return false; + } +} + +function getAvailableInstallers() { + const installers = ["npm", "yarn", "pnpm"]; + const availableInstallers = installers.filter((installer) => hasPmInstalled(installer)); + + if (!availableInstallers.length) { + utils.logger.error("No package manager found."); + process.exit(2); + } + return availableInstallers; +} + +module.exports = getAvailableInstallers; diff --git a/packages/webpack-cli/lib/utils/index.js b/packages/webpack-cli/lib/utils/index.js index 800174bec22..e5ac14c3407 100644 --- a/packages/webpack-cli/lib/utils/index.js +++ b/packages/webpack-cli/lib/utils/index.js @@ -23,6 +23,10 @@ module.exports = { return require("./dynamic-import-loader"); }, + get getAvailableInstallers() { + return require("./get-available-installers"); + }, + get getPackageManager() { return require("./get-package-manager"); }, diff --git a/test/init/init.test.js b/test/init/init.test.js index a8ef6cca672..c7221110496 100644 --- a/test/init/init.test.js +++ b/test/init/init.test.js @@ -144,7 +144,7 @@ describe("init command", () => { const { stdout, stderr } = await runPromptWithAnswers( assetsPath, ["init"], - [`${DOWN}${DOWN}${ENTER}`, `n${ENTER}`, `n${ENTER}`, `n${ENTER}`, ENTER], + [`${DOWN}${DOWN}${ENTER}`, `n${ENTER}`, `n${ENTER}`, `n${ENTER}`, ENTER, ENTER], ); expect(stdout).toContain("Project has been initialised with webpack!"); @@ -170,7 +170,7 @@ describe("init command", () => { const { stdout, stderr } = await runPromptWithAnswers( assetsPath, ["init"], - [`${DOWN}${ENTER}`, `n${ENTER}`, `n${ENTER}`, `n${ENTER}`, ENTER], + [`${DOWN}${ENTER}`, `n${ENTER}`, `n${ENTER}`, `n${ENTER}`, ENTER, ENTER], ); expect(stdout).toContain("Project has been initialised with webpack!"); @@ -205,6 +205,7 @@ describe("init command", () => { `n${ENTER}`, `n${ENTER}`, `n${ENTER}`, + ENTER, ], ); @@ -239,6 +240,7 @@ describe("init command", () => { `n${ENTER}`, `y${ENTER}`, `n${ENTER}`, + ENTER, ], ); @@ -279,6 +281,7 @@ describe("init command", () => { `n${ENTER}`, `n${ENTER}`, `y${ENTER}`, + ENTER, ], ); @@ -313,6 +316,7 @@ describe("init command", () => { `y${ENTER}`, `y${ENTER}`, `n${ENTER}`, + ENTER, ], ); @@ -353,6 +357,7 @@ describe("init command", () => { `n${ENTER}`, `n${ENTER}`, `n${ENTER}`, + ENTER, ], ); @@ -387,6 +392,7 @@ describe("init command", () => { `n${ENTER}`, `n${ENTER}`, `n${ENTER}`, + ENTER, ], ); @@ -412,7 +418,7 @@ describe("init command", () => { const { stdout, stderr } = await runPromptWithAnswers( assetsPath, ["init"], - [ENTER, ENTER, `n${ENTER}`, `n${ENTER}`, ENTER], + [ENTER, ENTER, `n${ENTER}`, `n${ENTER}`, ENTER, ENTER], ); expect(stdout).toContain("Do you want to use webpack-dev-server?"); @@ -445,6 +451,7 @@ describe("init command", () => { `${DOWN}${ENTER}`, ENTER, `n${ENTER}`, + ENTER, ], ); @@ -476,7 +483,7 @@ describe("init command", () => { const { stdout, stderr } = await runPromptWithAnswers( assetsPath, ["init"], - [ENTER, `n${ENTER}`, ENTER, `n${ENTER}`, ENTER], + [ENTER, `n${ENTER}`, ENTER, `n${ENTER}`, ENTER, ENTER], ); expect(stdout).toContain( @@ -504,7 +511,7 @@ describe("init command", () => { const { stdout, stderr } = await runPromptWithAnswers( assetsPath, ["init"], - [ENTER, `n${ENTER}`, ENTER, ENTER, ENTER], + [ENTER, `n${ENTER}`, ENTER, ENTER, ENTER, ENTER], ); expect(stdout).toContain("Do you want to add PWA support?");