From 9bffa13e0b96efe1039d9075fdcb11d5946b2f90 Mon Sep 17 00:00:00 2001 From: Gar Date: Wed, 27 Mar 2024 09:50:11 -0700 Subject: [PATCH] fix(query): properly return :missing nodes (#7320) Fixes https://github.com/npm/cli/issues/7316 --- lib/commands/query.js | 6 +++-- .../test/lib/commands/query.js.test.cjs | 25 +++++++++++++++++++ test/lib/commands/query.js | 22 ++++++++++++++++ workspaces/arborist/lib/query-selector-all.js | 7 +++++- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/lib/commands/query.js b/lib/commands/query.js index 17a55a446b086..dfa1356ebf436 100644 --- a/lib/commands/query.js +++ b/lib/commands/query.js @@ -113,10 +113,12 @@ class Query extends BaseCommand { // builds a normalized inventory buildResponse (items) { for (const node of items) { - if (!this.#seen.has(node.target.location)) { + if (!node.target.location || !this.#seen.has(node.target.location)) { const item = new QuerySelectorItem(node) this.#response.push(item) - this.#seen.add(item.location) + if (node.target.location) { + this.#seen.add(item.location) + } } } } diff --git a/tap-snapshots/test/lib/commands/query.js.test.cjs b/tap-snapshots/test/lib/commands/query.js.test.cjs index e732135468965..b41b875f8ea94 100644 --- a/tap-snapshots/test/lib/commands/query.js.test.cjs +++ b/tap-snapshots/test/lib/commands/query.js.test.cjs @@ -99,6 +99,31 @@ exports[`test/lib/commands/query.js TAP linked node > should return linked node ] ` +exports[`test/lib/commands/query.js TAP missing > should return missing node 1`] = ` +[ + { + "name": "b", + "version": "^1.0.0", + "_id": "b@^1.0.0", + "pkgid": "b@^1.0.0", + "path": null, + "realpath": null, + "resolved": null, + "from": [ + "" + ], + "to": [], + "dev": true, + "inBundle": false, + "deduped": false, + "overridden": false, + "queryContext": { + "missing": true + } + } +] +` + exports[`test/lib/commands/query.js TAP package-lock-only with package lock > should return valid response with only lock info 1`] = ` [ { diff --git a/test/lib/commands/query.js b/test/lib/commands/query.js index ebe89ed0da278..5292c50e1d365 100644 --- a/test/lib/commands/query.js +++ b/test/lib/commands/query.js @@ -320,3 +320,25 @@ t.test('expect entries', t => { }) t.end() }) + +t.test('missing', async t => { + const { npm, joinedOutput } = await loadMockNpm(t, { + prefixDir: { + node_modules: { + a: { + name: 'a', + version: '1.0.0', + }, + }, + 'package.json': JSON.stringify({ + name: 'project', + dependencies: { + a: '^1.0.0', + b: '^1.0.0', + }, + }), + }, + }) + await npm.exec('query', [':missing']) + t.matchSnapshot(joinedOutput(), 'should return missing node') +}) diff --git a/workspaces/arborist/lib/query-selector-all.js b/workspaces/arborist/lib/query-selector-all.js index ce49201ce624c..c8ec866f0f969 100644 --- a/workspaces/arborist/lib/query-selector-all.js +++ b/workspaces/arborist/lib/query-selector-all.js @@ -257,7 +257,12 @@ class Results { for (const edge of node.edgesOut.values()) { if (edge.missing) { const pkg = { name: edge.name, version: edge.spec } - res.push(new this.#targetNode.constructor({ pkg })) + const item = new this.#targetNode.constructor({ pkg }) + item.queryContext = { + missing: true, + } + item.edgesIn = new Set([edge]) + res.push(item) } } return res