Skip to content

Commit fdb8a86

Browse files
committedSep 11, 2023
feat: add package-lock-only mode to npm query
1 parent 16c04b1 commit fdb8a86

File tree

5 files changed

+128
-2
lines changed

5 files changed

+128
-2
lines changed
 

‎docs/lib/content/commands/npm-query.md

+6
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ npm query ":type(git)" | jq 'map(.name)' | xargs -I {} npm why {}
133133
},
134134
...
135135
```
136+
### Package lock only mode
137+
138+
If package-lock-only is enabled, only the information in the package
139+
lock (or shrinkwrap) is loaded. This means that information from the
140+
package.json files of your dependencies will not be included in the
141+
result set (e.g. description, homepage, engines).
136142

137143
### Package lock only mode
138144

‎lib/commands/query.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const { resolve } = require('path')
44
const BaseCommand = require('../base-command.js')
5+
const log = require('../utils/log-shim.js')
56

67
class QuerySelectorItem {
78
constructor (node) {
@@ -48,6 +49,7 @@ class Query extends BaseCommand {
4849
'workspace',
4950
'workspaces',
5051
'include-workspace-root',
52+
'package-lock-only',
5153
]
5254

5355
get parsedResponse () {
@@ -64,7 +66,18 @@ class Query extends BaseCommand {
6466
forceActual: true,
6567
}
6668
const arb = new Arborist(opts)
67-
const tree = await arb.loadActual(opts)
69+
let tree
70+
if (this.npm.config.get('package-lock-only')) {
71+
try {
72+
tree = await arb.loadVirtual()
73+
} catch (err) {
74+
log.verbose('loadVirtual', err.stack)
75+
/* eslint-disable-next-line max-len */
76+
throw this.usageError('A package lock or shrinkwrap file is required in package-lock-only mode')
77+
}
78+
} else {
79+
tree = await arb.loadActual(opts)
80+
}
6881
const items = await tree.querySelectorAll(args[0], this.npm.flatOptions)
6982
this.buildResponse(items)
7083

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

+48
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,54 @@ exports[`test/lib/commands/query.js TAP linked node > should return linked node
9999
]
100100
`
101101

102+
exports[`test/lib/commands/query.js TAP package-lock-only with package lock > should return valid response with only lock info 1`] = `
103+
[
104+
{
105+
"name": "project",
106+
"dependencies": {
107+
"a": "^1.0.0"
108+
},
109+
"pkgid": "project@",
110+
"location": "",
111+
"path": "{CWD}/prefix",
112+
"realpath": "{CWD}/prefix",
113+
"resolved": null,
114+
"from": [],
115+
"to": [
116+
"node_modules/a"
117+
],
118+
"dev": false,
119+
"inBundle": false,
120+
"deduped": false,
121+
"overridden": false,
122+
"queryContext": {}
123+
},
124+
{
125+
"version": "1.2.3",
126+
"resolved": "https://dummy.npmjs.org/a/-/a-1.2.3.tgz",
127+
"integrity": "sha512-dummy",
128+
"engines": {
129+
"node": ">=14.17"
130+
},
131+
"name": "a",
132+
"_id": "a@1.2.3",
133+
"pkgid": "a@1.2.3",
134+
"location": "node_modules/a",
135+
"path": "{CWD}/prefix/node_modules/a",
136+
"realpath": "{CWD}/prefix/node_modules/a",
137+
"from": [
138+
""
139+
],
140+
"to": [],
141+
"dev": false,
142+
"inBundle": false,
143+
"deduped": false,
144+
"overridden": false,
145+
"queryContext": {}
146+
}
147+
]
148+
`
149+
102150
exports[`test/lib/commands/query.js TAP recursive tree > should return everything in the tree, accounting for recursion 1`] = `
103151
[
104152
{

‎tap-snapshots/test/lib/docs.js.test.cjs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3831,7 +3831,7 @@ npm query <selector>
38313831
Options:
38323832
[-g|--global]
38333833
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
3834-
[-ws|--workspaces] [--include-workspace-root]
3834+
[-ws|--workspaces] [--include-workspace-root] [--package-lock-only]
38353835
38363836
Run "npm help query" for more info
38373837
@@ -3843,6 +3843,7 @@ npm query <selector>
38433843
#### \`workspace\`
38443844
#### \`workspaces\`
38453845
#### \`include-workspace-root\`
3846+
#### \`package-lock-only\`
38463847
`
38473848

38483849
exports[`test/lib/docs.js TAP usage rebuild > must match snapshot 1`] = `

‎test/lib/commands/query.js

+58
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,61 @@ t.test('global', async t => {
179179
await npm.exec('query', ['[name=lorem]'])
180180
t.matchSnapshot(joinedOutput(), 'should return global package')
181181
})
182+
183+
t.test('package-lock-only', t => {
184+
t.test('no package lock', async t => {
185+
const { npm } = await loadMockNpm(t, {
186+
config: {
187+
'package-lock-only': true,
188+
},
189+
prefixDir: {
190+
'package.json': JSON.stringify({
191+
name: 'project',
192+
dependencies: {
193+
a: '^1.0.0',
194+
},
195+
}),
196+
},
197+
})
198+
await t.rejects(npm.exec('query', [':root, :root > *']), { code: 'EUSAGE' })
199+
})
200+
201+
t.test('with package lock', async t => {
202+
const { npm, joinedOutput } = await loadMockNpm(t, {
203+
config: {
204+
'package-lock-only': true,
205+
},
206+
prefixDir: {
207+
'package.json': JSON.stringify({
208+
name: 'project',
209+
dependencies: {
210+
a: '^1.0.0',
211+
},
212+
}),
213+
'package-lock.json': JSON.stringify({
214+
name: 'project',
215+
lockfileVersion: 3,
216+
requires: true,
217+
packages: {
218+
'': {
219+
dependencies: {
220+
a: '^1.0.0',
221+
},
222+
},
223+
'node_modules/a': {
224+
version: '1.2.3',
225+
resolved: 'https://dummy.npmjs.org/a/-/a-1.2.3.tgz',
226+
integrity: 'sha512-dummy',
227+
engines: {
228+
node: '>=14.17',
229+
},
230+
},
231+
},
232+
}),
233+
},
234+
})
235+
await npm.exec('query', ['*'])
236+
t.matchSnapshot(joinedOutput(), 'should return valid response with only lock info')
237+
})
238+
t.end()
239+
})

0 commit comments

Comments
 (0)
Please sign in to comment.