Skip to content

Commit

Permalink
fix: npm search include/exclude
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
ruyadorno authored and isaacs committed Dec 11, 2020
1 parent c3ba1da commit 244c206
Show file tree
Hide file tree
Showing 6 changed files with 533 additions and 34 deletions.
73 changes: 39 additions & 34 deletions lib/search.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
'use strict'

module.exports = exports = search

const Minipass = require('minipass')
const Pipeline = require('minipass-pipeline')

const npm = require('./npm.js')
const formatPackageStream = require('./search/format-package-stream.js')

const libSearch = require('libnpmsearch')
const log = require('npmlog')

const formatPackageStream = require('./search/format-package-stream.js')
const packageFilter = require('./search/package-filter.js')
const npm = require('./npm.js')
const output = require('./utils/output.js')
const usage = require('./utils/usage')
const usageUtil = require('./utils/usage.js')
const completion = require('./utils/completion/none.js')

search.usage = usage(
const usage = usageUtil(
'search',
'npm search [--long] [search terms ...]'
)

search.completion = function (opts, cb) {
cb(null, [])
}
const cmd = (args, cb) => search(args).then(() => cb()).catch(cb)

function search (args, cb) {
const search = async (args) => {
const opts = {
...npm.flatOptions,
...npm.flatOptions.search,
Expand All @@ -30,47 +28,52 @@ function search (args, cb) {
}

if (opts.include.length === 0)
return cb(new Error('search must be called with arguments'))
throw new Error('search must be called with arguments')

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

class FilterStream extends Minipass {
write (pkg) {
if (packageFilter(pkg, opts.include, opts.exclude))
super.write(pkg)
}
}

const filterStream = new FilterStream()

// Grab a configured output stream that will spit out packages in the
// desired format.
//
// This is a text minipass stream
var outputStream = formatPackageStream({
const outputStream = formatPackageStream({
args, // --searchinclude options are not highlighted
...opts,
})

log.silly('search', 'searching packages')
const p = new Pipeline(libSearch.stream(opts.include, opts), outputStream)
const p = new Pipeline(
libSearch.stream(opts.include, opts),
filterStream,
outputStream
)

p.on('data', chunk => {
if (!anyOutput)
anyOutput = true
output(chunk.toString('utf8'))
})

p.promise().then(() => {
if (!anyOutput && !opts.json && !opts.parseable)
output('No matches found for ' + (args.map(JSON.stringify).join(' ')))
await p.promise()
if (!anyOutput && !opts.json && !opts.parseable)
output('No matches found for ' + (args.map(JSON.stringify).join(' ')))

log.silly('search', 'search completed')
log.clearProgress()
cb(null, {})
}, err => cb(err))
log.silly('search', 'search completed')
log.clearProgress()
}

function prepareIncludes (args, searchopts) {
if (typeof searchopts !== 'string')
searchopts = ''
return searchopts.split(/\s+/).concat(args).map(function (s) {
return s.toLowerCase()
}).filter(function (s) {
return s
})
return args
.map(s => s.toLowerCase())
.filter(s => s)
}

function prepareExcludes (searchexclude) {
Expand All @@ -80,7 +83,9 @@ function prepareExcludes (searchexclude) {
else
exclude = []

return exclude.map(function (s) {
return s.toLowerCase()
})
return exclude
.map(s => s.toLowerCase())
.filter(s => s)
}

module.exports = Object.assign(cmd, { completion, usage })
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
"libnpmteam": "^2.0.2",
"libnpmversion": "^1.0.7",
"make-fetch-happen": "^8.0.12",
"minipass": "^3.1.3",
"minipass-pipeline": "^1.2.4",
"mkdirp": "^1.0.4",
"mkdirp-infer-owner": "^2.0.0",
"ms": "^2.1.2",
Expand Down
20 changes: 20 additions & 0 deletions tap-snapshots/test-lib-search.js-TAP.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* IMPORTANT
* This snapshot file is auto-generated, but designed for humans.
* It should be checked into source control and tracked carefully.
* Re-generate by setting TAP_SNAPSHOT=1 and running tests.
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`test/lib/search.js TAP empty search results > should have expected search results 1`] = `
No matches found for "foo"
`

exports[`test/lib/search.js TAP search <name> --searchexclude --searchopts > should have filtered expected search results 1`] = `
NAME | AUTHOR | DATE | VERSION | KEYWORDS
foo | =foo | prehistoric | 1.0.0 |
`

exports[`test/lib/search.js TAP search <name> > should have expected search results 1`] = `
NAME | AUTHOR | DATE | VERSION | KEYWORDS
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 |
`
Loading

0 comments on commit 244c206

Please sign in to comment.