Skip to content

Commit 244c206

Browse files
ruyadornoisaacs
authored andcommitted
fix: npm search include/exclude
- Fixes `npm search --searchexclude=<value>` option - Tweaks `--searchopt` logic - Refactor and cleanup `lib/search.js` - Add `test/lib/search.js` tests - Fixes: npm/statusboard#171 PR-URL: #2325 Credit: @ruyadorno Close: #2325 Reviewed-by: @isaacs
1 parent c3ba1da commit 244c206

File tree

6 files changed

+533
-34
lines changed

6 files changed

+533
-34
lines changed

lib/search.js

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
'use strict'
22

3-
module.exports = exports = search
4-
3+
const Minipass = require('minipass')
54
const Pipeline = require('minipass-pipeline')
6-
7-
const npm = require('./npm.js')
8-
const formatPackageStream = require('./search/format-package-stream.js')
9-
105
const libSearch = require('libnpmsearch')
116
const log = require('npmlog')
7+
8+
const formatPackageStream = require('./search/format-package-stream.js')
9+
const packageFilter = require('./search/package-filter.js')
10+
const npm = require('./npm.js')
1211
const output = require('./utils/output.js')
13-
const usage = require('./utils/usage')
12+
const usageUtil = require('./utils/usage.js')
13+
const completion = require('./utils/completion/none.js')
1414

15-
search.usage = usage(
15+
const usage = usageUtil(
1616
'search',
1717
'npm search [--long] [search terms ...]'
1818
)
1919

20-
search.completion = function (opts, cb) {
21-
cb(null, [])
22-
}
20+
const cmd = (args, cb) => search(args).then(() => cb()).catch(cb)
2321

24-
function search (args, cb) {
22+
const search = async (args) => {
2523
const opts = {
2624
...npm.flatOptions,
2725
...npm.flatOptions.search,
@@ -30,47 +28,52 @@ function search (args, cb) {
3028
}
3129

3230
if (opts.include.length === 0)
33-
return cb(new Error('search must be called with arguments'))
31+
throw new Error('search must be called with arguments')
3432

3533
// Used later to figure out whether we had any packages go out
3634
let anyOutput = false
3735

36+
class FilterStream extends Minipass {
37+
write (pkg) {
38+
if (packageFilter(pkg, opts.include, opts.exclude))
39+
super.write(pkg)
40+
}
41+
}
42+
43+
const filterStream = new FilterStream()
44+
3845
// Grab a configured output stream that will spit out packages in the
3946
// desired format.
40-
//
41-
// This is a text minipass stream
42-
var outputStream = formatPackageStream({
47+
const outputStream = formatPackageStream({
4348
args, // --searchinclude options are not highlighted
4449
...opts,
4550
})
4651

4752
log.silly('search', 'searching packages')
48-
const p = new Pipeline(libSearch.stream(opts.include, opts), outputStream)
53+
const p = new Pipeline(
54+
libSearch.stream(opts.include, opts),
55+
filterStream,
56+
outputStream
57+
)
4958

5059
p.on('data', chunk => {
5160
if (!anyOutput)
5261
anyOutput = true
5362
output(chunk.toString('utf8'))
5463
})
5564

56-
p.promise().then(() => {
57-
if (!anyOutput && !opts.json && !opts.parseable)
58-
output('No matches found for ' + (args.map(JSON.stringify).join(' ')))
65+
await p.promise()
66+
if (!anyOutput && !opts.json && !opts.parseable)
67+
output('No matches found for ' + (args.map(JSON.stringify).join(' ')))
5968

60-
log.silly('search', 'search completed')
61-
log.clearProgress()
62-
cb(null, {})
63-
}, err => cb(err))
69+
log.silly('search', 'search completed')
70+
log.clearProgress()
6471
}
6572

6673
function prepareIncludes (args, searchopts) {
67-
if (typeof searchopts !== 'string')
68-
searchopts = ''
69-
return searchopts.split(/\s+/).concat(args).map(function (s) {
70-
return s.toLowerCase()
71-
}).filter(function (s) {
72-
return s
73-
})
74+
return args
75+
.map(s => s.toLowerCase())
76+
.filter(s => s)
7477
}
7578

7679
function prepareExcludes (searchexclude) {
@@ -80,7 +83,9 @@ function prepareExcludes (searchexclude) {
8083
else
8184
exclude = []
8285

83-
return exclude.map(function (s) {
84-
return s.toLowerCase()
85-
})
86+
return exclude
87+
.map(s => s.toLowerCase())
88+
.filter(s => s)
8689
}
90+
91+
module.exports = Object.assign(cmd, { completion, usage })

package-lock.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@
7878
"libnpmteam": "^2.0.2",
7979
"libnpmversion": "^1.0.7",
8080
"make-fetch-happen": "^8.0.12",
81+
"minipass": "^3.1.3",
82+
"minipass-pipeline": "^1.2.4",
8183
"mkdirp": "^1.0.4",
8284
"mkdirp-infer-owner": "^2.0.0",
8385
"ms": "^2.1.2",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* IMPORTANT
2+
* This snapshot file is auto-generated, but designed for humans.
3+
* It should be checked into source control and tracked carefully.
4+
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
5+
* Make sure to inspect the output below. Do not ignore changes!
6+
*/
7+
'use strict'
8+
exports[`test/lib/search.js TAP empty search results > should have expected search results 1`] = `
9+
No matches found for "foo"
10+
`
11+
12+
exports[`test/lib/search.js TAP search <name> --searchexclude --searchopts > should have filtered expected search results 1`] = `
13+
NAME | AUTHOR | DATE | VERSION | KEYWORDS
14+
foo | =foo | prehistoric | 1.0.0 |
15+
`
16+
17+
exports[`test/lib/search.js TAP search <name> > should have expected search results 1`] = `
18+
NAME | AUTHOR | DATE | VERSION | KEYWORDS
19+
libnpm | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager liblibnpmaccess | =nlf… | 2020-11-03 | 4.0.1 | @evocateur/libnpmaccess | =evocateur | 2019-07-16 | 3.1.2 | @evocateur/libnpmpublish | =evocateur | 2019-07-16 | 1.2.2 | libnpmorg | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teamslibnpmsearch | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpmlibnpmteam | =nlf… | 2020-11-03 | 2.0.2 | libnpmhook | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm apilibnpmpublish | =nlf… | 2020-11-03 | 4.0.0 | libnpmfund | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund@npmcli/map-workspaces | =nlf… | 2020-09-30 | 1.0.1 | npm npmcli libnpm cli workspaces map-workspaceslibnpmversion | =nlf… | 2020-11-04 | 1.0.7 | @types/libnpmsearch | =types | 2019-09-26 | 2.0.1 |
20+
`

0 commit comments

Comments
 (0)