11cb0ef41Sopenharmony_ci// this is called when an ERESOLVE error is caught in the exit-handler,
21cb0ef41Sopenharmony_ci// or when there's a log.warn('eresolve', msg, explanation), to turn it
31cb0ef41Sopenharmony_ci// into a human-intelligible explanation of what's wrong and how to fix.
41cb0ef41Sopenharmony_ciconst { explainEdge, explainNode, printNode } = require('./explain-dep.js')
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci// expl is an explanation object that comes from Arborist.  It looks like:
71cb0ef41Sopenharmony_ci// Depth is how far we want to want to descend into the object making a report.
81cb0ef41Sopenharmony_ci// The full report (ie, depth=Infinity) is always written to the cache folder
91cb0ef41Sopenharmony_ci// at ${cache}/eresolve-report.txt along with full json.
101cb0ef41Sopenharmony_ciconst explain = (expl, chalk, depth) => {
111cb0ef41Sopenharmony_ci  const { edge, dep, current, peerConflict, currentEdge } = expl
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci  const out = []
141cb0ef41Sopenharmony_ci  const whileInstalling = dep && dep.whileInstalling ||
151cb0ef41Sopenharmony_ci    current && current.whileInstalling ||
161cb0ef41Sopenharmony_ci    edge && edge.from && edge.from.whileInstalling
171cb0ef41Sopenharmony_ci  if (whileInstalling) {
181cb0ef41Sopenharmony_ci    out.push('While resolving: ' + printNode(whileInstalling, chalk))
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  // it "should" be impossible for an ERESOLVE explanation to lack both
221cb0ef41Sopenharmony_ci  // current and currentEdge, but better to have a less helpful error
231cb0ef41Sopenharmony_ci  // than a crashing failure.
241cb0ef41Sopenharmony_ci  if (current) {
251cb0ef41Sopenharmony_ci    out.push('Found: ' + explainNode(current, depth, chalk))
261cb0ef41Sopenharmony_ci  } else if (peerConflict && peerConflict.current) {
271cb0ef41Sopenharmony_ci    out.push('Found: ' + explainNode(peerConflict.current, depth, chalk))
281cb0ef41Sopenharmony_ci  } else if (currentEdge) {
291cb0ef41Sopenharmony_ci    out.push('Found: ' + explainEdge(currentEdge, depth, chalk))
301cb0ef41Sopenharmony_ci  } else /* istanbul ignore else - should always have one */ if (edge) {
311cb0ef41Sopenharmony_ci    out.push('Found: ' + explainEdge(edge, depth, chalk))
321cb0ef41Sopenharmony_ci  }
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  out.push('\nCould not resolve dependency:\n' +
351cb0ef41Sopenharmony_ci    explainEdge(edge, depth, chalk))
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  if (peerConflict) {
381cb0ef41Sopenharmony_ci    const heading = '\nConflicting peer dependency:'
391cb0ef41Sopenharmony_ci    const pc = explainNode(peerConflict.peer, depth, chalk)
401cb0ef41Sopenharmony_ci    out.push(heading + ' ' + pc)
411cb0ef41Sopenharmony_ci  }
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  return out.join('\n')
441cb0ef41Sopenharmony_ci}
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci// generate a full verbose report and tell the user how to fix it
471cb0ef41Sopenharmony_ciconst report = (expl, chalk, noColorChalk) => {
481cb0ef41Sopenharmony_ci  const flags = [
491cb0ef41Sopenharmony_ci    expl.strictPeerDeps ? '--no-strict-peer-deps' : '',
501cb0ef41Sopenharmony_ci    '--force',
511cb0ef41Sopenharmony_ci    '--legacy-peer-deps',
521cb0ef41Sopenharmony_ci  ].filter(Boolean)
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  const or = (arr) => arr.length <= 2
551cb0ef41Sopenharmony_ci    ? arr.join(' or ') :
561cb0ef41Sopenharmony_ci    arr.map((v, i, l) => i + 1 === l.length ? `or ${v}` : v).join(', ')
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  const fix = `Fix the upstream dependency conflict, or retry
591cb0ef41Sopenharmony_cithis command with ${or(flags)}
601cb0ef41Sopenharmony_cito accept an incorrect (and potentially broken) dependency resolution.`
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  return {
631cb0ef41Sopenharmony_ci    explanation: `${explain(expl, chalk, 4)}\n\n${fix}`,
641cb0ef41Sopenharmony_ci    file: `# npm resolution error report\n\n${explain(expl, noColorChalk, Infinity)}\n\n${fix}`,
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_cimodule.exports = {
691cb0ef41Sopenharmony_ci  explain,
701cb0ef41Sopenharmony_ci  report,
711cb0ef41Sopenharmony_ci}
72