1'use strict' 2// remove a package. 3 4module.exports = uninstall 5 6const path = require('path') 7const validate = require('aproba') 8const readJson = require('read-package-json') 9const iferr = require('iferr') 10const npm = require('./npm.js') 11const Installer = require('./install.js').Installer 12const getSaveType = require('./install/save.js').getSaveType 13const removeDeps = require('./install/deps.js').removeDeps 14const log = require('npmlog') 15const usage = require('./utils/usage') 16 17uninstall.usage = usage( 18 'uninstall', 19 'npm uninstall [<@scope>/]<pkg>[@<version>]... [--save-prod|--save-dev|--save-optional] [--no-save]' 20) 21 22uninstall.completion = require('./utils/completion/installed-shallow.js') 23 24function uninstall (args, cb) { 25 validate('AF', arguments) 26 // the /path/to/node_modules/.. 27 const dryrun = !!npm.config.get('dry-run') 28 29 if (args.length === 1 && args[0] === '.') args = [] 30 31 const where = npm.config.get('global') || !args.length 32 ? path.resolve(npm.globalDir, '..') 33 : npm.prefix 34 35 args = args.filter(function (a) { 36 return path.resolve(a) !== where 37 }) 38 39 if (args.length) { 40 new Uninstaller(where, dryrun, args).run(cb) 41 } else { 42 // remove this package from the global space, if it's installed there 43 readJson(path.resolve(npm.localPrefix, 'package.json'), function (er, pkg) { 44 if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er) 45 if (er) return cb(uninstall.usage) 46 new Uninstaller(where, dryrun, [pkg.name]).run(cb) 47 }) 48 } 49} 50 51class Uninstaller extends Installer { 52 constructor (where, dryrun, args) { 53 super(where, dryrun, args) 54 this.remove = [] 55 } 56 57 loadArgMetadata (next) { 58 this.args = this.args.map(function (arg) { return {name: arg} }) 59 next() 60 } 61 62 loadAllDepsIntoIdealTree (cb) { 63 validate('F', arguments) 64 this.remove = this.args 65 this.args = [] 66 log.silly('uninstall', 'loadAllDepsIntoIdealTree') 67 const saveDeps = getSaveType() 68 69 super.loadAllDepsIntoIdealTree(iferr(cb, () => { 70 removeDeps(this.remove, this.idealTree, saveDeps, cb) 71 })) 72 } 73 74 // no top level lifecycles on rm 75 runPreinstallTopLevelLifecycles (cb) { cb() } 76 runPostinstallTopLevelLifecycles (cb) { cb() } 77} 78 79module.exports.Uninstaller = Uninstaller 80