Skip to content

Commit 06e91a8

Browse files
committed
fix: --include-workspace-root
1 parent 130c129 commit 06e91a8

File tree

3 files changed

+102
-26
lines changed

3 files changed

+102
-26
lines changed

lib/commands/query.js

+31-26
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const BaseCommand = require('../base-command.js')
66

77
class QuerySelectorItem {
88
constructor (node) {
9+
// all enumerable properties from the target
910
Object.assign(this, node.target.package)
1011

1112
// append extra info
@@ -19,21 +20,10 @@ class QuerySelectorItem {
1920
}
2021
}
2122

22-
// retrieves a normalized inventory
23-
const convertInventoryItemsToResponses = inventory => {
24-
const responses = []
25-
const responsesSeen = new Set()
26-
for (const node of inventory) {
27-
if (!responsesSeen.has(node.target.realpath)) {
28-
const item = new QuerySelectorItem(node)
29-
responses.push(item)
30-
responsesSeen.add(item.path)
31-
}
32-
}
33-
return responses
34-
}
35-
3623
class Query extends BaseCommand {
24+
#response = [] // response is the query response
25+
#seen = new Set() // paths we've seen so we can keep response deduped
26+
3727
static description = 'Retrieve a filtered list of packages'
3828
static name = 'query'
3929
static usage = ['<selector>']
@@ -47,7 +37,11 @@ class Query extends BaseCommand {
4737
'include-workspace-root',
4838
]
4939

50-
async exec (args, workspaces) {
40+
get parsedResponse () {
41+
return JSON.stringify(this.#response, null, 2)
42+
}
43+
44+
async exec (args) {
5145
// one dir up from wherever node_modules lives
5246
const where = resolve(this.npm.dir, '..')
5347
const opts = {
@@ -57,31 +51,42 @@ class Query extends BaseCommand {
5751
const arb = new Arborist(opts)
5852
const tree = await arb.loadActual(opts)
5953
const items = await tree.querySelectorAll(args[0])
60-
const res = convertInventoryItemsToResponses(items)
54+
this.buildResponse(items)
6155

62-
this.npm.output(JSON.stringify(res, null, 2))
56+
this.npm.output(this.parsedResponse)
6357
}
6458

6559
async execWorkspaces (args, filters) {
6660
await this.setWorkspaces(filters)
67-
const result = new Set()
6861
const opts = {
6962
...this.npm.flatOptions,
7063
path: this.npm.prefix,
7164
}
7265
const arb = new Arborist(opts)
7366
const tree = await arb.loadActual(opts)
7467
for (const workspacePath of this.workspacePaths) {
75-
const [workspace] = await tree.querySelectorAll(`.workspace:path(${workspacePath})`)
76-
const res = await workspace.querySelectorAll(args[0])
77-
const converted = convertInventoryItemsToResponses(res)
78-
for (const item of converted) {
79-
result.add(item)
68+
let items
69+
if (workspacePath === tree.root.path) {
70+
// include-workspace-root
71+
items = await tree.querySelectorAll(args[0])
72+
} else {
73+
const [workspace] = await tree.querySelectorAll(`.workspace:path(${workspacePath})`)
74+
items = await workspace.querySelectorAll(args[0])
75+
}
76+
this.buildResponse(items)
77+
}
78+
this.npm.output(this.parsedResponse)
79+
}
80+
81+
// builds a normalized inventory
82+
buildResponse (items) {
83+
for (const node of items) {
84+
if (!this.#seen.has(node.target.realpath)) {
85+
const item = new QuerySelectorItem(node)
86+
this.#response.push(item)
87+
this.#seen.add(item.realpath)
8088
}
8189
}
82-
// when running in workspaces names, make sure to key by workspace
83-
// name the results of each value retrieved in each ws
84-
this.npm.output(JSON.stringify([...result], null, 2))
8590
}
8691
}
8792

tap-snapshots/test/lib/commands/query.js.test.cjs

+34
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,40 @@ exports[`test/lib/commands/query.js TAP global > should return global package 1`
2222
]
2323
`
2424

25+
exports[`test/lib/commands/query.js TAP include-workspace-root > should return workspace object and root object 1`] = `
26+
[
27+
{
28+
"name": "project",
29+
"workspaces": [
30+
"c"
31+
],
32+
"dependencies": {
33+
"a": "^1.0.0",
34+
"b": "^1.0.0"
35+
},
36+
"pkgid": "project@",
37+
"location": "",
38+
"path": "{CWD}/test/lib/commands/tap-testdir-query-include-workspace-root/prefix",
39+
"realpath": "{CWD}/test/lib/commands/tap-testdir-query-include-workspace-root/prefix",
40+
"resolved": null,
41+
"isLink": false,
42+
"isWorkspace": false
43+
},
44+
{
45+
"name": "c",
46+
"version": "1.0.0",
47+
48+
"pkgid": "[email protected]",
49+
"location": "c",
50+
"path": "{CWD}/test/lib/commands/tap-testdir-query-include-workspace-root/prefix/c",
51+
"realpath": "{CWD}/test/lib/commands/tap-testdir-query-include-workspace-root/prefix/c",
52+
"resolved": null,
53+
"isLink": false,
54+
"isWorkspace": true
55+
}
56+
]
57+
`
58+
2559
exports[`test/lib/commands/query.js TAP linked node > should return linked node res 1`] = `
2660
[
2761
{

test/lib/commands/query.js

+37
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,43 @@ t.test('workspace query', async t => {
7474
t.matchSnapshot(joinedOutput(), 'should return workspace object')
7575
})
7676

77+
t.test('include-workspace-root', async t => {
78+
const { npm, joinedOutput } = await loadMockNpm(t, {
79+
config: {
80+
'include-workspace-root': true,
81+
workspaces: ['c'],
82+
},
83+
prefixDir: {
84+
node_modules: {
85+
a: {
86+
name: 'a',
87+
version: '1.0.0',
88+
},
89+
b: {
90+
name: 'b',
91+
version: '^2.0.0',
92+
},
93+
c: t.fixture('symlink', '../c'),
94+
},
95+
c: {
96+
'package.json': JSON.stringify({
97+
name: 'c',
98+
version: '1.0.0',
99+
}),
100+
},
101+
'package.json': JSON.stringify({
102+
name: 'project',
103+
workspaces: ['c'],
104+
dependencies: {
105+
a: '^1.0.0',
106+
b: '^1.0.0',
107+
},
108+
}),
109+
},
110+
})
111+
await npm.exec('query', [':scope'], ['c'])
112+
t.matchSnapshot(joinedOutput(), 'should return workspace object and root object')
113+
})
77114
t.test('linked node', async t => {
78115
const { npm, joinedOutput } = await loadMockNpm(t, {
79116
prefixDir: {

0 commit comments

Comments
 (0)