• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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