Skip to content

Commit 7418970

Browse files
committed
Tighten up the output of dep node explanations
Reduce visual noise, make the more important information more obvious.
1 parent 58c2155 commit 7418970

5 files changed

Lines changed: 1227 additions & 878 deletions

File tree

lib/utils/explain-dep.js

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

lib/utils/explain-eresolve.js

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@
88
const npm = require('../npm.js')
99
const { writeFileSync } = require('fs')
1010
const { resolve } = require('path')
11-
12-
const chalk = require('chalk')
13-
const nocolor = {
14-
bold: s => s,
15-
dim: s => s
16-
}
11+
const { explainNode, printNode } = require('./explain-dep.js')
1712

1813
// expl is an explanation object that comes from Arborist. It looks like:
1914
// {
@@ -50,69 +45,20 @@ const explainEresolve = (expl, color, depth) => {
5045
out.push('While resolving: ' + printNode(dep.whileInstalling, color))
5146
}
5247

53-
out.push(explainNode('Found:', current, depth, color))
48+
out.push('Found: ' + explainNode(current, depth, color))
5449

55-
out.push(explainNode('\nCould not add conflicting dependency:', dep, depth, color))
50+
out.push('\nCould not add conflicting dependency: ' +
51+
explainNode(dep, depth, color))
5652

5753
if (peerConflict) {
5854
const heading = '\nConflicting peer dependency:'
59-
const pc = explainNode(heading, peerConflict, depth, color)
60-
out.push(pc)
55+
const pc = explainNode(peerConflict, depth, color)
56+
out.push(heading + ' ' + pc)
6157
}
6258

6359
return out.join('\n')
6460
}
6561

