Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib/utils
diff options
context:
space:
mode:
authorGar <gar+gh@danger.computer>2022-05-07 19:11:18 +0300
committerGitHub <noreply@github.com>2022-05-07 19:11:18 +0300
commit48d2db6037487fd782f67bbcd2cf12e009ece17b (patch)
treeaf1907ea0d36bfd9d7c5673ae51e4e8b3a4c7760 /lib/utils
parent8e7ea9b61afe37de6017ff77c142ef3abdff6bec (diff)
fix: remove test coverage map (#4862)
Turns out there were three files that still had no test coverage because of the combination of the mocks in tests and the coverage map. Removing the map altogether exposed them. This PR removes the coverage map and fixes test to cover all lines that were being missed. While adding coverage to the `npm search` codebase multiple unneeded guards and at least one bug was found (it was impossible to exclude searches based on username). These were fixed. The `npm view` tests were also refactored to use the real npm object. Finally, a small inlining of lib/utils/file-exists.js was done.
Diffstat (limited to 'lib/utils')
-rw-r--r--lib/utils/config/definitions.js2
-rw-r--r--lib/utils/file-exists.js10
-rw-r--r--lib/utils/format-bytes.js1
-rw-r--r--lib/utils/format-search-stream.js160
-rw-r--r--lib/utils/read-package-name.js9
5 files changed, 162 insertions, 20 deletions
diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js
index 6f1b1a724..a5eac8c82 100644
--- a/lib/utils/config/definitions.js
+++ b/lib/utils/config/definitions.js
@@ -1856,7 +1856,7 @@ define('searchexclude', {
`,
flatten (key, obj, flatOptions) {
flatOptions.search = flatOptions.search || { limit: 20 }
- flatOptions.search.exclude = obj[key]
+ flatOptions.search.exclude = obj[key].toLowerCase()
},
})
diff --git a/lib/utils/file-exists.js b/lib/utils/file-exists.js
deleted file mode 100644
index 605472536..000000000
--- a/lib/utils/file-exists.js
+++ /dev/null
@@ -1,10 +0,0 @@
-const fs = require('fs')
-const util = require('util')
-
-const stat = util.promisify(fs.stat)
-
-const fileExists = (file) => stat(file)
- .then((stat) => stat.isFile())
- .catch(() => false)
-
-module.exports = fileExists
diff --git a/lib/utils/format-bytes.js b/lib/utils/format-bytes.js
index d7cf6d144..d293001df 100644
--- a/lib/utils/format-bytes.js
+++ b/lib/utils/format-bytes.js
@@ -23,6 +23,7 @@ const formatBytes = (bytes, space = true) => {
return `${(bytes / 1000000).toFixed(1)}${spacer}MB`
}
+ // GB
return `${(bytes / 1000000000).toFixed(1)}${spacer}GB`
}
diff --git a/lib/utils/format-search-stream.js b/lib/utils/format-search-stream.js
new file mode 100644
index 000000000..2a2dadd5c
--- /dev/null
+++ b/lib/utils/format-search-stream.js
@@ -0,0 +1,160 @@
+const Minipass = require('minipass')
+const columnify = require('columnify')
+
+// This module consumes package data in the following format:
+//
+// {
+// name: String,
+// description: String,
+// maintainers: [{ username: String, email: String }],
+// keywords: String | [String],
+// version: String,
+// date: Date // can be null,
+// }
+//
+// The returned stream will format this package data
+// into a byte stream of formatted, displayable output.
+
+module.exports = (opts) => {
+ return opts.json ? new JSONOutputStream() : new TextOutputStream(opts)
+}
+
+class JSONOutputStream extends Minipass {
+ #didFirst = false
+
+ write (obj) {
+ if (!this.#didFirst) {
+ super.write('[\n')
+ this.#didFirst = true
+ } else {
+ super.write('\n,\n')
+ }
+
+ return super.write(JSON.stringify(obj))
+ }
+
+ end () {
+ super.write(this.#didFirst ? ']\n' : '\n[]\n')
+ super.end()
+ }
+}
+
+class TextOutputStream extends Minipass {
+ constructor (opts) {
+ super()
+ this._opts = opts
+ this._line = 0
+ }
+
+ write (pkg) {
+ return super.write(prettify(pkg, ++this._line, this._opts))
+ }
+}
+
+function prettify (data, num, opts) {
+ var truncate = !opts.long
+
+ var pkg = normalizePackage(data, opts)
+
+ var columns = ['name', 'description', 'author', 'date', 'version', 'keywords']
+
+ if (opts.parseable) {
+ return columns.map(function (col) {
+ return pkg[col] && ('' + pkg[col]).replace(/\t/g, ' ')
+ }).join('\t')
+ }
+
+ // stdout in tap is never a tty
+ /* istanbul ignore next */
+ const maxWidth = process.stdout.isTTY ? process.stdout.getWindowSize()[0] : Infinity
+ let output = columnify(
+ [pkg],
+ {
+ include: columns,
+ showHeaders: num <= 1,
+ columnSplitter: ' | ',
+ truncate: truncate,
+ config: {
+ name: { minWidth: 25, maxWidth: 25, truncate: false, truncateMarker: '' },
+ description: { minWidth: 20, maxWidth: 20 },
+ author: { minWidth: 15, maxWidth: 15 },
+ date: { maxWidth: 11 },
+ version: { minWidth: 8, maxWidth: 8 },
+ keywords: { maxWidth: Infinity },
+ },
+ }
+ ).split('\n').map(line => line.slice(0, maxWidth)).join('\n')
+
+ if (opts.color) {
+ output = highlightSearchTerms(output, opts.args)
+ }
+
+ return output
+}
+
+var colors = [31, 33, 32, 36, 34, 35]
+var cl = colors.length
+
+function addColorMarker (str, arg, i) {
+ var m = i % cl + 1
+ var markStart = String.fromCharCode(m)
+ var markEnd = String.fromCharCode(0)
+
+ if (arg.charAt(0) === '/') {
+ return str.replace(
+ new RegExp(arg.slice(1, -1), 'gi'),
+ bit => markStart + bit + markEnd
+ )
+ }
+
+ // just a normal string, do the split/map thing
+ var pieces = str.toLowerCase().split(arg.toLowerCase())
+ var p = 0
+
+ return pieces.map(function (piece) {
+ piece = str.slice(p, p + piece.length)
+ var mark = markStart +
+ str.slice(p + piece.length, p + piece.length + arg.length) +
+ markEnd
+ p += piece.length + arg.length
+ return piece + mark
+ }).join('')
+}
+
+function colorize (line) {
+ for (var i = 0; i < cl; i++) {
+ var m = i + 1
+ var color = '\u001B[' + colors[i] + 'm'
+ line = line.split(String.fromCharCode(m)).join(color)
+ }
+ var uncolor = '\u001B[0m'
+ return line.split('\u0000').join(uncolor)
+}
+
+function highlightSearchTerms (str, terms) {
+ terms.forEach(function (arg, i) {
+ str = addColorMarker(str, arg, i)
+ })
+
+ return colorize(str).trim()
+}
+
+function normalizePackage (data, opts) {
+ return {
+ name: data.name,
+ description: data.description,
+ author: data.maintainers.map((m) => `=${m.username}`).join(' '),
+ keywords: Array.isArray(data.keywords)
+ ? data.keywords.join(' ')
+ : typeof data.keywords === 'string'
+ ? data.keywords.replace(/[,\s]+/, ' ')
+ : '',
+ version: data.version,
+ date: (data.date &&
+ (data.date.toISOString() // remove time
+ .split('T').join(' ')
+ .replace(/:[0-9]{2}\.[0-9]{3}Z$/, ''))
+ .slice(0, -5)) ||
+ 'prehistoric',
+ }
+}
diff --git a/lib/utils/read-package-name.js b/lib/utils/read-package-name.js
deleted file mode 100644
index 7ed159877..000000000
--- a/lib/utils/read-package-name.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const { resolve } = require('path')
-const readJson = require('read-package-json-fast')
-async function readLocalPackageName (prefix) {
- const filepath = resolve(prefix, 'package.json')
- const json = await readJson(filepath)
- return json.name
-}
-
-module.exports = readLocalPackageName