diff --git a/lib/config/config-initializer.js b/lib/config/config-initializer.js index d344fa0ac77..11d441029c3 100644 --- a/lib/config/config-initializer.js +++ b/lib/config/config-initializer.js @@ -65,6 +65,7 @@ function writeFile(config, format) { * @param {string} moduleName The module name to get. * @returns {Object} The peer dependencies of the given module. * This object is the object of `peerDependencies` field of `package.json`. + * Returns null if npm was not found. */ function getPeerDependencies(moduleName) { let result = getPeerDependencies.cache.get(moduleName); @@ -356,7 +357,8 @@ function hasESLintVersionConflict(answers) { // Get the required range of ESLint version. const configName = getStyleGuideName(answers); const moduleName = `eslint-config-${configName}@latest`; - const requiredESLintVersionRange = getPeerDependencies(moduleName).eslint; + const peerDependencies = getPeerDependencies(moduleName) || {}; + const requiredESLintVersionRange = peerDependencies.eslint; if (!requiredESLintVersionRange) { return false; diff --git a/lib/util/npm-util.js b/lib/util/npm-util.js index 4f488c0121e..6c431e0395b 100644 --- a/lib/util/npm-util.js +++ b/lib/util/npm-util.js @@ -53,22 +53,39 @@ function installSyncSaveDev(packages) { if (!Array.isArray(packages)) { packages = [packages]; } - spawn.sync("npm", ["i", "--save-dev"].concat(packages), { stdio: "inherit" }); + const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packages), + { stdio: "inherit" }); + const error = npmProcess.error; + + if (error && error.code === "ENOENT") { + const pluralS = packages.length > 1 ? "s" : ""; + + log.error(`Could not execute npm. Please install the following package${pluralS} with your package manager of choice: ${packages.join(", ")}`); + } } /** * Fetch `peerDependencies` of the given package by `npm show` command. * @param {string} packageName The package name to fetch peerDependencies. - * @returns {Object} Gotten peerDependencies. + * @returns {Object} Gotten peerDependencies. Returns null if npm was not found. */ function fetchPeerDependencies(packageName) { - const fetchedText = spawn.sync( + const npmProcess = spawn.sync( "npm", ["show", "--json", packageName, "peerDependencies"], { encoding: "utf8" } - ).stdout.trim(); + ); + + const error = npmProcess.error; + + if (error && error.code === "ENOENT") { + return null; + } + const fetchedText = npmProcess.stdout.trim(); return JSON.parse(fetchedText || "{}"); + + } /** diff --git a/tests/lib/util/npm-util.js b/tests/lib/util/npm-util.js index 466d4b839e8..fa9a0d1995e 100644 --- a/tests/lib/util/npm-util.js +++ b/tests/lib/util/npm-util.js @@ -170,7 +170,7 @@ describe("npmUtil", () => { describe("installSyncSaveDev()", () => { it("should invoke npm to install a single desired package", () => { - const stub = sandbox.stub(spawn, "sync"); + const stub = sandbox.stub(spawn, "sync").returns({ stdout: "" }); npmUtil.installSyncSaveDev("desired-package"); assert(stub.calledOnce); @@ -180,7 +180,7 @@ describe("npmUtil", () => { }); it("should accept an array of packages to install", () => { - const stub = sandbox.stub(spawn, "sync"); + const stub = sandbox.stub(spawn, "sync").returns({ stdout: "" }); npmUtil.installSyncSaveDev(["first-package", "second-package"]); assert(stub.calledOnce); @@ -188,6 +188,18 @@ describe("npmUtil", () => { assert.deepEqual(stub.firstCall.args[1], ["i", "--save-dev", "first-package", "second-package"]); stub.restore(); }); + + it("should log an error message if npm throws ENOENT error", () => { + const logErrorStub = sandbox.stub(log, "error"); + const npmUtilStub = sandbox.stub(spawn, "sync").returns({ error: { code: "ENOENT" } }); + + npmUtil.installSyncSaveDev("some-package"); + + assert(logErrorStub.calledOnce); + + logErrorStub.restore(); + npmUtilStub.restore(); + }); }); describe("fetchPeerDependencies()", () => { @@ -200,5 +212,15 @@ describe("npmUtil", () => { assert.deepEqual(stub.firstCall.args[1], ["show", "--json", "desired-package", "peerDependencies"]); stub.restore(); }); + + it("should return null if npm throws ENOENT error", () => { + const stub = sandbox.stub(spawn, "sync").returns({ error: { code: "ENOENT" } }); + + const peerDependencies = npmUtil.fetchPeerDependencies("desired-package"); + + assert.isNull(peerDependencies); + + stub.restore(); + }); }); });