From d6d0b3e128f5be942ba67f2048591109e7d0a5dd Mon Sep 17 00:00:00 2001 From: Josh Brobst Date: Tue, 13 Jan 2026 20:37:10 -0500 Subject: [PATCH 1/2] fix(ls): load actual tree for --long descriptions --- lib/commands/ls.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/commands/ls.js b/lib/commands/ls.js index bc8beb007e809..eddebc3243675 100644 --- a/lib/commands/ls.js +++ b/lib/commands/ls.js @@ -69,6 +69,7 @@ class LS extends ArboristWorkspaceCmd { ...this.npm.flatOptions, legacyPeerDeps: false, path, + forceActual: long && !json && !parseable && !packageLockOnly, }) const tree = await this.initTree({ arb, args, packageLockOnly }) From b62e180690fa263941fd80fa127ad30ebcb1c312 Mon Sep 17 00:00:00 2001 From: Josh Brobst Date: Tue, 13 Jan 2026 20:37:10 -0500 Subject: [PATCH 2/2] fix(ls): avoid description for missing nodes --- lib/commands/ls.js | 2 +- .../test/lib/commands/ls.js.test.cjs | 26 +++++++++++++++++++ test/lib/commands/ls.js | 5 ++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/commands/ls.js b/lib/commands/ls.js index eddebc3243675..9c46b21ff4cb1 100644 --- a/lib/commands/ls.js +++ b/lib/commands/ls.js @@ -340,7 +340,7 @@ const getHumanOutputItem = (node, { args, chalk, global, long }) => { ) + (isGitNode(node) ? ` (${node.resolved})` : '') + (node.isLink ? ` -> ${relativePrefix}${targetLocation}` : '') + - (long ? `\n${node.package.description || ''}` : '') + (long && !node[_missing] ? `\n${node.package.description || ''}` : '') return augmentItemWithIncludeMetadata(node, { label, nodes: [] }) } diff --git a/tap-snapshots/test/lib/commands/ls.js.test.cjs b/tap-snapshots/test/lib/commands/ls.js.test.cjs index fc7fbdf8a906f..26bcbcf4b68f5 100644 --- a/tap-snapshots/test/lib/commands/ls.js.test.cjs +++ b/tap-snapshots/test/lib/commands/ls.js.test.cjs @@ -18,6 +18,32 @@ Array [ ] ` +exports[`test/lib/commands/ls.js TAP ignore missing optional deps --long human output > ls --long result 1`] = ` +test-npm-ls-ignore-missing-optional@1.2.3 +| {CWD}/prefix +| ++-- UNMET OPTIONAL DEPENDENCY optional-missing@1 ++-- optional-ok@1.2.3 +| ++-- optional-wrong@3.2.1 invalid: "1" from the root project +| ++-- UNMET DEPENDENCY peer-missing@1 ++-- peer-ok@1.2.3 +| ++-- UNMET OPTIONAL DEPENDENCY peer-optional-missing@1 ++-- peer-optional-ok@1.2.3 extraneous +| ++-- peer-optional-wrong@3.2.1 invalid: "1" from the root project extraneous +| ++-- peer-wrong@3.2.1 invalid: "1" from the root project +| ++-- UNMET DEPENDENCY prod-missing@1 ++-- prod-ok@1.2.3 +| +\`-- prod-wrong@3.2.1 invalid: "1" from the root project + +` + exports[`test/lib/commands/ls.js TAP ignore missing optional deps --parseable > ls --parseable result 1`] = ` {CWD}/prefix {CWD}/prefix/node_modules/optional-ok diff --git a/test/lib/commands/ls.js b/test/lib/commands/ls.js index c876af9e83ddf..f84212ea68900 100644 --- a/test/lib/commands/ls.js +++ b/test/lib/commands/ls.js @@ -2663,6 +2663,11 @@ t.test('ignore missing optional deps', async t => { const result = await mock(t) t.matchSnapshot(result, 'ls result') }) + + t.test('--long human output', async t => { + const result = await mock(t, { long: true }) + t.matchSnapshot(result, 'ls --long result') + }) }) t.test('ls --json', async t => {