11cb0ef41Sopenharmony_ciconst { relative } = require('path')
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst explainNode = (node, depth, chalk) =>
41cb0ef41Sopenharmony_ci  printNode(node, chalk) +
51cb0ef41Sopenharmony_ci  explainDependents(node, depth, chalk) +
61cb0ef41Sopenharmony_ci  explainLinksIn(node, depth, chalk)
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst colorType = (type, chalk) => {
91cb0ef41Sopenharmony_ci  const { red, yellow, cyan, magenta, blue, green, gray } = chalk
101cb0ef41Sopenharmony_ci  const style = type === 'extraneous' ? red
111cb0ef41Sopenharmony_ci    : type === 'dev' ? yellow
121cb0ef41Sopenharmony_ci    : type === 'optional' ? cyan
131cb0ef41Sopenharmony_ci    : type === 'peer' ? magenta
141cb0ef41Sopenharmony_ci    : type === 'bundled' ? blue
151cb0ef41Sopenharmony_ci    : type === 'workspace' ? green
161cb0ef41Sopenharmony_ci    : type === 'overridden' ? gray
171cb0ef41Sopenharmony_ci    : /* istanbul ignore next */ s => s
181cb0ef41Sopenharmony_ci  return style(type)
191cb0ef41Sopenharmony_ci}
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciconst printNode = (node, chalk) => {
221cb0ef41Sopenharmony_ci  const {
231cb0ef41Sopenharmony_ci    name,
241cb0ef41Sopenharmony_ci    version,
251cb0ef41Sopenharmony_ci    location,
261cb0ef41Sopenharmony_ci    extraneous,
271cb0ef41Sopenharmony_ci    dev,
281cb0ef41Sopenharmony_ci    optional,
291cb0ef41Sopenharmony_ci    peer,
301cb0ef41Sopenharmony_ci    bundled,
311cb0ef41Sopenharmony_ci    isWorkspace,
321cb0ef41Sopenharmony_ci    overridden,
331cb0ef41Sopenharmony_ci  } = node
341cb0ef41Sopenharmony_ci  const { bold, dim, green } = chalk
351cb0ef41Sopenharmony_ci  const extra = []
361cb0ef41Sopenharmony_ci  if (extraneous) {
371cb0ef41Sopenharmony_ci    extra.push(' ' + bold(colorType('extraneous', chalk)))
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  if (dev) {
411cb0ef41Sopenharmony_ci    extra.push(' ' + bold(colorType('dev', chalk)))
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  if (optional) {
451cb0ef41Sopenharmony_ci    extra.push(' ' + bold(colorType('optional', chalk)))
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  if (peer) {
491cb0ef41Sopenharmony_ci    extra.push(' ' + bold(colorType('peer', chalk)))
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  if (bundled) {
531cb0ef41Sopenharmony_ci    extra.push(' ' + bold(colorType('bundled', chalk)))
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  if (overridden) {
571cb0ef41Sopenharmony_ci    extra.push(' ' + bold(colorType('overridden', chalk)))
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  const pkgid = isWorkspace
611cb0ef41Sopenharmony_ci    ? green(`${name}@${version}`)
621cb0ef41Sopenharmony_ci    : `${bold(name)}@${bold(version)}`
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  return `${pkgid}${extra.join('')}` +
651cb0ef41Sopenharmony_ci    (location ? dim(`\n${location}`) : '')
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ciconst explainLinksIn = ({ linksIn }, depth, chalk) => {
691cb0ef41Sopenharmony_ci  if (!linksIn || !linksIn.length || depth <= 0) {
701cb0ef41Sopenharmony_ci    return ''
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  const messages = linksIn.map(link => explainNode(link, depth - 1, chalk))
741cb0ef41Sopenharmony_ci  const str = '\n' + messages.join('\n')
751cb0ef41Sopenharmony_ci  return str.split('\n').join('\n  ')
761cb0ef41Sopenharmony_ci}
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ciconst explainDependents = ({ name, dependents }, depth, chalk) => {
791cb0ef41Sopenharmony_ci  if (!dependents || !dependents.length || depth <= 0) {
801cb0ef41Sopenharmony_ci    return ''
811cb0ef41Sopenharmony_ci  }
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  const max = Math.ceil(depth / 2)
841cb0ef41Sopenharmony_ci  const messages = dependents.slice(0, max)
851cb0ef41Sopenharmony_ci    .map(edge => explainEdge(edge, depth, chalk))
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  // show just the names of the first 5 deps that overflowed the list
881cb0ef41Sopenharmony_ci  if (dependents.length > max) {
891cb0ef41Sopenharmony_ci    let len = 0
901cb0ef41Sopenharmony_ci    const maxLen = 50
911cb0ef41Sopenharmony_ci    const showNames = []
921cb0ef41Sopenharmony_ci    for (let i = max; i < dependents.length; i++) {
931cb0ef41Sopenharmony_ci      const { from: { name: depName = 'the root project' } } = dependents[i]
941cb0ef41Sopenharmony_ci      len += depName.length
951cb0ef41Sopenharmony_ci      if (len >= maxLen && i < dependents.length - 1) {
961cb0ef41Sopenharmony_ci        showNames.push('...')
971cb0ef41Sopenharmony_ci        break
981cb0ef41Sopenharmony_ci      }
991cb0ef41Sopenharmony_ci      showNames.push(depName)
1001cb0ef41Sopenharmony_ci    }
1011cb0ef41Sopenharmony_ci    const show = `(${showNames.join(', ')})`
1021cb0ef41Sopenharmony_ci    messages.push(`${dependents.length - max} more ${show}`)
1031cb0ef41Sopenharmony_ci  }
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  const str = '\n' + messages.join('\n')
1061cb0ef41Sopenharmony_ci  return str.split('\n').join('\n  ')
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ciconst explainEdge = ({ name, type, bundled, from, spec, rawSpec, overridden }, depth, chalk) => {
1101cb0ef41Sopenharmony_ci  const { bold } = chalk
1111cb0ef41Sopenharmony_ci  let dep = type === 'workspace'
1121cb0ef41Sopenharmony_ci    ? bold(relative(from.location, spec.slice('file:'.length)))
1131cb0ef41Sopenharmony_ci    : `${bold(name)}@"${bold(spec)}"`
1141cb0ef41Sopenharmony_ci  if (overridden) {
1151cb0ef41Sopenharmony_ci    dep = `${colorType('overridden', chalk)} ${dep} (was "${rawSpec}")`
1161cb0ef41Sopenharmony_ci  }
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  const fromMsg = ` from ${explainFrom(from, depth, chalk)}`
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  return (type === 'prod' ? '' : `${colorType(type, chalk)} `) +
1211cb0ef41Sopenharmony_ci    (bundled ? `${colorType('bundled', chalk)} ` : '') +
1221cb0ef41Sopenharmony_ci    `${dep}${fromMsg}`
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ciconst explainFrom = (from, depth, chalk) => {
1261cb0ef41Sopenharmony_ci  if (!from.name && !from.version) {
1271cb0ef41Sopenharmony_ci    return 'the root project'
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  return printNode(from, chalk) +
1311cb0ef41Sopenharmony_ci    explainDependents(from, depth - 1, chalk) +
1321cb0ef41Sopenharmony_ci    explainLinksIn(from, depth - 1, chalk)
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_cimodule.exports = { explainNode, printNode, explainEdge }
136