Skip to content

Commit 56d1fce

Browse files
committed
ls: show installed but unmet peer deps
Any completely missing peer deps are filled in in the package tree, but with only a name and the version with which it is required, and some additional, derived metadata. However, if the dep does exist, but simply is the wrong version, it is still marked as a missing peer dep. This patch makes it so that `npm ls` does not hide *all* "missing" peer deps, but just the ones that are not installed in some way already. See https://npm.community/t/4770
1 parent 671cad1 commit 56d1fce

2 files changed

Lines changed: 125 additions & 1 deletion

File tree

lib/ls.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ function filterFound (root, args) {
305305
if (!markDeps) continue
306306
Object.keys(markDeps).forEach(function (depName) {
307307
var dep = markDeps[depName]
308-
if (dep.peerMissing) return
308+
if (dep.peerMissing && !dep._from) return
309309
dep._parent = markPkg
310310
for (var ii = 0; ii < args.length; ii++) {
311311
var argName = args[ii][0]

test/tap/ls-peer.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
'use strict'
2+
const path = require('path')
3+
const test = require('tap').test
4+
const Tacks = require('tacks')
5+
const File = Tacks.File
6+
const Symlink = Tacks.Symlink
7+
const Dir = Tacks.Dir
8+
const common = require('../common-tap.js')
9+
10+
const basedir = path.join(__dirname, path.basename(__filename, '.js'))
11+
const testdir = path.join(basedir, 'testdir')
12+
const cachedir = path.join(basedir, 'cache')
13+
const globaldir = path.join(basedir, 'global')
14+
const tmpdir = path.join(basedir, 'tmp')
15+
16+
const conf = {
17+
cwd: testdir,
18+
env: common.newEnv().extend({
19+
npm_config_cache: cachedir,
20+
npm_config_tmp: tmpdir,
21+
npm_config_prefix: globaldir,
22+
npm_config_registry: common.registry,
23+
npm_config_loglevel: 'warn'
24+
})
25+
}
26+
27+
const fixture = new Tacks(Dir({
28+
cache: Dir(),
29+
global: Dir(),
30+
tmp: Dir(),
31+
testdir: Dir({
32+
'package.json': File({
33+
name: 'fixture',
34+
version: '1.0.0',
35+
dependencies: {
36+
dep: 'file:dep-1.0.0.tgz',
37+
'peer-dep': 'file:peer-dep-2.0.0.tgz'
38+
}
39+
}),
40+
// Source dir
41+
// dep: Dir({
42+
// 'package.json': File({
43+
// name: 'dep',
44+
// version: '1.0.0',
45+
// peerDependencies: {
46+
// 'peer-dep': 'file:peer-dep-1.0.0.tgz'
47+
// }
48+
// })
49+
// }),
50+
'dep-1.0.0.tgz': File(new Buffer(
51+
'1f8b0800000000000003ed8f3d0ec2300c853be71451661a1cd166e8cc45' +
52+
'a2d654e1278d92c200eadd491a60ea462584946fb1f5fc9e655bd59e548f' +
53+
'5b9b2a3ffac1142b0300b2aae8921e1152d062574b10424a08bed0d4d10f' +
54+
'6b1fb2c4d58fca8553bedd937ea19ffa273c08a5cca80bb286b20e2ddb44' +
55+
'e186ceebc1444d70e090548be8f668d174685a8d3e8c63fc3529633a040e' +
56+
'fa8ccd5b28e7381ffb3b0bce894ce4d70f6732994c66e60975aec5690008' +
57+
'0000',
58+
'hex'
59+
)),
60+
// Source dir
61+
// 'peer-dep': Dir({
62+
// 'package.json': File({
63+
// name: 'peer-dep',
64+
// version: '2.0.0'
65+
// })
66+
// }),
67+
'peer-dep-1.0.0.tgz': File(new Buffer(
68+
'1f8b08000000000000032b484cce4e4c4fd52f80d07a59c5f9790c540606' +
69+
'06066626260ad8c4c1c0d45c81c1d8d4ccc0d0d0cccc00a80ec830353500' +
70+
'd2d4760836505a5c925804740aa5e640bca200a78708a8e6525050ca4bcc' +
71+
'4d55b252502a484d2dd24d492d50d2018996a5161567e6e781240cf50cf4' +
72+
'0c94b86ab906dab9a360148c8251300aa80400c1c67f6300080000',
73+
'hex'
74+
)),
75+
'peer-dep-2.0.0.tgz': File(new Buffer(
76+
'1f8b08000000000000032b484cce4e4c4fd52f80d07a59c5f9790c540606' +
77+
'06066626260ad8c4c1c0d45c81c1d8d4ccc0d0d0cccc00a80ec830353500' +
78+
'd2d4760836505a5c925804740aa5e640bca200a78708a8e6525050ca4bcc' +
79+
'4d55b252502a484d2dd24d492d50d2018996a5161567e6e781248cf40cf4' +
80+
'0c94b86ab906dab9a360148c8251300aa80400cb30060800080000',
81+
'hex'
82+
))
83+
})
84+
}))
85+
86+
function setup () {
87+
cleanup()
88+
fixture.create(basedir)
89+
}
90+
91+
function cleanup () {
92+
fixture.remove(basedir)
93+
}
94+
95+
test('setup', t => {
96+
setup()
97+
return common.fakeRegistry.listen().then(() => common.npm(['install'], conf))
98+
})
99+
100+
test('list warns about unmet peer dependency', t => {
101+
return common.npm(['ls'], conf).then(([code, stdout, stderr]) => {
102+
t.is(code, 1, 'command ran not ok')
103+
t.comment(stdout.trim())
104+
t.comment(stderr.trim())
105+
t.match(stdout, 'UNMET PEER DEPENDENCY peer-dep@2.0.0')
106+
t.match(stderr, 'npm ERR! peer dep missing: peer-dep@file:peer-dep-1.0.0.tgz, required by dep@1.0.0')
107+
})
108+
})
109+
110+
test('list shows installed but unmet peer dependency', t => {
111+
return common.npm(['ls', 'peer-dep'], conf).then(([code, stdout, stderr]) => {
112+
t.is(code, 1, 'command ran not ok')
113+
t.comment(stdout.trim())
114+
t.comment(stderr.trim())
115+
t.match(stdout, 'UNMET PEER DEPENDENCY peer-dep@2.0.0')
116+
t.match(stderr, 'npm ERR! peer dep missing: peer-dep@file:peer-dep-1.0.0.tgz, required by dep@1.0.0')
117+
})
118+
})
119+
120+
test('cleanup', t => {
121+
common.fakeRegistry.close()
122+
cleanup()
123+
t.done()
124+
})

0 commit comments

Comments
 (0)