UNPKG

4.53 kBJavaScriptView Raw
1/**
2 * @fileoverview Utility for executing npm commands.
3 * @author Ian VanSchooten
4 * @copyright 2016 Ilya Volodin. All rights reserved.
5 * See LICENSE file in root directory for full license.
6 */
7
8"use strict";
9
10//------------------------------------------------------------------------------
11// Requirements
12//------------------------------------------------------------------------------
13
14var fs = require("fs"),
15 path = require("path"),
16 shell = require("shelljs");
17
18//------------------------------------------------------------------------------
19// Helpers
20//------------------------------------------------------------------------------
21
22/**
23 * Find the closest package.json file, starting at process.cwd (by default),
24 * and working up to root.
25 *
26 * @param {string} [startDir=process.cwd()] Starting directory
27 * @returns {string} Absolute path to closest package.json file
28 */
29function findPackageJson(startDir) {
30 var dir = path.resolve(startDir || process.cwd());
31 do {
32 var pkgfile = path.join(dir, "package.json");
33 if (!fs.existsSync(pkgfile)) {
34 dir = path.join(dir, "..");
35 continue;
36 }
37 return pkgfile;
38 } while (dir !== path.resolve(dir, ".."));
39 return null;
40}
41
42//------------------------------------------------------------------------------
43// Private
44//------------------------------------------------------------------------------
45
46/**
47 * Install node modules synchronously and save to devDependencies in package.json
48 * @param {string|string[]} packages Node module or modules to install
49 * @returns {void}
50 */
51function installSyncSaveDev(packages) {
52 if (Array.isArray(packages)) {
53 packages = packages.join(" ");
54 }
55 shell.exec("npm i --save-dev " + packages, {stdio: "inherit"});
56}
57
58/**
59 * Check whether node modules are include in a project's package.json.
60 *
61 * @param {string[]} packages Array of node module names
62 * @param {Object} opt Options Object
63 * @param {boolean} opt.dependencies Set to true to check for direct dependencies
64 * @param {boolean} opt.devDependencies Set to true to check for development dependencies
65 * @param {boolean} opt.startdir Directory to begin searching from
66 * @returns {Object} An object whose keys are the module names
67 * and values are booleans indicating installation.
68 */
69function check(packages, opt) {
70 var deps = [];
71 var pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson();
72 if (!pkgJson) {
73 throw new Error("Could not find a package.json file. Run 'npm init' to create one.");
74 }
75 var fileJson = JSON.parse(fs.readFileSync(pkgJson, "utf8"));
76 if (opt.devDependencies && typeof fileJson.devDependencies === "object") {
77 deps = deps.concat(Object.keys(fileJson.devDependencies));
78 }
79 if (opt.dependencies && typeof fileJson.dependencies === "object") {
80 deps = deps.concat(Object.keys(fileJson.dependencies));
81 }
82 return packages.reduce(function(status, pkg) {
83 status[pkg] = deps.indexOf(pkg) !== -1;
84 return status;
85 }, {});
86}
87
88/**
89 * Check whether node modules are included in the dependencies of a project's
90 * package.json.
91 *
92 * Convienience wrapper around check().
93 *
94 * @param {string[]} packages Array of node modules to check.
95 * @param {string} rootDir The directory contianing a package.json
96 * @returns {Object} An object whose keys are the module names
97 * and values are booleans indicating installation.
98 */
99function checkDeps(packages, rootDir) {
100 return check(packages, {dependencies: true, startDir: rootDir});
101}
102
103/**
104 * Check whether node modules are included in the devDependencies of a project's
105 * package.json.
106 *
107 * Convienience wrapper around check().
108 *
109 * @param {string[]} packages Array of node modules to check.
110 * @returns {Object} An object whose keys are the module names
111 * and values are booleans indicating installation.
112 */
113function checkDevDeps(packages) {
114 return check(packages, {devDependencies: true});
115}
116
117//------------------------------------------------------------------------------
118// Public Interface
119//------------------------------------------------------------------------------
120
121module.exports = {
122 installSyncSaveDev: installSyncSaveDev,
123 checkDeps: checkDeps,
124 checkDevDeps: checkDevDeps
125};