]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/lib/outdated.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / lib / outdated.js
1 /*
2
3 npm outdated [pkg]
4
5 Does the following:
6
7 1. check for a new version of pkg
8
9 If no packages are specified, then run for all installed
10 packages.
11
12 --parseable creates output like this:
13 <fullpath>:<name@wanted>:<name@installed>:<name@latest>
14
15 */
16
17 module.exports = outdated
18
19 outdated.usage = "npm outdated [<pkg> [<pkg> ...]]"
20
21 outdated.completion = require("./utils/completion/installed-deep.js")
22
23
24 var path = require("path")
25   , readJson = require("read-package-json")
26   , cache = require("./cache.js")
27   , asyncMap = require("slide").asyncMap
28   , npm = require("./npm.js")
29   , url = require("url")
30   , color = require("ansicolors")
31   , styles = require("ansistyles")
32   , table = require("text-table")
33   , semver = require("semver")
34   , os = require("os")
35   , mapToRegistry = require("./utils/map-to-registry.js")
36   , npa = require("npm-package-arg")
37   , readInstalled = require("read-installed")
38   , long = npm.config.get("long")
39   , log = require("npmlog")
40
41 function outdated (args, silent, cb) {
42   if (typeof cb !== "function") cb = silent, silent = false
43   var dir = path.resolve(npm.dir, "..")
44
45   // default depth for `outdated` is 0 (cf. `ls`)
46   if (npm.config.get("depth") === Infinity) npm.config.set("depth", 0)
47
48   outdated_(args, dir, {}, 0, function (er, list) {
49     if (!list) list = []
50     if (er || silent || list.length === 0) return cb(er, list)
51     list.sort(function(a, b) {
52       var aa = a[1].toLowerCase()
53         , bb = b[1].toLowerCase()
54       return aa === bb ? 0
55            : aa < bb ? -1 : 1
56     })
57     if (npm.config.get("json")) {
58       console.log(makeJSON(list))
59     } else if (npm.config.get("parseable")) {
60       console.log(makeParseable(list))
61     } else {
62       var outList = list.map(makePretty)
63       var outHead = [ "Package"
64                     , "Current"
65                     , "Wanted"
66                     , "Latest"
67                     , "Location"
68                     ]
69       if (long) outHead.push("Package Type")
70       var outTable = [outHead].concat(outList)
71
72       if (npm.color) {
73         outTable[0] = outTable[0].map(function(heading) {
74           return styles.underline(heading)
75         })
76       }
77
78       var tableOpts = { align: ["l", "r", "r", "r", "l"]
79                       , stringLength: function(s) { return ansiTrim(s).length }
80                       }
81       console.log(table(outTable, tableOpts))
82     }
83     cb(null, list)
84   })
85 }
86
87 // [[ dir, dep, has, want, latest, type ]]
88 function makePretty (p) {
89   var dep = p[1]
90     , dir = path.resolve(p[0], "node_modules", dep)
91     , has = p[2]
92     , want = p[3]
93     , latest = p[4]
94     , type = p[6]
95
96   if (!npm.config.get("global")) {
97     dir = path.relative(process.cwd(), dir)
98   }
99
100   var columns = [ dep
101                 , has || "MISSING"
102                 , want
103                 , latest
104                 , dirToPrettyLocation(dir)
105                 ]
106   if (long) columns[5] = type
107
108   if (npm.color) {
109     columns[0] = color[has === want ? "yellow" : "red"](columns[0]) // dep
110     columns[2] = color.green(columns[2]) // want
111     columns[3] = color.magenta(columns[3]) // latest
112     columns[4] = color.brightBlack(columns[4]) // dir
113     if (long) columns[5] = color.brightBlack(columns[5]) // type
114   }
115
116   return columns
117 }
118
119 function ansiTrim (str) {
120   var r = new RegExp("\x1b(?:\\[(?:\\d+[ABCDEFGJKSTm]|\\d+;\\d+[Hfm]|" +
121         "\\d+;\\d+;\\d+m|6n|s|u|\\?25[lh])|\\w)", "g")
122   return str.replace(r, "")
123 }
124
125 function dirToPrettyLocation (dir) {
126   return dir.replace(/^node_modules[/\\]/, "")
127             .replace(/[[/\\]node_modules[/\\]/g, " > ")
128 }
129
130 function makeParseable (list) {
131   return list.map(function (p) {
132
133     var dep = p[1]
134       , dir = path.resolve(p[0], "node_modules", dep)
135       , has = p[2]
136       , want = p[3]
137       , latest = p[4]
138       , type = p[6]
139
140     var out = [ dir
141            , dep + "@" + want
142            , (has ? (dep + "@" + has) : "MISSING")
143            , dep + "@" + latest
144            ]
145    if (long) out.push(type)
146
147    return out.join(":")
148   }).join(os.EOL)
149 }
150
151 function makeJSON (list) {
152   var out = {}
153   list.forEach(function (p) {
154     var dir = path.resolve(p[0], "node_modules", p[1])
155     if (!npm.config.get("global")) {
156       dir = path.relative(process.cwd(), dir)
157     }
158     out[p[1]] = { current: p[2]
159                 , wanted: p[3]
160                 , latest: p[4]
161                 , location: dir
162                 }
163     if (long) out[p[1]].type = p[6]
164   })
165   return JSON.stringify(out, null, 2)
166 }
167
168 function outdated_ (args, dir, parentHas, depth, cb) {
169   // get the deps from package.json, or {<dir/node_modules/*>:"*"}
170   // asyncMap over deps:
171   //   shouldHave = cache.add(dep, req).version
172   //   if has === shouldHave then
173   //     return outdated(args, dir/node_modules/dep, parentHas + has)
174   //   else if dep in args or args is empty
175   //     return [dir, dep, has, shouldHave]
176
177   if (depth > npm.config.get("depth")) {
178     return cb(null, [])
179   }
180   var deps = null
181   var types = {}
182   readJson(path.resolve(dir, "package.json"), function (er, d) {
183     d = d || {}
184     if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
185     deps = (er) ? true : (d.dependencies || {})
186     if (!er) {
187       Object.keys(deps).forEach(function (k) {
188         types[k] = "dependencies"
189       })
190     }
191
192     if (npm.config.get("save-dev")) {
193       deps = d.devDependencies || {}
194       Object.keys(deps).forEach(function (k) {
195         types[k] = "devDependencies"
196       })
197
198       return next()
199     }
200
201     if (npm.config.get("save")) {
202       // remove optional dependencies from dependencies during --save.
203       Object.keys(d.optionalDependencies || {}).forEach(function (k) {
204         delete deps[k]
205       })
206       return next()
207     }
208
209     if (npm.config.get("save-optional")) {
210       deps = d.optionalDependencies || {}
211       Object.keys(deps).forEach(function (k) {
212         types[k] = "optionalDependencies"
213       })
214       return next()
215     }
216
217     var doUpdate = npm.config.get("dev") ||
218                     (!npm.config.get("production") &&
219                     !Object.keys(parentHas).length &&
220                     !npm.config.get("global"))
221
222     if (!er && d && doUpdate) {
223       Object.keys(d.devDependencies || {}).forEach(function (k) {
224         if (!(k in parentHas)) {
225           deps[k] = d.devDependencies[k]
226           types[k] = "devDependencies"
227         }
228       })
229     }
230     return next()
231   })
232
233   var has = null
234   readInstalled(path.resolve(dir), { dev : true }, function (er, data) {
235     if (er) {
236       has = Object.create(parentHas)
237       return next()
238     }
239     var pkgs = Object.keys(data.dependencies)
240     pkgs = pkgs.filter(function (p) {
241       return !p.match(/^[\._-]/)
242     })
243     asyncMap(pkgs, function (pkg, cb) {
244       var jsonFile = path.resolve(dir, "node_modules", pkg, "package.json")
245       readJson(jsonFile, function (er, d) {
246         if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
247         if (d && d.name && d.private) delete deps[d.name]
248         cb(null, er ? [] : [[d.name, d.version, d._from]])
249       })
250     }, function (er, pvs) {
251       if (er) return cb(er)
252       has = Object.create(parentHas)
253       pvs.forEach(function (pv) {
254         has[pv[0]] = {
255           link: data.dependencies[pv[0]].link,
256           version: pv[1],
257           from: pv[2]
258         }
259       })
260
261       next()
262     })
263   })
264
265   function next () {
266     if (!has || !deps) return
267     if (deps === true) {
268       deps = Object.keys(has).reduce(function (l, r) {
269         l[r] = "latest"
270         return l
271       }, {})
272     }
273
274     // now get what we should have, based on the dep.
275     // if has[dep] !== shouldHave[dep], then cb with the data
276     // otherwise dive into the folder
277     asyncMap(Object.keys(deps), function (dep, cb) {
278       if (!long) return shouldUpdate(args, dir, dep, has, deps[dep], depth, cb)
279
280       shouldUpdate(args, dir, dep, has, deps[dep], depth, cb, types[dep])
281     }, cb)
282   }
283 }
284
285 function shouldUpdate (args, dir, dep, has, req, depth, cb, type) {
286   // look up the most recent version.
287   // if that's what we already have, or if it's not on the args list,
288   // then dive into it.  Otherwise, cb() with the data.
289
290   // { version: , from: }
291   var curr = has[dep]
292
293   function skip (er) {
294     // show user that no viable version can be found
295     if (er) return cb(er)
296     outdated_( args
297              , path.resolve(dir, "node_modules", dep)
298              , has
299              , depth + 1
300              , cb )
301   }
302
303   function doIt (wanted, latest) {
304     if (!long) {
305       return cb(null, [[ dir, dep, curr && curr.version, wanted, latest, req]])
306     }
307     cb(null, [[ dir, dep, curr && curr.version, wanted, latest, req, type]])
308   }
309
310   if (args.length && args.indexOf(dep) === -1) return skip()
311   var parsed = npa(dep + '@' + req)
312   if (parsed.type === "git" || (parsed.hosted && parsed.hosted.type === "github")) {
313     return doIt("git", "git")
314   }
315   if (curr && curr.link) {
316     return doIt("linked", "linked")
317   }
318
319   // search for the latest package
320   mapToRegistry(dep, npm.config, function (er, uri, auth) {
321     if (er) return cb(er)
322
323     npm.registry.get(uri, { auth : auth }, updateDeps)
324   })
325
326   function updateLocalDeps (latestRegistryVersion) {
327     readJson(path.resolve(parsed.spec, 'package.json'), function (er, localDependency) {
328       if (er) return cb()
329
330       var wanted = localDependency.version
331       var latest = localDependency.version
332
333       if (latestRegistryVersion) {
334         latest = latestRegistryVersion
335         if (semver.lt(wanted, latestRegistryVersion)) {
336           wanted = latestRegistryVersion
337           req = dep + '@' + latest
338         }
339       }
340
341       if (curr.version !== wanted) {
342         doIt(wanted, latest)
343       } else {
344         skip()
345       }
346     })
347   }
348
349   function updateDeps (er, d) {
350     if (er) {
351       if (parsed.type !== 'local') return cb(er)
352       return updateLocalDeps()
353     }
354
355     if (!d || !d["dist-tags"] || !d.versions) return cb()
356     var l = d.versions[d["dist-tags"].latest]
357     if (!l) return cb()
358
359     var r = req
360     if (d["dist-tags"][req])
361       r = d["dist-tags"][req]
362
363     if (semver.validRange(r, true)) {
364       // some kind of semver range.
365       // see if it's in the doc.
366       var vers = Object.keys(d.versions)
367       var v = semver.maxSatisfying(vers, r, true)
368       if (v) {
369         return onCacheAdd(null, d.versions[v])
370       }
371     }
372
373     // We didn't find the version in the doc.  See if cache can find it.
374     cache.add(dep, req, null, false, onCacheAdd)
375
376     function onCacheAdd(er, d) {
377       // if this fails, then it means we can't update this thing.
378       // it's probably a thing that isn't published.
379       if (er) {
380         if (er.code && er.code === "ETARGET") {
381           // no viable version found
382           return skip(er)
383         }
384         return skip()
385       }
386
387       // check that the url origin hasn't changed (#1727) and that
388       // there is no newer version available
389       var dFromUrl = d._from && url.parse(d._from).protocol
390       var cFromUrl = curr && curr.from && url.parse(curr.from).protocol
391
392       if (!curr || dFromUrl && cFromUrl && d._from !== curr.from
393           || d.version !== curr.version
394           || d.version !== l.version) {
395         if (parsed.type === 'local') return updateLocalDeps(l.version)
396
397         doIt(d.version, l.version)
398       }
399       else {
400         skip()
401       }
402     }
403   }
404 }