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