66-
const explainNode = (heading, node, depth, color) =>
67-
`${heading} ${printNode(node, color)}` +
68-
explainDependents(node, depth, color)
69-
70-
const printNode = ({ name, version, location }, color) => {
71-
const { bold, dim } = color ? chalk : nocolor
72-
return `${bold(name)}@${bold(version)}` +
73-
(location ? dim(` at ${location}`) : '')
74-
}
75-
76-
const explainDependents = ({ name, dependents }, depth, color) => {
77-
if (!dependents || !dependents.length || depth <= 0) {
78-
return ''
79-
}
80-
81-
const max = Math.ceil(depth / 2)
82-
const messages = dependents.slice(0, max)
83-
.map(dep => explainDependency(name, dep, depth, color))
84-
85-
// show just the names of the first 5 deps that overflowed the list
86-
if (dependents.length > max) {
87-
const names = dependents.slice(max).map(d => d.from.name)
88-
const showNames = names.slice(0, 5)
89-
if (showNames.length < names.length) {
90-
showNames.push('...')
91-
}
92-
const show = `(${showNames.join(', ')})`
93-
messages.push(`${names.length} more ${show}`)
94-
}
95-
96-
const str = '\nfor: ' + messages.join('\nand: ')
97-
return str.split('\n').join('\n ')
98-
}
99-
100-
const explainDependency = (name, { type, from, spec }, depth, color) => {
101-
const { bold } = color ? chalk : nocolor
102-
return `${type} dependency ` +
103-
`${bold(name)}@"${bold(spec)}"\nfrom: ` +
104-
explainFrom(from, depth, color)
105-
}
106-
107-
const explainFrom = (from, depth, color) => {
108-
if (!from.name && !from.version) {
109-
return 'the root project'
110-
}
111-
112-
return printNode(from, color) +
113-
explainDependents(from, depth - 1, color)
114-
}
115-
11662
// generate a full verbose report and tell the user how to fix it
11763
const report = (expl, depth = 4) => {
11864
const fullReport = resolve(npm.cache, 'eresolve-report.txt')
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/* IMPORTANT
2+
* This snapshot file is auto-generated, but designed for humans.
3+
* It should be checked into source control and tracked carefully.
4+
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
5+
* Make sure to inspect the output below. Do not ignore changes!
6+
*/
7+
'use strict'
8+
exports[`test/lib/utils/explain-dep.js TAP > ellipses test one 1`] = `
9+
10+
manydep@"1.0.0" from [email protected]
11+
node_modules/prod-dep
12+
prod-dep@"1.x" from the root project
13+
6 more (optdep, extra-neos, deep-dev, peer, ...)
14+
`
15+
16+
exports[`test/lib/utils/explain-dep.js TAP > ellipses test two 1`] = `
17+
18+
manydep@"1.0.0" from [email protected]
19+
node_modules/prod-dep
20+
prod-dep@"1.x" from the root project
21+
5 more (optdep, extra-neos, deep-dev, peer, a package with a pretty long name)
22+
`
23+
24+
exports[`test/lib/utils/explain-dep.js TAP deepDev > explain color deep 1`] = `
25+
deep-dev@2.3.4 dev
26+
node_modules/deep-dev
27+
deep-dev@"2.x" from metadev@3.4.5
28+
node_modules/dev/node_modules/metadev
29+
metadev@"3.x" from topdev@4.5.6
30+
node_modules/topdev
31+
dev topdev@"4.x" from the root project
32+
`
33+
34+
exports[`test/lib/utils/explain-dep.js TAP deepDev > explain nocolor shallow 1`] = `
35+
36+
node_modules/deep-dev
37+
deep-dev@"2.x" from [email protected]
38+
node_modules/dev/node_modules/metadev
39+
metadev@"3.x" from [email protected]
40+
node_modules/topdev
41+
`
42+
43+
exports[`test/lib/utils/explain-dep.js TAP deepDev > print color 1`] = `
44+
deep-dev@2.3.4 dev
45+
node_modules/deep-dev
46+
`
47+
48+
exports[`test/lib/utils/explain-dep.js TAP deepDev > print nocolor 1`] = `
49+
50+
node_modules/deep-dev
51+
`
52+
53+
exports[`test/lib/utils/explain-dep.js TAP extraneous > explain color deep 1`] = `
54+
extra-neos@1337.420.69-lol extraneous
55+
node_modules/extra-neos
56+
`
57+
58+
exports[`test/lib/utils/explain-dep.js TAP extraneous > explain nocolor shallow 1`] = `
59+
60+
node_modules/extra-neos
61+
`
62+
63+
exports[`test/lib/utils/explain-dep.js TAP extraneous > print color 1`] = `
64+
extra-neos@1337.420.69-lol extraneous
65+
node_modules/extra-neos
66+
`
67+
68+
exports[`test/lib/utils/explain-dep.js TAP extraneous > print nocolor 1`] = `
69+
70+
node_modules/extra-neos
71+
`
72+
73+
exports[`test/lib/utils/explain-dep.js TAP manyDeps > explain color deep 1`] = `
74+
manydep@1.0.0
75+
manydep@"1.0.0" from prod-dep@1.2.3
76+
node_modules/prod-dep
77+
prod-dep@"1.x" from the root project
78+
optional manydep@"1.x" from optdep@1.0.0 optional
79+
node_modules/optdep
80+
optdep optdep@"1.0.0" from the root project
81+
manydep@"1.0.x" from extra-neos@1337.420.69-lol extraneous
82+
node_modules/extra-neos
83+
dev manydep@"*" from deep-dev@2.3.4 dev
84+
node_modules/deep-dev
85+
deep-dev@"2.x" from metadev@3.4.5
86+
node_modules/dev/node_modules/metadev
87+
metadev@"3.x" from topdev@4.5.6
88+
node_modules/topdev
89+
dev topdev@"4.x" from the root project
90+
peer manydep@">1.0.0-beta <1.0.1" from peer@1.0.0 peer
91+
node_modules/peer
92+
peer peer@"1.0.0" from the root project
93+
manydep@"1" from a package with a pretty long name@1.2.3
94+
manydep@"1" from another package with a pretty long name@1.2.3
95+
manydep@"1" from yet another a package with a pretty long name@1.2.3
96+
`
97+
98+
exports[`test/lib/utils/explain-dep.js TAP manyDeps > explain nocolor shallow 1`] = `
99+
100+
manydep@"1.0.0" from [email protected]
101+
node_modules/prod-dep
102+
prod-dep@"1.x" from the root project
103+
7 more (optdep, extra-neos, deep-dev, peer, ...)
104+
`
105+
106+
exports[`test/lib/utils/explain-dep.js TAP manyDeps > print color 1`] = `
107+
manydep@1.0.0
108+
`
109+
110+
exports[`test/lib/utils/explain-dep.js TAP manyDeps > print nocolor 1`] = `
111+
112+
`
113+
114+
exports[`test/lib/utils/explain-dep.js TAP optional > explain color deep 1`] = `
115+
optdep@1.0.0 optional
116+
node_modules/optdep
117+
optdep optdep@"1.0.0" from the root project
118+
`
119+
120+
exports[`test/lib/utils/explain-dep.js TAP optional > explain nocolor shallow 1`] = `
121+
122+
node_modules/optdep
123+
optdep optdep@"1.0.0" from the root project
124+
`
125+
126+
exports[`test/lib/utils/explain-dep.js TAP optional > print color 1`] = `
127+
optdep@1.0.0 optional
128+
node_modules/optdep
129+
`
130+
131+
exports[`test/lib/utils/explain-dep.js TAP optional > print nocolor 1`] = `
132+
133+
node_modules/optdep
134+
`
135+
136+
exports[`test/lib/utils/explain-dep.js TAP peer > explain color deep 1`] = `
137+
peer@1.0.0 peer
138+
node_modules/peer
139+
peer peer@"1.0.0" from the root project
140+
`
141+
142+
exports[`test/lib/utils/explain-dep.js TAP peer > explain nocolor shallow 1`] = `
143+
144+
node_modules/peer
145+
peer peer@"1.0.0" from the root project
146+
`
147+
148+
exports[`test/lib/utils/explain-dep.js TAP peer > print color 1`] = `
149+
peer@1.0.0 peer
150+
node_modules/peer
151+
`
152+
153+
exports[`test/lib/utils/explain-dep.js TAP peer > print nocolor 1`] = `
154+
155+
node_modules/peer
156+
`
157+
158+
exports[`test/lib/utils/explain-dep.js TAP prodDep > explain color deep 1`] = `
159+
prod-dep@1.2.3
160+
node_modules/prod-dep
161+
prod-dep@"1.x" from the root project
162+
`
163+
164+
exports[`test/lib/utils/explain-dep.js TAP prodDep > explain nocolor shallow 1`] = `
165+
166+
node_modules/prod-dep
167+
prod-dep@"1.x" from the root project
168+
`
169+
170+
exports[`test/lib/utils/explain-dep.js TAP prodDep > print color 1`] = `
171+
prod-dep@1.2.3
172+
node_modules/prod-dep
173+
`
174+
175+
exports[`test/lib/utils/explain-dep.js TAP prodDep > print nocolor 1`] = `
176+
177+
node_modules/prod-dep
178+
`

0 commit comments

Comments
 (0)