UNPKG

3.93 kBJavaScriptView Raw
1
2// remove a package.
3
4module.exports = uninstall
5
6uninstall.usage = "npm uninstall <name>[@<version> [<name>[@<version>] ...]"
7 + "\nnpm rm <name>[@<version> [<name>[@<version>] ...]"
8
9uninstall.completion = require("./utils/completion/installed-shallow.js")
10
11var fs = require("graceful-fs")
12 , writeFileAtomic = require("write-file-atomic")
13 , log = require("npmlog")
14 , readJson = require("read-package-json")
15 , path = require("path")
16 , npm = require("./npm.js")
17 , asyncMap = require("slide").asyncMap
18
19function uninstall (args, cb) {
20 // this is super easy
21 // get the list of args that correspond to package names in either
22 // the global npm.dir,
23 // then call unbuild on all those folders to pull out their bins
24 // and mans and whatnot, and then delete the folder.
25
26 var nm = npm.dir
27 if (args.length === 1 && args[0] === ".") args = []
28 if (args.length) return uninstall_(args, nm, cb)
29
30 // remove this package from the global space, if it's installed there
31 if (npm.config.get("global")) return cb(uninstall.usage)
32 readJson(path.resolve(npm.prefix, "package.json"), function (er, pkg) {
33 if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
34 if (er) return cb(uninstall.usage)
35 uninstall_( [pkg.name]
36 , npm.dir
37 , cb )
38 })
39
40}
41
42function uninstall_ (args, nm, cb) {
43 // if we've been asked to --save or --save-dev or --save-optional,
44 // then also remove it from the associated dependencies hash.
45 var s = npm.config.get('save')
46 , d = npm.config.get('save-dev')
47 , o = npm.config.get('save-optional')
48 if (s || d || o) {
49 cb = saver(args, nm, cb)
50 }
51
52 asyncMap(args, function (arg, cb) {
53 // uninstall .. should not delete /usr/local/lib/node_modules/..
54 var p = path.join(path.resolve(nm), path.join("/", arg))
55 if (path.resolve(p) === nm) {
56 log.warn("uninstall", "invalid argument: %j", arg)
57 return cb(null, [])
58 }
59 fs.lstat(p, function (er) {
60 if (er) {
61 log.warn("uninstall", "not installed in %s: %j", nm, arg)
62 return cb(null, [])
63 }
64 cb(null, p)
65 })
66 }, function (er, folders) {
67 if (er) return cb(er)
68 asyncMap(folders, npm.commands.unbuild, cb)
69 })
70}
71
72function saver (args, nm, cb_) {
73 return cb
74 function cb (er, data) {
75 var s = npm.config.get('save')
76 , d = npm.config.get('save-dev')
77 , o = npm.config.get('save-optional')
78 if (er || !(s || d || o)) return cb_(er, data)
79 var pj = path.resolve(nm, '..', 'package.json')
80 // don't use readJson here, because we don't want all the defaults
81 // filled in, for mans and other bs.
82 fs.readFile(pj, 'utf8', function (er, json) {
83 var pkg
84 try {
85 pkg = JSON.parse(json)
86 } catch (_) {}
87 if (!pkg) return cb_(null, data)
88
89 var bundle
90 if (npm.config.get('save-bundle')) {
91 bundle = pkg.bundleDependencies || pkg.bundledDependencies
92 if (!Array.isArray(bundle)) bundle = undefined
93 }
94
95 var changed = false
96 args.forEach(function (a) {
97 ; [ [s, 'dependencies']
98 , [o, 'optionalDependencies']
99 , [d, 'devDependencies'] ].forEach(function (f) {
100 var flag = f[0]
101 , field = f[1]
102 if (!flag || !pkg[field] || !pkg[field].hasOwnProperty(a)) return
103 changed = true
104
105 if (bundle) {
106 var i = bundle.indexOf(a)
107 if (i !== -1) bundle.splice(i, 1)
108 }
109
110 delete pkg[field][a]
111 })
112 })
113 if (!changed) return cb_(null, data)
114
115 if (bundle) {
116 delete pkg.bundledDependencies
117 if (bundle.length) {
118 pkg.bundleDependencies = bundle
119 } else {
120 delete pkg.bundleDependencies
121 }
122 }
123
124 writeFileAtomic(pj, JSON.stringify(pkg, null, 2) + "\n", function (er) {
125 return cb_(er, data)
126 })
127 })
128 }
129}