doctor.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. 'use strict'
  2. const ansiTrim = require('./utils/ansi-trim')
  3. const chain = require('slide').chain
  4. const color = require('ansicolors')
  5. const defaultRegistry = require('./config/defaults').defaults.registry
  6. const log = require('npmlog')
  7. const npm = require('./npm')
  8. const output = require('./utils/output')
  9. const path = require('path')
  10. const semver = require('semver')
  11. const styles = require('ansistyles')
  12. const table = require('text-table')
  13. // steps
  14. const checkFilesPermission = require('./doctor/check-files-permission')
  15. const checkPing = require('./doctor/check-ping')
  16. const getGitPath = require('./doctor/get-git-path')
  17. const getLatestNodejsVersion = require('./doctor/get-latest-nodejs-version')
  18. const getLatestNpmVersion = require('./doctor/get-latest-npm-version')
  19. const verifyCachedFiles = require('./doctor/verify-cached-files')
  20. const globalNodeModules = path.join(npm.config.globalPrefix, 'lib', 'node_modules')
  21. const localNodeModules = path.join(npm.config.localPrefix, 'node_modules')
  22. module.exports = doctor
  23. doctor.usage = 'npm doctor'
  24. function doctor (args, silent, cb) {
  25. args = args || {}
  26. if (typeof cb !== 'function') {
  27. cb = silent
  28. silent = false
  29. }
  30. const actionsToRun = [
  31. [checkPing],
  32. [getLatestNpmVersion],
  33. [getLatestNodejsVersion, args['node-url']],
  34. [getGitPath],
  35. [checkFilesPermission, npm.cache, 4, 6],
  36. [checkFilesPermission, globalNodeModules, 4, 4],
  37. [checkFilesPermission, localNodeModules, 6, 6],
  38. [verifyCachedFiles, path.join(npm.cache, '_cacache')]
  39. ]
  40. log.info('doctor', 'Running checkup')
  41. chain(actionsToRun, function (stderr, stdout) {
  42. if (stderr && stderr.message !== 'not found: git') return cb(stderr)
  43. const list = makePretty(stdout)
  44. let outHead = ['Check', 'Value', 'Recommendation']
  45. let outBody = list
  46. if (npm.color) {
  47. outHead = outHead.map(function (item) {
  48. return styles.underline(item)
  49. })
  50. outBody = outBody.map(function (item) {
  51. if (item[2]) {
  52. item[0] = color.red(item[0])
  53. item[2] = color.magenta(item[2])
  54. }
  55. return item
  56. })
  57. }
  58. const outTable = [outHead].concat(outBody)
  59. const tableOpts = {
  60. stringLength: function (s) { return ansiTrim(s).length }
  61. }
  62. if (!silent) output(table(outTable, tableOpts))
  63. cb(null, list)
  64. })
  65. }
  66. function makePretty (p) {
  67. const ping = p[1]
  68. const npmLTS = p[2]
  69. const nodeLTS = p[3].replace('v', '')
  70. const whichGit = p[4] || 'not installed'
  71. const readbleCaches = p[5] ? 'ok' : 'notOk'
  72. const executableGlobalModules = p[6] ? 'ok' : 'notOk'
  73. const executableLocalModules = p[7] ? 'ok' : 'notOk'
  74. const cacheStatus = p[8] ? `verified ${p[8].verifiedContent} tarballs` : 'notOk'
  75. const npmV = npm.version
  76. const nodeV = process.version.replace('v', '')
  77. const registry = npm.config.get('registry') || ''
  78. const list = [
  79. ['npm ping', ping],
  80. ['npm -v', 'v' + npmV],
  81. ['node -v', 'v' + nodeV],
  82. ['npm config get registry', registry],
  83. ['which git', whichGit],
  84. ['Perms check on cached files', readbleCaches],
  85. ['Perms check on global node_modules', executableGlobalModules],
  86. ['Perms check on local node_modules', executableLocalModules],
  87. ['Verify cache contents', cacheStatus]
  88. ]
  89. if (p[0] !== 200) list[0][2] = 'Check your internet connection'
  90. if (!semver.satisfies(npmV, '>=' + npmLTS)) list[1][2] = 'Use npm v' + npmLTS
  91. if (!semver.satisfies(nodeV, '>=' + nodeLTS)) list[2][2] = 'Use node v' + nodeLTS
  92. if (registry !== defaultRegistry) list[3][2] = 'Try `npm config set registry ' + defaultRegistry + '`'
  93. if (whichGit === 'not installed') list[4][2] = 'Install git and ensure it\'s in your PATH.'
  94. if (readbleCaches !== 'ok') list[5][2] = 'Check the permissions of your files in ' + npm.config.get('cache')
  95. if (executableGlobalModules !== 'ok') list[6][2] = globalNodeModules + ' must be readable and writable by the current user.'
  96. if (executableLocalModules !== 'ok') list[7][2] = localNodeModules + ' must be readable and writable by the current user.'
  97. return list
  98. }