• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2var validate = require('aproba')
3var asyncMap = require('slide').asyncMap
4var chain = require('slide').chain
5var npmInstallChecks = require('npm-install-checks')
6var iferr = require('iferr')
7var checkEngine = npmInstallChecks.checkEngine
8var checkPlatform = npmInstallChecks.checkPlatform
9var npm = require('../npm.js')
10
11module.exports = function (idealTree, args, next) {
12  validate('OAF', arguments)
13  var force = npm.config.get('force')
14
15  asyncMap(args, function (pkg, done) {
16    chain([
17      [hasMinimumFields, pkg],
18      [checkSelf, idealTree, pkg, force],
19      [isInstallable, idealTree, pkg]
20    ], done)
21  }, next)
22}
23
24function hasMinimumFields (pkg, cb) {
25  if (pkg.name === '' || pkg.name == null) {
26    return cb(new Error(`Can't install ${pkg._resolved}: Missing package name`))
27  } else if (pkg.version === '' || pkg.version == null) {
28    return cb(new Error(`Can't install ${pkg._resolved}: Missing package version`))
29  } else {
30    return cb()
31  }
32}
33
34function setWarnings (idealTree, warn) {
35  function top (tree) {
36    if (tree.parent) return top(tree.parent)
37    return tree
38  }
39
40  var topTree = top(idealTree)
41  if (!topTree.warnings) topTree.warnings = []
42
43  if (topTree.warnings.every(i => (
44    i.code !== warn.code ||
45    i.required !== warn.required ||
46    i.pkgid !== warn.pkgid))) {
47    topTree.warnings.push(warn)
48  }
49}
50
51var isInstallable = module.exports.isInstallable = function (idealTree, pkg, next) {
52  var force = npm.config.get('force')
53  var nodeVersion = npm.config.get('node-version')
54  if (/-/.test(nodeVersion)) {
55    // for the purposes of validation, if the node version is a prerelease,
56    // strip that. We check and warn about this sceanrio over in validate-tree.
57    nodeVersion = nodeVersion.replace(/-.*/, '')
58  }
59  var strict = npm.config.get('engine-strict')
60  checkEngine(pkg, npm.version, nodeVersion, force, strict, iferr(next, thenWarnEngineIssues))
61  function thenWarnEngineIssues (warn) {
62    if (idealTree && warn) setWarnings(idealTree, warn)
63    checkPlatform(pkg, force, next)
64  }
65}
66
67function checkSelf (idealTree, pkg, force, next) {
68  if (idealTree.package && idealTree.package.name !== pkg.name) return next()
69  if (force) {
70    var warn = new Error("Wouldn't install " + pkg.name + ' as a dependency of itself, but being forced')
71    warn.code = 'ENOSELF'
72    idealTree.warnings.push(warn)
73    next()
74  } else {
75    var er = new Error('Refusing to install package with name "' + pkg.name +
76     '" under a package\n' +
77     'also called "' + pkg.name + '". Did you name your project the same\n' +
78     'as the dependency you\'re installing?\n\n' +
79     'For more information, see:\n' +
80     '    <https://docs.npmjs.com/cli/install#limitations-of-npms-install-algorithm>')
81    er.code = 'ENOSELF'
82    next(er)
83  }
84}
85