// remove a package. module.exports = uninstall uninstall.usage = "npm uninstall [@ [[@] ...]" + "\nnpm rm [@ [[@] ...]" uninstall.completion = require("./utils/completion/installed-shallow.js") var fs = require("graceful-fs") , log = require("npmlog") , readJson = require("read-package-json") , path = require("path") , npm = require("./npm.js") , asyncMap = require("slide").asyncMap function uninstall (args, cb) { // this is super easy // get the list of args that correspond to package names in either // the global npm.dir, // then call unbuild on all those folders to pull out their bins // and mans and whatnot, and then delete the folder. var nm = npm.dir if (args.length === 1 && args[0] === ".") args = [] if (args.length) return uninstall_(args, nm, cb) // remove this package from the global space, if it's installed there if (npm.config.get("global")) return cb(uninstall.usage) readJson(path.resolve(npm.prefix, "package.json"), function (er, pkg) { if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er) if (er) return cb(uninstall.usage) uninstall_( [pkg.name] , npm.dir , cb ) }) } function uninstall_ (args, nm, cb) { // if we've been asked to --save or --save-dev or --save-optional, // then also remove it from the associated dependencies hash. var s = npm.config.get('save') , d = npm.config.get('save-dev') , o = npm.config.get('save-optional') if (s || d || o) { cb = saver(args, nm, cb) } asyncMap(args, function (arg, cb) { // uninstall .. should not delete /usr/local/lib/node_modules/.. var p = path.join(path.resolve(nm), path.join("/", arg)) if (path.resolve(p) === nm) { log.warn("uninstall", "invalid argument: %j", arg) return cb(null, []) } fs.lstat(p, function (er) { if (er) { log.warn("uninstall", "not installed in %s: %j", nm, arg) return cb(null, []) } cb(null, p) }) }, function (er, folders) { if (er) return cb(er) asyncMap(folders, npm.commands.unbuild, cb) }) } function saver (args, nm, cb_) { return cb function cb (er, data) { var s = npm.config.get('save') , d = npm.config.get('save-dev') , o = npm.config.get('save-optional') if (er || !(s || d || o)) return cb_(er, data) var pj = path.resolve(nm, '..', 'package.json') // don't use readJson here, because we don't want all the defaults // filled in, for mans and other bs. fs.readFile(pj, 'utf8', function (er, json) { try { var pkg = JSON.parse(json) } catch (_) {} if (!pkg) return cb_(null, data) var bundle if (npm.config.get('save-bundle')) { var bundle = pkg.bundleDependencies || pkg.bundledDependencies if (!Array.isArray(bundle)) bundle = undefined } var changed = false args.forEach(function (a) { ; [ [s, 'dependencies'] , [o, 'optionalDependencies'] , [d, 'devDependencies'] ].forEach(function (f) { var flag = f[0] , field = f[1] if (!flag || !pkg[field] || !pkg[field].hasOwnProperty(a)) return changed = true if (bundle) { var i = bundle.indexOf(a) if (i !== -1) bundle.splice(i, 1) } delete pkg[field][a] }) }) if (!changed) return cb_(null, data) if (bundle) { delete pkg.bundledDependencies if (bundle.length) { pkg.bundleDependencies = bundle } else { delete pkg.bundleDependencies } } fs.writeFile(pj, JSON.stringify(pkg, null, 2) + "\n", function (er) { return cb_(er, data) }) }) } }