Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added yarn and pnpm installations #24

Merged
merged 5 commits into from
Mar 29, 2022
Merged
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
21 changes: 16 additions & 5 deletions lib/init/config-initializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,12 @@ function hasESLintVersionConflict(answers) {
/**
* Install modules.
* @param {string[]} modules Modules to be installed.
* @param {string} packageManager Package manager to use for installation.
* @returns {void}
*/
function installModules(modules) {
function installModules(modules, packageManager) {
info(`Installing ${modules.join(", ")}`);
npmUtils.installSyncSaveDev(modules);
npmUtils.installSyncSaveDev(modules, packageManager);
}

/* istanbul ignore next: no need to test enquirer */
Expand All @@ -310,7 +311,7 @@ function askInstallModules(modules, packageJsonExists) {
{
type: "toggle",
name: "executeInstallation",
message: "Would you like to install them now with npm?",
message: "Would you like to install them now?",
enabled: "Yes",
disabled: "No",
initial: 1,
Expand All @@ -320,10 +321,20 @@ function askInstallModules(modules, packageJsonExists) {
result(input) {
return this.skipped ? null : input;
}
},
{
type: "select",
name: "packageManager",
message: "Which package manager do you want to use?",
initial: 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just wondering if it can be a smarter default by checking how it was run. e.g

`npm init/npx`  => npm
`yarn create` => yarn

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably do that by checking if we already have an existing package.lock or yarn.lock or pnpm lock file and default to package managers.
Also, we might want to change the text to Which package manager do you want to use?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but someone may don't use lockfile, or the lockfile can be configured a different name?

the text change lgtm. 👍

Copy link
Member Author

@harish-sethuraman harish-sethuraman Mar 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought of using something similar to this code eslint/eslint#13756 (comment)

but someone may don't use lockfile, or the lockfile can be configured a different name?

Not sure about this

Is there any other way to find currently configured package manager?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea.(^人^)
or it can be another PR (an enhancement) I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. Also I've seen some projects with both package.lock and yarn.lock as well. At that time we might want to default to one of the two package managers 😅 .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think there’s a good way to detect this. Just best to ask.

choices: ["npm", "yarn", "pnpm"],
skip() {
return !this.state.answers.executeInstallation;
}
}
]).then(({ executeInstallation }) => {
]).then(({ executeInstallation, packageManager }) => {
if (executeInstallation) {
installModules(modules);
installModules(modules, packageManager);
}
});
}
Expand Down
11 changes: 7 additions & 4 deletions lib/init/npm-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,20 @@ function findPackageJson(startDir) {
/**
* Install node modules synchronously and save to devDependencies in package.json
* @param {string|string[]} packages Node module or modules to install
* @param {string} packageManager Package manager to use for installation.
* @returns {void}
*/
function installSyncSaveDev(packages) {
function installSyncSaveDev(packages, packageManager = "npm") {
const packageList = Array.isArray(packages) ? packages : [packages];
const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList), { stdio: "inherit" });
const error = npmProcess.error;
const installCmd = packageManager === "yarn" ? "add" : "install";
const installProcess = spawn.sync(packageManager, [installCmd, "-D"].concat(packageList),
{ stdio: "inherit" });
const error = installProcess.error;

if (error && error.code === "ENOENT") {
const pluralS = packageList.length > 1 ? "s" : "";

log.error(`Could not execute npm. Please install the following package${pluralS} with a package manager of your choice: ${packageList.join(", ")}`);
log.error(`Could not execute ${packageManager}. Please install the following package${pluralS} with a package manager of your choice: ${packageList.join(", ")}`);
}
}

Expand Down
19 changes: 15 additions & 4 deletions tests/init/npm-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,20 +178,31 @@ describe("npmUtils", () => {
it("should invoke npm to install a single desired package", () => {
const stub = sinon.stub(spawn, "sync").returns({ stdout: "" });

installSyncSaveDev("desired-package");
installSyncSaveDev("desired-package", "npm");
assert(stub.calledOnce);
assert.strictEqual(stub.firstCall.args[0], "npm");
assert.deepStrictEqual(stub.firstCall.args[1], ["i", "--save-dev", "desired-package"]);
assert.deepStrictEqual(stub.firstCall.args[1], ["install", "-D", "desired-package"]);
stub.restore();
});

it("should invoke yarn to install a single desired package", () => {
const stub = sinon.stub(spawn, "sync").returns({ stdout: "" });

installSyncSaveDev("desired-package", "yarn");
assert(stub.calledOnce);
assert.strictEqual(stub.firstCall.args[0], "yarn");
assert.deepStrictEqual(stub.firstCall.args[1], ["add", "-D", "desired-package"]);
stub.restore();
});


it("should accept an array of packages to install", () => {
const stub = sinon.stub(spawn, "sync").returns({ stdout: "" });

installSyncSaveDev(["first-package", "second-package"]);
installSyncSaveDev(["first-package", "second-package"], "npm");
assert(stub.calledOnce);
assert.strictEqual(stub.firstCall.args[0], "npm");
assert.deepStrictEqual(stub.firstCall.args[1], ["i", "--save-dev", "first-package", "second-package"]);
assert.deepStrictEqual(stub.firstCall.args[1], ["install", "-D", "first-package", "second-package"]);
stub.restore();
});

Expand Down