1'use strict' 2var path = require('path') 3var validate = require('aproba') 4var asyncMap = require('slide').asyncMap 5var chain = require('slide').chain 6var npmInstallChecks = require('npm-install-checks') 7var checkGit = npmInstallChecks.checkGit 8var clone = require('lodash.clonedeep') 9var normalizePackageData = require('normalize-package-data') 10var npm = require('../npm.js') 11var andFinishTracker = require('./and-finish-tracker.js') 12var flattenTree = require('./flatten-tree.js') 13var validateAllPeerDeps = require('./deps.js').validateAllPeerDeps 14var packageId = require('../utils/package-id.js') 15 16module.exports = function (idealTree, log, next) { 17 validate('OOF', arguments) 18 var moduleMap = flattenTree(idealTree) 19 var modules = Object.keys(moduleMap).map(function (name) { return moduleMap[name] }) 20 21 chain([ 22 [asyncMap, modules, function (mod, done) { 23 chain([ 24 mod.parent && !mod.isLink && [checkGit, mod.realpath], 25 [checkErrors, mod, idealTree] 26 ], done) 27 }], 28 [thenValidateAllPeerDeps, idealTree], 29 [thenCheckTop, idealTree], 30 [thenCheckDuplicateDeps, idealTree] 31 ], andFinishTracker(log, next)) 32} 33 34function checkErrors (mod, idealTree, next) { 35 if (mod.error && (mod.parent || path.resolve(npm.globalDir, '..') !== mod.path)) idealTree.warnings.push(mod.error) 36 next() 37} 38 39function thenValidateAllPeerDeps (idealTree, next) { 40 validate('OF', arguments) 41 validateAllPeerDeps(idealTree, function (tree, pkgname, version) { 42 var warn = new Error(packageId(tree) + ' requires a peer of ' + pkgname + '@' + 43 version + ' but none is installed. You must install peer dependencies yourself.') 44 warn.code = 'EPEERINVALID' 45 idealTree.warnings.push(warn) 46 }) 47 next() 48} 49 50function thenCheckTop (idealTree, next) { 51 validate('OF', arguments) 52 if (idealTree.package.error) return next() 53 54 // FIXME: when we replace read-package-json with something less magic, 55 // this should done elsewhere. 56 // As it is, the package has already been normalized and thus some 57 // errors are suppressed. 58 var pkg = clone(idealTree.package) 59 try { 60 normalizePackageData(pkg, function (warn) { 61 var warnObj = new Error(packageId(idealTree) + ' ' + warn) 62 warnObj.code = 'EPACKAGEJSON' 63 idealTree.warnings.push(warnObj) 64 }, false) 65 } catch (er) { 66 er.code = 'EPACKAGEJSON' 67 idealTree.warnings.push(er) 68 } 69 70 var nodeVersion = npm.config.get('node-version') 71 if (/-/.test(nodeVersion)) { 72 // if this is a prerelease node… 73 var warnObj = new Error('You are using a pre-release version of node and things may not work as expected') 74 warnObj.code = 'ENODEPRE' 75 idealTree.warnings.push(warnObj) 76 } 77 78 next() 79} 80 81// check for deps duplciated between devdeps and regular deps 82function thenCheckDuplicateDeps (idealTree, next) { 83 var deps = idealTree.package.dependencies || {} 84 var devDeps = idealTree.package.devDependencies || {} 85 86 for (var pkg in devDeps) { 87 if (pkg in deps) { 88 var warnObj = new Error('The package ' + pkg + ' is included as both a dev and production dependency.') 89 warnObj.code = 'EDUPLICATEDEP' 90 idealTree.warnings.push(warnObj) 91 } 92 } 93 94 next() 95} 96