"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/npm/lib/ls.js" (8 Mar 2017, 14274 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // show the installed versions of packages
    2 //
    3 // --parseable creates output like this:
    4 // <fullpath>:<name@ver>:<realpath>:<flags>
    5 // Flags are a :-separated list of zero or more indicators
    6 
    7 module.exports = exports = ls
    8 
    9 var path = require('path')
   10 var url = require('url')
   11 var readPackageTree = require('read-package-tree')
   12 var log = require('npmlog')
   13 var archy = require('archy')
   14 var semver = require('semver')
   15 var color = require('ansicolors')
   16 var npa = require('npm-package-arg')
   17 var iferr = require('iferr')
   18 var npm = require('./npm.js')
   19 var mutateIntoLogicalTree = require('./install/mutate-into-logical-tree.js')
   20 var recalculateMetadata = require('./install/deps.js').recalculateMetadata
   21 var packageId = require('./utils/package-id.js')
   22 var usage = require('./utils/usage')
   23 var output = require('./utils/output.js')
   24 
   25 ls.usage = usage(
   26   'ls',
   27   'npm ls [[<@scope>/]<pkg> ...]'
   28 )
   29 
   30 ls.completion = require('./utils/completion/installed-deep.js')
   31 
   32 function ls (args, silent, cb) {
   33   if (typeof cb !== 'function') {
   34     cb = silent
   35     silent = false
   36   }
   37   var dir = path.resolve(npm.dir, '..')
   38   readPackageTree(dir, andRecalculateMetadata(iferr(cb, function (physicalTree) {
   39     lsFromTree(dir, physicalTree, args, silent, cb)
   40   })))
   41 }
   42 
   43 function andRecalculateMetadata (next) {
   44   return function (er, tree) {
   45     recalculateMetadata(tree || {}, log, next)
   46   }
   47 }
   48 
   49 function inList (list, value) {
   50   return list.indexOf(value) !== -1
   51 }
   52 
   53 var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
   54   if (typeof cb !== 'function') {
   55     cb = silent
   56     silent = false
   57   }
   58 
   59   // npm ls 'foo@~1.3' bar 'baz@<2'
   60   if (!args) {
   61     args = []
   62   } else {
   63     args = args.map(function (a) {
   64       var p = npa(a)
   65       var name = p.name
   66       // When version spec is missing, we'll skip using it when filtering.
   67       // Otherwise, `semver.validRange` would return '*', which won't
   68       // match prerelease versions.
   69       var ver = (p.rawSpec &&
   70                  (semver.validRange(p.rawSpec) || ''))
   71       return [ name, ver, a ]
   72     })
   73   }
   74 
   75   var data = mutateIntoLogicalTree.asReadInstalled(physicalTree)
   76 
   77   pruneNestedExtraneous(data)
   78   filterByEnv(data)
   79   var bfs = filterFound(bfsify(data), args)
   80   var lite = getLite(bfs)
   81 
   82   if (silent) return cb(null, data, lite)
   83 
   84   var long = npm.config.get('long')
   85   var json = npm.config.get('json')
   86   var out
   87   if (json) {
   88     var seen = []
   89     var d = long ? bfs : lite
   90     // the raw data can be circular
   91     out = JSON.stringify(d, function (k, o) {
   92       if (typeof o === 'object') {
   93         if (inList(seen, o)) return '[Circular]'
   94         seen.push(o)
   95       }
   96       return o
   97     }, 2)
   98   } else if (npm.config.get('parseable')) {
   99     out = makeParseable(bfs, long, dir)
  100   } else if (data) {
  101     out = makeArchy(bfs, long, dir)
  102   }
  103   output(out)
  104 
  105   if (args.length && !data._found) process.exitCode = 1
  106 
  107   var er
  108   // if any errors were found, then complain and exit status 1
  109   if (lite.problems && lite.problems.length) {
  110     er = lite.problems.join('\n')
  111   }
  112   cb(er, data, lite)
  113 }
  114 
  115 function pruneNestedExtraneous (data, visited) {
  116   visited = visited || []
  117   visited.push(data)
  118   for (var i in data.dependencies) {
  119     if (data.dependencies[i].extraneous) {
  120       data.dependencies[i].dependencies = {}
  121     } else if (visited.indexOf(data.dependencies[i]) === -1) {
  122       pruneNestedExtraneous(data.dependencies[i], visited)
  123     }
  124   }
  125 }
  126 
  127 function filterByEnv (data) {
  128   var dev = npm.config.get('dev') || /^dev(elopment)?$/.test(npm.config.get('only'))
  129   var production = npm.config.get('production') || /^prod(uction)?$/.test(npm.config.get('only'))
  130   var dependencies = {}
  131   var devKeys = Object.keys(data.devDependencies || [])
  132   var prodKeys = Object.keys(data._dependencies || [])
  133   Object.keys(data.dependencies).forEach(function (name) {
  134     if (!dev && inList(devKeys, name) && data.dependencies[name].missing) {
  135       return
  136     }
  137 
  138     if ((dev && inList(devKeys, name)) ||            // only --dev
  139         (production && inList(prodKeys, name)) ||    // only --production
  140         (!dev && !production)) {                            // no --production|--dev|--only=xxx
  141       dependencies[name] = data.dependencies[name]
  142     }
  143   })
  144   data.dependencies = dependencies
  145 }
  146 
  147 function alphasort (a, b) {
  148   a = a.toLowerCase()
  149   b = b.toLowerCase()
  150   return a > b ? 1
  151        : a < b ? -1 : 0
  152 }
  153 
  154 function isCruft (data) {
  155   return data.extraneous && data.error && data.error.code === 'ENOTDIR'
  156 }
  157 
  158 function getLite (data, noname, depth) {
  159   var lite = {}
  160 
  161   if (isCruft(data)) return lite
  162 
  163   var maxDepth = npm.config.get('depth')
  164 
  165   if (typeof depth === 'undefined') depth = 0
  166   if (!noname && data.name) lite.name = data.name
  167   if (data.version) lite.version = data.version
  168   if (data.extraneous) {
  169     lite.extraneous = true
  170     lite.problems = lite.problems || []
  171     lite.problems.push('extraneous: ' + packageId(data) + ' ' + (data.path || ''))
  172   }
  173 
  174   if (data.error && data.path !== path.resolve(npm.globalDir, '..') &&
  175       (data.error.code !== 'ENOENT' || noname)) {
  176     lite.invalid = true
  177     lite.problems = lite.problems || []
  178     var message = data.error.message
  179     lite.problems.push('error in ' + data.path + ': ' + message)
  180   }
  181 
  182   if (data._from) {
  183     lite.from = data._from
  184   }
  185 
  186   if (data._resolved) {
  187     lite.resolved = data._resolved
  188   }
  189 
  190   if (data.invalid) {
  191     lite.invalid = true
  192     lite.problems = lite.problems || []
  193     lite.problems.push('invalid: ' +
  194                        packageId(data) +
  195                        ' ' + (data.path || ''))
  196   }
  197 
  198   if (data.peerInvalid) {
  199     lite.peerInvalid = true
  200     lite.problems = lite.problems || []
  201     lite.problems.push('peer dep not met: ' +
  202                        packageId(data) +
  203                        ' ' + (data.path || ''))
  204   }
  205 
  206   var deps = (data.dependencies && Object.keys(data.dependencies)) || []
  207   if (deps.length) {
  208     lite.dependencies = deps.map(function (d) {
  209       var dep = data.dependencies[d]
  210       if (dep.missing && !dep.optional) {
  211         lite.problems = lite.problems || []
  212         var p
  213         if (data.depth > maxDepth) {
  214           p = 'max depth reached: '
  215         } else {
  216           p = 'missing: '
  217         }
  218         p += d + '@' + dep.requiredBy +
  219             ', required by ' +
  220             packageId(data)
  221         lite.problems.push(p)
  222         return [d, { required: dep.requiredBy, missing: true }]
  223       } else if (dep.peerMissing) {
  224         lite.problems = lite.problems || []
  225         dep.peerMissing.forEach(function (missing) {
  226           var pdm = 'peer dep missing: ' +
  227               missing.requires +
  228               ', required by ' +
  229               missing.requiredBy
  230           lite.problems.push(pdm)
  231         })
  232         return [d, { required: dep, peerMissing: true }]
  233       } else if (npm.config.get('json')) {
  234         if (depth === maxDepth) delete dep.dependencies
  235         return [d, getLite(dep, true, depth + 1)]
  236       }
  237       return [d, getLite(dep, true)]
  238     }).reduce(function (deps, d) {
  239       if (d[1].problems) {
  240         lite.problems = lite.problems || []
  241         lite.problems.push.apply(lite.problems, d[1].problems)
  242       }
  243       deps[d[0]] = d[1]
  244       return deps
  245     }, {})
  246   }
  247   return lite
  248 }
  249 
  250 function bfsify (root) {
  251   // walk over the data, and turn it from this:
  252   // +-- a
  253   // |   `-- b
  254   // |       `-- a (truncated)
  255   // `--b (truncated)
  256   // into this:
  257   // +-- a
  258   // `-- b
  259   // which looks nicer
  260   var queue = [root]
  261   var seen = [root]
  262 
  263   while (queue.length) {
  264     var current = queue.shift()
  265     var deps = current.dependencies = current.dependencies || {}
  266     Object.keys(deps).forEach(function (d) {
  267       var dep = deps[d]
  268       if (dep.missing) return
  269       if (inList(seen, dep)) {
  270         if (npm.config.get('parseable') || !npm.config.get('long')) {
  271           delete deps[d]
  272           return
  273         } else {
  274           dep = deps[d] = Object.create(dep)
  275           dep.dependencies = {}
  276         }
  277       }
  278       queue.push(dep)
  279       seen.push(dep)
  280     })
  281   }
  282 
  283   return root
  284 }
  285 
  286 function filterFound (root, args) {
  287   if (!args.length) return root
  288   var deps = root.dependencies
  289   if (deps) {
  290     Object.keys(deps).forEach(function (depName) {
  291       var dep = filterFound(deps[depName], args)
  292       if (dep.peerMissing) return
  293 
  294       // see if this one itself matches
  295       var found = false
  296       for (var ii = 0; !found && ii < args.length; ii++) {
  297         var argName = args[ii][0]
  298         var argVersion = args[ii][1]
  299         var argRaw = args[ii][2]
  300         if (depName === argName && argVersion) {
  301           found = semver.satisfies(dep.version, argVersion, true)
  302         } else if (depName === argName) {
  303           // If version is missing from arg, just do a name match.
  304           found = true
  305         } else if (dep.path === argRaw) {
  306           found = true
  307         }
  308       }
  309       // included explicitly
  310       if (found) dep._found = true
  311       // included because a child was included
  312       if (dep._found && !root._found) root._found = 1
  313       // not included
  314       if (!dep._found) delete deps[depName]
  315     })
  316   }
  317   if (!root._found) root._found = false
  318   return root
  319 }
  320 
  321 function makeArchy (data, long, dir) {
  322   var out = makeArchy_(data, long, dir, 0)
  323   return archy(out, '', { unicode: npm.config.get('unicode') })
  324 }
  325 
  326 function makeArchy_ (data, long, dir, depth, parent, d) {
  327   if (data.missing) {
  328     if (depth - 1 <= npm.config.get('depth')) {
  329       // just missing
  330       var unmet = 'UNMET ' + (data.optional ? 'OPTIONAL ' : '') + 'DEPENDENCY'
  331       if (npm.color) {
  332         if (data.optional) {
  333           unmet = color.bgBlack(color.yellow(unmet))
  334         } else {
  335           unmet = color.bgBlack(color.red(unmet))
  336         }
  337       }
  338       data = unmet + ' ' + d + '@' + data.requiredBy
  339     } else {
  340       data = d + '@' + data.requiredBy
  341     }
  342     return data
  343   }
  344 
  345   var out = {}
  346   // the top level is a bit special.
  347   out.label = data._id || ''
  348   if (data._found === true && data._id) {
  349     if (npm.color) {
  350       out.label = color.bgBlack(color.yellow(out.label.trim())) + ' '
  351     } else {
  352       out.label = out.label.trim() + ' '
  353     }
  354   }
  355   if (data.link) out.label += ' -> ' + data.link
  356 
  357   if (data.invalid) {
  358     if (data.realName !== data.name) out.label += ' (' + data.realName + ')'
  359     var invalid = 'invalid'
  360     if (npm.color) invalid = color.bgBlack(color.red(invalid))
  361     out.label += ' ' + invalid
  362   }
  363 
  364   if (data.peerInvalid) {
  365     var peerInvalid = 'peer invalid'
  366     if (npm.color) peerInvalid = color.bgBlack(color.red(peerInvalid))
  367     out.label += ' ' + peerInvalid
  368   }
  369 
  370   if (data.peerMissing) {
  371     var peerMissing = 'UNMET PEER DEPENDENCY'
  372     if (npm.color) peerMissing = color.bgBlack(color.red(peerMissing))
  373     out.label = peerMissing + ' ' + out.label
  374   }
  375 
  376   if (data.extraneous && data.path !== dir) {
  377     var extraneous = 'extraneous'
  378     if (npm.color) extraneous = color.bgBlack(color.green(extraneous))
  379     out.label += ' ' + extraneous
  380   }
  381 
  382   if (data.error && depth) {
  383     var message = data.error.message
  384     if (message.indexOf('\n')) message = message.slice(0, message.indexOf('\n'))
  385     var error = 'error: ' + message
  386     if (npm.color) error = color.bgRed(color.brightWhite(error))
  387     out.label += ' ' + error
  388   }
  389 
  390   // add giturl to name@version
  391   if (data._resolved) {
  392     try {
  393       var type = npa(data._resolved).type
  394       var isGit = type === 'git' || type === 'hosted'
  395       if (isGit) {
  396         out.label += ' (' + data._resolved + ')'
  397       }
  398     } catch (ex) {
  399       // npa threw an exception then it ain't git so whatev
  400     }
  401   }
  402 
  403   if (long) {
  404     if (dir === data.path) out.label += '\n' + dir
  405     out.label += '\n' + getExtras(data, dir)
  406   } else if (dir === data.path) {
  407     if (out.label) out.label += ' '
  408     out.label += dir
  409   }
  410 
  411   // now all the children.
  412   out.nodes = []
  413   if (depth <= npm.config.get('depth')) {
  414     out.nodes = Object.keys(data.dependencies || {})
  415       .sort(alphasort).filter(function (d) {
  416         return !isCruft(data.dependencies[d])
  417       }).map(function (d) {
  418         return makeArchy_(data.dependencies[d], long, dir, depth + 1, data, d)
  419       })
  420   }
  421 
  422   if (out.nodes.length === 0 && data.path === dir) {
  423     out.nodes = ['(empty)']
  424   }
  425 
  426   return out
  427 }
  428 
  429 function getExtras (data) {
  430   var extras = []
  431 
  432   if (data.description) extras.push(data.description)
  433   if (data.repository) extras.push(data.repository.url)
  434   if (data.homepage) extras.push(data.homepage)
  435   if (data._from) {
  436     var from = data._from
  437     if (from.indexOf(data.name + '@') === 0) {
  438       from = from.substr(data.name.length + 1)
  439     }
  440     var u = url.parse(from)
  441     if (u.protocol) extras.push(from)
  442   }
  443   return extras.join('\n')
  444 }
  445 
  446 function makeParseable (data, long, dir, depth, parent, d) {
  447   depth = depth || 0
  448   if (depth > npm.config.get('depth')) return [ makeParseable_(data, long, dir, depth, parent, d) ]
  449   return [ makeParseable_(data, long, dir, depth, parent, d) ]
  450   .concat(Object.keys(data.dependencies || {})
  451     .sort(alphasort).map(function (d) {
  452       return makeParseable(data.dependencies[d], long, dir, depth + 1, data, d)
  453     }))
  454   .filter(function (x) { return x })
  455   .join('\n')
  456 }
  457 
  458 function makeParseable_ (data, long, dir, depth, parent, d) {
  459   if (data.hasOwnProperty('_found') && data._found !== true) return ''
  460 
  461   if (data.missing) {
  462     if (depth < npm.config.get('depth')) {
  463       data = npm.config.get('long')
  464            ? path.resolve(parent.path, 'node_modules', d) +
  465              ':' + d + '@' + JSON.stringify(data.requiredBy) + ':INVALID:MISSING'
  466            : ''
  467     } else {
  468       data = path.resolve(dir || '', 'node_modules', d || '') +
  469              (npm.config.get('long')
  470              ? ':' + d + '@' + JSON.stringify(data.requiredBy) +
  471                ':' + // no realpath resolved
  472                ':MAXDEPTH'
  473              : '')
  474     }
  475 
  476     return data
  477   }
  478 
  479   if (!npm.config.get('long')) return data.path
  480 
  481   return data.path +
  482          ':' + (data._id || '') +
  483          ':' + (data.realPath !== data.path ? data.realPath : '') +
  484          (data.extraneous ? ':EXTRANEOUS' : '') +
  485          (data.error && data.path !== path.resolve(npm.globalDir, '..') ? ':ERROR' : '') +
  486          (data.invalid ? ':INVALID' : '') +
  487          (data.peerInvalid ? ':PEERINVALID' : '') +
  488          (data.peerMissing ? ':PEERINVALID:MISSING' : '')
  489 }