Skip to content

Commit 83590d4

Browse files
isaacswraithgar
authored andcommitted
fix(ls): show relative paths from root
Change the output in `npm ls` for symlink dependencies (including workspaces) to show the relative path from the project root, rather than the absolute path of the link target. This makes the output much less noisy and more ergonomic when many workspaces and link dependencies are in use, especially when paths are long. It is arguable that this output might be slightly misleading, since the _actual_ workspace symlink from `${root}/node_modules/b` to `${root}/packages/b` has a link value of `../packages/b`, not just `packages/b`. (Or on Windows, always the full absolute path, because junctions.) Thus, `npm ls b` will not show the same output as `ls -l node_modules/b`. However, `npm ls` shows the logical tree, not the physical tree, so presenting the user with a path that they can use and interpret is more important than presenting them with the strictly accurate details of their filesystem. PR-URL: #3272 Credit: @isaacs Close: #3272 Reviewed-by: @darcyclarke
1 parent 46a9bcb commit 83590d4

File tree

3 files changed

+39
-26
lines changed

3 files changed

+39
-26
lines changed

lib/ls.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
const { resolve } = require('path')
1+
const { resolve, relative, sep } = require('path')
2+
const relativePrefix = `.${sep}`
23
const { EOL } = require('os')
34

45
const archy = require('archy')
@@ -298,6 +299,9 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
298299
? chalk.yellow.bgBlack
299300
: chalk.red.bgBlack
300301
const missingMsg = `UNMET ${isOptional(node) ? 'OPTIONAL ' : ''}DEPENDENCY`
302+
const targetLocation = node.root
303+
? relative(node.root.realpath, node.realpath)
304+
: node.targetLocation
301305
const label =
302306
(
303307
node[_missing]
@@ -321,7 +325,7 @@ const getHumanOutputItem = (node, { args, color, global, long }) => {
321325
: ''
322326
) +
323327
(isGitNode(node) ? ` (${node.resolved})` : '') +
324-
(node.isLink ? ` -> ${node.realpath}` : '') +
328+
(node.isLink ? ` -> ${relativePrefix}${targetLocation}` : '') +
325329
(long ? `${EOL}${node.package.description || ''}` : '')
326330

327331
return augmentItemWithIncludeMetadata(node, { label, nodes: [] })
@@ -445,6 +449,9 @@ const augmentNodesWithMetadata = ({
445449
// revisit that node in tree traversal logic, so we make it so that
446450
// we have a diff obj for deduped nodes:
447451
if (seenNodes.has(node.path)) {
452+
const { realpath, root } = node
453+
const targetLocation = root ? relative(root.realpath, realpath)
454+
: node.targetLocation
448455
node = {
449456
name: node.name,
450457
version: node.version,
@@ -453,6 +460,7 @@ const augmentNodesWithMetadata = ({
453460
path: node.path,
454461
isLink: node.isLink,
455462
realpath: node.realpath,
463+
targetLocation,
456464
[_type]: node[_type],
457465
[_invalid]: node[_invalid],
458466
[_missing]: node[_missing],

tap-snapshots/test/lib/ls.js.test.cjs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---dev
7070

7171
exports[`test/lib/ls.js TAP ls --link > should output tree containing linked deps 1`] = `
7272
test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls---link
73-
\`-- linked-dep@1.0.0 -> {CWD}/tap-testdir-ls-ls---link/linked-dep
73+
\`-- linked-dep@1.0.0 -> ./linked-dep
7474
7575
`
7676

@@ -480,59 +480,59 @@ exports[`test/lib/ls.js TAP ls json read problems > should print empty result 1`
480480

481481
exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should filter by parent folder workspace config 1`] = `
482482
workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
483-
+-- e@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/e
484-
\`-- f@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/f
483+
+-- e@1.0.0 -> ./group/e
484+
\`-- f@1.0.0 -> ./group/f
485485
486486
`
487487

488488
exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should filter single workspace 1`] = `
489489
workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
490-
+-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
491-
| \`-- d@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
492-
\`-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
490+
+-- a@1.0.0 -> ./a
491+
| \`-- d@1.0.0 deduped -> ./d
492+
\`-- d@1.0.0 -> ./d
493493
494494
`
495495

496496
exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should filter using workspace config 1`] = `
497497
workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
498-
\`-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
498+
\`-- a@1.0.0 -> ./a
499499
+-- c@1.0.0
500-
\`-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
500+
\`-- d@1.0.0 -> ./d
501501
\`-- foo@1.1.1
502502
\`-- bar@1.0.0
503503
504504
`
505505

506506
exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should list --all workspaces properly 1`] = `
507507
workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
508-
+-- a@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a
508+
+-- a@1.0.0 -> ./a
509509
| +-- c@1.0.0
510-
| \`-- d@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
511-
+-- b@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/b
512-
+-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
510+
| \`-- d@1.0.0 deduped -> ./d
511+
+-- b@1.0.0 -> ./b
512+
+-- d@1.0.0 -> ./d
513513
| \`-- foo@1.1.1
514514
| \`-- bar@1.0.0
515-
+-- e@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/e
516-
\`-- f@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/f
515+
+-- e@1.0.0 -> ./group/e
516+
\`-- f@1.0.0 -> ./group/f
517517
518518
`
519519

520520
exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should list workspaces properly with default configs 1`] = `
521521
workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
522-
[0m+-- [32ma@1.0.0[39m -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/a[0m
522+
[0m+-- [32ma@1.0.0[39m -> ./a[0m
523523
| +-- c@1.0.0
524-
[0m| \`-- d@1.0.0 [90mdeduped[39m -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d[0m
525-
[0m+-- [32mb@1.0.0[39m -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/b[0m
526-
[0m+-- [32md@1.0.0[39m -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d[0m
524+
[0m| \`-- d@1.0.0 [90mdeduped[39m -> ./d[0m
525+
[0m+-- [32mb@1.0.0[39m -> ./b[0m
526+
[0m+-- [32md@1.0.0[39m -> ./d[0m
527527
| \`-- foo@1.1.1
528-
[0m+-- [32me@1.0.0[39m -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/e[0m
529-
[0m\`-- [32mf@1.0.0[39m -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/group/f[0m
528+
[0m+-- [32me@1.0.0[39m -> ./group/e[0m
529+
[0m\`-- [32mf@1.0.0[39m -> ./group/f[0m
530530

531531
`
532532

533533
exports[`test/lib/ls.js TAP ls loading a tree containing workspaces > should print all tree and filter by dep within only the ws subtree 1`] = `
534534
workspaces-tree@1.0.0 {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces
535-
\`-- d@1.0.0 -> {CWD}/tap-testdir-ls-ls-loading-a-tree-containing-workspaces/d
535+
\`-- d@1.0.0 -> ./d
536536
\`-- foo@1.1.1
537537
\`-- bar@1.0.0
538538
@@ -567,8 +567,8 @@ test-npm-ls@1.0.0 {CWD}/tap-testdir-ls-ls-no-args
567567
exports[`test/lib/ls.js TAP ls print deduped symlinks > should output tree containing linked deps 1`] = `
568568
print-deduped-symlinks@1.0.0 {CWD}/tap-testdir-ls-ls-print-deduped-symlinks
569569
+-- a@1.0.0
570-
| \`-- b@1.0.0 deduped -> {CWD}/tap-testdir-ls-ls-print-deduped-symlinks/b
571-
\`-- b@1.0.0 -> {CWD}/tap-testdir-ls-ls-print-deduped-symlinks/b
570+
| \`-- b@1.0.0 deduped -> ./b
571+
\`-- b@1.0.0 -> ./b
572572
573573
`
574574

test/lib/ls.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ const diffDepTypesNmFixture = {
9090
}
9191

9292
let result = ''
93-
const LS = require('../../lib/ls.js')
93+
const LS = t.mock('../../lib/ls.js', {
94+
path: {
95+
...require('path'),
96+
sep: '/',
97+
},
98+
})
9499
const config = {
95100
all: true,
96101
color: false,

0 commit comments

Comments
 (0)