explain-dep.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. const chalk = require('chalk')
  2. const nocolor = {
  3. bold: s => s,
  4. dim: s => s,
  5. red: s => s,
  6. yellow: s => s,
  7. cyan: s => s,
  8. magenta: s => s,
  9. blue: s => s,
  10. green: s => s,
  11. }
  12. const { relative } = require('path')
  13. const explainNode = (node, depth, color) =>
  14. printNode(node, color) +
  15. explainDependents(node, depth, color) +
  16. explainLinksIn(node, depth, color)
  17. const colorType = (type, color) => {
  18. const { red, yellow, cyan, magenta, blue, green } = color ? chalk : nocolor
  19. const style = type === 'extraneous' ? red
  20. : type === 'dev' ? yellow
  21. : type === 'optional' ? cyan
  22. : type === 'peer' ? magenta
  23. : type === 'bundled' ? blue
  24. : type === 'workspace' ? green
  25. : /* istanbul ignore next */ s => s
  26. return style(type)
  27. }
  28. const printNode = (node, color) => {
  29. const {
  30. name,
  31. version,
  32. location,
  33. extraneous,
  34. dev,
  35. optional,
  36. peer,
  37. bundled,
  38. isWorkspace,
  39. } = node
  40. const { bold, dim, green } = color ? chalk : nocolor
  41. const extra = []
  42. if (extraneous)
  43. extra.push(' ' + bold(colorType('extraneous', color)))
  44. if (dev)
  45. extra.push(' ' + bold(colorType('dev', color)))
  46. if (optional)
  47. extra.push(' ' + bold(colorType('optional', color)))
  48. if (peer)
  49. extra.push(' ' + bold(colorType('peer', color)))
  50. if (bundled)
  51. extra.push(' ' + bold(colorType('bundled', color)))
  52. const pkgid = isWorkspace
  53. ? green(`${name}@${version}`)
  54. : `${bold(name)}@${bold(version)}`
  55. return `${pkgid}${extra.join('')}` +
  56. (location ? dim(`\n${location}`) : '')
  57. }
  58. const explainLinksIn = ({ linksIn }, depth, color) => {
  59. if (!linksIn || !linksIn.length || depth <= 0)
  60. return ''
  61. const messages = linksIn.map(link => explainNode(link, depth - 1, color))
  62. const str = '\n' + messages.join('\n')
  63. return str.split('\n').join('\n ')
  64. }
  65. const explainDependents = ({ name, dependents }, depth, color) => {
  66. if (!dependents || !dependents.length || depth <= 0)
  67. return ''
  68. const max = Math.ceil(depth / 2)
  69. const messages = dependents.slice(0, max)
  70. .map(edge => explainEdge(edge, depth, color))
  71. // show just the names of the first 5 deps that overflowed the list
  72. if (dependents.length > max) {
  73. let len = 0
  74. const maxLen = 50
  75. const showNames = []
  76. for (let i = max; i < dependents.length; i++) {
  77. const { from: { name = 'the root project' } } = dependents[i]
  78. len += name.length
  79. if (len >= maxLen && i < dependents.length - 1) {
  80. showNames.push('...')
  81. break
  82. }
  83. showNames.push(name)
  84. }
  85. const show = `(${showNames.join(', ')})`
  86. messages.push(`${dependents.length - max} more ${show}`)
  87. }
  88. const str = '\n' + messages.join('\n')
  89. return str.split('\n').join('\n ')
  90. }
  91. const explainEdge = ({ name, type, bundled, from, spec }, depth, color) => {
  92. const { bold } = color ? chalk : nocolor
  93. const dep = type === 'workspace'
  94. ? bold(relative(from.location, spec.slice('file:'.length)))
  95. : `${bold(name)}@"${bold(spec)}"`
  96. const fromMsg = ` from ${explainFrom(from, depth, color)}`
  97. return (type === 'prod' ? '' : `${colorType(type, color)} `) +
  98. (bundled ? `${colorType('bundled', color)} ` : '') +
  99. `${dep}${fromMsg}`
  100. }
  101. const explainFrom = (from, depth, color) => {
  102. if (!from.name && !from.version)
  103. return 'the root project'
  104. return printNode(from, color) +
  105. explainDependents(from, depth - 1, color) +
  106. explainLinksIn(from, depth - 1, color)
  107. }
  108. module.exports = { explainNode, printNode, explainEdge }