Skip to content

Commit

Permalink
Use yarn if available (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
evenstensberg authored Oct 5, 2017
1 parent acb6285 commit 21ebcbe
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 34 deletions.
2 changes: 1 addition & 1 deletion lib/creator/transformations/devServer/devServer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const defineTest = require("../../../transformations/defineTest");

defineTest(__dirname, "devServer", "devServer-0",{
defineTest(__dirname, "devServer", "devServer-0", {
contentBase: "path.join(__dirname, 'dist')",
compress: true,
port: 9000
Expand Down
21 changes: 13 additions & 8 deletions lib/creator/yeoman/webpack-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const Input = require("webpack-addons").Input;
const Confirm = require("webpack-addons").Confirm;
const RawList = require("webpack-addons").RawList;

const getPackageManager = require("../../utils/package-manager")
.getPackageManager;

const entryQuestions = require("./utils/entry");
const getBabelPlugin = require("./utils/module");
const getDefaultPlugins = require("./utils/plugins");
Expand All @@ -19,7 +22,7 @@ module.exports = class WebpackGenerator extends Generator {
constructor(args, opts) {
super(args, opts);
this.isProd = false;
this.npmInstalls = ["webpack", "uglifyjs-webpack-plugin"];
this.dependencies = ["webpack", "uglifyjs-webpack-plugin"];
this.configuration = {
config: {
webpackOptions: {},
Expand Down Expand Up @@ -109,7 +112,7 @@ module.exports = class WebpackGenerator extends Generator {
this.configuration.config.webpackOptions.module.rules.push(
getBabelPlugin()
);
this.npmInstalls.push(
this.dependencies.push(
"babel-loader",
"babel-core",
"babel-preset-es2015"
Expand All @@ -130,7 +133,7 @@ module.exports = class WebpackGenerator extends Generator {
}
switch (stylingAnswer["stylingType"]) {
case "SASS":
this.npmInstalls.push(
this.dependencies.push(
"sass-loader",
"node-sass",
"style-loader",
Expand Down Expand Up @@ -166,7 +169,7 @@ module.exports = class WebpackGenerator extends Generator {
break;
case "LESS":
regExpForStyles = new RegExp(/\.(less|css)$/);
this.npmInstalls.push(
this.dependencies.push(
"less-loader",
"less",
"style-loader",
Expand Down Expand Up @@ -210,7 +213,7 @@ module.exports = class WebpackGenerator extends Generator {
"const precss = require('precss');",
"\n"
);
this.npmInstalls.push(
this.dependencies.push(
"style-loader",
"css-loader",
"postcss-loader",
Expand Down Expand Up @@ -267,7 +270,7 @@ module.exports = class WebpackGenerator extends Generator {
}
break;
case "CSS":
this.npmInstalls.push(
this.dependencies.push(
"style-loader",
"css-loader"
);
Expand Down Expand Up @@ -312,7 +315,7 @@ module.exports = class WebpackGenerator extends Generator {
this.configuration.config.topScope.push(
tooltip.cssPlugin()
);
this.npmInstalls.push(
this.dependencies.push(
"extract-text-webpack-plugin"
);
if (
Expand Down Expand Up @@ -390,7 +393,9 @@ module.exports = class WebpackGenerator extends Generator {
})
.then(() => {
asyncNamePrompt();
this.npmInstall(this.npmInstalls, { "save-dev": true });
this.runInstall(getPackageManager(), this.dependencies, {
"save-dev": true
});
});
}
};
61 changes: 61 additions & 0 deletions lib/utils/package-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use strict";

const path = require("path");
const fs = require("fs");
const spawn = require("cross-spawn");
const globalPath = require("global-modules");

const SPAWN_FUNCTIONS = {
npm: spawnNPM,
yarn: spawnYarn
};

function spawnNPM(pkg, isNew) {
return spawn.sync("npm", [isNew ? "install" : "update", "-g", pkg], {
stdio: "inherit"
});
}

function spawnYarn(pkg, isNew) {
return spawn.sync("yarn", ["global", isNew ? "add" : "upgrade", pkg], {
stdio: "inherit"
});
}
/*
* @function spawnChild
*
* Spawns a new process that installs the addon/dependency
*
* @param { String } pkg - The dependency to be installed
* @returns { <Function> } spawn - Installs the package
*/

function spawnChild(pkg) {
const pkgPath = path.resolve(globalPath, pkg);
const packageManager = getPackageManager();
const isNew = !fs.existsSync(pkgPath);

return SPAWN_FUNCTIONS[packageManager](pkg, isNew);
}

/*
* @function getPackageManager
*
* Returns the name of package manager to use,
* preferring yarn over npm if available
*
* @returns { String } - The package manager name
*/

function getPackageManager() {
if (spawn.sync("yarn", [" --version"], { stdio: "ignore" }).error) {
return "npm";
}

return "yarn";
}

module.exports = {
getPackageManager,
spawnChild
};
90 changes: 90 additions & 0 deletions lib/utils/package-manager.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"use strict";

jest.mock("cross-spawn");
jest.mock("fs");

describe("package-manager", () => {
const packageManager = require("./package-manager");
const spawn = require("cross-spawn");
const fs = require("fs");

const defaultSyncResult = {
pid: 1234,
output: [null, null, null],
stdout: null,
stderr: null,
signal: null,
status: 1,
error: null
};

function mockSpawnErrorOnce() {
spawn.sync.mockReturnValueOnce(
Object.assign({}, defaultSyncResult, {
status: null,
error: new Error()
})
);
}

spawn.sync.mockReturnValue(defaultSyncResult);

it("should return 'yarn' from getPackageManager if it's installed", () => {
expect(packageManager.getPackageManager()).toEqual("yarn");
});

it("should return 'npm' from getPackageManager if yarn is not installed", () => {
mockSpawnErrorOnce();
expect(packageManager.getPackageManager()).toEqual("npm");
});

it("should spawn yarn add from spawnChild", () => {
const packageName = "some-pkg";

packageManager.spawnChild(packageName);
expect(spawn.sync).toHaveBeenLastCalledWith(
"yarn",
["global", "add", packageName],
{ stdio: "inherit" }
);
});

it("should spawn yarn upgrade from spawnChild", () => {
const packageName = "some-pkg";

fs.existsSync.mockReturnValueOnce(true);

packageManager.spawnChild(packageName);
expect(spawn.sync).toHaveBeenLastCalledWith(
"yarn",
["global", "upgrade", packageName],
{ stdio: "inherit" }
);
});

it("should spawn npm install from spawnChild", () => {
const packageName = "some-pkg";

mockSpawnErrorOnce();
packageManager.spawnChild(packageName);
expect(spawn.sync).toHaveBeenLastCalledWith(
"npm",
["install", "-g", packageName],
{ stdio: "inherit" }
);
});

it("should spawn npm update from spawnChild", () => {
const packageName = "some-pkg";

mockSpawnErrorOnce();
fs.existsSync.mockReturnValueOnce(true);

packageManager.spawnChild(packageName);
expect(spawn.sync).toHaveBeenLastCalledWith(
"npm",
["update", "-g", packageName],
{ stdio: "inherit" }
);
});
});
30 changes: 5 additions & 25 deletions lib/utils/resolve-packages.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"use strict";

const path = require("path");
const fs = require("fs");
const chalk = require("chalk");
const spawn = require("cross-spawn");
const creator = require("../creator/index").creator;
const globalPath = require("global-modules");

const creator = require("../creator/index").creator;

const spawnChild = require("./package-manager").spawnChild;

/*
* @function processPromise
*
Expand All @@ -26,28 +28,6 @@ function processPromise(child) {
});
}

/*
* @function spawnChild
*
* Spawns a new process that installs the addon/dependency
*
* @param { String } pkg - The dependency to be installed
* @returns { <Function> } spawn - Installs the package
*/

function spawnChild(pkg) {
const pkgPath = path.resolve(globalPath, pkg);
let installType;
if (fs.existsSync(pkgPath)) {
installType = "update";
} else {
installType = "install";
}
return spawn.sync("npm", [installType, "-g", pkg], {
stdio: "inherit"
});
}

/*
* @function resolvePackages
*
Expand Down

0 comments on commit 21ebcbe

Please sign in to comment.