| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 | /** * @fileoverview Utility for executing npm commands. * @author Ian VanSchooten */"use strict";//------------------------------------------------------------------------------// Requirements//------------------------------------------------------------------------------const fs = require("fs"),    spawn = require("cross-spawn"),    path = require("path"),    log = require("../logging");//------------------------------------------------------------------------------// Helpers//------------------------------------------------------------------------------/** * Find the closest package.json file, starting at process.cwd (by default), * and working up to root. * * @param   {string} [startDir=process.cwd()] Starting directory * @returns {string}                          Absolute path to closest package.json file */function findPackageJson(startDir) {    let dir = path.resolve(startDir || process.cwd());    do {        const pkgFile = path.join(dir, "package.json");        if (!fs.existsSync(pkgFile) || !fs.statSync(pkgFile).isFile()) {            dir = path.join(dir, "..");            continue;        }        return pkgFile;    } while (dir !== path.resolve(dir, ".."));    return null;}//------------------------------------------------------------------------------// Private//------------------------------------------------------------------------------/** * Install node modules synchronously and save to devDependencies in package.json * @param   {string|string[]} packages Node module or modules to install * @returns {void} */function installSyncSaveDev(packages) {    const packageList = Array.isArray(packages) ? packages : [packages];    const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList),        { stdio: "inherit" });    const error = npmProcess.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(", ")}`);    }}/** * Fetch `peerDependencies` of the given package by `npm show` command. * @param {string} packageName The package name to fetch peerDependencies. * @returns {Object} Gotten peerDependencies. Returns null if npm was not found. */function fetchPeerDependencies(packageName) {    const npmProcess = spawn.sync(        "npm",        ["show", "--json", packageName, "peerDependencies"],        { encoding: "utf8" }    );    const error = npmProcess.error;    if (error && error.code === "ENOENT") {        return null;    }    const fetchedText = npmProcess.stdout.trim();    return JSON.parse(fetchedText || "{}");}/** * Check whether node modules are include in a project's package.json. * * @param   {string[]} packages           Array of node module names * @param   {Object}  opt                 Options Object * @param   {boolean} opt.dependencies    Set to true to check for direct dependencies * @param   {boolean} opt.devDependencies Set to true to check for development dependencies * @param   {boolean} opt.startdir        Directory to begin searching from * @returns {Object}                      An object whose keys are the module names *                                        and values are booleans indicating installation. */function check(packages, opt) {    let deps = [];    const pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson();    let fileJson;    if (!pkgJson) {        throw new Error("Could not find a package.json file. Run 'npm init' to create one.");    }    try {        fileJson = JSON.parse(fs.readFileSync(pkgJson, "utf8"));    } catch (e) {        log.info("Could not read package.json file. Please check that the file contains valid JSON.");        throw new Error(e);    }    if (opt.devDependencies && typeof fileJson.devDependencies === "object") {        deps = deps.concat(Object.keys(fileJson.devDependencies));    }    if (opt.dependencies && typeof fileJson.dependencies === "object") {        deps = deps.concat(Object.keys(fileJson.dependencies));    }    return packages.reduce((status, pkg) => {        status[pkg] = deps.indexOf(pkg) !== -1;        return status;    }, {});}/** * Check whether node modules are included in the dependencies of a project's * package.json. * * Convienience wrapper around check(). * * @param   {string[]} packages  Array of node modules to check. * @param   {string}   rootDir   The directory contianing a package.json * @returns {Object}             An object whose keys are the module names *                               and values are booleans indicating installation. */function checkDeps(packages, rootDir) {    return check(packages, { dependencies: true, startDir: rootDir });}/** * Check whether node modules are included in the devDependencies of a project's * package.json. * * Convienience wrapper around check(). * * @param   {string[]} packages  Array of node modules to check. * @returns {Object}             An object whose keys are the module names *                               and values are booleans indicating installation. */function checkDevDeps(packages) {    return check(packages, { devDependencies: true });}/** * Check whether package.json is found in current path. * * @param   {string=} startDir Starting directory * @returns {boolean} Whether a package.json is found in current path. */function checkPackageJson(startDir) {    return !!findPackageJson(startDir);}//------------------------------------------------------------------------------// Public Interface//------------------------------------------------------------------------------module.exports = {    installSyncSaveDev,    fetchPeerDependencies,    checkDeps,    checkDevDeps,    checkPackageJson};
 |