From 2ec690da99fb441cdd7069480b42b6302e098005 Mon Sep 17 00:00:00 2001 From: Gar Date: Sat, 20 Apr 2024 10:02:27 -0700 Subject: [PATCH 01/42] deps: move cli-table3 to devDependencies We only need it for `scripts/publish.js` --- DEPENDENCIES.md | 2 - node_modules/.gitignore | 4 - node_modules/@colors/colors/LICENSE | 26 -- .../@colors/colors/examples/normal-usage.js | 83 ---- .../@colors/colors/examples/safe-string.js | 80 ---- node_modules/@colors/colors/lib/colors.js | 211 --------- .../@colors/colors/lib/custom/trap.js | 46 -- .../@colors/colors/lib/custom/zalgo.js | 110 ----- .../colors/lib/extendStringPrototype.js | 110 ----- node_modules/@colors/colors/lib/index.js | 13 - .../@colors/colors/lib/maps/america.js | 10 - .../@colors/colors/lib/maps/rainbow.js | 12 - .../@colors/colors/lib/maps/random.js | 11 - node_modules/@colors/colors/lib/maps/zebra.js | 5 - node_modules/@colors/colors/lib/styles.js | 95 ---- .../@colors/colors/lib/system/has-flag.js | 35 -- .../colors/lib/system/supports-colors.js | 151 ------- node_modules/@colors/colors/package.json | 45 -- node_modules/@colors/colors/safe.js | 10 - .../@colors/colors/themes/generic-logging.js | 12 - node_modules/cli-table3/LICENSE | 21 - node_modules/cli-table3/index.js | 1 - node_modules/cli-table3/package.json | 100 ----- node_modules/cli-table3/src/cell.js | 409 ------------------ node_modules/cli-table3/src/debug.js | 28 -- node_modules/cli-table3/src/layout-manager.js | 254 ----------- node_modules/cli-table3/src/table.js | 106 ----- node_modules/cli-table3/src/utils.js | 336 -------------- package-lock.json | 7 +- package.json | 3 +- 30 files changed, 4 insertions(+), 2332 deletions(-) delete mode 100644 node_modules/@colors/colors/LICENSE delete mode 100644 node_modules/@colors/colors/examples/normal-usage.js delete mode 100644 node_modules/@colors/colors/examples/safe-string.js delete mode 100644 node_modules/@colors/colors/lib/colors.js delete mode 100644 node_modules/@colors/colors/lib/custom/trap.js delete mode 100644 node_modules/@colors/colors/lib/custom/zalgo.js delete mode 100644 node_modules/@colors/colors/lib/extendStringPrototype.js delete mode 100644 node_modules/@colors/colors/lib/index.js delete mode 100644 node_modules/@colors/colors/lib/maps/america.js delete mode 100644 node_modules/@colors/colors/lib/maps/rainbow.js delete mode 100644 node_modules/@colors/colors/lib/maps/random.js delete mode 100644 node_modules/@colors/colors/lib/maps/zebra.js delete mode 100644 node_modules/@colors/colors/lib/styles.js delete mode 100644 node_modules/@colors/colors/lib/system/has-flag.js delete mode 100644 node_modules/@colors/colors/lib/system/supports-colors.js delete mode 100644 node_modules/@colors/colors/package.json delete mode 100644 node_modules/@colors/colors/safe.js delete mode 100644 node_modules/@colors/colors/themes/generic-logging.js delete mode 100644 node_modules/cli-table3/LICENSE delete mode 100644 node_modules/cli-table3/index.js delete mode 100644 node_modules/cli-table3/package.json delete mode 100644 node_modules/cli-table3/src/cell.js delete mode 100644 node_modules/cli-table3/src/debug.js delete mode 100644 node_modules/cli-table3/src/layout-manager.js delete mode 100644 node_modules/cli-table3/src/table.js delete mode 100644 node_modules/cli-table3/src/utils.js diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index c4a34f98a8c7c..89274c35261a8 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -288,8 +288,6 @@ graph LR; cidr-regex-->ip-regex; cli-columns-->string-width; cli-columns-->strip-ansi; - cli-table3-->colors-colors["@colors/colors"]; - cli-table3-->string-width; color-convert-->color-name; columnify-->strip-ansi; columnify-->wcwidth; diff --git a/node_modules/.gitignore b/node_modules/.gitignore index beddaa3541d3e..f12013c0f8d76 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -3,9 +3,6 @@ /* !/.gitignore # Allow all bundled deps -!/@colors/ -/@colors/* -!/@colors/colors !/@isaacs/ /@isaacs/* !/@isaacs/cliui @@ -69,7 +66,6 @@ !/cidr-regex !/clean-stack !/cli-columns -!/cli-table3 !/clone !/cmd-shim !/color-convert diff --git a/node_modules/@colors/colors/LICENSE b/node_modules/@colors/colors/LICENSE deleted file mode 100644 index 6b86056199d2a..0000000000000 --- a/node_modules/@colors/colors/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -MIT License - -Original Library - - Copyright (c) Marak Squires - -Additional Functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - - Copyright (c) DABH (https://github.com/DABH) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/@colors/colors/examples/normal-usage.js b/node_modules/@colors/colors/examples/normal-usage.js deleted file mode 100644 index a4bfe7b7be633..0000000000000 --- a/node_modules/@colors/colors/examples/normal-usage.js +++ /dev/null @@ -1,83 +0,0 @@ -var colors = require('../lib/index'); - -console.log('First some yellow text'.yellow); - -console.log('Underline that text'.yellow.underline); - -console.log('Make it bold and red'.red.bold); - -console.log(('Double Raindows All Day Long').rainbow); - -console.log('Drop the bass'.trap); - -console.log('DROP THE RAINBOW BASS'.trap.rainbow); - -// styles not widely supported -console.log('Chains are also cool.'.bold.italic.underline.red); - -// styles not widely supported -console.log('So '.green + 'are'.underline + ' ' + 'inverse'.inverse - + ' styles! '.yellow.bold); -console.log('Zebras are so fun!'.zebra); - -// -// Remark: .strikethrough may not work with Mac OS Terminal App -// -console.log('This is ' + 'not'.strikethrough + ' fun.'); - -console.log('Background color attack!'.black.bgWhite); -console.log('Use random styles on everything!'.random); -console.log('America, Heck Yeah!'.america); - -// eslint-disable-next-line max-len -console.log('Blindingly '.brightCyan + 'bright? '.brightRed + 'Why '.brightYellow + 'not?!'.brightGreen); - -console.log('Setting themes is useful'); - -// -// Custom themes -// -console.log('Generic logging theme as JSON'.green.bold.underline); -// Load theme with JSON literal -colors.setTheme({ - silly: 'rainbow', - input: 'grey', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}); - -// outputs red text -console.log('this is an error'.error); - -// outputs yellow text -console.log('this is a warning'.warn); - -// outputs grey text -console.log('this is an input'.input); - -console.log('Generic logging theme as file'.green.bold.underline); - -// Load a theme from file -try { - colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); -} catch (err) { - console.log(err); -} - -// outputs red text -console.log('this is an error'.error); - -// outputs yellow text -console.log('this is a warning'.warn); - -// outputs grey text -console.log('this is an input'.input); - -// console.log("Don't summon".zalgo) - diff --git a/node_modules/@colors/colors/examples/safe-string.js b/node_modules/@colors/colors/examples/safe-string.js deleted file mode 100644 index fc664745705f3..0000000000000 --- a/node_modules/@colors/colors/examples/safe-string.js +++ /dev/null @@ -1,80 +0,0 @@ -var colors = require('../safe'); - -console.log(colors.yellow('First some yellow text')); - -console.log(colors.yellow.underline('Underline that text')); - -console.log(colors.red.bold('Make it bold and red')); - -console.log(colors.rainbow('Double Raindows All Day Long')); - -console.log(colors.trap('Drop the bass')); - -console.log(colors.rainbow(colors.trap('DROP THE RAINBOW BASS'))); - -// styles not widely supported -console.log(colors.bold.italic.underline.red('Chains are also cool.')); - -// styles not widely supported -console.log(colors.green('So ') + colors.underline('are') + ' ' - + colors.inverse('inverse') + colors.yellow.bold(' styles! ')); - -console.log(colors.zebra('Zebras are so fun!')); - -console.log('This is ' + colors.strikethrough('not') + ' fun.'); - - -console.log(colors.black.bgWhite('Background color attack!')); -console.log(colors.random('Use random styles on everything!')); -console.log(colors.america('America, Heck Yeah!')); - -// eslint-disable-next-line max-len -console.log(colors.brightCyan('Blindingly ') + colors.brightRed('bright? ') + colors.brightYellow('Why ') + colors.brightGreen('not?!')); - -console.log('Setting themes is useful'); - -// -// Custom themes -// -// console.log('Generic logging theme as JSON'.green.bold.underline); -// Load theme with JSON literal -colors.setTheme({ - silly: 'rainbow', - input: 'blue', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}); - -// outputs red text -console.log(colors.error('this is an error')); - -// outputs yellow text -console.log(colors.warn('this is a warning')); - -// outputs blue text -console.log(colors.input('this is an input')); - - -// console.log('Generic logging theme as file'.green.bold.underline); - -// Load a theme from file -colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); - -// outputs red text -console.log(colors.error('this is an error')); - -// outputs yellow text -console.log(colors.warn('this is a warning')); - -// outputs grey text -console.log(colors.input('this is an input')); - -// console.log(colors.zalgo("Don't summon him")) - - diff --git a/node_modules/@colors/colors/lib/colors.js b/node_modules/@colors/colors/lib/colors.js deleted file mode 100644 index d9fb08762fde5..0000000000000 --- a/node_modules/@colors/colors/lib/colors.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - -The MIT License (MIT) - -Original Library - - Copyright (c) Marak Squires - -Additional functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var colors = {}; -module['exports'] = colors; - -colors.themes = {}; - -var util = require('util'); -var ansiStyles = colors.styles = require('./styles'); -var defineProps = Object.defineProperties; -var newLineRegex = new RegExp(/[\r\n]+/g); - -colors.supportsColor = require('./system/supports-colors').supportsColor; - -if (typeof colors.enabled === 'undefined') { - colors.enabled = colors.supportsColor() !== false; -} - -colors.enable = function() { - colors.enabled = true; -}; - -colors.disable = function() { - colors.enabled = false; -}; - -colors.stripColors = colors.strip = function(str) { - return ('' + str).replace(/\x1B\[\d+m/g, ''); -}; - -// eslint-disable-next-line no-unused-vars -var stylize = colors.stylize = function stylize(str, style) { - if (!colors.enabled) { - return str+''; - } - - var styleMap = ansiStyles[style]; - - // Stylize should work for non-ANSI styles, too - if (!styleMap && style in colors) { - // Style maps like trap operate as functions on strings; - // they don't have properties like open or close. - return colors[style](str); - } - - return styleMap.open + str + styleMap.close; -}; - -var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; -var escapeStringRegexp = function(str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } - return str.replace(matchOperatorsRe, '\\$&'); -}; - -function build(_styles) { - var builder = function builder() { - return applyStyle.apply(builder, arguments); - }; - builder._styles = _styles; - // __proto__ is used because we must return a function, but there is - // no way to create a function with a different prototype. - builder.__proto__ = proto; - return builder; -} - -var styles = (function() { - var ret = {}; - ansiStyles.grey = ansiStyles.gray; - Object.keys(ansiStyles).forEach(function(key) { - ansiStyles[key].closeRe = - new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); - ret[key] = { - get: function() { - return build(this._styles.concat(key)); - }, - }; - }); - return ret; -})(); - -var proto = defineProps(function colors() {}, styles); - -function applyStyle() { - var args = Array.prototype.slice.call(arguments); - - var str = args.map(function(arg) { - // Use weak equality check so we can colorize null/undefined in safe mode - if (arg != null && arg.constructor === String) { - return arg; - } else { - return util.inspect(arg); - } - }).join(' '); - - if (!colors.enabled || !str) { - return str; - } - - var newLinesPresent = str.indexOf('\n') != -1; - - var nestedStyles = this._styles; - - var i = nestedStyles.length; - while (i--) { - var code = ansiStyles[nestedStyles[i]]; - str = code.open + str.replace(code.closeRe, code.open) + code.close; - if (newLinesPresent) { - str = str.replace(newLineRegex, function(match) { - return code.close + match + code.open; - }); - } - } - - return str; -} - -colors.setTheme = function(theme) { - if (typeof theme === 'string') { - console.log('colors.setTheme now only accepts an object, not a string. ' + - 'If you are trying to set a theme from a file, it is now your (the ' + - 'caller\'s) responsibility to require the file. The old syntax ' + - 'looked like colors.setTheme(__dirname + ' + - '\'/../themes/generic-logging.js\'); The new syntax looks like '+ - 'colors.setTheme(require(__dirname + ' + - '\'/../themes/generic-logging.js\'));'); - return; - } - for (var style in theme) { - (function(style) { - colors[style] = function(str) { - if (typeof theme[style] === 'object') { - var out = str; - for (var i in theme[style]) { - out = colors[theme[style][i]](out); - } - return out; - } - return colors[theme[style]](str); - }; - })(style); - } -}; - -function init() { - var ret = {}; - Object.keys(styles).forEach(function(name) { - ret[name] = { - get: function() { - return build([name]); - }, - }; - }); - return ret; -} - -var sequencer = function sequencer(map, str) { - var exploded = str.split(''); - exploded = exploded.map(map); - return exploded.join(''); -}; - -// custom formatter methods -colors.trap = require('./custom/trap'); -colors.zalgo = require('./custom/zalgo'); - -// maps -colors.maps = {}; -colors.maps.america = require('./maps/america')(colors); -colors.maps.zebra = require('./maps/zebra')(colors); -colors.maps.rainbow = require('./maps/rainbow')(colors); -colors.maps.random = require('./maps/random')(colors); - -for (var map in colors.maps) { - (function(map) { - colors[map] = function(str) { - return sequencer(colors.maps[map], str); - }; - })(map); -} - -defineProps(colors, init()); diff --git a/node_modules/@colors/colors/lib/custom/trap.js b/node_modules/@colors/colors/lib/custom/trap.js deleted file mode 100644 index fbccf88dede0b..0000000000000 --- a/node_modules/@colors/colors/lib/custom/trap.js +++ /dev/null @@ -1,46 +0,0 @@ -module['exports'] = function runTheTrap(text, options) { - var result = ''; - text = text || 'Run the trap, drop the bass'; - text = text.split(''); - var trap = { - a: ['\u0040', '\u0104', '\u023a', '\u0245', '\u0394', '\u039b', '\u0414'], - b: ['\u00df', '\u0181', '\u0243', '\u026e', '\u03b2', '\u0e3f'], - c: ['\u00a9', '\u023b', '\u03fe'], - d: ['\u00d0', '\u018a', '\u0500', '\u0501', '\u0502', '\u0503'], - e: ['\u00cb', '\u0115', '\u018e', '\u0258', '\u03a3', '\u03be', '\u04bc', - '\u0a6c'], - f: ['\u04fa'], - g: ['\u0262'], - h: ['\u0126', '\u0195', '\u04a2', '\u04ba', '\u04c7', '\u050a'], - i: ['\u0f0f'], - j: ['\u0134'], - k: ['\u0138', '\u04a0', '\u04c3', '\u051e'], - l: ['\u0139'], - m: ['\u028d', '\u04cd', '\u04ce', '\u0520', '\u0521', '\u0d69'], - n: ['\u00d1', '\u014b', '\u019d', '\u0376', '\u03a0', '\u048a'], - o: ['\u00d8', '\u00f5', '\u00f8', '\u01fe', '\u0298', '\u047a', '\u05dd', - '\u06dd', '\u0e4f'], - p: ['\u01f7', '\u048e'], - q: ['\u09cd'], - r: ['\u00ae', '\u01a6', '\u0210', '\u024c', '\u0280', '\u042f'], - s: ['\u00a7', '\u03de', '\u03df', '\u03e8'], - t: ['\u0141', '\u0166', '\u0373'], - u: ['\u01b1', '\u054d'], - v: ['\u05d8'], - w: ['\u0428', '\u0460', '\u047c', '\u0d70'], - x: ['\u04b2', '\u04fe', '\u04fc', '\u04fd'], - y: ['\u00a5', '\u04b0', '\u04cb'], - z: ['\u01b5', '\u0240'], - }; - text.forEach(function(c) { - c = c.toLowerCase(); - var chars = trap[c] || [' ']; - var rand = Math.floor(Math.random() * chars.length); - if (typeof trap[c] !== 'undefined') { - result += trap[c][rand]; - } else { - result += c; - } - }); - return result; -}; diff --git a/node_modules/@colors/colors/lib/custom/zalgo.js b/node_modules/@colors/colors/lib/custom/zalgo.js deleted file mode 100644 index 0ef2b01195635..0000000000000 --- a/node_modules/@colors/colors/lib/custom/zalgo.js +++ /dev/null @@ -1,110 +0,0 @@ -// please no -module['exports'] = function zalgo(text, options) { - text = text || ' he is here '; - var soul = { - 'up': [ - '̍', '̎', '̄', '̅', - '̿', '̑', '̆', '̐', - '͒', '͗', '͑', '̇', - '̈', '̊', '͂', '̓', - '̈', '͊', '͋', '͌', - '̃', '̂', '̌', '͐', - '̀', '́', '̋', '̏', - '̒', '̓', '̔', '̽', - '̉', 'ͣ', 'ͤ', 'ͥ', - 'ͦ', 'ͧ', 'ͨ', 'ͩ', - 'ͪ', 'ͫ', 'ͬ', 'ͭ', - 'ͮ', 'ͯ', '̾', '͛', - '͆', '̚', - ], - 'down': [ - '̖', '̗', '̘', '̙', - '̜', '̝', '̞', '̟', - '̠', '̤', '̥', '̦', - '̩', '̪', '̫', '̬', - '̭', '̮', '̯', '̰', - '̱', '̲', '̳', '̹', - '̺', '̻', '̼', 'ͅ', - '͇', '͈', '͉', '͍', - '͎', '͓', '͔', '͕', - '͖', '͙', '͚', '̣', - ], - 'mid': [ - '̕', '̛', '̀', '́', - '͘', '̡', '̢', '̧', - '̨', '̴', '̵', '̶', - '͜', '͝', '͞', - '͟', '͠', '͢', '̸', - '̷', '͡', ' ҉', - ], - }; - var all = [].concat(soul.up, soul.down, soul.mid); - - function randomNumber(range) { - var r = Math.floor(Math.random() * range); - return r; - } - - function isChar(character) { - var bool = false; - all.filter(function(i) { - bool = (i === character); - }); - return bool; - } - - - function heComes(text, options) { - var result = ''; - var counts; - var l; - options = options || {}; - options['up'] = - typeof options['up'] !== 'undefined' ? options['up'] : true; - options['mid'] = - typeof options['mid'] !== 'undefined' ? options['mid'] : true; - options['down'] = - typeof options['down'] !== 'undefined' ? options['down'] : true; - options['size'] = - typeof options['size'] !== 'undefined' ? options['size'] : 'maxi'; - text = text.split(''); - for (l in text) { - if (isChar(l)) { - continue; - } - result = result + text[l]; - counts = {'up': 0, 'down': 0, 'mid': 0}; - switch (options.size) { - case 'mini': - counts.up = randomNumber(8); - counts.mid = randomNumber(2); - counts.down = randomNumber(8); - break; - case 'maxi': - counts.up = randomNumber(16) + 3; - counts.mid = randomNumber(4) + 1; - counts.down = randomNumber(64) + 3; - break; - default: - counts.up = randomNumber(8) + 1; - counts.mid = randomNumber(6) / 2; - counts.down = randomNumber(8) + 1; - break; - } - - var arr = ['up', 'mid', 'down']; - for (var d in arr) { - var index = arr[d]; - for (var i = 0; i <= counts[index]; i++) { - if (options[index]) { - result = result + soul[index][randomNumber(soul[index].length)]; - } - } - } - } - return result; - } - // don't summon him - return heComes(text, options); -}; - diff --git a/node_modules/@colors/colors/lib/extendStringPrototype.js b/node_modules/@colors/colors/lib/extendStringPrototype.js deleted file mode 100644 index 46fd386a915a6..0000000000000 --- a/node_modules/@colors/colors/lib/extendStringPrototype.js +++ /dev/null @@ -1,110 +0,0 @@ -var colors = require('./colors'); - -module['exports'] = function() { - // - // Extends prototype of native string object to allow for "foo".red syntax - // - var addProperty = function(color, func) { - String.prototype.__defineGetter__(color, func); - }; - - addProperty('strip', function() { - return colors.strip(this); - }); - - addProperty('stripColors', function() { - return colors.strip(this); - }); - - addProperty('trap', function() { - return colors.trap(this); - }); - - addProperty('zalgo', function() { - return colors.zalgo(this); - }); - - addProperty('zebra', function() { - return colors.zebra(this); - }); - - addProperty('rainbow', function() { - return colors.rainbow(this); - }); - - addProperty('random', function() { - return colors.random(this); - }); - - addProperty('america', function() { - return colors.america(this); - }); - - // - // Iterate through all default styles and colors - // - var x = Object.keys(colors.styles); - x.forEach(function(style) { - addProperty(style, function() { - return colors.stylize(this, style); - }); - }); - - function applyTheme(theme) { - // - // Remark: This is a list of methods that exist - // on String that you should not overwrite. - // - var stringPrototypeBlacklist = [ - '__defineGetter__', '__defineSetter__', '__lookupGetter__', - '__lookupSetter__', 'charAt', 'constructor', 'hasOwnProperty', - 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', - 'valueOf', 'charCodeAt', 'indexOf', 'lastIndexOf', 'length', - 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', - 'split', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase', - 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', - ]; - - Object.keys(theme).forEach(function(prop) { - if (stringPrototypeBlacklist.indexOf(prop) !== -1) { - console.log('warn: '.red + ('String.prototype' + prop).magenta + - ' is probably something you don\'t want to override. ' + - 'Ignoring style name'); - } else { - if (typeof(theme[prop]) === 'string') { - colors[prop] = colors[theme[prop]]; - addProperty(prop, function() { - return colors[prop](this); - }); - } else { - var themePropApplicator = function(str) { - var ret = str || this; - for (var t = 0; t < theme[prop].length; t++) { - ret = colors[theme[prop][t]](ret); - } - return ret; - }; - addProperty(prop, themePropApplicator); - colors[prop] = function(str) { - return themePropApplicator(str); - }; - } - } - }); - } - - colors.setTheme = function(theme) { - if (typeof theme === 'string') { - console.log('colors.setTheme now only accepts an object, not a string. ' + - 'If you are trying to set a theme from a file, it is now your (the ' + - 'caller\'s) responsibility to require the file. The old syntax ' + - 'looked like colors.setTheme(__dirname + ' + - '\'/../themes/generic-logging.js\'); The new syntax looks like '+ - 'colors.setTheme(require(__dirname + ' + - '\'/../themes/generic-logging.js\'));'); - return; - } else { - applyTheme(theme); - } - }; -}; diff --git a/node_modules/@colors/colors/lib/index.js b/node_modules/@colors/colors/lib/index.js deleted file mode 100644 index 9df5ab7df3077..0000000000000 --- a/node_modules/@colors/colors/lib/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var colors = require('./colors'); -module['exports'] = colors; - -// Remark: By default, colors will add style properties to String.prototype. -// -// If you don't wish to extend String.prototype, you can do this instead and -// native String will not be touched: -// -// var colors = require('colors/safe); -// colors.red("foo") -// -// -require('./extendStringPrototype')(); diff --git a/node_modules/@colors/colors/lib/maps/america.js b/node_modules/@colors/colors/lib/maps/america.js deleted file mode 100644 index dc96903328989..0000000000000 --- a/node_modules/@colors/colors/lib/maps/america.js +++ /dev/null @@ -1,10 +0,0 @@ -module['exports'] = function(colors) { - return function(letter, i, exploded) { - if (letter === ' ') return letter; - switch (i%3) { - case 0: return colors.red(letter); - case 1: return colors.white(letter); - case 2: return colors.blue(letter); - } - }; -}; diff --git a/node_modules/@colors/colors/lib/maps/rainbow.js b/node_modules/@colors/colors/lib/maps/rainbow.js deleted file mode 100644 index 2b00ac0ac998e..0000000000000 --- a/node_modules/@colors/colors/lib/maps/rainbow.js +++ /dev/null @@ -1,12 +0,0 @@ -module['exports'] = function(colors) { - // RoY G BiV - var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; - return function(letter, i, exploded) { - if (letter === ' ') { - return letter; - } else { - return colors[rainbowColors[i++ % rainbowColors.length]](letter); - } - }; -}; - diff --git a/node_modules/@colors/colors/lib/maps/random.js b/node_modules/@colors/colors/lib/maps/random.js deleted file mode 100644 index 3d82a39ec0fab..0000000000000 --- a/node_modules/@colors/colors/lib/maps/random.js +++ /dev/null @@ -1,11 +0,0 @@ -module['exports'] = function(colors) { - var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', - 'blue', 'white', 'cyan', 'magenta', 'brightYellow', 'brightRed', - 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 'brightMagenta']; - return function(letter, i, exploded) { - return letter === ' ' ? letter : - colors[ - available[Math.round(Math.random() * (available.length - 2))] - ](letter); - }; -}; diff --git a/node_modules/@colors/colors/lib/maps/zebra.js b/node_modules/@colors/colors/lib/maps/zebra.js deleted file mode 100644 index fa73623544a82..0000000000000 --- a/node_modules/@colors/colors/lib/maps/zebra.js +++ /dev/null @@ -1,5 +0,0 @@ -module['exports'] = function(colors) { - return function(letter, i, exploded) { - return i % 2 === 0 ? letter : colors.inverse(letter); - }; -}; diff --git a/node_modules/@colors/colors/lib/styles.js b/node_modules/@colors/colors/lib/styles.js deleted file mode 100644 index 011dafd8c28f7..0000000000000 --- a/node_modules/@colors/colors/lib/styles.js +++ /dev/null @@ -1,95 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -var styles = {}; -module['exports'] = styles; - -var codes = { - reset: [0, 0], - - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29], - - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], - gray: [90, 39], - grey: [90, 39], - - brightRed: [91, 39], - brightGreen: [92, 39], - brightYellow: [93, 39], - brightBlue: [94, 39], - brightMagenta: [95, 39], - brightCyan: [96, 39], - brightWhite: [97, 39], - - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - bgGray: [100, 49], - bgGrey: [100, 49], - - bgBrightRed: [101, 49], - bgBrightGreen: [102, 49], - bgBrightYellow: [103, 49], - bgBrightBlue: [104, 49], - bgBrightMagenta: [105, 49], - bgBrightCyan: [106, 49], - bgBrightWhite: [107, 49], - - // legacy styles for colors pre v1.0.0 - blackBG: [40, 49], - redBG: [41, 49], - greenBG: [42, 49], - yellowBG: [43, 49], - blueBG: [44, 49], - magentaBG: [45, 49], - cyanBG: [46, 49], - whiteBG: [47, 49], - -}; - -Object.keys(codes).forEach(function(key) { - var val = codes[key]; - var style = styles[key] = []; - style.open = '\u001b[' + val[0] + 'm'; - style.close = '\u001b[' + val[1] + 'm'; -}); diff --git a/node_modules/@colors/colors/lib/system/has-flag.js b/node_modules/@colors/colors/lib/system/has-flag.js deleted file mode 100644 index a347dd4d7a697..0000000000000 --- a/node_modules/@colors/colors/lib/system/has-flag.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -'use strict'; - -module.exports = function(flag, argv) { - argv = argv || process.argv; - - var terminatorPos = argv.indexOf('--'); - var prefix = /^-{1,2}/.test(flag) ? '' : '--'; - var pos = argv.indexOf(prefix + flag); - - return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); -}; diff --git a/node_modules/@colors/colors/lib/system/supports-colors.js b/node_modules/@colors/colors/lib/system/supports-colors.js deleted file mode 100644 index f1f9c8ff3da28..0000000000000 --- a/node_modules/@colors/colors/lib/system/supports-colors.js +++ /dev/null @@ -1,151 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -'use strict'; - -var os = require('os'); -var hasFlag = require('./has-flag.js'); - -var env = process.env; - -var forceColor = void 0; -if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) { - forceColor = false; -} else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true') - || hasFlag('color=always')) { - forceColor = true; -} -if ('FORCE_COLOR' in env) { - forceColor = env.FORCE_COLOR.length === 0 - || parseInt(env.FORCE_COLOR, 10) !== 0; -} - -function translateLevel(level) { - if (level === 0) { - return false; - } - - return { - level: level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3, - }; -} - -function supportsColor(stream) { - if (forceColor === false) { - return 0; - } - - if (hasFlag('color=16m') || hasFlag('color=full') - || hasFlag('color=truecolor')) { - return 3; - } - - if (hasFlag('color=256')) { - return 2; - } - - if (stream && !stream.isTTY && forceColor !== true) { - return 0; - } - - var min = forceColor ? 1 : 0; - - if (process.platform === 'win32') { - // Node.js 7.5.0 is the first version of Node.js to include a patch to - // libuv that enables 256 color output on Windows. Anything earlier and it - // won't work. However, here we target Node.js 8 at minimum as it is an LTS - // release, and Node.js 7 is not. Windows 10 build 10586 is the first - // Windows release that supports 256 colors. Windows 10 build 14931 is the - // first release that supports 16m/TrueColor. - var osRelease = os.release().split('.'); - if (Number(process.versions.node.split('.')[0]) >= 8 - && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - - return 1; - } - - if ('CI' in env) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) { - return sign in env; - }) || env.CI_NAME === 'codeship') { - return 1; - } - - return min; - } - - if ('TEAMCITY_VERSION' in env) { - return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0 - ); - } - - if ('TERM_PROGRAM' in env) { - var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Hyper': - return 3; - case 'Apple_Terminal': - return 2; - // No default - } - } - - if (/-256(color)?$/i.test(env.TERM)) { - return 2; - } - - if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { - return 1; - } - - if ('COLORTERM' in env) { - return 1; - } - - if (env.TERM === 'dumb') { - return min; - } - - return min; -} - -function getSupportLevel(stream) { - var level = supportsColor(stream); - return translateLevel(level); -} - -module.exports = { - supportsColor: getSupportLevel, - stdout: getSupportLevel(process.stdout), - stderr: getSupportLevel(process.stderr), -}; diff --git a/node_modules/@colors/colors/package.json b/node_modules/@colors/colors/package.json deleted file mode 100644 index cb87f20953886..0000000000000 --- a/node_modules/@colors/colors/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "@colors/colors", - "description": "get colors in your node.js console", - "version": "1.5.0", - "author": "DABH", - "contributors": [ - { - "name": "DABH", - "url": "https://github.com/DABH" - } - ], - "homepage": "https://github.com/DABH/colors.js", - "bugs": "https://github.com/DABH/colors.js/issues", - "keywords": [ - "ansi", - "terminal", - "colors" - ], - "repository": { - "type": "git", - "url": "http://github.com/DABH/colors.js.git" - }, - "license": "MIT", - "scripts": { - "lint": "eslint . --fix", - "test": "export FORCE_COLOR=1 && node tests/basic-test.js && node tests/safe-test.js" - }, - "engines": { - "node": ">=0.1.90" - }, - "main": "lib/index.js", - "files": [ - "examples", - "lib", - "LICENSE", - "safe.js", - "themes", - "index.d.ts", - "safe.d.ts" - ], - "devDependencies": { - "eslint": "^5.2.0", - "eslint-config-google": "^0.11.0" - } -} diff --git a/node_modules/@colors/colors/safe.js b/node_modules/@colors/colors/safe.js deleted file mode 100644 index a013d54246485..0000000000000 --- a/node_modules/@colors/colors/safe.js +++ /dev/null @@ -1,10 +0,0 @@ -// -// Remark: Requiring this file will use the "safe" colors API, -// which will not touch String.prototype. -// -// var colors = require('colors/safe'); -// colors.red("foo") -// -// -var colors = require('./lib/colors'); -module['exports'] = colors; diff --git a/node_modules/@colors/colors/themes/generic-logging.js b/node_modules/@colors/colors/themes/generic-logging.js deleted file mode 100644 index 63adfe4ac31f9..0000000000000 --- a/node_modules/@colors/colors/themes/generic-logging.js +++ /dev/null @@ -1,12 +0,0 @@ -module['exports'] = { - silly: 'rainbow', - input: 'grey', - verbose: 'cyan', - prompt: 'grey', - info: 'green', - data: 'grey', - help: 'cyan', - warn: 'yellow', - debug: 'blue', - error: 'red', -}; diff --git a/node_modules/cli-table3/LICENSE b/node_modules/cli-table3/LICENSE deleted file mode 100644 index a09b7de012ac8..0000000000000 --- a/node_modules/cli-table3/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2014 James Talmage - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/node_modules/cli-table3/index.js b/node_modules/cli-table3/index.js deleted file mode 100644 index b49d920dd3ef6..0000000000000 --- a/node_modules/cli-table3/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./src/table'); \ No newline at end of file diff --git a/node_modules/cli-table3/package.json b/node_modules/cli-table3/package.json deleted file mode 100644 index 0bd5d31d10246..0000000000000 --- a/node_modules/cli-table3/package.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "name": "cli-table3", - "version": "0.6.4", - "description": "Pretty unicode tables for the command line. Based on the original cli-table.", - "main": "index.js", - "types": "index.d.ts", - "files": [ - "src/", - "index.d.ts", - "index.js" - ], - "directories": { - "test": "test" - }, - "dependencies": { - "string-width": "^4.2.0" - }, - "devDependencies": { - "cli-table": "^0.3.1", - "eslint": "^6.0.0", - "eslint-config-prettier": "^6.0.0", - "eslint-plugin-prettier": "^3.0.0", - "jest": "^25.2.4", - "jest-runner-eslint": "^0.7.0", - "lerna-changelog": "^1.0.1", - "prettier": "2.3.2" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - }, - "scripts": { - "changelog": "lerna-changelog", - "docs": "node ./scripts/update-docs.js", - "prettier": "prettier --write '{examples,lib,scripts,src,test}/**/*.js'", - "test": "jest --color", - "test:watch": "jest --color --watchAll --notify" - }, - "repository": { - "type": "git", - "url": "https://github.com/cli-table/cli-table3.git" - }, - "keywords": [ - "node", - "command", - "line", - "cli", - "table", - "tables", - "tabular", - "unicode", - "colors", - "grid" - ], - "author": "James Talmage", - "license": "MIT", - "bugs": { - "url": "https://github.com/cli-table/cli-table3/issues" - }, - "homepage": "https://github.com/cli-table/cli-table3", - "engines": { - "node": "10.* || >= 12.*" - }, - "changelog": { - "repo": "cli-table/cli-table3", - "labels": { - "breaking": ":boom: Breaking Change", - "enhancement": ":rocket: Enhancement", - "bug": ":bug: Bug Fix", - "documentation": ":memo: Documentation", - "internal": ":house: Internal" - } - }, - "jest": { - "projects": [ - { - "displayName": "test", - "testMatch": [ - "/test/**/*.js" - ] - }, - { - "runner": "jest-runner-eslint", - "displayName": "lint", - "testMatch": [ - "/examples/**/*.js", - "/lib/**/*.js", - "/scripts/**/*.js", - "/src/**/*.js", - "/test/**/*.js" - ] - } - ] - }, - "prettier": { - "printWidth": 120, - "tabWidth": 2, - "singleQuote": true, - "trailingComma": "es5" - } -} diff --git a/node_modules/cli-table3/src/cell.js b/node_modules/cli-table3/src/cell.js deleted file mode 100644 index 8c3df35d19407..0000000000000 --- a/node_modules/cli-table3/src/cell.js +++ /dev/null @@ -1,409 +0,0 @@ -const { info, debug } = require('./debug'); -const utils = require('./utils'); - -class Cell { - /** - * A representation of a cell within the table. - * Implementations must have `init` and `draw` methods, - * as well as `colSpan`, `rowSpan`, `desiredHeight` and `desiredWidth` properties. - * @param options - * @constructor - */ - constructor(options) { - this.setOptions(options); - - /** - * Each cell will have it's `x` and `y` values set by the `layout-manager` prior to - * `init` being called; - * @type {Number} - */ - this.x = null; - this.y = null; - } - - setOptions(options) { - if (['boolean', 'number', 'string'].indexOf(typeof options) !== -1) { - options = { content: '' + options }; - } - options = options || {}; - this.options = options; - let content = options.content; - if (['boolean', 'number', 'string'].indexOf(typeof content) !== -1) { - this.content = String(content); - } else if (!content) { - this.content = this.options.href || ''; - } else { - throw new Error('Content needs to be a primitive, got: ' + typeof content); - } - this.colSpan = options.colSpan || 1; - this.rowSpan = options.rowSpan || 1; - if (this.options.href) { - Object.defineProperty(this, 'href', { - get() { - return this.options.href; - }, - }); - } - } - - mergeTableOptions(tableOptions, cells) { - this.cells = cells; - - let optionsChars = this.options.chars || {}; - let tableChars = tableOptions.chars; - let chars = (this.chars = {}); - CHAR_NAMES.forEach(function (name) { - setOption(optionsChars, tableChars, name, chars); - }); - - this.truncate = this.options.truncate || tableOptions.truncate; - - let style = (this.options.style = this.options.style || {}); - let tableStyle = tableOptions.style; - setOption(style, tableStyle, 'padding-left', this); - setOption(style, tableStyle, 'padding-right', this); - this.head = style.head || tableStyle.head; - this.border = style.border || tableStyle.border; - - this.fixedWidth = tableOptions.colWidths[this.x]; - this.lines = this.computeLines(tableOptions); - - this.desiredWidth = utils.strlen(this.content) + this.paddingLeft + this.paddingRight; - this.desiredHeight = this.lines.length; - } - - computeLines(tableOptions) { - const tableWordWrap = tableOptions.wordWrap || tableOptions.textWrap; - const { wordWrap = tableWordWrap } = this.options; - if (this.fixedWidth && wordWrap) { - this.fixedWidth -= this.paddingLeft + this.paddingRight; - if (this.colSpan) { - let i = 1; - while (i < this.colSpan) { - this.fixedWidth += tableOptions.colWidths[this.x + i]; - i++; - } - } - const { wrapOnWordBoundary: tableWrapOnWordBoundary = true } = tableOptions; - const { wrapOnWordBoundary = tableWrapOnWordBoundary } = this.options; - return this.wrapLines(utils.wordWrap(this.fixedWidth, this.content, wrapOnWordBoundary)); - } - return this.wrapLines(this.content.split('\n')); - } - - wrapLines(computedLines) { - const lines = utils.colorizeLines(computedLines); - if (this.href) { - return lines.map((line) => utils.hyperlink(this.href, line)); - } - return lines; - } - - /** - * Initializes the Cells data structure. - * - * @param tableOptions - A fully populated set of tableOptions. - * In addition to the standard default values, tableOptions must have fully populated the - * `colWidths` and `rowWidths` arrays. Those arrays must have lengths equal to the number - * of columns or rows (respectively) in this table, and each array item must be a Number. - * - */ - init(tableOptions) { - let x = this.x; - let y = this.y; - this.widths = tableOptions.colWidths.slice(x, x + this.colSpan); - this.heights = tableOptions.rowHeights.slice(y, y + this.rowSpan); - this.width = this.widths.reduce(sumPlusOne, -1); - this.height = this.heights.reduce(sumPlusOne, -1); - - this.hAlign = this.options.hAlign || tableOptions.colAligns[x]; - this.vAlign = this.options.vAlign || tableOptions.rowAligns[y]; - - this.drawRight = x + this.colSpan == tableOptions.colWidths.length; - } - - /** - * Draws the given line of the cell. - * This default implementation defers to methods `drawTop`, `drawBottom`, `drawLine` and `drawEmpty`. - * @param lineNum - can be `top`, `bottom` or a numerical line number. - * @param spanningCell - will be a number if being called from a RowSpanCell, and will represent how - * many rows below it's being called from. Otherwise it's undefined. - * @returns {String} The representation of this line. - */ - draw(lineNum, spanningCell) { - if (lineNum == 'top') return this.drawTop(this.drawRight); - if (lineNum == 'bottom') return this.drawBottom(this.drawRight); - let content = utils.truncate(this.content, 10, this.truncate); - if (!lineNum) { - info(`${this.y}-${this.x}: ${this.rowSpan - lineNum}x${this.colSpan} Cell ${content}`); - } else { - // debug(`${lineNum}-${this.x}: 1x${this.colSpan} RowSpanCell ${content}`); - } - let padLen = Math.max(this.height - this.lines.length, 0); - let padTop; - switch (this.vAlign) { - case 'center': - padTop = Math.ceil(padLen / 2); - break; - case 'bottom': - padTop = padLen; - break; - default: - padTop = 0; - } - if (lineNum < padTop || lineNum >= padTop + this.lines.length) { - return this.drawEmpty(this.drawRight, spanningCell); - } - let forceTruncation = this.lines.length > this.height && lineNum + 1 >= this.height; - return this.drawLine(lineNum - padTop, this.drawRight, forceTruncation, spanningCell); - } - - /** - * Renders the top line of the cell. - * @param drawRight - true if this method should render the right edge of the cell. - * @returns {String} - */ - drawTop(drawRight) { - let content = []; - if (this.cells) { - //TODO: cells should always exist - some tests don't fill it in though - this.widths.forEach(function (width, index) { - content.push(this._topLeftChar(index)); - content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], width)); - }, this); - } else { - content.push(this._topLeftChar(0)); - content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], this.width)); - } - if (drawRight) { - content.push(this.chars[this.y == 0 ? 'topRight' : 'rightMid']); - } - return this.wrapWithStyleColors('border', content.join('')); - } - - _topLeftChar(offset) { - let x = this.x + offset; - let leftChar; - if (this.y == 0) { - leftChar = x == 0 ? 'topLeft' : offset == 0 ? 'topMid' : 'top'; - } else { - if (x == 0) { - leftChar = 'leftMid'; - } else { - leftChar = offset == 0 ? 'midMid' : 'bottomMid'; - if (this.cells) { - //TODO: cells should always exist - some tests don't fill it in though - let spanAbove = this.cells[this.y - 1][x] instanceof Cell.ColSpanCell; - if (spanAbove) { - leftChar = offset == 0 ? 'topMid' : 'mid'; - } - if (offset == 0) { - let i = 1; - while (this.cells[this.y][x - i] instanceof Cell.ColSpanCell) { - i++; - } - if (this.cells[this.y][x - i] instanceof Cell.RowSpanCell) { - leftChar = 'leftMid'; - } - } - } - } - } - return this.chars[leftChar]; - } - - wrapWithStyleColors(styleProperty, content) { - if (this[styleProperty] && this[styleProperty].length) { - try { - let colors = require('@colors/colors/safe'); - for (let i = this[styleProperty].length - 1; i >= 0; i--) { - colors = colors[this[styleProperty][i]]; - } - return colors(content); - } catch (e) { - return content; - } - } else { - return content; - } - } - - /** - * Renders a line of text. - * @param lineNum - Which line of text to render. This is not necessarily the line within the cell. - * There may be top-padding above the first line of text. - * @param drawRight - true if this method should render the right edge of the cell. - * @param forceTruncationSymbol - `true` if the rendered text should end with the truncation symbol even - * if the text fits. This is used when the cell is vertically truncated. If `false` the text should - * only include the truncation symbol if the text will not fit horizontally within the cell width. - * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined. - * @returns {String} - */ - drawLine(lineNum, drawRight, forceTruncationSymbol, spanningCell) { - let left = this.chars[this.x == 0 ? 'left' : 'middle']; - if (this.x && spanningCell && this.cells) { - let cellLeft = this.cells[this.y + spanningCell][this.x - 1]; - while (cellLeft instanceof ColSpanCell) { - cellLeft = this.cells[cellLeft.y][cellLeft.x - 1]; - } - if (!(cellLeft instanceof RowSpanCell)) { - left = this.chars['rightMid']; - } - } - let leftPadding = utils.repeat(' ', this.paddingLeft); - let right = drawRight ? this.chars['right'] : ''; - let rightPadding = utils.repeat(' ', this.paddingRight); - let line = this.lines[lineNum]; - let len = this.width - (this.paddingLeft + this.paddingRight); - if (forceTruncationSymbol) line += this.truncate || '…'; - let content = utils.truncate(line, len, this.truncate); - content = utils.pad(content, len, ' ', this.hAlign); - content = leftPadding + content + rightPadding; - return this.stylizeLine(left, content, right); - } - - stylizeLine(left, content, right) { - left = this.wrapWithStyleColors('border', left); - right = this.wrapWithStyleColors('border', right); - if (this.y === 0) { - content = this.wrapWithStyleColors('head', content); - } - return left + content + right; - } - - /** - * Renders the bottom line of the cell. - * @param drawRight - true if this method should render the right edge of the cell. - * @returns {String} - */ - drawBottom(drawRight) { - let left = this.chars[this.x == 0 ? 'bottomLeft' : 'bottomMid']; - let content = utils.repeat(this.chars.bottom, this.width); - let right = drawRight ? this.chars['bottomRight'] : ''; - return this.wrapWithStyleColors('border', left + content + right); - } - - /** - * Renders a blank line of text within the cell. Used for top and/or bottom padding. - * @param drawRight - true if this method should render the right edge of the cell. - * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined. - * @returns {String} - */ - drawEmpty(drawRight, spanningCell) { - let left = this.chars[this.x == 0 ? 'left' : 'middle']; - if (this.x && spanningCell && this.cells) { - let cellLeft = this.cells[this.y + spanningCell][this.x - 1]; - while (cellLeft instanceof ColSpanCell) { - cellLeft = this.cells[cellLeft.y][cellLeft.x - 1]; - } - if (!(cellLeft instanceof RowSpanCell)) { - left = this.chars['rightMid']; - } - } - let right = drawRight ? this.chars['right'] : ''; - let content = utils.repeat(' ', this.width); - return this.stylizeLine(left, content, right); - } -} - -class ColSpanCell { - /** - * A Cell that doesn't do anything. It just draws empty lines. - * Used as a placeholder in column spanning. - * @constructor - */ - constructor() {} - - draw(lineNum) { - if (typeof lineNum === 'number') { - debug(`${this.y}-${this.x}: 1x1 ColSpanCell`); - } - return ''; - } - - init() {} - - mergeTableOptions() {} -} - -class RowSpanCell { - /** - * A placeholder Cell for a Cell that spans multiple rows. - * It delegates rendering to the original cell, but adds the appropriate offset. - * @param originalCell - * @constructor - */ - constructor(originalCell) { - this.originalCell = originalCell; - } - - init(tableOptions) { - let y = this.y; - let originalY = this.originalCell.y; - this.cellOffset = y - originalY; - this.offset = findDimension(tableOptions.rowHeights, originalY, this.cellOffset); - } - - draw(lineNum) { - if (lineNum == 'top') { - return this.originalCell.draw(this.offset, this.cellOffset); - } - if (lineNum == 'bottom') { - return this.originalCell.draw('bottom'); - } - debug(`${this.y}-${this.x}: 1x${this.colSpan} RowSpanCell for ${this.originalCell.content}`); - return this.originalCell.draw(this.offset + 1 + lineNum); - } - - mergeTableOptions() {} -} - -function firstDefined(...args) { - return args.filter((v) => v !== undefined && v !== null).shift(); -} - -// HELPER FUNCTIONS -function setOption(objA, objB, nameB, targetObj) { - let nameA = nameB.split('-'); - if (nameA.length > 1) { - nameA[1] = nameA[1].charAt(0).toUpperCase() + nameA[1].substr(1); - nameA = nameA.join(''); - targetObj[nameA] = firstDefined(objA[nameA], objA[nameB], objB[nameA], objB[nameB]); - } else { - targetObj[nameB] = firstDefined(objA[nameB], objB[nameB]); - } -} - -function findDimension(dimensionTable, startingIndex, span) { - let ret = dimensionTable[startingIndex]; - for (let i = 1; i < span; i++) { - ret += 1 + dimensionTable[startingIndex + i]; - } - return ret; -} - -function sumPlusOne(a, b) { - return a + b + 1; -} - -let CHAR_NAMES = [ - 'top', - 'top-mid', - 'top-left', - 'top-right', - 'bottom', - 'bottom-mid', - 'bottom-left', - 'bottom-right', - 'left', - 'left-mid', - 'mid', - 'mid-mid', - 'right', - 'right-mid', - 'middle', -]; - -module.exports = Cell; -module.exports.ColSpanCell = ColSpanCell; -module.exports.RowSpanCell = RowSpanCell; diff --git a/node_modules/cli-table3/src/debug.js b/node_modules/cli-table3/src/debug.js deleted file mode 100644 index 6acfb03032159..0000000000000 --- a/node_modules/cli-table3/src/debug.js +++ /dev/null @@ -1,28 +0,0 @@ -let messages = []; -let level = 0; - -const debug = (msg, min) => { - if (level >= min) { - messages.push(msg); - } -}; - -debug.WARN = 1; -debug.INFO = 2; -debug.DEBUG = 3; - -debug.reset = () => { - messages = []; -}; - -debug.setDebugLevel = (v) => { - level = v; -}; - -debug.warn = (msg) => debug(msg, debug.WARN); -debug.info = (msg) => debug(msg, debug.INFO); -debug.debug = (msg) => debug(msg, debug.DEBUG); - -debug.debugMessages = () => messages; - -module.exports = debug; diff --git a/node_modules/cli-table3/src/layout-manager.js b/node_modules/cli-table3/src/layout-manager.js deleted file mode 100644 index 3937452274d72..0000000000000 --- a/node_modules/cli-table3/src/layout-manager.js +++ /dev/null @@ -1,254 +0,0 @@ -const { warn, debug } = require('./debug'); -const Cell = require('./cell'); -const { ColSpanCell, RowSpanCell } = Cell; - -(function () { - function next(alloc, col) { - if (alloc[col] > 0) { - return next(alloc, col + 1); - } - return col; - } - - function layoutTable(table) { - let alloc = {}; - table.forEach(function (row, rowIndex) { - let col = 0; - row.forEach(function (cell) { - cell.y = rowIndex; - // Avoid erroneous call to next() on first row - cell.x = rowIndex ? next(alloc, col) : col; - const rowSpan = cell.rowSpan || 1; - const colSpan = cell.colSpan || 1; - if (rowSpan > 1) { - for (let cs = 0; cs < colSpan; cs++) { - alloc[cell.x + cs] = rowSpan; - } - } - col = cell.x + colSpan; - }); - Object.keys(alloc).forEach((idx) => { - alloc[idx]--; - if (alloc[idx] < 1) delete alloc[idx]; - }); - }); - } - - function maxWidth(table) { - let mw = 0; - table.forEach(function (row) { - row.forEach(function (cell) { - mw = Math.max(mw, cell.x + (cell.colSpan || 1)); - }); - }); - return mw; - } - - function maxHeight(table) { - return table.length; - } - - function cellsConflict(cell1, cell2) { - let yMin1 = cell1.y; - let yMax1 = cell1.y - 1 + (cell1.rowSpan || 1); - let yMin2 = cell2.y; - let yMax2 = cell2.y - 1 + (cell2.rowSpan || 1); - let yConflict = !(yMin1 > yMax2 || yMin2 > yMax1); - - let xMin1 = cell1.x; - let xMax1 = cell1.x - 1 + (cell1.colSpan || 1); - let xMin2 = cell2.x; - let xMax2 = cell2.x - 1 + (cell2.colSpan || 1); - let xConflict = !(xMin1 > xMax2 || xMin2 > xMax1); - - return yConflict && xConflict; - } - - function conflictExists(rows, x, y) { - let i_max = Math.min(rows.length - 1, y); - let cell = { x: x, y: y }; - for (let i = 0; i <= i_max; i++) { - let row = rows[i]; - for (let j = 0; j < row.length; j++) { - if (cellsConflict(cell, row[j])) { - return true; - } - } - } - return false; - } - - function allBlank(rows, y, xMin, xMax) { - for (let x = xMin; x < xMax; x++) { - if (conflictExists(rows, x, y)) { - return false; - } - } - return true; - } - - function addRowSpanCells(table) { - table.forEach(function (row, rowIndex) { - row.forEach(function (cell) { - for (let i = 1; i < cell.rowSpan; i++) { - let rowSpanCell = new RowSpanCell(cell); - rowSpanCell.x = cell.x; - rowSpanCell.y = cell.y + i; - rowSpanCell.colSpan = cell.colSpan; - insertCell(rowSpanCell, table[rowIndex + i]); - } - }); - }); - } - - function addColSpanCells(cellRows) { - for (let rowIndex = cellRows.length - 1; rowIndex >= 0; rowIndex--) { - let cellColumns = cellRows[rowIndex]; - for (let columnIndex = 0; columnIndex < cellColumns.length; columnIndex++) { - let cell = cellColumns[columnIndex]; - for (let k = 1; k < cell.colSpan; k++) { - let colSpanCell = new ColSpanCell(); - colSpanCell.x = cell.x + k; - colSpanCell.y = cell.y; - cellColumns.splice(columnIndex + 1, 0, colSpanCell); - } - } - } - } - - function insertCell(cell, row) { - let x = 0; - while (x < row.length && row[x].x < cell.x) { - x++; - } - row.splice(x, 0, cell); - } - - function fillInTable(table) { - let h_max = maxHeight(table); - let w_max = maxWidth(table); - debug(`Max rows: ${h_max}; Max cols: ${w_max}`); - for (let y = 0; y < h_max; y++) { - for (let x = 0; x < w_max; x++) { - if (!conflictExists(table, x, y)) { - let opts = { x: x, y: y, colSpan: 1, rowSpan: 1 }; - x++; - while (x < w_max && !conflictExists(table, x, y)) { - opts.colSpan++; - x++; - } - let y2 = y + 1; - while (y2 < h_max && allBlank(table, y2, opts.x, opts.x + opts.colSpan)) { - opts.rowSpan++; - y2++; - } - let cell = new Cell(opts); - cell.x = opts.x; - cell.y = opts.y; - warn(`Missing cell at ${cell.y}-${cell.x}.`); - insertCell(cell, table[y]); - } - } - } - } - - function generateCells(rows) { - return rows.map(function (row) { - if (!Array.isArray(row)) { - let key = Object.keys(row)[0]; - row = row[key]; - if (Array.isArray(row)) { - row = row.slice(); - row.unshift(key); - } else { - row = [key, row]; - } - } - return row.map(function (cell) { - return new Cell(cell); - }); - }); - } - - function makeTableLayout(rows) { - let cellRows = generateCells(rows); - layoutTable(cellRows); - fillInTable(cellRows); - addRowSpanCells(cellRows); - addColSpanCells(cellRows); - return cellRows; - } - - module.exports = { - makeTableLayout: makeTableLayout, - layoutTable: layoutTable, - addRowSpanCells: addRowSpanCells, - maxWidth: maxWidth, - fillInTable: fillInTable, - computeWidths: makeComputeWidths('colSpan', 'desiredWidth', 'x', 1), - computeHeights: makeComputeWidths('rowSpan', 'desiredHeight', 'y', 1), - }; -})(); - -function makeComputeWidths(colSpan, desiredWidth, x, forcedMin) { - return function (vals, table) { - let result = []; - let spanners = []; - let auto = {}; - table.forEach(function (row) { - row.forEach(function (cell) { - if ((cell[colSpan] || 1) > 1) { - spanners.push(cell); - } else { - result[cell[x]] = Math.max(result[cell[x]] || 0, cell[desiredWidth] || 0, forcedMin); - } - }); - }); - - vals.forEach(function (val, index) { - if (typeof val === 'number') { - result[index] = val; - } - }); - - //spanners.forEach(function(cell){ - for (let k = spanners.length - 1; k >= 0; k--) { - let cell = spanners[k]; - let span = cell[colSpan]; - let col = cell[x]; - let existingWidth = result[col]; - let editableCols = typeof vals[col] === 'number' ? 0 : 1; - if (typeof existingWidth === 'number') { - for (let i = 1; i < span; i++) { - existingWidth += 1 + result[col + i]; - if (typeof vals[col + i] !== 'number') { - editableCols++; - } - } - } else { - existingWidth = desiredWidth === 'desiredWidth' ? cell.desiredWidth - 1 : 1; - if (!auto[col] || auto[col] < existingWidth) { - auto[col] = existingWidth; - } - } - - if (cell[desiredWidth] > existingWidth) { - let i = 0; - while (editableCols > 0 && cell[desiredWidth] > existingWidth) { - if (typeof vals[col + i] !== 'number') { - let dif = Math.round((cell[desiredWidth] - existingWidth) / editableCols); - existingWidth += dif; - result[col + i] += dif; - editableCols--; - } - i++; - } - } - } - - Object.assign(vals, result, auto); - for (let j = 0; j < vals.length; j++) { - vals[j] = Math.max(forcedMin, vals[j] || 0); - } - }; -} diff --git a/node_modules/cli-table3/src/table.js b/node_modules/cli-table3/src/table.js deleted file mode 100644 index eb4a9bda9a364..0000000000000 --- a/node_modules/cli-table3/src/table.js +++ /dev/null @@ -1,106 +0,0 @@ -const debug = require('./debug'); -const utils = require('./utils'); -const tableLayout = require('./layout-manager'); - -class Table extends Array { - constructor(opts) { - super(); - - const options = utils.mergeOptions(opts); - Object.defineProperty(this, 'options', { - value: options, - enumerable: options.debug, - }); - - if (options.debug) { - switch (typeof options.debug) { - case 'boolean': - debug.setDebugLevel(debug.WARN); - break; - case 'number': - debug.setDebugLevel(options.debug); - break; - case 'string': - debug.setDebugLevel(parseInt(options.debug, 10)); - break; - default: - debug.setDebugLevel(debug.WARN); - debug.warn(`Debug option is expected to be boolean, number, or string. Received a ${typeof options.debug}`); - } - Object.defineProperty(this, 'messages', { - get() { - return debug.debugMessages(); - }, - }); - } - } - - toString() { - let array = this; - let headersPresent = this.options.head && this.options.head.length; - if (headersPresent) { - array = [this.options.head]; - if (this.length) { - array.push.apply(array, this); - } - } else { - this.options.style.head = []; - } - - let cells = tableLayout.makeTableLayout(array); - - cells.forEach(function (row) { - row.forEach(function (cell) { - cell.mergeTableOptions(this.options, cells); - }, this); - }, this); - - tableLayout.computeWidths(this.options.colWidths, cells); - tableLayout.computeHeights(this.options.rowHeights, cells); - - cells.forEach(function (row) { - row.forEach(function (cell) { - cell.init(this.options); - }, this); - }, this); - - let result = []; - - for (let rowIndex = 0; rowIndex < cells.length; rowIndex++) { - let row = cells[rowIndex]; - let heightOfRow = this.options.rowHeights[rowIndex]; - - if (rowIndex === 0 || !this.options.style.compact || (rowIndex == 1 && headersPresent)) { - doDraw(row, 'top', result); - } - - for (let lineNum = 0; lineNum < heightOfRow; lineNum++) { - doDraw(row, lineNum, result); - } - - if (rowIndex + 1 == cells.length) { - doDraw(row, 'bottom', result); - } - } - - return result.join('\n'); - } - - get width() { - let str = this.toString().split('\n'); - return str[0].length; - } -} - -Table.reset = () => debug.reset(); - -function doDraw(row, lineNum, result) { - let line = []; - row.forEach(function (cell) { - line.push(cell.draw(lineNum)); - }); - let str = line.join(''); - if (str.length) result.push(str); -} - -module.exports = Table; diff --git a/node_modules/cli-table3/src/utils.js b/node_modules/cli-table3/src/utils.js deleted file mode 100644 index c922c5b9adb62..0000000000000 --- a/node_modules/cli-table3/src/utils.js +++ /dev/null @@ -1,336 +0,0 @@ -const stringWidth = require('string-width'); - -function codeRegex(capture) { - return capture ? /\u001b\[((?:\d*;){0,5}\d*)m/g : /\u001b\[(?:\d*;){0,5}\d*m/g; -} - -function strlen(str) { - let code = codeRegex(); - let stripped = ('' + str).replace(code, ''); - let split = stripped.split('\n'); - return split.reduce(function (memo, s) { - return stringWidth(s) > memo ? stringWidth(s) : memo; - }, 0); -} - -function repeat(str, times) { - return Array(times + 1).join(str); -} - -function pad(str, len, pad, dir) { - let length = strlen(str); - if (len + 1 >= length) { - let padlen = len - length; - switch (dir) { - case 'right': { - str = repeat(pad, padlen) + str; - break; - } - case 'center': { - let right = Math.ceil(padlen / 2); - let left = padlen - right; - str = repeat(pad, left) + str + repeat(pad, right); - break; - } - default: { - str = str + repeat(pad, padlen); - break; - } - } - } - return str; -} - -let codeCache = {}; - -function addToCodeCache(name, on, off) { - on = '\u001b[' + on + 'm'; - off = '\u001b[' + off + 'm'; - codeCache[on] = { set: name, to: true }; - codeCache[off] = { set: name, to: false }; - codeCache[name] = { on: on, off: off }; -} - -//https://github.com/Marak/colors.js/blob/master/lib/styles.js -addToCodeCache('bold', 1, 22); -addToCodeCache('italics', 3, 23); -addToCodeCache('underline', 4, 24); -addToCodeCache('inverse', 7, 27); -addToCodeCache('strikethrough', 9, 29); - -function updateState(state, controlChars) { - let controlCode = controlChars[1] ? parseInt(controlChars[1].split(';')[0]) : 0; - if ((controlCode >= 30 && controlCode <= 39) || (controlCode >= 90 && controlCode <= 97)) { - state.lastForegroundAdded = controlChars[0]; - return; - } - if ((controlCode >= 40 && controlCode <= 49) || (controlCode >= 100 && controlCode <= 107)) { - state.lastBackgroundAdded = controlChars[0]; - return; - } - if (controlCode === 0) { - for (let i in state) { - /* istanbul ignore else */ - if (Object.prototype.hasOwnProperty.call(state, i)) { - delete state[i]; - } - } - return; - } - let info = codeCache[controlChars[0]]; - if (info) { - state[info.set] = info.to; - } -} - -function readState(line) { - let code = codeRegex(true); - let controlChars = code.exec(line); - let state = {}; - while (controlChars !== null) { - updateState(state, controlChars); - controlChars = code.exec(line); - } - return state; -} - -function unwindState(state, ret) { - let lastBackgroundAdded = state.lastBackgroundAdded; - let lastForegroundAdded = state.lastForegroundAdded; - - delete state.lastBackgroundAdded; - delete state.lastForegroundAdded; - - Object.keys(state).forEach(function (key) { - if (state[key]) { - ret += codeCache[key].off; - } - }); - - if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { - ret += '\u001b[49m'; - } - if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { - ret += '\u001b[39m'; - } - - return ret; -} - -function rewindState(state, ret) { - let lastBackgroundAdded = state.lastBackgroundAdded; - let lastForegroundAdded = state.lastForegroundAdded; - - delete state.lastBackgroundAdded; - delete state.lastForegroundAdded; - - Object.keys(state).forEach(function (key) { - if (state[key]) { - ret = codeCache[key].on + ret; - } - }); - - if (lastBackgroundAdded && lastBackgroundAdded != '\u001b[49m') { - ret = lastBackgroundAdded + ret; - } - if (lastForegroundAdded && lastForegroundAdded != '\u001b[39m') { - ret = lastForegroundAdded + ret; - } - - return ret; -} - -function truncateWidth(str, desiredLength) { - if (str.length === strlen(str)) { - return str.substr(0, desiredLength); - } - - while (strlen(str) > desiredLength) { - str = str.slice(0, -1); - } - - return str; -} - -function truncateWidthWithAnsi(str, desiredLength) { - let code = codeRegex(true); - let split = str.split(codeRegex()); - let splitIndex = 0; - let retLen = 0; - let ret = ''; - let myArray; - let state = {}; - - while (retLen < desiredLength) { - myArray = code.exec(str); - let toAdd = split[splitIndex]; - splitIndex++; - if (retLen + strlen(toAdd) > desiredLength) { - toAdd = truncateWidth(toAdd, desiredLength - retLen); - } - ret += toAdd; - retLen += strlen(toAdd); - - if (retLen < desiredLength) { - if (!myArray) { - break; - } // full-width chars may cause a whitespace which cannot be filled - ret += myArray[0]; - updateState(state, myArray); - } - } - - return unwindState(state, ret); -} - -function truncate(str, desiredLength, truncateChar) { - truncateChar = truncateChar || '…'; - let lengthOfStr = strlen(str); - if (lengthOfStr <= desiredLength) { - return str; - } - desiredLength -= strlen(truncateChar); - - let ret = truncateWidthWithAnsi(str, desiredLength); - - return ret + truncateChar; -} - -function defaultOptions() { - return { - chars: { - top: '─', - 'top-mid': '┬', - 'top-left': '┌', - 'top-right': '┐', - bottom: '─', - 'bottom-mid': '┴', - 'bottom-left': '└', - 'bottom-right': '┘', - left: '│', - 'left-mid': '├', - mid: '─', - 'mid-mid': '┼', - right: '│', - 'right-mid': '┤', - middle: '│', - }, - truncate: '…', - colWidths: [], - rowHeights: [], - colAligns: [], - rowAligns: [], - style: { - 'padding-left': 1, - 'padding-right': 1, - head: ['red'], - border: ['grey'], - compact: false, - }, - head: [], - }; -} - -function mergeOptions(options, defaults) { - options = options || {}; - defaults = defaults || defaultOptions(); - let ret = Object.assign({}, defaults, options); - ret.chars = Object.assign({}, defaults.chars, options.chars); - ret.style = Object.assign({}, defaults.style, options.style); - return ret; -} - -// Wrap on word boundary -function wordWrap(maxLength, input) { - let lines = []; - let split = input.split(/(\s+)/g); - let line = []; - let lineLength = 0; - let whitespace; - for (let i = 0; i < split.length; i += 2) { - let word = split[i]; - let newLength = lineLength + strlen(word); - if (lineLength > 0 && whitespace) { - newLength += whitespace.length; - } - if (newLength > maxLength) { - if (lineLength !== 0) { - lines.push(line.join('')); - } - line = [word]; - lineLength = strlen(word); - } else { - line.push(whitespace || '', word); - lineLength = newLength; - } - whitespace = split[i + 1]; - } - if (lineLength) { - lines.push(line.join('')); - } - return lines; -} - -// Wrap text (ignoring word boundaries) -function textWrap(maxLength, input) { - let lines = []; - let line = ''; - function pushLine(str, ws) { - if (line.length && ws) line += ws; - line += str; - while (line.length > maxLength) { - lines.push(line.slice(0, maxLength)); - line = line.slice(maxLength); - } - } - let split = input.split(/(\s+)/g); - for (let i = 0; i < split.length; i += 2) { - pushLine(split[i], i && split[i - 1]); - } - if (line.length) lines.push(line); - return lines; -} - -function multiLineWordWrap(maxLength, input, wrapOnWordBoundary = true) { - let output = []; - input = input.split('\n'); - const handler = wrapOnWordBoundary ? wordWrap : textWrap; - for (let i = 0; i < input.length; i++) { - output.push.apply(output, handler(maxLength, input[i])); - } - return output; -} - -function colorizeLines(input) { - let state = {}; - let output = []; - for (let i = 0; i < input.length; i++) { - let line = rewindState(state, input[i]); - state = readState(line); - let temp = Object.assign({}, state); - output.push(unwindState(temp, line)); - } - return output; -} - -/** - * Credit: Matheus Sampaio https://github.com/matheussampaio - */ -function hyperlink(url, text) { - const OSC = '\u001B]'; - const BEL = '\u0007'; - const SEP = ';'; - - return [OSC, '8', SEP, SEP, url || text, BEL, text, OSC, '8', SEP, SEP, BEL].join(''); -} - -module.exports = { - strlen: strlen, - repeat: repeat, - pad: pad, - truncate: truncate, - mergeOptions: mergeOptions, - wordWrap: multiLineWordWrap, - colorizeLines: colorizeLines, - hyperlink, -}; diff --git a/package-lock.json b/package-lock.json index 600177687c223..42ae49fd161d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,6 @@ "chalk", "ci-info", "cli-columns", - "cli-table3", "columnify", "fastest-levenshtein", "fs-minipass", @@ -105,7 +104,6 @@ "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", - "cli-table3": "^0.6.4", "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", @@ -176,6 +174,7 @@ "ajv": "^8.12.0", "ajv-formats": "^2.1.1", "ajv-formats-draft2019": "^1.6.1", + "cli-table3": "^0.6.4", "diff": "^5.2.0", "licensee": "^10.0.0", "nock": "^13.4.0", @@ -699,7 +698,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "inBundle": true, + "dev": true, "optional": true, "engines": { "node": ">=0.1.90" @@ -3319,7 +3318,7 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz", "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==", - "inBundle": true, + "dev": true, "dependencies": { "string-width": "^4.2.0" }, diff --git a/package.json b/package.json index ba634024edcfc..6661e394d4185 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", - "cli-table3": "^0.6.4", "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", @@ -140,7 +139,6 @@ "chalk", "ci-info", "cli-columns", - "cli-table3", "columnify", "fastest-levenshtein", "fs-minipass", @@ -207,6 +205,7 @@ "ajv": "^8.12.0", "ajv-formats": "^2.1.1", "ajv-formats-draft2019": "^1.6.1", + "cli-table3": "^0.6.4", "diff": "^5.2.0", "licensee": "^10.0.0", "nock": "^13.4.0", From c209e989b405fa3e86df7015c22e6840e18313b8 Mon Sep 17 00:00:00 2001 From: Gar Date: Tue, 16 Apr 2024 14:31:38 -0700 Subject: [PATCH 02/42] fix: Remove table output from many commands This removes table output from `hook`, `profile`, `doctor`, `org`, and `token`. It also removes table output from the `--long` or `--dry-run` output of install commands. Table output is discouraged in a cli for accessibility reasons. The tests for `token` were also rewritten because they did not actually test the behavior of npm with the registry. `this.config` was also removed from `token`. npm-registry-fetch pulls all this from flatOptions already. --- docs/lib/content/commands/npm-doctor.md | 19 +- lib/commands/doctor.js | 97 +- lib/commands/hook.js | 38 +- lib/commands/org.js | 12 +- lib/commands/profile.js | 8 +- lib/commands/token.js | 113 +- lib/utils/reify-output.js | 51 +- mock-registry/lib/index.js | 25 + .../test/lib/commands/doctor.js.test.cjs | 964 ++++++++++++------ .../test/lib/commands/profile.js.test.cjs | 13 - tap-snapshots/test/lib/docs.js.test.cjs | 4 +- .../test/lib/utils/reify-output.js.test.cjs | 14 +- test/lib/commands/hook.js | 38 +- test/lib/commands/login.js | 6 +- test/lib/commands/org.js | 20 +- test/lib/commands/profile.js | 17 - test/lib/commands/token.js | 675 +++++------- 17 files changed, 1118 insertions(+), 996 deletions(-) diff --git a/docs/lib/content/commands/npm-doctor.md b/docs/lib/content/commands/npm-doctor.md index d43164eb3a5d3..b5c8126b272c0 100644 --- a/docs/lib/content/commands/npm-doctor.md +++ b/docs/lib/content/commands/npm-doctor.md @@ -34,20 +34,21 @@ there are any recommended changes, it will display them. By default npm runs all of these checks. You can limit what checks are ran by specifying them as extra arguments. -#### `npm ping` +#### `Connecting to the registry` By default, npm installs from the primary npm registry, -`registry.npmjs.org`. `npm doctor` hits a special ping endpoint within the -registry. This can also be checked with `npm ping`. If this check fails, -you may be using a proxy that needs to be configured, or may need to talk -to your IT staff to get access over HTTPS to `registry.npmjs.org`. +`registry.npmjs.org`. `npm doctor` hits a special connection testing +endpoint within the registry. This can also be checked with `npm ping`. +If this check fails, you may be using a proxy that needs to be +configured, or may need to talk to your IT staff to get access over +HTTPS to `registry.npmjs.org`. This check is done against whichever registry you've configured (you can see what that is by running `npm config get registry`), and if you're using a private registry that doesn't support the `/whoami` endpoint supported by the primary registry, this check may fail. -#### `npm -v` +#### `Checking npm version` While Node.js may come bundled with a particular version of npm, it's the policy of the CLI team that we recommend all users run `npm@latest` if they @@ -57,7 +58,7 @@ support releases typically only receive critical security and regression fixes. The team believes that the latest tested version of npm is almost always likely to be the most functional and defect-free version of npm. -#### `node -v` +#### `Checking node version` For most users, in most circumstances, the best version of Node will be the latest long-term support (LTS) release. Those of you who want access to new @@ -66,7 +67,7 @@ be running a newer version, and some may be required to run an older version of Node because of enterprise change control policies. That's OK! But in general, the npm team recommends that most users run Node.js LTS. -#### `npm config get registry` +#### `Checking configured npm registry` You may be installing from private package registries for your project or company. That's great! Others may be following tutorials or StackOverflow @@ -75,7 +76,7 @@ Sometimes, this may entail changing the registry you're pointing at. This part of `npm doctor` just lets you, and maybe whoever's helping you with support, know that you're not using the default registry. -#### `which git` +#### `Checking for git executable in PATH` While it's documented in the README, it may not be obvious that npm needs Git installed to do many of the things that it does. Also, in some cases diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index f74fe2ecbcc7e..3048a123d6eb1 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -1,7 +1,6 @@ const cacache = require('cacache') const fs = require('fs') const fetch = require('make-fetch-happen') -const Table = require('cli-table3') const which = require('which') const pacote = require('pacote') const { resolve } = require('path') @@ -34,57 +33,59 @@ const maskLabel = mask => { const subcommands = [ { - groups: ['ping', 'registry'], - title: 'npm ping', + // Ping is left in as a legacy command but is listed as "connection" to + // make more sense to more people + groups: ['connection', 'ping', 'registry'], + title: 'Connecting to the registry', cmd: 'checkPing', }, { groups: ['versions'], - title: 'npm -v', + title: 'Checking npm version', cmd: 'getLatestNpmVersion', }, { groups: ['versions'], - title: 'node -v', + title: 'Checking node version', cmd: 'getLatestNodejsVersion', }, { groups: ['registry'], - title: 'npm config get registry', + title: 'Checking configured npm registry', cmd: 'checkNpmRegistry', }, { groups: ['environment'], - title: 'git executable in PATH', + title: 'Checking for git executable in PATH', cmd: 'getGitPath', }, { groups: ['environment'], - title: 'global bin folder in PATH', + title: 'Checking for global bin folder in PATH', cmd: 'getBinPath', }, { groups: ['permissions', 'cache'], - title: 'Perms check on cached files', + title: 'Checking permissions on cached files (this may take awhile)', cmd: 'checkCachePermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on local node_modules', + title: 'Checking permissions on local node_modules (this may take awhile)', cmd: 'checkLocalModulesPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on global node_modules', + title: 'Checking permissions on global node_modules (this may take awhile)', cmd: 'checkGlobalModulesPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on local bin folder', + title: 'Checking permissions on local bin folder', cmd: 'checkLocalBinPermission', windows: false, }, { groups: ['permissions'], - title: 'Perms check on global bin folder', + title: 'Checking permissions on global bin folder', cmd: 'checkGlobalBinPermission', windows: false, }, { groups: ['cache'], - title: 'Verify cache contents', + title: 'Verifying cache contents (this may take awhile)', cmd: 'verifyCachedFiles', windows: false, }, @@ -104,43 +105,28 @@ class Doctor extends BaseCommand { static params = ['registry'] static ignoreImplicitWorkspace = false static usage = [`[${subcommands.flatMap(s => s.groups) - .filter((value, index, self) => self.indexOf(value) === index) + .filter((value, index, self) => self.indexOf(value) === index && value !== 'ping') .join('] [')}]`] static subcommands = subcommands - // minimum width of check column, enough for the word `Check` - #checkWidth = 5 - async exec (args) { log.info('doctor', 'Running checkup') let allOk = true const actions = this.actions(args) - this.#checkWidth = actions.reduce((length, item) => - Math.max(item.title.length, length), this.#checkWidth) - if (!this.npm.silent) { - this.output(['Check', 'Value', 'Recommendation/Notes'].map(h => this.npm.chalk.underline(h))) - } - // Do the actual work + const chalk = this.npm.chalk for (const { title, cmd } of actions) { - const item = [title] + this.output(title) + // TODO when we have an in progress indicator that could go here + let result try { - item.push(true, await this[cmd]()) + result = await this[cmd]() + this.output(`${chalk.green('Ok')}${result ? `\n${result}` : ''}\n`) } catch (err) { - item.push(false, err) - } - if (!item[1]) { allOk = false - item[0] = this.npm.chalk.red(item[0]) - item[1] = this.npm.chalk.red('not ok') - item[2] = this.npm.chalk.cyan(String(item[2])) - } else { - item[1] = this.npm.chalk.green('ok') - } - if (!this.npm.silent) { - this.output(item) + this.output(`${chalk.red('Not ok')}\n${chalk.cyan(err)}\n`) } } @@ -343,38 +329,11 @@ class Doctor extends BaseCommand { } } - output (row) { - const t = new Table({ - chars: { - top: '', - 'top-mid': '', - 'top-left': '', - 'top-right': '', - bottom: '', - 'bottom-mid': '', - 'bottom-left': '', - 'bottom-right': '', - left: '', - 'left-mid': '', - mid: '', - 'mid-mid': '', - right: '', - 'right-mid': '', - middle: ' ', - }, - style: { - 'padding-left': 0, - 'padding-right': 0, - // setting border here is not necessary visually since we've already - // zeroed out all the chars above, but without it cli-table3 will wrap - // some of the separator spaces with ansi codes which show up in - // snapshots. - border: 0, - }, - colWidths: [this.#checkWidth, 6], - }) - t.push(row) - output.standard(t.toString()) + output (...args) { + // TODO display layer should do this + if (!this.npm.silent) { + output.standard(...args) + } } actions (params) { diff --git a/lib/commands/hook.js b/lib/commands/hook.js index 5e6b593cccfd6..7ec95e079d660 100644 --- a/lib/commands/hook.js +++ b/lib/commands/hook.js @@ -1,7 +1,6 @@ const hookApi = require('libnpmhook') const otplease = require('../utils/otplease.js') const relativeDate = require('tiny-relative-date') -const Table = require('cli-table3') const { output } = require('proc-log') const BaseCommand = require('../base-command.js') @@ -52,6 +51,7 @@ class Hook extends BaseCommand { async ls (pkg, opts) { const hooks = await hookApi.ls({ ...opts, package: pkg }) + if (opts.json) { output.standard(JSON.stringify(hooks, null, 2)) } else if (opts.parseable) { @@ -62,32 +62,18 @@ class Hook extends BaseCommand { } else if (!hooks.length) { output.standard("You don't have any hooks configured yet.") } else if (!this.npm.silent) { - if (hooks.length === 1) { - output.standard('You have one hook configured.') - } else { - output.standard(`You have ${hooks.length} hooks configured.`) - } + output.standard(`You have ${hooks.length} hook${hooks.length !== 1 ? 's' : ''} configured.`) - const table = new Table({ head: ['id', 'target', 'endpoint'] }) - hooks.forEach((hook) => { - table.push([ - { rowSpan: 2, content: hook.id }, - this.hookName(hook), - hook.endpoint, - ]) + for (const hook of hooks) { + output.standard(`Hook ${hook.id}: ${this.hookName(hook)}`) + output.standard(`Endpoint: ${hook.endpoint}`) if (hook.last_delivery) { - table.push([ - { - colSpan: 1, - content: `triggered ${relativeDate(hook.last_delivery)}`, - }, - hook.response_code, - ]) + /* eslint-disable-next-line max-len */ + output.standard(`Triggered ${relativeDate(hook.last_delivery)}, response code was "${hook.response_code}"\n`) } else { - table.push([{ colSpan: 2, content: 'never triggered' }]) + output.standard('Never triggered\n') } - }) - output.standard(table.toString()) + } } } @@ -116,11 +102,7 @@ class Hook extends BaseCommand { } hookName (hook) { - let target = hook.name - if (hook.type === 'owner') { - target = '~' + target - } - return target + return `${hook.type === 'owner' ? '~' : ''}${hook.name}` } } module.exports = Hook diff --git a/lib/commands/org.js b/lib/commands/org.js index 8881ded70f638..f1e5b0e09c62c 100644 --- a/lib/commands/org.js +++ b/lib/commands/org.js @@ -1,6 +1,5 @@ const liborg = require('libnpmorg') const otplease = require('../utils/otplease.js') -const Table = require('cli-table3') const BaseCommand = require('../base-command.js') const { output } = require('proc-log') @@ -143,13 +142,10 @@ class Org extends BaseCommand { output.standard([u, roster[u]].join('\t')) }) } else if (!this.npm.silent) { - const table = new Table({ head: ['user', 'role'] }) - Object.keys(roster) - .sort() - .forEach(u => { - table.push([u, roster[u]]) - }) - output.standard(table.toString()) + const chalk = this.npm.chalk + for (const u of Object.keys(roster).sort()) { + output.standard(`${u} - ${chalk.cyan(roster[u])}`) + } } } } diff --git a/lib/commands/profile.js b/lib/commands/profile.js index 98a8dcd050ee9..8bb19e69fd484 100644 --- a/lib/commands/profile.js +++ b/lib/commands/profile.js @@ -3,7 +3,6 @@ const { URL } = require('url') const { log, output } = require('proc-log') const npmProfile = require('npm-profile') const qrcodeTerminal = require('qrcode-terminal') -const Table = require('cli-table3') const otplease = require('../utils/otplease.js') const readUserInfo = require('../utils/read-user-info.js') @@ -153,12 +152,9 @@ class Profile extends BaseCommand { } } } else { - const table = new Table() - for (const key of Object.keys(cleaned)) { - table.push({ [this.npm.chalk.bold(key)]: cleaned[key] }) + for (const [key, value] of Object.entries(cleaned)) { + output.standard(`${key}: ${value}`) } - - output.standard(table.toString()) } } } diff --git a/lib/commands/token.js b/lib/commands/token.js index 991112d1bc1ba..70ff0a332b18a 100644 --- a/lib/commands/token.js +++ b/lib/commands/token.js @@ -1,4 +1,3 @@ -const Table = require('cli-table3') const { log, output } = require('proc-log') const profile = require('npm-profile') @@ -34,10 +33,10 @@ class Token extends BaseCommand { case 'list': case 'ls': return this.list() + case 'rm': case 'delete': case 'revoke': case 'remove': - case 'rm': return this.rm(args.slice(1)) case 'create': return this.create(args.slice(1)) @@ -47,13 +46,15 @@ class Token extends BaseCommand { } async list () { - const conf = this.config() + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') log.info('token', 'getting list') - const tokens = await profile.listTokens(conf) - if (conf.json) { + const tokens = await profile.listTokens(this.npm.flatOptions) + if (json) { output.standard(JSON.stringify(tokens, null, 2)) return - } else if (conf.parseable) { + } + if (parseable) { output.standard(['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t')) tokens.forEach(token => { output.standard( @@ -69,21 +70,17 @@ class Token extends BaseCommand { return } this.generateTokenIds(tokens, 6) - const idWidth = tokens.reduce((acc, token) => Math.max(acc, token.id.length), 0) - const table = new Table({ - head: ['id', 'token', 'created', 'readonly', 'CIDR whitelist'], - colWidths: [Math.max(idWidth, 2) + 2, 9, 12, 10], - }) - tokens.forEach(token => { - table.push([ - token.id, - token.token + '…', - String(token.created).slice(0, 10), - token.readonly ? 'yes' : 'no', - token.cidr_whitelist ? token.cidr_whitelist.join(', ') : '', - ]) - }) - output.standard(table.toString()) + const chalk = this.npm.chalk + for (const token of tokens) { + const level = token.readonly ? 'Read only token' : 'Publish token' + const created = String(token.created).slice(0, 10) + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.blue(level)} ${token.token}… with id ${chalk.cyan(token.id)} created ${created}`) + if (token.cidr_whitelist) { + output.standard(`with IP whitelist: ${chalk.green(token.cidr_whitelist.join(','))}`) + } + output.standard() + } } async rm (args) { @@ -91,10 +88,12 @@ class Token extends BaseCommand { throw this.usageError('`` argument is required.') } - const conf = this.config() + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') const toRemove = [] + const opts = { ...this.npm.flatOptions } log.info('token', `removing ${toRemove.length} tokens`) - const tokens = await profile.listTokens(conf) + const tokens = await profile.listTokens(opts) args.forEach(id => { const matches = tokens.filter(token => token.key.indexOf(id) === 0) if (matches.length === 1) { @@ -115,12 +114,12 @@ class Token extends BaseCommand { }) await Promise.all( toRemove.map(key => { - return otplease(this.npm, conf, c => profile.removeToken(key, c)) + return otplease(this.npm, opts, c => profile.removeToken(key, c)) }) ) - if (conf.json) { + if (json) { output.standard(JSON.stringify(toRemove)) - } else if (conf.parseable) { + } else if (parseable) { output.standard(toRemove.join('\t')) } else { output.standard('Removed ' + toRemove.length + ' token' + (toRemove.length !== 1 ? 's' : '')) @@ -128,61 +127,34 @@ class Token extends BaseCommand { } async create (args) { - const conf = this.config() - const cidr = conf.cidr - const readonly = conf.readOnly + const json = this.npm.config.get('json') + const parseable = this.npm.config.get('parseable') + const cidr = this.npm.config.get('cidr') + const readonly = this.npm.config.get('read-only') - const password = await readUserInfo.password() const validCIDR = await this.validateCIDRList(cidr) + const password = await readUserInfo.password() log.info('token', 'creating') const result = await otplease( this.npm, - conf, + { ...this.npm.flatOptions }, c => profile.createToken(password, readonly, validCIDR, c) ) delete result.key delete result.updated - if (conf.json) { + if (json) { output.standard(JSON.stringify(result)) - } else if (conf.parseable) { + } else if (parseable) { Object.keys(result).forEach(k => output.standard(k + '\t' + result[k])) } else { - const table = new Table() - for (const k of Object.keys(result)) { - table.push({ [this.npm.chalk.bold(k)]: String(result[k]) }) - } - output.standard(table.toString()) - } - } - - config () { - const conf = { ...this.npm.flatOptions } - const creds = this.npm.config.getCredentialsByURI(conf.registry) - if (creds.token) { - conf.auth = { token: creds.token } - } else if (creds.username) { - conf.auth = { - basic: { - username: creds.username, - password: creds.password, - }, + const chalk = this.npm.chalk + // Identical to list + const level = result.readonly ? 'read only' : 'publish' + output.standard(`Created ${chalk.blue(level)} token ${result.token}`) + if (result.cidr_whitelist?.length) { + output.standard(`with IP whitelist: ${chalk.green(result.cidr_whitelist.join(','))}`) } - } else if (creds.auth) { - const auth = Buffer.from(creds.auth, 'base64').toString().split(':', 2) - conf.auth = { - basic: { - username: auth[0], - password: auth[1], - }, - } - } else { - conf.auth = {} - } - - if (conf.otp) { - conf.auth.otp = conf.otp } - return conf } invalidCIDRError (msg) { @@ -190,7 +162,6 @@ class Token extends BaseCommand { } generateTokenIds (tokens, minLength) { - const byId = {} for (const token of tokens) { token.id = token.key for (let ii = minLength; ii < token.key.length; ++ii) { @@ -202,9 +173,7 @@ class Token extends BaseCommand { break } } - byId[token.id] = token } - return byId } async validateCIDRList (cidrs) { @@ -214,12 +183,12 @@ class Token extends BaseCommand { for (const cidr of list) { if (isCidrV6(cidr)) { throw this.invalidCIDRError( - 'CIDR whitelist can only contain IPv4 addresses, ' + cidr + ' is IPv6' + `CIDR whitelist can only contain IPv4 addresses${cidr} is IPv6` ) } if (!isCidrV4(cidr)) { - throw this.invalidCIDRError('CIDR whitelist contains invalid CIDR entry: ' + cidr) + throw this.invalidCIDRError(`CIDR whitelist contains invalid CIDR entry: ${cidr}`) } } return list diff --git a/lib/utils/reify-output.js b/lib/utils/reify-output.js index 40f1722f246e9..a858a546c4010 100644 --- a/lib/utils/reify-output.js +++ b/lib/utils/reify-output.js @@ -15,7 +15,6 @@ const ms = require('ms') const npmAuditReport = require('npm-audit-report') const { readTree: getFundingInfo } = require('libnpmfund') const auditError = require('./audit-error.js') -const Table = require('cli-table3') // TODO: output JSON if flatOptions.json is true const reifyOutput = (npm, arb) => { @@ -42,51 +41,31 @@ const reifyOutput = (npm, arb) => { } if (diff) { - let diffTable - if (npm.config.get('dry-run') || npm.config.get('long')) { - diffTable = new Table({ - chars: { - top: '', - 'top-mid': '', - 'top-left': '', - 'top-right': '', - bottom: '', - 'bottom-mid': '', - 'bottom-left': '', - 'bottom-right': '', - left: '', - 'left-mid': '', - mid: '', - 'mid-mid': '', - right: '', - 'right-mid': '', - middle: ' ', - }, - style: { - 'padding-left': 0, - 'padding-right': 0, - border: 0, - }, - }) - } + const showDiff = npm.config.get('dry-run') || npm.config.get('long') + const chalk = npm.chalk depth({ tree: diff, visit: d => { switch (d.action) { case 'REMOVE': - diffTable?.push(['remove', d.actual.name, d.actual.package.version]) + if (showDiff) { + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.blue('remove')} ${d.actual.name} ${d.actual.package.version}`) + } summary.removed++ break case 'ADD': - diffTable?.push(['add', d.ideal.name, d.ideal.package.version]) + if (showDiff) { + output.standard(`${chalk.green('add')} ${d.ideal.name} ${d.ideal.package.version}`) + } actualTree.inventory.has(d.ideal) && summary.added++ break case 'CHANGE': - diffTable?.push(['change', - d.actual.name, - d.actual.package.version + ' -> ' + d.ideal.package.version, - ]) + if (showDiff) { + /* eslint-disable-next-line max-len */ + output.standard(`${chalk.cyan('change')} ${d.actual.name} ${d.actual.package.version} => ${d.ideal.package.version}`) + } summary.changed++ break default: @@ -97,10 +76,6 @@ const reifyOutput = (npm, arb) => { }, getChildren: d => d.children, }) - - if (diffTable) { - output.standard('\n' + diffTable.toString()) - } } if (npm.flatOptions.fund) { diff --git a/mock-registry/lib/index.js b/mock-registry/lib/index.js index 8664ac56fbefb..d98cb055a1713 100644 --- a/mock-registry/lib/index.js +++ b/mock-registry/lib/index.js @@ -334,6 +334,31 @@ class MockRegistry { this.nock = nock } + getTokens (tokens) { + return this.nock.get('/-/npm/v1/tokens') + .reply(200, { + objects: tokens, + urls: {}, + total: tokens.length, + userHasOldFormatToken: false, + }) + } + + createToken ({ password, readonly = false, cidr = [] }) { + return this.nock.post('/-/npm/v1/tokens', { + password, + readonly, + cidr_whitelist: cidr, + }).reply(200, { + key: 'n3wk3y', + token: 'n3wt0k3n', + created: new Date(), + updated: new Date(), + readonly, + cidr_whitelist: cidr, + }) + } + async package ({ manifest, times = 1, query, tarballs }) { let nock = this.nock const spec = npa(manifest.name) diff --git a/tap-snapshots/test/lib/commands/doctor.js.test.cjs b/tap-snapshots/test/lib/commands/doctor.js.test.cjs index ded43c37a693f..985d76e5d12a5 100644 --- a/tap-snapshots/test/lib/commands/doctor.js.test.cjs +++ b/tap-snapshots/test/lib/commands/doctor.js.test.cjs @@ -30,35 +30,69 @@ Object { ` exports[`test/lib/commands/doctor.js TAP all clear > output 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP all clear in color > everything is ok in color 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP all clear in color > logs 1`] = ` @@ -110,35 +144,70 @@ Object { ` exports[`test/lib/commands/doctor.js TAP bad proxy > output 1`] = ` -Check Value Recommendation/Notes -npm ping not ok Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` -npm -v not ok Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` -node -v not ok Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` +Checking npm version +Not ok +Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` +Checking node version +Not ok +Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\` +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache badContent > corrupted cache content 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 2 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 2 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache badContent > logs 1`] = ` @@ -196,35 +265,69 @@ Object { ` exports[`test/lib/commands/doctor.js TAP cacache missingContent > missing content 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 2 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 2 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache reclaimedCount > content garbage collected 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 2 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 2 tarballs ` exports[`test/lib/commands/doctor.js TAP cacache reclaimedCount > logs 1`] = ` @@ -274,9 +377,11 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks cache > output 1`] = ` -Check Value Recommendation/Notes -Perms check on cached files ok -Verify cache contents ok verified 0 tarballs +Checking permissions on cached files (this may take awhile) +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP discrete checks git > logs 1`] = ` @@ -290,7 +395,7 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks git > output 1`] = ` -Check Value Recommendation/Notes + ` exports[`test/lib/commands/doctor.js TAP discrete checks invalid environment > logs 1`] = ` @@ -306,9 +411,12 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks invalid environment > output 1`] = ` -Check Value Recommendation/Notes -git executable in PATH ok /path/to/git -global bin folder in PATH not ok Error: Add {CWD}/global/bin to your $PATH +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Not ok +Error: Add {CWD}/global/bin to your $PATH ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - not windows > logs 1`] = ` @@ -322,12 +430,16 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - not windows > output 1`] = ` -Check Value Recommendation/Notes -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - windows > logs 1`] = ` @@ -341,7 +453,7 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks permissions - windows > output 1`] = ` -Check Value Recommendation/Notes + ` exports[`test/lib/commands/doctor.js TAP discrete checks ping > logs 1`] = ` @@ -356,8 +468,8 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks ping > output 1`] = ` -Check Value Recommendation/Notes -npm ping ok +Connecting to the registry +Ok ` exports[`test/lib/commands/doctor.js TAP discrete checks registry > logs 1`] = ` @@ -372,9 +484,11 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks registry > output 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm config get registry ok using default registry (https://registry.npmjs.org/) +Connecting to the registry +Ok +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) ` exports[`test/lib/commands/doctor.js TAP discrete checks versions > logs 1`] = ` @@ -390,9 +504,12 @@ Object { ` exports[`test/lib/commands/doctor.js TAP discrete checks versions > output 1`] = ` -Check Value Recommendation/Notes -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 ` exports[`test/lib/commands/doctor.js TAP error reading directory > logs 1`] = ` @@ -426,35 +543,75 @@ Object { ` exports[`test/lib/commands/doctor.js TAP error reading directory > readdir error 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files not ok Check the permissions of files in {CWD}/cache (should be owned by current user) -Perms check on local node_modules not ok Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) -Perms check on global node_modules not ok Check the permissions of files in {CWD}/global/node_modules -Perms check on local bin folder not ok Check the permissions of files in {CWD}/prefix/node_modules/.bin -Perms check on global bin folder not ok Check the permissions of files in {CWD}/global/bin -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Not ok +Check the permissions of files in {CWD}/cache (should be owned by current user) +Checking permissions on local node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) +Checking permissions on global node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/global/node_modules +Checking permissions on local bin folder +Not ok +Check the permissions of files in {CWD}/prefix/node_modules/.bin +Checking permissions on global bin folder +Not ok +Check the permissions of files in {CWD}/global/bin +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP incorrect owner > incorrect owner 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files not ok Check the permissions of files in {CWD}/cache (should be owned by current user) -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Not ok +Check the permissions of files in {CWD}/cache (should be owned by current user) +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP incorrect owner > logs 1`] = ` @@ -484,19 +641,41 @@ Object { ` exports[`test/lib/commands/doctor.js TAP incorrect permissions > incorrect owner 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files not ok Check the permissions of files in {CWD}/cache (should be owned by current user) -Perms check on local node_modules not ok Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) -Perms check on global node_modules not ok Check the permissions of files in {CWD}/global/node_modules -Perms check on local bin folder not ok Check the permissions of files in {CWD}/prefix/node_modules/.bin -Perms check on global bin folder not ok Check the permissions of files in {CWD}/global/bin -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Not ok +Check the permissions of files in {CWD}/cache (should be owned by current user) +Checking permissions on local node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/prefix/node_modules (should be owned by current user) +Checking permissions on global node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/global/node_modules +Checking permissions on local bin folder +Not ok +Check the permissions of files in {CWD}/prefix/node_modules/.bin +Checking permissions on global bin folder +Not ok +Check the permissions of files in {CWD}/global/bin +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP incorrect permissions > logs 1`] = ` @@ -553,8 +732,8 @@ Object { String( doctor getGitPath Error: test error doctor at which ({CWD}/{TESTDIR}/doctor.js:313:15) - doctor at Doctor.getGitPath ({CWD}/lib/commands/doctor.js:300:18) - doctor at Doctor.exec ({CWD}/lib/commands/doctor.js:130:40) + doctor at Doctor.getGitPath ({CWD}/lib/commands/doctor.js:286:18) + doctor at Doctor.exec ({CWD}/lib/commands/doctor.js:125:33) doctor at processTicksAndRejections (node:internal/process/task_queues:95:5) doctor at MockNpm.exec ({CWD}/test/fixtures/mock-npm.js:80:26) ), @@ -563,19 +742,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP missing git > missing git 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH not ok Error: Install git and ensure it's in your PATH. -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Not ok +Error: Install git and ensure it's in your PATH. +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP missing global directories > logs 1`] = ` @@ -606,19 +802,38 @@ Object { ` exports[`test/lib/commands/doctor.js TAP missing global directories > missing global directories 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules not ok Check the permissions of files in {CWD}/global/node_modules -Perms check on local bin folder ok -Perms check on global bin folder not ok Check the permissions of files in {CWD}/global/bin -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Not ok +Check the permissions of files in {CWD}/global/node_modules +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Not ok +Check the permissions of files in {CWD}/global/bin +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP missing local node_modules > logs 1`] = ` @@ -646,19 +861,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP missing local node_modules > missing local node_modules 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP node out of date - current > logs 1`] = ` @@ -686,19 +918,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP node out of date - current > node is out of date 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v not ok Use node v2.0.1 (current: v2.0.0) -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Not ok +Use node v2.0.1 (current: v2.0.0) +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP node out of date - lts > logs 1`] = ` @@ -726,19 +975,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP node out of date - lts > node is out of date 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v not ok Use node v1.0.0 (current: v0.0.1) -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Not ok +Use node v1.0.0 (current: v0.0.1) +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP non-default registry > logs 1`] = ` @@ -766,19 +1032,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP non-default registry > non default registry 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry not ok Try \`npm config set registry=https://registry.npmjs.org/\` -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Not ok +Try \`npm config set registry=https://registry.npmjs.org/\` +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP npm out of date > logs 1`] = ` @@ -806,19 +1089,36 @@ Object { ` exports[`test/lib/commands/doctor.js TAP npm out of date > npm is out of date 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v not ok Use npm v2.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Ok +Checking npm version +Not ok +Use npm v2.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping 404 > logs 1`] = ` @@ -846,19 +1146,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping 404 > ping 404 1`] = ` -Check Value Recommendation/Notes -npm ping not ok 404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping 404 in color > logs 1`] = ` @@ -886,19 +1204,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping 404 in color > ping 404 in color 1`] = ` -Check Value Recommendation/Notes -npm ping not ok 404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +404 404 Not Found - GET https://registry.npmjs.org/-/ping?write=true +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping exception with code > logs 1`] = ` @@ -926,19 +1262,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping exception with code > ping failure 1`] = ` -Check Value Recommendation/Notes -npm ping not ok request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP ping exception without code > logs 1`] = ` @@ -966,19 +1320,37 @@ Object { ` exports[`test/lib/commands/doctor.js TAP ping exception without code > ping failure 1`] = ` -Check Value Recommendation/Notes -npm ping not ok request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global/bin -Perms check on cached files ok -Perms check on local node_modules ok -Perms check on global node_modules ok -Perms check on local bin folder ok -Perms check on global bin folder ok -Verify cache contents ok verified 0 tarballs +Connecting to the registry +Not ok +request to https://registry.npmjs.org/-/ping?write=true failed, reason: Test Error +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global/bin +Checking permissions on cached files (this may take awhile) +Ok +Checking permissions on local node_modules (this may take awhile) +Ok +Checking permissions on global node_modules (this may take awhile) +Ok +Checking permissions on local bin folder +Ok +Checking permissions on global bin folder +Ok +Verifying cache contents (this may take awhile) +Ok +verified 0 tarballs ` exports[`test/lib/commands/doctor.js TAP silent errors > logs 1`] = ` @@ -1021,11 +1393,21 @@ Object { ` exports[`test/lib/commands/doctor.js TAP windows skips permissions checks > no permissions checks 1`] = ` -Check Value Recommendation/Notes -npm ping ok -npm -v ok current: v1.0.0, latest: v1.0.0 -node -v ok current: v1.0.0, recommended: v1.0.0 -npm config get registry ok using default registry (https://registry.npmjs.org/) -git executable in PATH ok /path/to/git -global bin folder in PATH ok {CWD}/global +Connecting to the registry +Ok +Checking npm version +Ok +current: v1.0.0, latest: v1.0.0 +Checking node version +Ok +current: v1.0.0, recommended: v1.0.0 +Checking configured npm registry +Ok +using default registry (https://registry.npmjs.org/) +Checking for git executable in PATH +Ok +/path/to/git +Checking for global bin folder in PATH +Ok +{CWD}/global ` diff --git a/tap-snapshots/test/lib/commands/profile.js.test.cjs b/tap-snapshots/test/lib/commands/profile.js.test.cjs index 4530dbf95cec2..1fbb09de29f3c 100644 --- a/tap-snapshots/test/lib/commands/profile.js.test.cjs +++ b/tap-snapshots/test/lib/commands/profile.js.test.cjs @@ -31,19 +31,6 @@ exports[`test/lib/commands/profile.js TAP profile get multiple args default outp foo foo@github.com (verified) https://github.com/npm ` -exports[`test/lib/commands/profile.js TAP profile get no args --color > should output all profile info with color result 1`] = ` -name: foo -email: foo@github.com (verified) -two-factor auth: auth-and-writes -fullname: Foo Bar -homepage: https://github.com -freenode: foobar -twitter: https://twitter.com/npmjs -github: https://github.com/npm -created: 2015-02-26T01:26:37.384Z -updated: 2020-08-12T16:19:35.326Z -` - exports[`test/lib/commands/profile.js TAP profile get no args --parseable > should output all profile info as parseable result 1`] = ` tfa auth-and-writes name foo diff --git a/tap-snapshots/test/lib/docs.js.test.cjs b/tap-snapshots/test/lib/docs.js.test.cjs index ad20cfa5069e0..671e614851074 100644 --- a/tap-snapshots/test/lib/docs.js.test.cjs +++ b/tap-snapshots/test/lib/docs.js.test.cjs @@ -2958,7 +2958,7 @@ exports[`test/lib/docs.js TAP usage doctor > must match snapshot 1`] = ` Check the health of your npm environment Usage: -npm doctor [ping] [registry] [versions] [environment] [permissions] [cache] +npm doctor [connection] [registry] [versions] [environment] [permissions] [cache] Options: [--registry ] @@ -2966,7 +2966,7 @@ Options: Run "npm help doctor" for more info \`\`\`bash -npm doctor [ping] [registry] [versions] [environment] [permissions] [cache] +npm doctor [connection] [registry] [versions] [environment] [permissions] [cache] \`\`\` Note: This command is unaware of workspaces. diff --git a/tap-snapshots/test/lib/utils/reify-output.js.test.cjs b/tap-snapshots/test/lib/utils/reify-output.js.test.cjs index 5983ac224e26e..d653d4c1fadc0 100644 --- a/tap-snapshots/test/lib/utils/reify-output.js.test.cjs +++ b/tap-snapshots/test/lib/utils/reify-output.js.test.cjs @@ -1634,19 +1634,17 @@ exports[`test/lib/utils/reify-output.js TAP packages changed message > {"added" ` exports[`test/lib/utils/reify-output.js TAP prints dedupe difference on dry-run > diff table 1`] = ` - -change bar 1.0.0 -> 2.1.0 -remove bar 1.0.0 -add foo 1.0.0 +change bar 1.0.0 => 2.1.0 +remove bar 1.0.0 +add foo 1.0.0 removed 1 package, and changed 1 package in {TIME} ` exports[`test/lib/utils/reify-output.js TAP prints dedupe difference on long > diff table 1`] = ` - -change bar 1.0.0 -> 2.1.0 -remove bar 1.0.0 -add foo 1.0.0 +change bar 1.0.0 => 2.1.0 +remove bar 1.0.0 +add foo 1.0.0 removed 1 package, and changed 1 package in {TIME} ` diff --git a/test/lib/commands/hook.js b/test/lib/commands/hook.js index a93b0c99f5267..003dae647a35a 100644 --- a/test/lib/commands/hook.js +++ b/test/lib/commands/hook.js @@ -1,6 +1,5 @@ const t = require('tap') const mockNpm = require('../../fixtures/mock-npm') -const { stripVTControlCharacters } = require('node:util') const mockHook = async (t, { hookResponse, ...npmOpts } = {}) => { const now = Date.now() @@ -31,6 +30,7 @@ const mockHook = async (t, { hookResponse, ...npmOpts } = {}) => { type: pkgTypes[name], endpoint: 'https://google.com', last_delivery: id % 2 === 0 ? now : undefined, + response_code: 200, })) }, rm: async (id, opts) => { @@ -243,11 +243,18 @@ t.test('npm hook ls', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0], 'You have 3 hooks configured.', 'prints the correct header') - const out = stripVTControlCharacters(outputs[1]) - t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') - t.match(out, /@npmcli.*https:\/\/google.com.*\n.*\n.*triggered just now/, 'prints scope hook') - t.match(out, /~npm.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints owner hook') + t.strictSame(outputs, [ + 'You have 3 hooks configured.', + 'Hook 1: semver', + 'Endpoint: https://google.com', + 'Never triggered\n', + 'Hook 2: @npmcli', + 'Endpoint: https://google.com', + 'Triggered just now, response code was "200"\n', + 'Hook 3: ~npm', + 'Endpoint: https://google.com', + 'Never triggered\n', + ]) }) t.test('npm hook ls, no results', async t => { @@ -266,7 +273,7 @@ t.test('npm hook ls, no results', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0], "You don't have any hooks configured yet.", 'prints the correct result') + t.strictSame(outputs, [`You don't have any hooks configured yet.`]) }) t.test('npm hook ls, single result', async t => { @@ -292,9 +299,12 @@ t.test('npm hook ls, single result', async t => { }, 'received the correct arguments' ) - t.equal(outputs[0], 'You have one hook configured.', 'prints the correct header') - const out = stripVTControlCharacters(outputs[1]) - t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') + t.strictSame(outputs, [ + 'You have 1 hook configured.', + 'Hook 1: semver', + 'Endpoint: https://google.com', + 'Never triggered\n', + ]) }) t.test('npm hook ls - json output', async t => { @@ -363,10 +373,10 @@ t.test('npm hook ls - parseable output', async t => { t.strictSame( outputs.map(line => line.split(/\t/)), [ - ['id', 'name', 'type', 'endpoint', 'last_delivery'], - ['1', 'semver', 'package', 'https://google.com', ''], - ['2', '@npmcli', 'scope', 'https://google.com', `${now}`], - ['3', 'npm', 'owner', 'https://google.com', ''], + ['id', 'name', 'type', 'endpoint', 'last_delivery', 'response_code'], + ['1', 'semver', 'package', 'https://google.com', '', '200'], + ['2', '@npmcli', 'scope', 'https://google.com', `${now}`, '200'], + ['3', 'npm', 'owner', 'https://google.com', '', '200'], ], 'prints the correct result' ) diff --git a/test/lib/commands/login.js b/test/lib/commands/login.js index b42d3001ebb90..a55637f9e00e2 100644 --- a/test/lib/commands/login.js +++ b/test/lib/commands/login.js @@ -1,12 +1,12 @@ const t = require('tap') -const fs = require('fs') -const path = require('path') +const fs = require('node:fs') +const path = require('node:path') +const stream = require('node:stream') const ini = require('ini') const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') const mockGlobals = require('@npmcli/mock-globals') const MockRegistry = require('@npmcli/mock-registry') -const stream = require('stream') const mockLogin = async (t, { stdin: stdinLines, registry: registryUrl, ...options } = {}) => { let stdin diff --git a/test/lib/commands/org.js b/test/lib/commands/org.js index 576a16d19303d..7a1538d9c69e4 100644 --- a/test/lib/commands/org.js +++ b/test/lib/commands/org.js @@ -1,6 +1,5 @@ const t = require('tap') const mockNpm = require('../../fixtures/mock-npm') -const { stripVTControlCharacters } = require('node:util') const mockOrg = async (t, { orgSize = 1, orgList = {}, ...npmOpts } = {}) => { let setArgs = null @@ -427,10 +426,11 @@ t.test('npm org ls', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0]) - t.match(out, /one.*developer/, 'contains the developer member') - t.match(out, /two.*admin/, 'contains the admin member') - t.match(out, /three.*owner/, 'contains the owner member') + t.strictSame(outputs, [ + 'one - developer', + 'three - owner', + 'two - admin', + ]) }) t.test('npm org ls - user filter', async t => { @@ -452,9 +452,9 @@ t.test('npm org ls - user filter', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0]) - t.match(out, /username.*admin/, 'contains the filtered member') - t.notMatch(out, /missing.*admin/, 'does not contain other members') + t.strictSame(outputs, [ + 'username - admin', + ]) }) t.test('npm org ls - user filter, missing user', async t => { @@ -475,9 +475,7 @@ t.test('npm org ls - user filter, missing user', async t => { }, 'receieved the correct args' ) - const out = stripVTControlCharacters(outputs[0][0]) - t.notMatch(out, /username/, 'does not contain the requested member') - t.notMatch(out, /missing.*admin/, 'does not contain other members') + t.strictSame(outputs, []) }) t.test('npm org ls - no org', async t => { diff --git a/test/lib/commands/profile.js b/test/lib/commands/profile.js index c6cf2a071dcfa..4cf0908aae816 100644 --- a/test/lib/commands/profile.js +++ b/test/lib/commands/profile.js @@ -9,13 +9,6 @@ const mockProfile = async (t, { npmProfile, readUserInfo, qrcode, config, ...opt async createToken () {}, }, 'qrcode-terminal': qrcode || { generate: (url, cb) => cb() }, - 'cli-table3': class extends Array { - toString () { - return this.filter(Boolean) - .map(i => [...Object.entries(i)].map(v => v.join(': '))) - .join('\n') - } - }, '{LIB}/utils/read-user-info.js': readUserInfo || { async password () {}, async otp () {}, @@ -96,16 +89,6 @@ t.test('profile get no args', async t => { t.matchSnapshot(result(), 'should output all profile info as parseable result') }) - t.test('--color', async t => { - const { profile, result } = await mockProfile(t, { - npmProfile: defaultNpmProfile, - config: { color: 'always' }, - }) - - await profile.exec(['get']) - t.matchSnapshot(result(), 'should output all profile info with color result') - }) - t.test('no tfa enabled', async t => { const npmProfile = { async get () { diff --git a/test/lib/commands/token.js b/test/lib/commands/token.js index 33759d01d1b71..1290a5ee9cb17 100644 --- a/test/lib/commands/token.js +++ b/test/lib/commands/token.js @@ -1,33 +1,38 @@ const t = require('tap') -const mockNpm = require('../../fixtures/mock-npm') +const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') +const MockRegistry = require('@npmcli/mock-registry') +const mockGlobals = require('@npmcli/mock-globals') +const stream = require('node:stream') -const mockToken = async (t, { profile, getCredentialsByURI, readUserInfo, ...opts } = {}) => { - const mocks = {} +const authToken = 'abcd1234' +const password = 'this is not really a password' - if (profile) { - mocks['npm-profile'] = profile - } - - if (readUserInfo) { - mocks['{LIB}/utils/read-user-info.js'] = readUserInfo - } - - const mock = await mockNpm(t, { - ...opts, - command: 'token', - mocks, - }) - - // XXX: replace with mock registry - if (getCredentialsByURI) { - mock.npm.config.getCredentialsByURI = getCredentialsByURI - } - - return mock +const auth = { + '//registry.npmjs.org/:_authToken': authToken, } +const now = new Date().toISOString() +const tokens = [ + { + key: 'abcd1234abcd1234', + token: 'efgh5678efgh5678', + cidr_whitelist: null, + readonly: false, + created: now, + updated: now, + }, + { + key: 'abcd1256', + token: 'hgfe8765', + cidr_whitelist: ['192.168.1.1/32'], + readonly: true, + created: now, + updated: now, + }, +] + t.test('completion', async t => { - const { token } = await mockToken(t) + const { token } = await loadMockNpm(t, { command: 'token' }) const testComp = (argv, expect) => { t.resolveMatch(token.completion({ conf: { argv: { remain: argv } } }), expect, argv.join(' ')) @@ -44,476 +49,332 @@ t.test('completion', async t => { }) t.test('token foobar', async t => { - const { token } = await mockToken(t) + const { npm } = await loadMockNpm(t) - await t.rejects(token.exec(['foobar']), /foobar is not a recognized subcommand/) + await t.rejects(npm.exec('token', ['foobar']), /foobar is not a recognized subcommand/) }) t.test('token list', async t => { - const now = new Date().toISOString() - const tokens = [ - { - key: 'abcd1234abcd1234', - token: 'efgh5678efgh5678', - cidr_whitelist: null, - readonly: false, - created: now, - updated: now, - }, - { - key: 'abcd1256', - token: 'hgfe8765', - cidr_whitelist: ['192.168.1.1/32'], - readonly: true, - created: now, - updated: now, - }, - ] - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', otp: '123456' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async conf => { - t.same(conf.auth, { token: 'thisisnotarealtoken', otp: '123456' }) - return tokens - }, - }, + const { npm, outputs } = await loadMockNpm(t, { + config: { ...auth }, }) - - await token.exec([]) - - const lines = joinedOutput().split(/\r?\n/) - t.match(lines[3], ' abcd123 ', 'includes the trimmed key') - t.match(lines[3], ' efgh56… ', 'includes the trimmed token') - t.match(lines[3], ` ${now.slice(0, 10)} `, 'includes the trimmed creation timestamp') - t.match(lines[3], ' no ', 'includes the "no" string for readonly state') - t.match(lines[5], ' abcd125 ', 'includes the trimmed key') - t.match(lines[5], ' hgfe87… ', 'includes the trimmed token') - t.match(lines[5], ` ${now.slice(0, 10)} `, 'includes the trimmed creation timestamp') - t.match(lines[5], ' yes ', 'includes the "no" string for readonly state') - t.match(lines[5], ` ${tokens[1].cidr_whitelist.join(',')} `, 'includes the cidr whitelist') + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await npm.exec('token', []) + t.strictSame(outputs, [ + `Publish token efgh5678efgh5678… with id abcd123 created ${now.slice(0, 10)}`, + '', + `Read only token hgfe8765… with id abcd125 created ${now.slice(0, 10)}`, + 'with IP whitelist: 192.168.1.1/32', + '', + ]) }) t.test('token list json output', async t => { - const now = new Date().toISOString() - const tokens = [ - { - key: 'abcd1234abcd1234', - token: 'efgh5678efgh5678', - cidr_whitelist: null, - readonly: false, - created: now, - updated: now, - }, - ] - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', json: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { username: 'foo', password: 'bar' } - }, - profile: { - listTokens: async conf => { - t.same( - conf.auth, - { basic: { username: 'foo', password: 'bar' } }, - 'passes the correct auth' - ) - return tokens - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + json: true, }, - }) - - await token.exec(['list']) - + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await npm.exec('token', ['list']) const parsed = JSON.parse(joinedOutput()) t.match(parsed, tokens, 'prints the json parsed tokens') }) t.test('token list parseable output', async t => { - const now = new Date().toISOString() - const tokens = [ - { - key: 'abcd1234abcd1234', - token: 'efgh5678efgh5678', - cidr_whitelist: null, - readonly: false, - created: now, - updated: now, - }, - { - key: 'efgh5678ijkl9101', - token: 'hgfe8765', - cidr_whitelist: ['192.168.1.1/32'], - readonly: true, - created: now, - updated: now, - }, - ] - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', parseable: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { auth: Buffer.from('foo:bar').toString('base64') } - }, - profile: { - listTokens: async conf => { - t.same( - conf.auth, - { basic: { username: 'foo', password: 'bar' } }, - 'passes the correct auth' - ) - return tokens - }, + const { npm, outputs } = await loadMockNpm(t, { + config: { + ...auth, + parseable: true, }, }) - - await token.exec(['list']) - - const lines = joinedOutput().split(/\r?\n/) - - t.equal( - lines[0], - ['key', 'token', 'created', 'readonly', 'CIDR whitelist'].join('\t'), - 'prints header' - ) - - t.equal( - lines[1], - [tokens[0].key, tokens[0].token, tokens[0].created, tokens[0].readonly, ''].join('\t'), - 'prints token info' - ) - - t.equal( - lines[2], - [ - tokens[1].key, - tokens[1].token, - tokens[1].created, - tokens[1].readonly, - tokens[1].cidr_whitelist.join(','), - ].join('\t'), - 'prints token info' - ) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await npm.exec('token', []) + t.strictSame(outputs, [ + 'key\ttoken\tcreated\treadonly\tCIDR whitelist', + `abcd1234abcd1234\tefgh5678efgh5678\t${now}\tfalse\t`, + `abcd1256\thgfe8765\t${now}\ttrue\t192.168.1.1/32`, + ]) }) t.test('token revoke', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return {} - }, - profile: { - listTokens: async conf => { - t.same(conf.auth, {}, 'passes the correct empty auth') - return Promise.resolve([{ key: 'abcd1234' }]) - }, - removeToken: async key => { - t.equal(key, 'abcd1234', 'deletes the correct token') - }, - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await token.exec(['rm', 'abcd']) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8)]) t.equal(joinedOutput(), 'Removed 1 token') }) t.test('token revoke multiple tokens', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }, { key: 'efgh5678' }]), - removeToken: async key => { - // this will run twice - t.ok(['abcd1234', 'efgh5678'].includes(key), 'deletes the correct token') - }, - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await token.exec(['revoke', 'abcd', 'efgh']) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[1].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8), tokens[1].key.slice(0, 8)]) t.equal(joinedOutput(), 'Removed 2 tokens') }) t.test('token revoke json output', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', json: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }]), - removeToken: async key => { - t.equal(key, 'abcd1234', 'deletes the correct token') - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + json: true, }, - + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await token.exec(['delete', 'abcd']) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8)]) const parsed = JSON.parse(joinedOutput()) - t.same(parsed, ['abcd1234'], 'logs the token as json') + t.same(parsed, [tokens[0].key], 'logs the token as json') }) t.test('token revoke parseable output', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', parseable: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }]), - removeToken: async key => { - t.equal(key, 'abcd1234', 'deletes the correct token') - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + parseable: true, }, }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) - await token.exec(['remove', 'abcd']) - - t.equal(joinedOutput(), 'abcd1234', 'logs the token as a string') + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].key}`).reply(200) + await npm.exec('token', ['rm', tokens[0].key.slice(0, 8)]) + t.equal(joinedOutput(), tokens[0].key, 'logs the token as a string') }) t.test('token revoke by token', async t => { - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234', token: 'efgh5678' }]), - removeToken: async key => { - t.equal(key, 'efgh5678', 'passes through user input') - }, - }, + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { ...auth }, }) - - await token.exec(['rm', 'efgh5678']) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + registry.nock.delete(`/-/npm/v1/tokens/token/${tokens[0].token}`).reply(200) + await npm.exec('token', ['rm', tokens[0].token]) t.equal(joinedOutput(), 'Removed 1 token') }) t.test('token revoke requires an id', async t => { - const { token } = await mockToken(t) + const { npm } = await loadMockNpm(t) - await t.rejects(token.exec(['rm']), /`` argument is required/) + await t.rejects(npm.exec('token', ['rm']), { + code: 'EUSAGE', + message: '`` argument is required', + }) }) t.test('token revoke ambiguous id errors', async t => { - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }, { key: 'abcd5678' }]), - }, + const { npm } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + registry.getTokens(tokens) + await t.rejects(npm.exec('token', ['rm', 'abcd']), { + message: /Token ID "abcd" was ambiguous/, }) - - await t.rejects(token.exec(['rm', 'abcd']), /Token ID "abcd" was ambiguous/) }) -t.test('token revoke unknown id errors', async t => { - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - profile: { - listTokens: async () => ([{ key: 'abcd1234' }]), - }, +t.test('token revoke unknown token', async t => { + const { npm } = await loadMockNpm(t, { + config: { ...auth }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, }) - await t.rejects(token.exec(['rm', 'efgh']), /Unknown token id or value "efgh"./) + registry.getTokens(tokens) + await t.rejects(npm.exec('token', ['rm', '0xnotreal']), + 'Unknown token id or value 0xnotreal' + ) }) t.test('token create', async t => { - const now = new Date().toISOString() - const password = 'thisisnotreallyapassword' - - const { token, joinedOutput } = await mockToken(t, { + const cidr = ['10.0.0.0/8', '192.168.1.0/24'] + const { npm, outputs } = await loadMockNpm(t, { config: { - registry: 'https://registry.npmjs.org', - cidr: ['10.0.0.0/8', '192.168.1.0/24'], - }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), + ...auth, + cidr, }, - profile: { - createToken: async (pw, readonly, cidr) => { - t.equal(pw, password) - t.equal(readonly, false) - t.same(cidr, ['10.0.0.0/8', '192.168.1.0/24'], 'defaults to empty array') - return { - key: 'abcd1234', - token: 'efgh5678', - created: now, - updated: now, - readonly: false, - cidr_whitelist: [], - } - }, - }, - }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ password, cidr }) + await npm.exec('token', ['create']) + t.strictSame(outputs, [ + 'Created publish token n3wt0k3n', + 'with IP whitelist: 10.0.0.0/8,192.168.1.0/24', + ]) +}) - await token.exec(['create']) - - const lines = joinedOutput().split(/\r?\n/) - t.match(lines[1], 'token') - t.match(lines[1], 'efgh5678', 'prints the whole token') - t.match(lines[3], 'created') - t.match(lines[3], now, 'prints the correct timestamp') - t.match(lines[5], 'readonly') - t.match(lines[5], 'false', 'prints the readonly flag') - t.match(lines[7], 'cidr_whitelist') +t.test('token create read only', async t => { + const { npm, outputs } = await loadMockNpm(t, { + config: { + ...auth, + 'read-only': true, + }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ readonly: true, password }) + await npm.exec('token', ['create']) + t.strictSame(outputs, [ + 'Created read only token n3wt0k3n', + ]) }) t.test('token create json output', async t => { - const now = new Date().toISOString() - const password = 'thisisnotreallyapassword' - - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', json: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), - }, - profile: { - createToken: async (pw, readonly, cidr) => { - t.equal(pw, password) - t.equal(readonly, false) - t.same(cidr, [], 'defaults to empty array') - return { - key: 'abcd1234', - token: 'efgh5678', - created: now, - updated: now, - readonly: false, - cidr_whitelist: [], - } - }, - }, - output: spec => { - t.type(spec, 'string', 'outputs a string') - const parsed = JSON.parse(spec) - t.same( - parsed, - { token: 'efgh5678', created: now, readonly: false, cidr_whitelist: [] }, - 'outputs the correct object' - ) + const cidr = ['10.0.0.0/8', '192.168.1.0/24'] + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + ...auth, + json: true, + cidr, }, }) - - await token.exec(['create']) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ password, cidr }) + await npm.exec('token', ['create']) + const parsed = JSON.parse(joinedOutput()) + t.match( + parsed, + { token: 'n3wt0k3n', readonly: false, cidr_whitelist: cidr } + ) + t.ok(parsed.created, 'also returns created') }) t.test('token create parseable output', async t => { - const now = new Date().toISOString() - const password = 'thisisnotreallyapassword' - - const { token, joinedOutput } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', parseable: true }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), - }, - profile: { - createToken: async (pw, readonly, cidr) => { - t.equal(pw, password) - t.equal(readonly, false) - t.same(cidr, [], 'defaults to empty array') - return { - key: 'abcd1234', - token: 'efgh5678', - created: now, - updated: now, - readonly: false, - cidr_whitelist: [], - } - }, + const cidr = ['10.0.0.0/8', '192.168.1.0/24'] + const { npm, outputs } = await loadMockNpm(t, { + config: { + ...auth, + parseable: true, + cidr, }, }) - - await token.exec(['create']) - - const spec = joinedOutput().split(/\r?\n/) - - t.match(spec[0], 'token\tefgh5678', 'prints the token') - t.match(spec[1], `created\t${now}`, 'prints the created timestamp') - t.match(spec[2], 'readonly\tfalse', 'prints the readonly flag') - t.match(spec[3], 'cidr_whitelist\t', 'prints the cidr whitelist') + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + authorization: authToken, + }) + const stdin = new stream.PassThrough() + stdin.write(`${password}\n`) + mockGlobals(t, { + 'process.stdin': stdin, + 'process.stdout': new stream.PassThrough(), // to quiet readline + }, { replace: true }) + registry.createToken({ password, cidr }) + await npm.exec('token', ['create']) + t.equal(outputs[0], 'token\tn3wt0k3n') + t.ok(outputs[1].startsWith('created\t')) + t.equal(outputs[2], 'readonly\tfalse') + t.equal(outputs[3], 'cidr_whitelist\t10.0.0.0/8,192.168.1.0/24') }) t.test('token create ipv6 cidr', async t => { - const password = 'thisisnotreallyapassword' - - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', cidr: '::1/128' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), + const { npm } = await loadMockNpm(t, { + config: { + ...auth, + cidr: '::1/128', }, }) - - await t.rejects( - token.exec(['create']), - { - code: 'EINVALIDCIDR', - message: /CIDR whitelist can only contain IPv4 addresses, ::1\/128 is IPv6/, - }, - 'returns correct error' - ) + await t.rejects(npm.exec('token', ['create'], { + code: 'EINVALIDCIDR', + message: /CIDR whitelist can only contain IPv4 addresses, ::1\/128 is IPv6/, + })) }) t.test('token create invalid cidr', async t => { - const password = 'thisisnotreallyapassword' - - const { token } = await mockToken(t, { - config: { registry: 'https://registry.npmjs.org', cidr: 'apple/cider' }, - getCredentialsByURI: uri => { - t.equal(uri, 'https://registry.npmjs.org/', 'requests correct registry') - return { token: 'thisisnotarealtoken' } - }, - readUserInfo: { - password: () => Promise.resolve(password), + const { npm } = await loadMockNpm(t, { + config: { + ...auth, + cidr: 'apple/cider', }, }) - - await t.rejects( - token.exec(['create']), - { code: 'EINVALIDCIDR', message: /CIDR whitelist contains invalid CIDR entry: apple\/cider/ }, - 'returns correct error' - ) + await t.rejects(npm.exec('token', ['create'], { + code: 'EINVALIDCIDR', + message: 'CIDR whitelist contains invalid CIDR entry: apple/cider', + })) }) From dfa4cabdccdd1c82cc160bb435c29c45ed05fdf4 Mon Sep 17 00:00:00 2001 From: Gar Date: Mon, 22 Apr 2024 07:23:38 -0700 Subject: [PATCH 03/42] docs: update output examples --- docs/lib/content/commands/npm-profile.md | 33 +++++++------------- docs/lib/content/commands/npm-token.md | 38 +++++++----------------- 2 files changed, 21 insertions(+), 50 deletions(-) diff --git a/docs/lib/content/commands/npm-profile.md b/docs/lib/content/commands/npm-profile.md index 0c93cef0d60da..ba6613393d736 100644 --- a/docs/lib/content/commands/npm-profile.md +++ b/docs/lib/content/commands/npm-profile.md @@ -17,28 +17,17 @@ support this interface. * `npm profile get []`: Display all of the properties of your profile, or one or more specific properties. It looks like: -```bash -+-----------------+---------------------------+ -| name | example | -+-----------------+---------------------------+ -| email | me@example.com (verified) | -+-----------------+---------------------------+ -| two factor auth | auth-and-writes | -+-----------------+---------------------------+ -| fullname | Example User | -+-----------------+---------------------------+ -| homepage | | -+-----------------+---------------------------+ -| freenode | | -+-----------------+---------------------------+ -| twitter | | -+-----------------+---------------------------+ -| github | | -+-----------------+---------------------------+ -| created | 2015-02-26T01:38:35.892Z | -+-----------------+---------------------------+ -| updated | 2017-10-02T21:29:45.922Z | -+-----------------+---------------------------+ +``` +name: example +email: e@example.com (verified) +two-factor auth: auth-and-writes +fullname: Example User +homepage: +freenode: +twitter: +github: +created: 2015-02-26T01:38:35.892Z +updated: 2017-10-02T21:29:45.922Z ``` * `npm profile set `: Set the value of a profile diff --git a/docs/lib/content/commands/npm-token.md b/docs/lib/content/commands/npm-token.md index 81624ba6952f8..d4d9d6bd83cce 100644 --- a/docs/lib/content/commands/npm-token.md +++ b/docs/lib/content/commands/npm-token.md @@ -16,24 +16,14 @@ This lets you list, create and revoke authentication tokens. Shows a table of all active authentication tokens. You can request this as JSON with `--json` or tab-separated values with `--parseable`. -```bash -+--------+---------+------------+----------+----------------+ -| id | token | created | read-only | CIDR whitelist | -+--------+---------+------------+----------+----------------+ -| 7f3134 | 1fa9ba… | 2017-10-02 | yes | | -+--------+---------+------------+----------+----------------+ -| c03241 | af7aef… | 2017-10-02 | no | 192.168.0.1/24 | -+--------+---------+------------+----------+----------------+ -| e0cf92 | 3a436a… | 2017-10-02 | no | | -+--------+---------+------------+----------+----------------+ -| 63eb9d | 74ef35… | 2017-09-28 | no | | -+--------+---------+------------+----------+----------------+ -| 2daaa8 | cbad5f… | 2017-09-26 | no | | -+--------+---------+------------+----------+----------------+ -| 68c2fe | 127e51… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ -| 6334e1 | 1dadd1… | 2017-09-23 | no | | -+--------+---------+------------+----------+----------------+ +``` +Read only token npm_1f… with id 7f3134 created 2017-10-21 + +Publish token npm_af… with id c03241 created 2017-10-02 +with IP Whitelist: 192.168.0.1/24 + +Publish token npm_… with id e0cf92 created 2017-10-02 + ``` * `npm token create [--read-only] [--cidr=]`: @@ -49,16 +39,8 @@ This lets you list, create and revoke authentication tokens. website](https://docs.npmjs.com/creating-and-viewing-access-tokens) for more information on generating automation tokens. -```bash -+----------------+--------------------------------------+ -| token | a73c9572-f1b9-8983-983d-ba3ac3cc913d | -+----------------+--------------------------------------+ -| cidr_whitelist | | -+----------------+--------------------------------------+ -| readonly | false | -+----------------+--------------------------------------+ -| created | 2017-10-02T07:52:24.838Z | -+----------------+--------------------------------------+ +``` +Created publish token a73c9572-f1b9-8983-983d-ba3ac3cc913d ``` * `npm token revoke `: From d531f8b9237fabf640d421a8c4ea3c4284e00f0a Mon Sep 17 00:00:00 2001 From: Gar Date: Tue, 23 Apr 2024 10:11:01 -0700 Subject: [PATCH 04/42] fix: Remove table output from search and tar summary This removes table output from `npm search` and from all commands that log a summary of tarball content (`npm publish` and `npm pack`). Table output is discouraged in a cli for accessibility reasons. --- lib/commands/search.js | 48 +- lib/utils/format-search-stream.js | 182 +-- lib/utils/tar.js | 69 +- .../test/lib/commands/pack.js.test.cjs | 88 +- .../test/lib/commands/publish.js.test.cjs | 134 +- .../test/lib/commands/search.js.test.cjs | 1083 +++++++++++++++-- tap-snapshots/test/lib/utils/tar.js.test.cjs | 90 +- test/fixtures/libnpmsearch-stream-result.js | 1 + test/lib/commands/search.js | 20 +- 9 files changed, 1283 insertions(+), 432 deletions(-) diff --git a/lib/commands/search.js b/lib/commands/search.js index 4a69c77a256e7..2b338ed4d39b8 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -1,37 +1,9 @@ -const { Minipass } = require('minipass') const Pipeline = require('minipass-pipeline') const libSearch = require('libnpmsearch') const { log, output } = require('proc-log') const formatSearchStream = require('../utils/format-search-stream.js') -function filter (data, include, exclude) { - const words = [data.name] - .concat(data.maintainers.map(m => `=${m.username}`)) - .concat(data.keywords || []) - .map(f => f && f.trim && f.trim()) - .filter(f => f) - .join(' ') - .toLowerCase() - - if (exclude.find(e => match(words, e))) { - return false - } - - return true -} - -function match (words, pattern) { - if (pattern.startsWith('/')) { - if (pattern.endsWith('/')) { - pattern = pattern.slice(0, -1) - } - pattern = new RegExp(pattern.slice(1)) - return words.match(pattern) - } - return words.indexOf(pattern) !== -1 -} - const BaseCommand = require('../base-command.js') class Search extends BaseCommand { static description = 'Search for packages' @@ -57,7 +29,7 @@ class Search extends BaseCommand { const opts = { ...this.npm.flatOptions, ...this.npm.flatOptions.search, - include: args.map(s => s.toLowerCase()).filter(s => s), + include: args.map(s => s.toLowerCase()).filter(Boolean), exclude: this.npm.flatOptions.search.exclude.split(/\s+/), } @@ -68,30 +40,16 @@ class Search extends BaseCommand { // Used later to figure out whether we had any packages go out let anyOutput = false - class FilterStream extends Minipass { - constructor () { - super({ objectMode: true }) - } - - write (pkg) { - if (filter(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. - const outputStream = await formatSearchStream({ + const outputStream = formatSearchStream({ args, // --searchinclude options are not highlighted ...opts, + npm: this.npm, }) log.silly('search', 'searching packages') const p = new Pipeline( libSearch.stream(opts.include, opts), - filterStream, outputStream ) diff --git a/lib/utils/format-search-stream.js b/lib/utils/format-search-stream.js index 046a4b1e20587..434d21f448acd 100644 --- a/lib/utils/format-search-stream.js +++ b/lib/utils/format-search-stream.js @@ -1,6 +1,6 @@ -const { stripVTControlCharacters } = require('node:util') +/* eslint-disable max-len */ +const { stripVTControlCharacters: strip } = require('node:util') const { Minipass } = require('minipass') -const columnify = require('columnify') // This module consumes package data in the following format: // @@ -16,14 +16,48 @@ const columnify = require('columnify') // The returned stream will format this package data // into a byte stream of formatted, displayable output. -module.exports = async (opts) => { - return opts.json ? new JSONOutputStream() : new TextOutputStream(opts) +function filter (data, exclude) { + const words = [data.name] + .concat(data.maintainers.map(m => m.username)) + .concat(data.keywords || []) + .map(f => f?.trim?.()) + .filter(Boolean) + .join(' ') + .toLowerCase() + + if (exclude.find(pattern => { + // Treats both /foo and /foo/ as regex searches + if (pattern.startsWith('/')) { + if (pattern.endsWith('/')) { + pattern = pattern.slice(0, -1) + } + return words.match(new RegExp(pattern.slice(1))) + } + return words.includes(pattern) + })) { + return false + } + + return true +} + +module.exports = (opts) => { + return opts.json ? new JSONOutputStream(opts) : new TextOutputStream(opts) } class JSONOutputStream extends Minipass { #didFirst = false + #exclude + + constructor (opts) { + super() + this.#exclude = opts.exclude + } write (obj) { + if (!filter(obj, this.#exclude)) { + return + } if (!this.#didFirst) { super.write('[\n') this.#didFirst = true @@ -41,94 +75,96 @@ class JSONOutputStream extends Minipass { } class TextOutputStream extends Minipass { - #opts - #line = 0 + #args + #chalk + #exclude + #parseable constructor (opts) { super() - this.#opts = opts + this.#args = opts.args.map(s => s.toLowerCase()).filter(Boolean) + this.#chalk = opts.npm.chalk + this.#exclude = opts.exclude + this.#parseable = opts.parseable } - write (pkg) { - return super.write(this.#prettify(pkg)) - } - - #prettify (data) { + write (data) { + if (!filter(data, this.#exclude)) { + return + } + // Normalize const pkg = { - author: data.maintainers.map((m) => `=${stripVTControlCharacters(m.username)}`).join(' '), - date: 'prehistoric', - description: stripVTControlCharacters(data.description ?? ''), - keywords: '', - name: stripVTControlCharacters(data.name), + authors: data.maintainers.map((m) => `${strip(m.username)}`).join(' '), + publisher: strip(data.publisher.username), + date: data.date ? data.date.toISOString().slice(0, 10) : 'prehistoric', + description: strip(data.description ?? ''), + keywords: [], + name: strip(data.name), version: data.version, } if (Array.isArray(data.keywords)) { - pkg.keywords = data.keywords.map((k) => stripVTControlCharacters(k)).join(' ') + pkg.keywords = data.keywords.map(strip) } else if (typeof data.keywords === 'string') { - pkg.keywords = stripVTControlCharacters(data.keywords.replace(/[,\s]+/, ' ')) - } - if (data.date) { - pkg.date = data.date.toISOString().split('T')[0] // remove time + pkg.keywords = strip(data.keywords.replace(/[,\s]+/, ' ')).split(' ') } - const columns = ['name', 'description', 'author', 'date', 'version', 'keywords'] - if (this.#opts.parseable) { - return columns.map((col) => pkg[col] && ('' + pkg[col]).replace(/\t/g, ' ')).join('\t') + let output + if (this.#parseable) { + output = [pkg.name, pkg.description, pkg.author, pkg.date, pkg.version, pkg.keywords] + .filter(Boolean) + .map(col => ('' + col).replace(/\t/g, ' ')).join('\t') + return super.write(output) } - // 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: ++this.#line <= 1, - columnSplitter: ' | ', - truncate: !this.#opts.long, - 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 }, - }, + const keywords = pkg.keywords.map(k => { + if (this.#args.includes(k)) { + return this.#chalk.cyan(k) + } else { + return k + } + }).join(' ') + + let description = [] + for (const arg of this.#args) { + const finder = pkg.description.toLowerCase().split(arg.toLowerCase()) + let p = 0 + for (const f of finder) { + description.push(pkg.description.slice(p, p + f.length)) + const word = pkg.description.slice(p + f.length, p + f.length + arg.length) + description.push(this.#chalk.cyan(word)) + p += f.length + arg.length } - ).split('\n').map(line => line.slice(0, maxWidth)).join('\n') - - if (!this.#opts.color) { - return output } - - const colors = ['31m', '33m', '32m', '36m', '34m', '35m'] - - this.#opts.args.forEach((arg, i) => { - const markStart = String.fromCharCode(i % colors.length + 1) - const markEnd = String.fromCharCode(0) - - if (arg.charAt(0) === '/') { - output = output.replace( - new RegExp(arg.slice(1, -1), 'gi'), - bit => `${markStart}${bit}${markEnd}` - ) - } else { - // just a normal string, do the split/map thing + description = description.filter(Boolean) + let name = pkg.name + if (this.#args.includes(pkg.name)) { + name = this.#chalk.cyan(pkg.name) + } else { + name = [] + for (const arg of this.#args) { + const finder = pkg.name.toLowerCase().split(arg.toLowerCase()) let p = 0 - - output = output.toLowerCase().split(arg.toLowerCase()).map(piece => { - piece = output.slice(p, p + piece.length) - p += piece.length - const mark = `${markStart}${output.slice(p, p + arg.length)}${markEnd}` - p += arg.length - return `${piece}${mark}` - }).join('') + for (const f of finder) { + name.push(pkg.name.slice(p, p + f.length)) + const word = pkg.name.slice(p + f.length, p + f.length + arg.length) + name.push(this.#chalk.cyan(word)) + p += f.length + arg.length + } } - }) + name = this.#chalk.blue(name.join('')) + } - for (let i = 1; i <= colors.length; i++) { - output = output.split(String.fromCharCode(i)).join(`\u001B[${colors[i - 1]}`) + if (description.length) { + output = `${name}\n${description.join('')}\n` + } else { + output = `${name}\n` + } + output += `Version ${this.#chalk.blue(pkg.version)} published ${this.#chalk.blue(pkg.date)} by ${this.#chalk.blue(pkg.publisher)}\n` + output += `Maintainers: ${pkg.authors}\n` + if (keywords) { + output += `Keywords: ${keywords}\n` } - return output.split('\u0000').join('\u001B[0m').trim() + output += `${this.#chalk.blue(`https://npm.im/${pkg.name}`)}\n` + return super.write(output) } } diff --git a/lib/utils/tar.js b/lib/utils/tar.js index 8883f231a8981..9085d9dd35016 100644 --- a/lib/utils/tar.js +++ b/lib/utils/tar.js @@ -2,7 +2,6 @@ const tar = require('tar') const ssri = require('ssri') const { log } = require('proc-log') const formatBytes = require('./format-bytes.js') -const columnify = require('columnify') const localeCompare = require('@isaacs/string-locale-compare')('en', { sensitivity: 'case', numeric: true, @@ -12,60 +11,36 @@ const logTar = (tarball, opts = {}) => { const { unicode = false } = opts log.notice('') log.notice('', `${unicode ? '📦 ' : 'package:'} ${tarball.name}@${tarball.version}`) - log.notice('=== Tarball Contents ===') + log.notice('Tarball Contents') if (tarball.files.length) { log.notice( '', - columnify( - tarball.files - .map(f => { - const bytes = formatBytes(f.size, false) - return /^node_modules\//.test(f.path) ? null : { path: f.path, size: `${bytes}` } - }) - .filter(f => f), - { - include: ['size', 'path'], - showHeaders: false, - } - ) + tarball.files.map(f => + /^node_modules\//.test(f.path) ? null : `${formatBytes(f.size, false)} ${f.path}` + ).filter(f => f).join('\n') ) } if (tarball.bundled.length) { - log.notice('=== Bundled Dependencies ===') + log.notice('Bundled Dependencies') tarball.bundled.forEach(name => log.notice('', name)) } - log.notice('=== Tarball Details ===') - log.notice( - '', - columnify( - [ - { name: 'name:', value: tarball.name }, - { name: 'version:', value: tarball.version }, - tarball.filename && { name: 'filename:', value: tarball.filename }, - { name: 'package size:', value: formatBytes(tarball.size) }, - { name: 'unpacked size:', value: formatBytes(tarball.unpackedSize) }, - { name: 'shasum:', value: tarball.shasum }, - { - name: 'integrity:', - value: - tarball.integrity.toString().slice(0, 20) + - '[...]' + - tarball.integrity.toString().slice(80), - }, - tarball.bundled.length && { name: 'bundled deps:', value: tarball.bundled.length }, - tarball.bundled.length && { - name: 'bundled files:', - value: tarball.entryCount - tarball.files.length, - }, - tarball.bundled.length && { name: 'own files:', value: tarball.files.length }, - { name: 'total files:', value: tarball.entryCount }, - ].filter(x => x), - { - include: ['name', 'value'], - showHeaders: false, - } - ) - ) + log.notice('Tarball Details') + log.notice('', `name: ${tarball.name}`) + log.notice('', `version: ${tarball.version}`) + if (tarball.filename) { + log.notice('', `filename: ${tarball.filename}`) + } + log.notice('', `package size: ${formatBytes(tarball.size)}`) + log.notice('', `unpacked size: ${formatBytes(tarball.unpackedSize)}`) + log.notice('', `shasum: ${tarball.shasum}`) + /* eslint-disable-next-line max-len */ + log.notice('', `integrity: ${tarball.integrity.toString().slice(0, 20)}[...]${tarball.integrity.toString().slice(80)}`) + if (tarball.bundled.length) { + log.notice('', `bundled deps: ${tarball.bundled.length}`) + log.notice('', `bundled files: ${tarball.entryCount - tarball.files.length}`) + log.notice('', `own files: ${tarball.files.length}`) + } + log.notice('', `total files: ${tarball.entryCount}`) log.notice('', '') } diff --git a/tap-snapshots/test/lib/commands/pack.js.test.cjs b/tap-snapshots/test/lib/commands/pack.js.test.cjs index d78bac7a1626e..e251e63d4c279 100644 --- a/tap-snapshots/test/lib/commands/pack.js.test.cjs +++ b/tap-snapshots/test/lib/commands/pack.js.test.cjs @@ -8,57 +8,51 @@ exports[`test/lib/commands/pack.js TAP dry run > logs pack contents 1`] = ` Array [ "package: test-package@1.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "41B package.json", - "=== Tarball Details ===", - String( - name: test-package - version: 1.0.0 - filename: test-package-1.0.0.tgz - package size: {size} - unpacked size: 41 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: test-package", + "version: 1.0.0", + "filename: test-package-1.0.0.tgz", + "package size: {size}", + "unpacked size: 41 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", ] ` exports[`test/lib/commands/pack.js TAP foreground-scripts can still be set to false > logs pack contents 1`] = ` Array [ "package: test-fg-scripts@0.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "110B package.json", - "=== Tarball Details ===", - String( - name: test-fg-scripts - version: 0.0.0 - filename: test-fg-scripts-0.0.0.tgz - package size: {size} - unpacked size: 110 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: test-fg-scripts", + "version: 0.0.0", + "filename: test-fg-scripts-0.0.0.tgz", + "package size: {size}", + "unpacked size: 110 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", ] ` exports[`test/lib/commands/pack.js TAP foreground-scripts defaults to true > logs pack contents 1`] = ` Array [ "package: test-fg-scripts@0.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "110B package.json", - "=== Tarball Details ===", - String( - name: test-fg-scripts - version: 0.0.0 - filename: test-fg-scripts-0.0.0.tgz - package size: {size} - unpacked size: 110 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: test-fg-scripts", + "version: 0.0.0", + "filename: test-fg-scripts-0.0.0.tgz", + "package size: {size}", + "unpacked size: 110 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", ] ` @@ -125,18 +119,16 @@ Array [ exports[`test/lib/commands/pack.js TAP should pack current directory with no arguments > logs pack contents 1`] = ` Array [ "package: test-package@1.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "41B package.json", - "=== Tarball Details ===", - String( - name: test-package - version: 1.0.0 - filename: test-package-1.0.0.tgz - package size: {size} - unpacked size: 41 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: test-package", + "version: 1.0.0", + "filename: test-package-1.0.0.tgz", + "package size: {size}", + "unpacked size: 41 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", ] ` diff --git a/tap-snapshots/test/lib/commands/publish.js.test.cjs b/tap-snapshots/test/lib/commands/publish.js.test.cjs index df2c66ab10e9f..c13834d5d694c 100644 --- a/tap-snapshots/test/lib/commands/publish.js.test.cjs +++ b/tap-snapshots/test/lib/commands/publish.js.test.cjs @@ -16,19 +16,17 @@ exports[`test/lib/commands/publish.js TAP bare _auth and registry config > new p exports[`test/lib/commands/publish.js TAP dry-run > must match snapshot 1`] = ` Array [ "package: test-package@1.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "87B package.json", - "=== Tarball Details ===", - String( - name: test-package - version: 1.0.0 - filename: test-package-1.0.0.tgz - package size: {size} - unpacked size: 87 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: test-package", + "version: 1.0.0", + "filename: test-package-1.0.0.tgz", + "package size: {size}", + "unpacked size: 87 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", ] ` @@ -36,19 +34,17 @@ Array [ exports[`test/lib/commands/publish.js TAP foreground-scripts can still be set to false > must match snapshot 1`] = ` Array [ "package: test-fg-scripts@0.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "110B package.json", - "=== Tarball Details ===", - String( - name: test-fg-scripts - version: 0.0.0 - filename: test-fg-scripts-0.0.0.tgz - package size: {size} - unpacked size: 110 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: test-fg-scripts", + "version: 0.0.0", + "filename: test-fg-scripts-0.0.0.tgz", + "package size: {size}", + "unpacked size: 110 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", ] ` @@ -56,19 +52,17 @@ Array [ exports[`test/lib/commands/publish.js TAP foreground-scripts defaults to true > must match snapshot 1`] = ` Array [ "package: test-fg-scripts@0.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "110B package.json", - "=== Tarball Details ===", - String( - name: test-fg-scripts - version: 0.0.0 - filename: test-fg-scripts-0.0.0.tgz - package size: {size} - unpacked size: 110 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: test-fg-scripts", + "version: 0.0.0", + "filename: test-fg-scripts-0.0.0.tgz", + "package size: {size}", + "unpacked size: 110 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", "Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)", ] ` @@ -276,19 +270,17 @@ exports[`test/lib/commands/publish.js TAP prioritize CLI flags over publishConfi exports[`test/lib/commands/publish.js TAP public access > must match snapshot 1`] = ` Array [ "package: @npm/test-package@1.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "55B package.json", - "=== Tarball Details ===", - String( - name: @npm/test-package - version: 1.0.0 - filename: npm-test-package-1.0.0.tgz - package size: {size} - unpacked size: 55 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: @npm/test-package", + "version: 1.0.0", + "filename: npm-test-package-1.0.0.tgz", + "package size: {size}", + "unpacked size: 55 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", "Publishing to https://registry.npmjs.org/ with tag latest and public access", ] ` @@ -308,19 +300,17 @@ exports[`test/lib/commands/publish.js TAP respects publishConfig.registry, runs exports[`test/lib/commands/publish.js TAP restricted access > must match snapshot 1`] = ` Array [ "package: @npm/test-package@1.0.0", - "=== Tarball Contents ===", + "Tarball Contents", "55B package.json", - "=== Tarball Details ===", - String( - name: @npm/test-package - version: 1.0.0 - filename: npm-test-package-1.0.0.tgz - package size: {size} - unpacked size: 55 B - shasum: {sha} - integrity: {integrity} - total files: 1 - ), + "Tarball Details", + "name: @npm/test-package", + "version: 1.0.0", + "filename: npm-test-package-1.0.0.tgz", + "package size: {size}", + "unpacked size: 55 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 1", "Publishing to https://registry.npmjs.org/ with tag latest and restricted access", ] ` @@ -336,22 +326,20 @@ exports[`test/lib/commands/publish.js TAP scoped _auth config scoped registry > exports[`test/lib/commands/publish.js TAP tarball > must match snapshot 1`] = ` Array [ "package: test-tar-package@1.0.0", - "=== Tarball Contents ===", + "Tarball Contents", String( - 26B index.js + 26B index.js 98B package.json ), - "=== Tarball Details ===", - String( - name: test-tar-package - version: 1.0.0 - filename: test-tar-package-1.0.0.tgz - package size: {size} - unpacked size: 124 B - shasum: {sha} - integrity: {integrity} - total files: 2 - ), + "Tarball Details", + "name: test-tar-package", + "version: 1.0.0", + "filename: test-tar-package-1.0.0.tgz", + "package size: {size}", + "unpacked size: 124 B", + "shasum: {sha}", + "integrity: {integrity} + "total files: 2", "Publishing to https://registry.npmjs.org/ with tag latest and default access", ] ` diff --git a/tap-snapshots/test/lib/commands/search.js.test.cjs b/tap-snapshots/test/lib/commands/search.js.test.cjs index 33d4a0533b93c..3135964f202f5 100644 --- a/tap-snapshots/test/lib/commands/search.js.test.cjs +++ b/tap-snapshots/test/lib/commands/search.js.test.cjs @@ -10,137 +10,1002 @@ No matches found for "foo" ` exports[`test/lib/commands/search.js TAP search //--color > should have expected search results with color 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm bad map npmcli libnpm cli workspaces map-workspaces -libnpmversion | library to do the… | =nlf… | 2020-11-04 | 1.0.7 | -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -pkg-no-desc | | =lukekarrys | 2019-09-26 | 1.0.0 | +libnpm +Collection of programmatic APIs for the npm CLI +Version 3.0.1 published 2019-07-16 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm api package manager lib +https://npm.im/libnpm +libnpmaccess +programmatic library for \`npm access\` commands +Version 4.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpmaccess +https://npm.im/libnpmaccess +@evocateur/libnpmaccess +programmatic library for \`npm access\` commands +Version 3.1.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmaccess +@evocateur/libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 1.2.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmpublish +libnpmorg +Programmatic api for \`npm org\` commands +Version 2.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpm npm package manager api orgs teams +https://npm.im/libnpmorg +libnpmsearch +Programmatic API for searching in npm and compatible registries. +Version 3.1.0 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm search api libnpm +https://npm.im/libnpmsearch +libnpmteam +npm Team management APIs +Version 2.0.2 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmteam +libnpmhook +programmatic API for managing npm registry hooks +Version 6.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm hooks registry npm api +https://npm.im/libnpmhook +libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 4.0.0 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmpublish +libnpmfund +Programmatic API for npm fund +Version 1.0.2 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm npmcli libnpm cli git fund gitfund +https://npm.im/libnpmfund +@npmcli/map-workspaces +Retrieves a name:pathname Map for a given workspaces config +Version 1.0.1 published 2020-09-30 by ruyadorno +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm bad map npmcli libnpm cli workspaces map-workspaces +https://npm.im/@npmcli/map-workspaces +libnpmversion +library to do the things that 'npm version' does +Version 1.0.7 published 2020-11-04 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmversion +@types/libnpmsearch +TypeScript definitions for libnpmsearch +Version 2.0.1 published 2019-09-26 by types +Maintainers: types +https://npm.im/@types/libnpmsearch +pkg-no-desc +Version 1.0.0 published 2019-09-26 by lukekarrys +Maintainers: lukekarrys +https://npm.im/pkg-no-desc ` exports[`test/lib/commands/search.js TAP search --color > should have expected search results with color 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 |  -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 |  -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 |  -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 |  -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm bad map npmcli libnpm cli workspaces map-workspaces -libnpmversion | library to do the… | =nlf… | 2020-11-04 | 1.0.7 |  -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 |  -pkg-no-desc | | =lukekarrys | 2019-09-26 | 1.0.0 |  +libnpm +Collection of programmatic APIs for the npm CLI +Version 3.0.1 published 2019-07-16 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm api package manager lib +https://npm.im/libnpm +libnpmaccess +programmatic library for \`npm access\` commands +Version 4.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpmaccess +https://npm.im/libnpmaccess +@evocateur/libnpmaccess +programmatic library for \`npm access\` commands +Version 3.1.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmaccess +@evocateur/libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 1.2.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmpublish +libnpmorg +Programmatic api for \`npm org\` commands +Version 2.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpm npm package manager api orgs teams +https://npm.im/libnpmorg +libnpmsearch +Programmatic API for searching in npm and compatible registries. +Version 3.1.0 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm search api libnpm +https://npm.im/libnpmsearch +libnpmteam +npm Team management APIs +Version 2.0.2 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmteam +libnpmhook +programmatic API for managing npm registry hooks +Version 6.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm hooks registry npm api +https://npm.im/libnpmhook +libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 4.0.0 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmpublish +libnpmfund +Programmatic API for npm fund +Version 1.0.2 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm npmcli libnpm cli git fund gitfund +https://npm.im/libnpmfund +@npmcli/map-workspaces +Retrieves a name:pathname Map for a given workspaces config +Version 1.0.1 published 2020-09-30 by ruyadorno +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm bad map npmcli libnpm cli workspaces map-workspaces +https://npm.im/@npmcli/map-workspaces +libnpmversion +library to do the things that 'npm version' does +Version 1.0.7 published 2020-11-04 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmversion +@types/libnpmsearch +TypeScript definitions for libnpmsearch +Version 2.0.1 published 2019-09-26 by types +Maintainers: types +https://npm.im/@types/libnpmsearch +pkg-no-desc +Version 1.0.0 published 2019-09-26 by lukekarrys +Maintainers: lukekarrys +https://npm.im/pkg-no-desc ` exports[`test/lib/commands/search.js TAP search --parseable > should have expected search results as parseable 1`] = ` -libnpm Collection of programmatic APIs for the npm CLI =nlf =ruyadorno =darcyclarke =isaacs 2019-07-16 3.0.1 npm api package manager lib -libnpmaccess programmatic library for \`npm access\` commands =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 4.0.1 libnpmaccess -@evocateur/libnpmaccess programmatic library for \`npm access\` commands =evocateur 2019-07-16 3.1.2 -@evocateur/libnpmpublish Programmatic API for the bits behind npm publish and unpublish =evocateur 2019-07-16 1.2.2 -libnpmorg Programmatic api for \`npm org\` commands =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 2.0.1 libnpm npm package manager api orgs teams -libnpmsearch Programmatic API for searching in npm and compatible registries. =nlf =ruyadorno =darcyclarke =isaacs 2020-12-08 3.1.0 npm search api libnpm -libnpmteam npm Team management APIs =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 2.0.2 -libnpmhook programmatic API for managing npm registry hooks =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 6.0.1 npm hooks registry npm api -libnpmpublish Programmatic API for the bits behind npm publish and unpublish =nlf =ruyadorno =darcyclarke =isaacs 2020-11-03 4.0.0 -libnpmfund Programmatic API for npm fund =nlf =ruyadorno =darcyclarke =isaacs 2020-12-08 1.0.2 npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces Retrieves a name:pathname Map for a given workspaces config =nlf =ruyadorno =darcyclarke =isaacs 2020-09-30 1.0.1 npm bad map npmcli libnpm cli workspaces map-workspaces -libnpmversion library to do the things that 'npm version' does =nlf =ruyadorno =darcyclarke =isaacs 2020-11-04 1.0.7 -@types/libnpmsearch TypeScript definitions for libnpmsearch =types 2019-09-26 2.0.1 -pkg-no-desc =lukekarrys 2019-09-26 1.0.0 +libnpm Collection of programmatic APIs for the npm CLI 2019-07-16 3.0.1 npm,api,package manager,lib +libnpmaccess programmatic library for \`npm access\` commands 2020-11-03 4.0.1 libnpmaccess +@evocateur/libnpmaccess programmatic library for \`npm access\` commands 2019-07-16 3.1.2 +@evocateur/libnpmpublish Programmatic API for the bits behind npm publish and unpublish 2019-07-16 1.2.2 +libnpmorg Programmatic api for \`npm org\` commands 2020-11-03 2.0.1 libnpm,npm,package manager,api,orgs,teams +libnpmsearch Programmatic API for searching in npm and compatible registries. 2020-12-08 3.1.0 npm,search,api,libnpm +libnpmteam npm Team management APIs 2020-11-03 2.0.2 +libnpmhook programmatic API for managing npm registry hooks 2020-11-03 6.0.1 npm,hooks,registry,npm api +libnpmpublish Programmatic API for the bits behind npm publish and unpublish 2020-11-03 4.0.0 +libnpmfund Programmatic API for npm fund 2020-12-08 1.0.2 npm,npmcli,libnpm,cli,git,fund,gitfund +@npmcli/map-workspaces Retrieves a name:pathname Map for a given workspaces config 2020-09-30 1.0.1 npm,,bad map,npmcli,libnpm,cli,workspaces,map-workspaces +libnpmversion library to do the things that 'npm version' does 2020-11-04 1.0.7 +@types/libnpmsearch TypeScript definitions for libnpmsearch 2019-09-26 2.0.1 +pkg-no-desc 2019-09-26 1.0.0 ` exports[`test/lib/commands/search.js TAP search > should have filtered expected search results 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -foo | | =foo | prehistoric | 1.0.0 | -libnpmversion | | =foo | prehistoric | 1.0.0 | +foo +Version 1.0.0 published prehistoric by foo +Maintainers: foo +https://npm.im/foo +libnpmversion +Version 1.0.0 published prehistoric by foo +Maintainers: foo +https://npm.im/libnpmversion ` exports[`test/lib/commands/search.js TAP search text > should have expected search results 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm bad map npmcli libnpm cli workspaces map-workspaces -libnpmversion | library to do the… | =nlf… | 2020-11-04 | 1.0.7 | -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -pkg-no-desc | | =lukekarrys | 2019-09-26 | 1.0.0 | +libnpm +Collection of programmatic APIs for the npm CLI +Version 3.0.1 published 2019-07-16 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm api package manager lib +https://npm.im/libnpm +libnpmaccess +programmatic library for \`npm access\` commands +Version 4.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpmaccess +https://npm.im/libnpmaccess +@evocateur/libnpmaccess +programmatic library for \`npm access\` commands +Version 3.1.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmaccess +@evocateur/libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 1.2.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmpublish +libnpmorg +Programmatic api for \`npm org\` commands +Version 2.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpm npm package manager api orgs teams +https://npm.im/libnpmorg +libnpmsearch +Programmatic API for searching in npm and compatible registries. +Version 3.1.0 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm search api libnpm +https://npm.im/libnpmsearch +libnpmteam +npm Team management APIs +Version 2.0.2 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmteam +libnpmhook +programmatic API for managing npm registry hooks +Version 6.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm hooks registry npm api +https://npm.im/libnpmhook +libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 4.0.0 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmpublish +libnpmfund +Programmatic API for npm fund +Version 1.0.2 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm npmcli libnpm cli git fund gitfund +https://npm.im/libnpmfund +@npmcli/map-workspaces +Retrieves a name:pathname Map for a given workspaces config +Version 1.0.1 published 2020-09-30 by ruyadorno +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm bad map npmcli libnpm cli workspaces map-workspaces +https://npm.im/@npmcli/map-workspaces +libnpmversion +library to do the things that 'npm version' does +Version 1.0.7 published 2020-11-04 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmversion +@types/libnpmsearch +TypeScript definitions for libnpmsearch +Version 2.0.1 published 2019-09-26 by types +Maintainers: types +https://npm.im/@types/libnpmsearch +pkg-no-desc +Version 1.0.0 published 2019-09-26 by lukekarrys +Maintainers: lukekarrys +https://npm.im/pkg-no-desc ` exports[`test/lib/commands/search.js TAP search exclude forward slash > results should not have libnpmversion 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm bad map npmcli libnpm cli workspaces map-workspaces -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -pkg-no-desc | | =lukekarrys | 2019-09-26 | 1.0.0 | +libnpm +Collection of programmatic APIs for the npm CLI +Version 3.0.1 published 2019-07-16 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm api package manager lib +https://npm.im/libnpm +libnpmaccess +programmatic library for \`npm access\` commands +Version 4.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpmaccess +https://npm.im/libnpmaccess +@evocateur/libnpmaccess +programmatic library for \`npm access\` commands +Version 3.1.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmaccess +@evocateur/libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 1.2.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmpublish +libnpmorg +Programmatic api for \`npm org\` commands +Version 2.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpm npm package manager api orgs teams +https://npm.im/libnpmorg +libnpmsearch +Programmatic API for searching in npm and compatible registries. +Version 3.1.0 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm search api libnpm +https://npm.im/libnpmsearch +libnpmteam +npm Team management APIs +Version 2.0.2 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmteam +libnpmhook +programmatic API for managing npm registry hooks +Version 6.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm hooks registry npm api +https://npm.im/libnpmhook +libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 4.0.0 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmpublish +libnpmfund +Programmatic API for npm fund +Version 1.0.2 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm npmcli libnpm cli git fund gitfund +https://npm.im/libnpmfund +@npmcli/map-workspaces +Retrieves a name:pathname Map for a given workspaces config +Version 1.0.1 published 2020-09-30 by ruyadorno +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm bad map npmcli libnpm cli workspaces map-workspaces +https://npm.im/@npmcli/map-workspaces +@types/libnpmsearch +TypeScript definitions for libnpmsearch +Version 2.0.1 published 2019-09-26 by types +Maintainers: types +https://npm.im/@types/libnpmsearch +pkg-no-desc +Version 1.0.0 published 2019-09-26 by lukekarrys +Maintainers: lukekarrys +https://npm.im/pkg-no-desc ` exports[`test/lib/commands/search.js TAP search exclude regex > results should not have libnpmversion 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm bad map npmcli libnpm cli workspaces map-workspaces -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -pkg-no-desc | | =lukekarrys | 2019-09-26 | 1.0.0 | +libnpm +Collection of programmatic APIs for the npm CLI +Version 3.0.1 published 2019-07-16 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm api package manager lib +https://npm.im/libnpm +libnpmaccess +programmatic library for \`npm access\` commands +Version 4.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpmaccess +https://npm.im/libnpmaccess +@evocateur/libnpmaccess +programmatic library for \`npm access\` commands +Version 3.1.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmaccess +@evocateur/libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 1.2.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmpublish +libnpmorg +Programmatic api for \`npm org\` commands +Version 2.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpm npm package manager api orgs teams +https://npm.im/libnpmorg +libnpmsearch +Programmatic API for searching in npm and compatible registries. +Version 3.1.0 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm search api libnpm +https://npm.im/libnpmsearch +libnpmteam +npm Team management APIs +Version 2.0.2 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmteam +libnpmhook +programmatic API for managing npm registry hooks +Version 6.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm hooks registry npm api +https://npm.im/libnpmhook +libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 4.0.0 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmpublish +libnpmfund +Programmatic API for npm fund +Version 1.0.2 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm npmcli libnpm cli git fund gitfund +https://npm.im/libnpmfund +@npmcli/map-workspaces +Retrieves a name:pathname Map for a given workspaces config +Version 1.0.1 published 2020-09-30 by ruyadorno +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm bad map npmcli libnpm cli workspaces map-workspaces +https://npm.im/@npmcli/map-workspaces +@types/libnpmsearch +TypeScript definitions for libnpmsearch +Version 2.0.1 published 2019-09-26 by types +Maintainers: types +https://npm.im/@types/libnpmsearch +pkg-no-desc +Version 1.0.0 published 2019-09-26 by lukekarrys +Maintainers: lukekarrys +https://npm.im/pkg-no-desc ` exports[`test/lib/commands/search.js TAP search exclude string > results should not have libnpmversion 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -libnpm | Collection of… | =nlf… | 2019-07-16 | 3.0.1 | npm api package manager lib -libnpmaccess | programmatic… | =nlf… | 2020-11-03 | 4.0.1 | libnpmaccess -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -libnpmorg | Programmatic api… | =nlf… | 2020-11-03 | 2.0.1 | libnpm npm package manager api orgs teams -libnpmsearch | Programmatic API… | =nlf… | 2020-12-08 | 3.1.0 | npm search api libnpm -libnpmteam | npm Team management… | =nlf… | 2020-11-03 | 2.0.2 | -libnpmhook | programmatic API… | =nlf… | 2020-11-03 | 6.0.1 | npm hooks registry npm api -libnpmpublish | Programmatic API… | =nlf… | 2020-11-03 | 4.0.0 | -libnpmfund | Programmatic API… | =nlf… | 2020-12-08 | 1.0.2 | npm npmcli libnpm cli git fund gitfund -@npmcli/map-workspaces | Retrieves a… | =nlf… | 2020-09-30 | 1.0.1 | npm bad map npmcli libnpm cli workspaces map-workspaces -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -pkg-no-desc | | =lukekarrys | 2019-09-26 | 1.0.0 | +libnpm +Collection of programmatic APIs for the npm CLI +Version 3.0.1 published 2019-07-16 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm api package manager lib +https://npm.im/libnpm +libnpmaccess +programmatic library for \`npm access\` commands +Version 4.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpmaccess +https://npm.im/libnpmaccess +@evocateur/libnpmaccess +programmatic library for \`npm access\` commands +Version 3.1.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmaccess +@evocateur/libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 1.2.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmpublish +libnpmorg +Programmatic api for \`npm org\` commands +Version 2.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: libnpm npm package manager api orgs teams +https://npm.im/libnpmorg +libnpmsearch +Programmatic API for searching in npm and compatible registries. +Version 3.1.0 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm search api libnpm +https://npm.im/libnpmsearch +libnpmteam +npm Team management APIs +Version 2.0.2 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmteam +libnpmhook +programmatic API for managing npm registry hooks +Version 6.0.1 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm hooks registry npm api +https://npm.im/libnpmhook +libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 4.0.0 published 2020-11-03 by nlf +Maintainers: nlf ruyadorno darcyclarke isaacs +https://npm.im/libnpmpublish +libnpmfund +Programmatic API for npm fund +Version 1.0.2 published 2020-12-08 by isaacs +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm npmcli libnpm cli git fund gitfund +https://npm.im/libnpmfund +@npmcli/map-workspaces +Retrieves a name:pathname Map for a given workspaces config +Version 1.0.1 published 2020-09-30 by ruyadorno +Maintainers: nlf ruyadorno darcyclarke isaacs +Keywords: npm bad map npmcli libnpm cli workspaces map-workspaces +https://npm.im/@npmcli/map-workspaces +@types/libnpmsearch +TypeScript definitions for libnpmsearch +Version 2.0.1 published 2019-09-26 by types +Maintainers: types +https://npm.im/@types/libnpmsearch +pkg-no-desc +Version 1.0.0 published 2019-09-26 by lukekarrys +Maintainers: lukekarrys +https://npm.im/pkg-no-desc +` + +exports[`test/lib/commands/search.js TAP search exclude string json > results should not have libnpmversion 1`] = ` +Array [ + Object { + "author": Object { + "email": "kzm@zkat.tech", + "name": "Kat Marchán", + }, + "date": "2019-07-16T17:50:00.572Z", + "description": "Collection of programmatic APIs for the npm CLI", + "keywords": Array [ + "npm", + "api", + "package manager", + "lib", + ], + "links": Object { + "bugs": "https://github.com/npm/libnpm/issues", + "homepage": "https://github.com/npm/libnpm#readme", + "npm": "https://www.npmjs.com/package/libnpm", + "repository": "https://github.com/npm/libnpm", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpm", + "publisher": Object { + "email": "i@izs.me", + "username": "isaacs", + }, + "scope": "unscoped", + "version": "3.0.1", + }, + Object { + "author": Object { + "email": "kzm@sykosomatic.org", + "name": "Kat Marchán", + }, + "date": "2020-11-03T19:19:00.526Z", + "description": "programmatic library for \`npm access\` commands", + "keywords": "libnpmaccess", + "links": Object { + "bugs": "https://github.com/npm/libnpmaccess/issues", + "homepage": "https://npmjs.com/package/libnpmaccess", + "npm": "https://www.npmjs.com/package/libnpmaccess", + "repository": "https://github.com/npm/libnpmaccess", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpmaccess", + "publisher": Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + "scope": "unscoped", + "version": "4.0.1", + }, + Object { + "author": Object { + "email": "kzm@zkat.tech", + "name": "Kat Marchán", + }, + "date": "2019-07-16T19:43:33.959Z", + "description": "programmatic library for \`npm access\` commands", + "links": Object { + "bugs": "https://github.com/evocateur/libnpmaccess/issues", + "homepage": "https://npmjs.com/package/@evocateur/libnpmaccess", + "npm": "https://www.npmjs.com/package/%40evocateur%2Flibnpmaccess", + "repository": "https://github.com/evocateur/libnpmaccess", + }, + "maintainers": Array [ + Object { + "email": "daniel.stockman@gmail.com", + "username": "evocateur", + }, + ], + "name": "@evocateur/libnpmaccess", + "publisher": Object { + "email": "daniel.stockman@gmail.com", + "username": "evocateur", + }, + "scope": "evocateur", + "version": "3.1.2", + }, + Object { + "author": Object { + "email": "kzm@zkat.tech", + "name": "Kat Marchán", + }, + "date": "2019-07-16T19:40:40.850Z", + "description": "Programmatic API for the bits behind npm publish and unpublish", + "links": Object { + "bugs": "https://github.com/evocateur/libnpmpublish/issues", + "homepage": "https://npmjs.com/package/@evocateur/libnpmpublish", + "npm": "https://www.npmjs.com/package/%40evocateur%2Flibnpmpublish", + "repository": "https://github.com/evocateur/libnpmpublish", + }, + "maintainers": Array [ + Object { + "email": "daniel.stockman@gmail.com", + "username": "evocateur", + }, + ], + "name": "@evocateur/libnpmpublish", + "publisher": Object { + "email": "daniel.stockman@gmail.com", + "username": "evocateur", + }, + "scope": "evocateur", + "version": "1.2.2", + }, + Object { + "author": Object { + "email": "kzm@sykosomatic.org", + "name": "Kat Marchán", + }, + "date": "2020-11-03T19:21:57.757Z", + "description": "Programmatic api for \`npm org\` commands", + "keywords": Array [ + "libnpm", + "npm", + "package manager", + "api", + "orgs", + "teams", + ], + "links": Object { + "bugs": "https://github.com/npm/libnpmorg/issues", + "homepage": "https://npmjs.com/package/libnpmorg", + "npm": "https://www.npmjs.com/package/libnpmorg", + "repository": "https://github.com/npm/libnpmorg", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpmorg", + "publisher": Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + "scope": "unscoped", + "version": "2.0.1", + }, + Object { + "author": Object { + "email": "kzm@sykosomatic.org", + "name": "Kat Marchán", + }, + "date": "2020-12-08T23:54:18.374Z", + "description": "Programmatic API for searching in npm and compatible registries.", + "keywords": Array [ + "npm", + "search", + "api", + "libnpm", + ], + "links": Object { + "bugs": "https://github.com/npm/libnpmsearch/issues", + "homepage": "https://npmjs.com/package/libnpmsearch", + "npm": "https://www.npmjs.com/package/libnpmsearch", + "repository": "https://github.com/npm/libnpmsearch", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpmsearch", + "publisher": Object { + "email": "i@izs.me", + "username": "isaacs", + }, + "scope": "unscoped", + "version": "3.1.0", + }, + Object { + "author": Object { + "email": "kzm@zkat.tech", + "name": "Kat Marchán", + }, + "date": "2020-11-03T19:24:42.380Z", + "description": "npm Team management APIs", + "links": Object { + "bugs": "https://github.com/npm/libnpmteam/issues", + "homepage": "https://npmjs.com/package/libnpmteam", + "npm": "https://www.npmjs.com/package/libnpmteam", + "repository": "https://github.com/npm/libnpmteam", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpmteam", + "publisher": Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + "scope": "unscoped", + "version": "2.0.2", + }, + Object { + "author": Object { + "email": "kzm@sykosomatic.org", + "name": "Kat Marchán", + }, + "date": "2020-11-03T19:20:45.818Z", + "description": "programmatic API for managing npm registry hooks", + "keywords": Array [ + "npm", + "hooks", + "registry", + "npm api", + ], + "links": Object { + "bugs": "https://github.com/npm/libnpmhook/issues", + "homepage": "https://github.com/npm/libnpmhook#readme", + "npm": "https://www.npmjs.com/package/libnpmhook", + "repository": "https://github.com/npm/libnpmhook", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpmhook", + "publisher": Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + "scope": "unscoped", + "version": "6.0.1", + }, + Object { + "author": Object { + "email": "support@npmjs.com", + "name": "npm Inc.", + }, + "date": "2020-11-03T19:13:43.780Z", + "description": "Programmatic API for the bits behind npm publish and unpublish", + "links": Object { + "bugs": "https://github.com/npm/libnpmpublish/issues", + "homepage": "https://npmjs.com/package/libnpmpublish", + "npm": "https://www.npmjs.com/package/libnpmpublish", + "repository": "https://github.com/npm/libnpmpublish", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpmpublish", + "publisher": Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + "scope": "unscoped", + "version": "4.0.0", + }, + Object { + "author": Object { + "email": "support@npmjs.com", + "name": "npm Inc.", + }, + "date": "2020-12-08T23:22:00.213Z", + "description": "Programmatic API for npm fund", + "keywords": Array [ + "npm", + "npmcli", + "libnpm", + "cli", + "git", + "fund", + "gitfund", + ], + "links": Object { + "bugs": "https://github.com/npm/libnpmfund/issues", + "homepage": "https://github.com/npm/libnpmfund#readme", + "npm": "https://www.npmjs.com/package/libnpmfund", + "repository": "https://github.com/npm/libnpmfund", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "libnpmfund", + "publisher": Object { + "email": "i@izs.me", + "username": "isaacs", + }, + "scope": "unscoped", + "version": "1.0.2", + }, + Object { + "author": Object { + "email": "support@npmjs.com", + "name": "npm Inc.", + }, + "date": "2020-09-30T15:16:29.017Z", + "description": "Retrieves a name:pathname Map for a given workspaces config", + "keywords": Array [ + "\\u001b[33mnpm\\u001b[39m", + "\\u001b]4;0;?\\u0007", + "\\u001b[Hbad map", + "npmcli", + "libnpm", + "cli", + "workspaces", + "map-workspaces", + ], + "links": Object { + "bugs": "https://github.com/npm/map-workspaces/issues", + "homepage": "https://github.com/npm/map-workspaces#readme", + "npm": "https://www.npmjs.com/package/%40npmcli%2Fmap-workspaces", + "repository": "https://github.com/npm/map-workspaces", + }, + "maintainers": Array [ + Object { + "email": "quitlahok@gmail.com", + "username": "nlf", + }, + Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + Object { + "email": "darcy@darcyclarke.me", + "username": "darcyclarke", + }, + Object { + "email": "i@izs.me", + "username": "isaacs", + }, + ], + "name": "@npmcli/map-workspaces", + "publisher": Object { + "email": "ruyadorno@hotmail.com", + "username": "ruyadorno", + }, + "scope": "npmcli", + "version": "1.0.1", + }, + Object { + "date": "2019-09-26T22:24:28.713Z", + "description": "TypeScript definitions for libnpmsearch", + "links": Object { + "npm": "https://www.npmjs.com/package/%40types%2Flibnpmsearch", + }, + "maintainers": Array [ + Object { + "email": "ts-npm-types@microsoft.com", + "username": "types", + }, + ], + "name": "@types/libnpmsearch", + "publisher": Object { + "email": "ts-npm-types@microsoft.com", + "username": "types", + }, + "scope": "types", + "version": "2.0.1", + }, + Object { + "date": "2019-09-26T22:24:28.713Z", + "maintainers": Array [ + Object { + "email": "lukekarrys", + "username": "lukekarrys", + }, + ], + "name": "pkg-no-desc", + "publisher": Object { + "email": "lukekarrys", + "username": "lukekarrys", + }, + "scope": "unscoped", + "version": "1.0.0", + }, +] ` exports[`test/lib/commands/search.js TAP search exclude username with upper case letters > results should not have nlf 1`] = ` -NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS -@evocateur/libnpmaccess | programmatic… | =evocateur | 2019-07-16 | 3.1.2 | -@evocateur/libnpmpublish | Programmatic API… | =evocateur | 2019-07-16 | 1.2.2 | -@types/libnpmsearch | TypeScript… | =types | 2019-09-26 | 2.0.1 | -pkg-no-desc | | =lukekarrys | 2019-09-26 | 1.0.0 | +@evocateur/libnpmaccess +programmatic library for \`npm access\` commands +Version 3.1.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmaccess +@evocateur/libnpmpublish +Programmatic API for the bits behind npm publish and unpublish +Version 1.2.2 published 2019-07-16 by evocateur +Maintainers: evocateur +https://npm.im/@evocateur/libnpmpublish +@types/libnpmsearch +TypeScript definitions for libnpmsearch +Version 2.0.1 published 2019-09-26 by types +Maintainers: types +https://npm.im/@types/libnpmsearch +pkg-no-desc +Version 1.0.0 published 2019-09-26 by lukekarrys +Maintainers: lukekarrys +https://npm.im/pkg-no-desc ` diff --git a/tap-snapshots/test/lib/utils/tar.js.test.cjs b/tap-snapshots/test/lib/utils/tar.js.test.cjs index 5f3a0f14c49a5..fda9577c84390 100644 --- a/tap-snapshots/test/lib/utils/tar.js.test.cjs +++ b/tap-snapshots/test/lib/utils/tar.js.test.cjs @@ -9,28 +9,38 @@ exports[`test/lib/utils/tar.js TAP should log tarball contents > must match snap package: my-cool-pkg@1.0.0 -=== Tarball Contents === +Tarball Contents -4B cat -4B chai -4B dog +4B cat +4B chai +4B dog 114B package.json -=== Bundled Dependencies === +Bundled Dependencies bundle-dep -=== Tarball Details === +Tarball Details -name: my-cool-pkg -version: 1.0.0 -filename: my-cool-pkg-1.0.0.tgz -package size: {size} -unpacked size: 126 B -shasum: {sha} -integrity: {integrity} -bundled deps: 1 -bundled files: 0 -own files: 5 -total files: 5 +name: my-cool-pkg + +version: 1.0.0 + +filename: my-cool-pkg-1.0.0.tgz + +package size: {size} + +unpacked size: 126 B + +shasum: {sha} + +integrity: {integrity} + +bundled deps: 1 + +bundled files: 0 + +own files: 5 + +total files: 5 ` @@ -39,28 +49,38 @@ exports[`test/lib/utils/tar.js TAP should log tarball contents of a scoped packa package: @myscope/my-cool-pkg@1.0.0 -=== Tarball Contents === +Tarball Contents -4B cat -4B chai -4B dog +4B cat +4B chai +4B dog 123B package.json -=== Bundled Dependencies === +Bundled Dependencies bundle-dep -=== Tarball Details === - -name: @myscope/my-cool-pkg -version: 1.0.0 -filename: myscope-my-cool-pkg-1.0.0.tgz -package size: {size} -unpacked size: 135 B -shasum: {sha} -integrity: {integrity} -bundled deps: 1 -bundled files: 0 -own files: 5 -total files: 5 +Tarball Details + +name: @myscope/my-cool-pkg + +version: 1.0.0 + +filename: myscope-my-cool-pkg-1.0.0.tgz + +package size: {size} + +unpacked size: 135 B + +shasum: {sha} + +integrity: {integrity} + +bundled deps: 1 + +bundled files: 0 + +own files: 5 + +total files: 5 ` diff --git a/test/fixtures/libnpmsearch-stream-result.js b/test/fixtures/libnpmsearch-stream-result.js index 68245beff6e46..872a7940340d4 100644 --- a/test/fixtures/libnpmsearch-stream-result.js +++ b/test/fixtures/libnpmsearch-stream-result.js @@ -283,6 +283,7 @@ module.exports = [ scope: 'unscoped', version: '1.0.0', date: '2019-09-26T22:24:28.713Z', + publisher: { username: 'lukekarrys', email: 'lukekarrys' }, maintainers: [{ username: 'lukekarrys', email: 'lukekarrys' }], }, ] diff --git a/test/lib/commands/search.js b/test/lib/commands/search.js index 56d0437c18f93..fb0db8b21c5de 100644 --- a/test/lib/commands/search.js +++ b/test/lib/commands/search.js @@ -94,7 +94,7 @@ t.test('search ', async t => { keywords: [], date: null, author: { name: 'Foo', email: 'foo@npmjs.com' }, - publisher: { name: 'Foo', email: 'foo@npmjs.com' }, + publisher: { username: 'foo', email: 'foo@npmjs.com' }, maintainers: [ { username: 'foo', email: 'foo@npmjs.com' }, ], @@ -106,7 +106,7 @@ t.test('search ', async t => { keywords: [], date: null, author: { name: 'Foo', email: 'foo@npmjs.com' }, - publisher: { name: 'Foo', email: 'foo@npmjs.com' }, + publisher: { username: 'foo', email: 'foo@npmjs.com' }, maintainers: [ { username: 'foo', email: 'foo@npmjs.com' }, ], @@ -171,6 +171,22 @@ t.test('search exclude string', async t => { await npm.exec('search', ['libnpm']) t.matchSnapshot(joinedOutput(), 'results should not have libnpmversion') }) +t.test('search exclude string json', async t => { + const { npm, joinedOutput } = await loadMockNpm(t, { + config: { + json: true, + searchexclude: 'libnpmversion', + }, + }) + const registry = new MockRegistry({ + tap: t, + registry: npm.config.get('registry'), + }) + + registry.search({ results: libnpmsearchResultFixture }) + await npm.exec('search', ['libnpm']) + t.matchSnapshot(JSON.parse(joinedOutput()), 'results should not have libnpmversion') +}) t.test('search exclude username with upper case letters', async t => { const { npm, joinedOutput } = await loadMockNpm(t, { config: { searchexclude: 'NLF' } }) From c77f035fc18fdc0a9eb3ef0a7d1faf2c7aec6af3 Mon Sep 17 00:00:00 2001 From: Gar Date: Tue, 23 Apr 2024 10:13:17 -0700 Subject: [PATCH 05/42] deps: remove columnify --- DEPENDENCIES.md | 5 - node_modules/.gitignore | 4 - node_modules/clone/LICENSE | 18 -- node_modules/clone/clone.iml | 10 - node_modules/clone/clone.js | 166 --------------- node_modules/clone/package.json | 51 ----- node_modules/columnify/LICENSE | 21 -- node_modules/columnify/Makefile | 9 - node_modules/columnify/columnify.js | 306 ---------------------------- node_modules/columnify/index.js | 297 --------------------------- node_modules/columnify/package.json | 53 ----- node_modules/columnify/utils.js | 193 ------------------ node_modules/columnify/width.js | 6 - node_modules/defaults/LICENSE | 22 -- node_modules/defaults/index.js | 13 -- node_modules/defaults/package.json | 33 --- node_modules/defaults/test.js | 34 ---- node_modules/wcwidth/LICENSE | 30 --- node_modules/wcwidth/combining.js | 50 ----- node_modules/wcwidth/docs/index.md | 65 ------ node_modules/wcwidth/index.js | 99 --------- node_modules/wcwidth/package.json | 42 ---- node_modules/wcwidth/test/index.js | 64 ------ package-lock.json | 45 ---- package.json | 2 - 25 files changed, 1638 deletions(-) delete mode 100644 node_modules/clone/LICENSE delete mode 100644 node_modules/clone/clone.iml delete mode 100644 node_modules/clone/clone.js delete mode 100644 node_modules/clone/package.json delete mode 100644 node_modules/columnify/LICENSE delete mode 100644 node_modules/columnify/Makefile delete mode 100644 node_modules/columnify/columnify.js delete mode 100644 node_modules/columnify/index.js delete mode 100644 node_modules/columnify/package.json delete mode 100644 node_modules/columnify/utils.js delete mode 100644 node_modules/columnify/width.js delete mode 100644 node_modules/defaults/LICENSE delete mode 100644 node_modules/defaults/index.js delete mode 100644 node_modules/defaults/package.json delete mode 100644 node_modules/defaults/test.js delete mode 100644 node_modules/wcwidth/LICENSE delete mode 100644 node_modules/wcwidth/combining.js delete mode 100644 node_modules/wcwidth/docs/index.md delete mode 100644 node_modules/wcwidth/index.js delete mode 100644 node_modules/wcwidth/package.json delete mode 100644 node_modules/wcwidth/test/index.js diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 89274c35261a8..5462ad11da200 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -289,13 +289,10 @@ graph LR; cli-columns-->string-width; cli-columns-->strip-ansi; color-convert-->color-name; - columnify-->strip-ansi; - columnify-->wcwidth; cross-spawn-->path-key; cross-spawn-->shebang-command; cross-spawn-->which; debug-->ms; - defaults-->clone; encoding-->iconv-lite; foreground-child-->cross-spawn; foreground-child-->signal-exit; @@ -480,7 +477,6 @@ graph LR; npm-->ci-info; npm-->cli-columns; npm-->cli-table3; - npm-->columnify; npm-->diff; npm-->fastest-levenshtein; npm-->fs-minipass; @@ -797,7 +793,6 @@ graph LR; validate-npm-package-license-->spdx-correct; validate-npm-package-license-->spdx-expression-parse; validate-npm-package-name-->builtins; - wcwidth-->defaults; which-->isexe; wrap-ansi-->ansi-styles; wrap-ansi-->string-width; diff --git a/node_modules/.gitignore b/node_modules/.gitignore index f12013c0f8d76..6e00159ec7a0f 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -66,11 +66,9 @@ !/cidr-regex !/clean-stack !/cli-columns -!/clone !/cmd-shim !/color-convert !/color-name -!/columnify !/common-ancestor-path !/cross-spawn !/cross-spawn/node_modules/ @@ -81,7 +79,6 @@ !/debug/node_modules/ /debug/node_modules/* !/debug/node_modules/ms -!/defaults !/diff !/eastasianwidth !/emoji-regex @@ -234,7 +231,6 @@ !/validate-npm-package-license/node_modules/spdx-expression-parse !/validate-npm-package-name !/walk-up-path -!/wcwidth !/which !/which/node_modules/ /which/node_modules/* diff --git a/node_modules/clone/LICENSE b/node_modules/clone/LICENSE deleted file mode 100644 index cc3c87bc3bfd8..0000000000000 --- a/node_modules/clone/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -Copyright © 2011-2015 Paul Vorbach - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the “Software”), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/clone/clone.iml b/node_modules/clone/clone.iml deleted file mode 100644 index 30de8aee9ba30..0000000000000 --- a/node_modules/clone/clone.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/node_modules/clone/clone.js b/node_modules/clone/clone.js deleted file mode 100644 index ba200c2f99288..0000000000000 --- a/node_modules/clone/clone.js +++ /dev/null @@ -1,166 +0,0 @@ -var clone = (function() { -'use strict'; - -/** - * Clones (copies) an Object using deep copying. - * - * This function supports circular references by default, but if you are certain - * there are no circular references in your object, you can save some CPU time - * by calling clone(obj, false). - * - * Caution: if `circular` is false and `parent` contains circular references, - * your program may enter an infinite loop and crash. - * - * @param `parent` - the object to be cloned - * @param `circular` - set to true if the object to be cloned may contain - * circular references. (optional - true by default) - * @param `depth` - set to a number if the object is only to be cloned to - * a particular depth. (optional - defaults to Infinity) - * @param `prototype` - sets the prototype to be used when cloning an object. - * (optional - defaults to parent prototype). -*/ -function clone(parent, circular, depth, prototype) { - var filter; - if (typeof circular === 'object') { - depth = circular.depth; - prototype = circular.prototype; - filter = circular.filter; - circular = circular.circular - } - // maintain two arrays for circular references, where corresponding parents - // and children have the same index - var allParents = []; - var allChildren = []; - - var useBuffer = typeof Buffer != 'undefined'; - - if (typeof circular == 'undefined') - circular = true; - - if (typeof depth == 'undefined') - depth = Infinity; - - // recurse this function so we don't reset allParents and allChildren - function _clone(parent, depth) { - // cloning null always returns null - if (parent === null) - return null; - - if (depth == 0) - return parent; - - var child; - var proto; - if (typeof parent != 'object') { - return parent; - } - - if (clone.__isArray(parent)) { - child = []; - } else if (clone.__isRegExp(parent)) { - child = new RegExp(parent.source, __getRegExpFlags(parent)); - if (parent.lastIndex) child.lastIndex = parent.lastIndex; - } else if (clone.__isDate(parent)) { - child = new Date(parent.getTime()); - } else if (useBuffer && Buffer.isBuffer(parent)) { - if (Buffer.allocUnsafe) { - // Node.js >= 4.5.0 - child = Buffer.allocUnsafe(parent.length); - } else { - // Older Node.js versions - child = new Buffer(parent.length); - } - parent.copy(child); - return child; - } else { - if (typeof prototype == 'undefined') { - proto = Object.getPrototypeOf(parent); - child = Object.create(proto); - } - else { - child = Object.create(prototype); - proto = prototype; - } - } - - if (circular) { - var index = allParents.indexOf(parent); - - if (index != -1) { - return allChildren[index]; - } - allParents.push(parent); - allChildren.push(child); - } - - for (var i in parent) { - var attrs; - if (proto) { - attrs = Object.getOwnPropertyDescriptor(proto, i); - } - - if (attrs && attrs.set == null) { - continue; - } - child[i] = _clone(parent[i], depth - 1); - } - - return child; - } - - return _clone(parent, depth); -} - -/** - * Simple flat clone using prototype, accepts only objects, usefull for property - * override on FLAT configuration object (no nested props). - * - * USE WITH CAUTION! This may not behave as you wish if you do not know how this - * works. - */ -clone.clonePrototype = function clonePrototype(parent) { - if (parent === null) - return null; - - var c = function () {}; - c.prototype = parent; - return new c(); -}; - -// private utility functions - -function __objToStr(o) { - return Object.prototype.toString.call(o); -}; -clone.__objToStr = __objToStr; - -function __isDate(o) { - return typeof o === 'object' && __objToStr(o) === '[object Date]'; -}; -clone.__isDate = __isDate; - -function __isArray(o) { - return typeof o === 'object' && __objToStr(o) === '[object Array]'; -}; -clone.__isArray = __isArray; - -function __isRegExp(o) { - return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; -}; -clone.__isRegExp = __isRegExp; - -function __getRegExpFlags(re) { - var flags = ''; - if (re.global) flags += 'g'; - if (re.ignoreCase) flags += 'i'; - if (re.multiline) flags += 'm'; - return flags; -}; -clone.__getRegExpFlags = __getRegExpFlags; - -return clone; -})(); - -if (typeof module === 'object' && module.exports) { - module.exports = clone; -} diff --git a/node_modules/clone/package.json b/node_modules/clone/package.json deleted file mode 100644 index 3ddd242f4a510..0000000000000 --- a/node_modules/clone/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "clone", - "description": "deep cloning of objects and arrays", - "tags": [ - "clone", - "object", - "array", - "function", - "date" - ], - "version": "1.0.4", - "repository": { - "type": "git", - "url": "git://github.com/pvorb/node-clone.git" - }, - "bugs": { - "url": "https://github.com/pvorb/node-clone/issues" - }, - "main": "clone.js", - "author": "Paul Vorbach (http://paul.vorba.ch/)", - "contributors": [ - "Blake Miner (http://www.blakeminer.com/)", - "Tian You (http://blog.axqd.net/)", - "George Stagas (http://stagas.com/)", - "Tobiasz Cudnik (https://github.com/TobiaszCudnik)", - "Pavel Lang (https://github.com/langpavel)", - "Dan MacTough (http://yabfog.com/)", - "w1nk (https://github.com/w1nk)", - "Hugh Kennedy (http://twitter.com/hughskennedy)", - "Dustin Diaz (http://dustindiaz.com)", - "Ilya Shaisultanov (https://github.com/diversario)", - "Nathan MacInnes (http://macinn.es/)", - "Benjamin E. Coe (https://twitter.com/benjamincoe)", - "Nathan Zadoks (https://github.com/nathan7)", - "Róbert Oroszi (https://github.com/oroce)", - "Aurélio A. Heckert (http://softwarelivre.org/aurium)", - "Guy Ellis (http://www.guyellisrocks.com/)" - ], - "license": "MIT", - "engines": { - "node": ">=0.8" - }, - "dependencies": {}, - "devDependencies": { - "nodeunit": "~0.9.0" - }, - "optionalDependencies": {}, - "scripts": { - "test": "nodeunit test.js" - } -} diff --git a/node_modules/columnify/LICENSE b/node_modules/columnify/LICENSE deleted file mode 100644 index ed47678e61c40..0000000000000 --- a/node_modules/columnify/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Tim Oxley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/columnify/Makefile b/node_modules/columnify/Makefile deleted file mode 100644 index 3a67c57a3b1e0..0000000000000 --- a/node_modules/columnify/Makefile +++ /dev/null @@ -1,9 +0,0 @@ - -all: columnify.js - -prepublish: all - -columnify.js: index.js package.json - babel index.js > columnify.js - -.PHONY: all prepublish diff --git a/node_modules/columnify/columnify.js b/node_modules/columnify/columnify.js deleted file mode 100644 index dcef9236e1843..0000000000000 --- a/node_modules/columnify/columnify.js +++ /dev/null @@ -1,306 +0,0 @@ -"use strict"; - -var wcwidth = require('./width'); - -var _require = require('./utils'), - padRight = _require.padRight, - padCenter = _require.padCenter, - padLeft = _require.padLeft, - splitIntoLines = _require.splitIntoLines, - splitLongWords = _require.splitLongWords, - truncateString = _require.truncateString; - -var DEFAULT_HEADING_TRANSFORM = function DEFAULT_HEADING_TRANSFORM(key) { - return key.toUpperCase(); -}; - -var DEFAULT_DATA_TRANSFORM = function DEFAULT_DATA_TRANSFORM(cell, column, index) { - return cell; -}; - -var DEFAULTS = Object.freeze({ - maxWidth: Infinity, - minWidth: 0, - columnSplitter: ' ', - truncate: false, - truncateMarker: '…', - preserveNewLines: false, - paddingChr: ' ', - showHeaders: true, - headingTransform: DEFAULT_HEADING_TRANSFORM, - dataTransform: DEFAULT_DATA_TRANSFORM -}); - -module.exports = function (items) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - - var columnConfigs = options.config || {}; - delete options.config; // remove config so doesn't appear on every column. - - var maxLineWidth = options.maxLineWidth || Infinity; - if (maxLineWidth === 'auto') maxLineWidth = process.stdout.columns || Infinity; - delete options.maxLineWidth; // this is a line control option, don't pass it to column - - // Option defaults inheritance: - // options.config[columnName] => options => DEFAULTS - options = mixin({}, DEFAULTS, options); - - options.config = options.config || Object.create(null); - - options.spacing = options.spacing || '\n'; // probably useless - options.preserveNewLines = !!options.preserveNewLines; - options.showHeaders = !!options.showHeaders; - options.columns = options.columns || options.include; // alias include/columns, prefer columns if supplied - var columnNames = options.columns || []; // optional user-supplied columns to include - - items = toArray(items, columnNames); - - // if not suppled column names, automatically determine columns from data keys - if (!columnNames.length) { - items.forEach(function (item) { - for (var columnName in item) { - if (columnNames.indexOf(columnName) === -1) columnNames.push(columnName); - } - }); - } - - // initialize column defaults (each column inherits from options.config) - var columns = columnNames.reduce(function (columns, columnName) { - var column = Object.create(options); - columns[columnName] = mixin(column, columnConfigs[columnName]); - return columns; - }, Object.create(null)); - - // sanitize column settings - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - column.name = columnName; - column.maxWidth = Math.ceil(column.maxWidth); - column.minWidth = Math.ceil(column.minWidth); - column.truncate = !!column.truncate; - column.align = column.align || 'left'; - }); - - // sanitize data - items = items.map(function (item) { - var result = Object.create(null); - columnNames.forEach(function (columnName) { - // null/undefined -> '' - result[columnName] = item[columnName] != null ? item[columnName] : ''; - // toString everything - result[columnName] = '' + result[columnName]; - if (columns[columnName].preserveNewLines) { - // merge non-newline whitespace chars - result[columnName] = result[columnName].replace(/[^\S\n]/gmi, ' '); - } else { - // merge all whitespace chars - result[columnName] = result[columnName].replace(/\s/gmi, ' '); - } - }); - return result; - }); - - // transform data cells - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - items = items.map(function (item, index) { - var col = Object.create(column); - item[columnName] = column.dataTransform(item[columnName], col, index); - - var changedKeys = Object.keys(col); - // disable default heading transform if we wrote to column.name - if (changedKeys.indexOf('name') !== -1) { - if (column.headingTransform !== DEFAULT_HEADING_TRANSFORM) return; - column.headingTransform = function (heading) { - return heading; - }; - } - changedKeys.forEach(function (key) { - return column[key] = col[key]; - }); - return item; - }); - }); - - // add headers - var headers = {}; - if (options.showHeaders) { - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - - if (!column.showHeaders) { - headers[columnName] = ''; - return; - } - - headers[columnName] = column.headingTransform(column.name); - }); - items.unshift(headers); - } - // get actual max-width between min & max - // based on length of data in columns - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - column.width = items.map(function (item) { - return item[columnName]; - }).reduce(function (min, cur) { - // if already at maxWidth don't bother testing - if (min >= column.maxWidth) return min; - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))); - }, 0); - }); - - // split long words so they can break onto multiple lines - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - items = items.map(function (item) { - item[columnName] = splitLongWords(item[columnName], column.width, column.truncateMarker); - return item; - }); - }); - - // wrap long lines. each item is now an array of lines. - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - items = items.map(function (item, index) { - var cell = item[columnName]; - item[columnName] = splitIntoLines(cell, column.width); - - // if truncating required, only include first line + add truncation char - if (column.truncate && item[columnName].length > 1) { - item[columnName] = splitIntoLines(cell, column.width - wcwidth(column.truncateMarker)); - var firstLine = item[columnName][0]; - if (!endsWith(firstLine, column.truncateMarker)) item[columnName][0] += column.truncateMarker; - item[columnName] = item[columnName].slice(0, 1); - } - return item; - }); - }); - - // recalculate column widths from truncated output/lines - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - column.width = items.map(function (item) { - return item[columnName].reduce(function (min, cur) { - if (min >= column.maxWidth) return min; - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))); - }, 0); - }).reduce(function (min, cur) { - if (min >= column.maxWidth) return min; - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, cur))); - }, 0); - }); - - var rows = createRows(items, columns, columnNames, options.paddingChr); // merge lines into rows - // conceive output - return rows.reduce(function (output, row) { - return output.concat(row.reduce(function (rowOut, line) { - return rowOut.concat(line.join(options.columnSplitter)); - }, [])); - }, []).map(function (line) { - return truncateString(line, maxLineWidth); - }).join(options.spacing); -}; - -/** - * Convert wrapped lines into rows with padded values. - * - * @param Array items data to process - * @param Array columns column width settings for wrapping - * @param Array columnNames column ordering - * @return Array items wrapped in arrays, corresponding to lines - */ - -function createRows(items, columns, columnNames, paddingChr) { - return items.map(function (item) { - var row = []; - var numLines = 0; - columnNames.forEach(function (columnName) { - numLines = Math.max(numLines, item[columnName].length); - }); - // combine matching lines of each rows - - var _loop = function _loop(i) { - row[i] = row[i] || []; - columnNames.forEach(function (columnName) { - var column = columns[columnName]; - var val = item[columnName][i] || ''; // || '' ensures empty columns get padded - if (column.align === 'right') row[i].push(padLeft(val, column.width, paddingChr));else if (column.align === 'center' || column.align === 'centre') row[i].push(padCenter(val, column.width, paddingChr));else row[i].push(padRight(val, column.width, paddingChr)); - }); - }; - - for (var i = 0; i < numLines; i++) { - _loop(i); - } - return row; - }); -} - -/** - * Object.assign - * - * @return Object Object with properties mixed in. - */ - -function mixin() { - if (Object.assign) return Object.assign.apply(Object, arguments); - return ObjectAssign.apply(undefined, arguments); -} - -function ObjectAssign(target, firstSource) { - "use strict"; - - if (target === undefined || target === null) throw new TypeError("Cannot convert first argument to object"); - - var to = Object(target); - - var hasPendingException = false; - var pendingException; - - for (var i = 1; i < arguments.length; i++) { - var nextSource = arguments[i]; - if (nextSource === undefined || nextSource === null) continue; - - var keysArray = Object.keys(Object(nextSource)); - for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { - var nextKey = keysArray[nextIndex]; - try { - var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); - if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey]; - } catch (e) { - if (!hasPendingException) { - hasPendingException = true; - pendingException = e; - } - } - } - - if (hasPendingException) throw pendingException; - } - return to; -} - -/** - * Adapted from String.prototype.endsWith polyfill. - */ - -function endsWith(target, searchString, position) { - position = position || target.length; - position = position - searchString.length; - var lastIndex = target.lastIndexOf(searchString); - return lastIndex !== -1 && lastIndex === position; -} - -function toArray(items, columnNames) { - if (Array.isArray(items)) return items; - var rows = []; - for (var key in items) { - var item = {}; - item[columnNames[0] || 'key'] = key; - item[columnNames[1] || 'value'] = items[key]; - rows.push(item); - } - return rows; -} - diff --git a/node_modules/columnify/index.js b/node_modules/columnify/index.js deleted file mode 100644 index 221269b3e76b7..0000000000000 --- a/node_modules/columnify/index.js +++ /dev/null @@ -1,297 +0,0 @@ -"use strict" - -const wcwidth = require('./width') -const { - padRight, - padCenter, - padLeft, - splitIntoLines, - splitLongWords, - truncateString -} = require('./utils') - -const DEFAULT_HEADING_TRANSFORM = key => key.toUpperCase() - -const DEFAULT_DATA_TRANSFORM = (cell, column, index) => cell - -const DEFAULTS = Object.freeze({ - maxWidth: Infinity, - minWidth: 0, - columnSplitter: ' ', - truncate: false, - truncateMarker: '…', - preserveNewLines: false, - paddingChr: ' ', - showHeaders: true, - headingTransform: DEFAULT_HEADING_TRANSFORM, - dataTransform: DEFAULT_DATA_TRANSFORM -}) - -module.exports = function(items, options = {}) { - - let columnConfigs = options.config || {} - delete options.config // remove config so doesn't appear on every column. - - let maxLineWidth = options.maxLineWidth || Infinity - if (maxLineWidth === 'auto') maxLineWidth = process.stdout.columns || Infinity - delete options.maxLineWidth // this is a line control option, don't pass it to column - - // Option defaults inheritance: - // options.config[columnName] => options => DEFAULTS - options = mixin({}, DEFAULTS, options) - - options.config = options.config || Object.create(null) - - options.spacing = options.spacing || '\n' // probably useless - options.preserveNewLines = !!options.preserveNewLines - options.showHeaders = !!options.showHeaders; - options.columns = options.columns || options.include // alias include/columns, prefer columns if supplied - let columnNames = options.columns || [] // optional user-supplied columns to include - - items = toArray(items, columnNames) - - // if not suppled column names, automatically determine columns from data keys - if (!columnNames.length) { - items.forEach(function(item) { - for (let columnName in item) { - if (columnNames.indexOf(columnName) === -1) columnNames.push(columnName) - } - }) - } - - // initialize column defaults (each column inherits from options.config) - let columns = columnNames.reduce((columns, columnName) => { - let column = Object.create(options) - columns[columnName] = mixin(column, columnConfigs[columnName]) - return columns - }, Object.create(null)) - - // sanitize column settings - columnNames.forEach(columnName => { - let column = columns[columnName] - column.name = columnName - column.maxWidth = Math.ceil(column.maxWidth) - column.minWidth = Math.ceil(column.minWidth) - column.truncate = !!column.truncate - column.align = column.align || 'left' - }) - - // sanitize data - items = items.map(item => { - let result = Object.create(null) - columnNames.forEach(columnName => { - // null/undefined -> '' - result[columnName] = item[columnName] != null ? item[columnName] : '' - // toString everything - result[columnName] = '' + result[columnName] - if (columns[columnName].preserveNewLines) { - // merge non-newline whitespace chars - result[columnName] = result[columnName].replace(/[^\S\n]/gmi, ' ') - } else { - // merge all whitespace chars - result[columnName] = result[columnName].replace(/\s/gmi, ' ') - } - }) - return result - }) - - // transform data cells - columnNames.forEach(columnName => { - let column = columns[columnName] - items = items.map((item, index) => { - let col = Object.create(column) - item[columnName] = column.dataTransform(item[columnName], col, index) - - let changedKeys = Object.keys(col) - // disable default heading transform if we wrote to column.name - if (changedKeys.indexOf('name') !== -1) { - if (column.headingTransform !== DEFAULT_HEADING_TRANSFORM) return - column.headingTransform = heading => heading - } - changedKeys.forEach(key => column[key] = col[key]) - return item - }) - }) - - // add headers - let headers = {} - if(options.showHeaders) { - columnNames.forEach(columnName => { - let column = columns[columnName] - - if(!column.showHeaders){ - headers[columnName] = ''; - return; - } - - headers[columnName] = column.headingTransform(column.name) - }) - items.unshift(headers) - } - // get actual max-width between min & max - // based on length of data in columns - columnNames.forEach(columnName => { - let column = columns[columnName] - column.width = items - .map(item => item[columnName]) - .reduce((min, cur) => { - // if already at maxWidth don't bother testing - if (min >= column.maxWidth) return min - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))) - }, 0) - }) - - // split long words so they can break onto multiple lines - columnNames.forEach(columnName => { - let column = columns[columnName] - items = items.map(item => { - item[columnName] = splitLongWords(item[columnName], column.width, column.truncateMarker) - return item - }) - }) - - // wrap long lines. each item is now an array of lines. - columnNames.forEach(columnName => { - let column = columns[columnName] - items = items.map((item, index) => { - let cell = item[columnName] - item[columnName] = splitIntoLines(cell, column.width) - - // if truncating required, only include first line + add truncation char - if (column.truncate && item[columnName].length > 1) { - item[columnName] = splitIntoLines(cell, column.width - wcwidth(column.truncateMarker)) - let firstLine = item[columnName][0] - if (!endsWith(firstLine, column.truncateMarker)) item[columnName][0] += column.truncateMarker - item[columnName] = item[columnName].slice(0, 1) - } - return item - }) - }) - - // recalculate column widths from truncated output/lines - columnNames.forEach(columnName => { - let column = columns[columnName] - column.width = items.map(item => { - return item[columnName].reduce((min, cur) => { - if (min >= column.maxWidth) return min - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur)))) - }, 0) - }).reduce((min, cur) => { - if (min >= column.maxWidth) return min - return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, cur))) - }, 0) - }) - - - let rows = createRows(items, columns, columnNames, options.paddingChr) // merge lines into rows - // conceive output - return rows.reduce((output, row) => { - return output.concat(row.reduce((rowOut, line) => { - return rowOut.concat(line.join(options.columnSplitter)) - }, [])) - }, []) - .map(line => truncateString(line, maxLineWidth)) - .join(options.spacing) -} - -/** - * Convert wrapped lines into rows with padded values. - * - * @param Array items data to process - * @param Array columns column width settings for wrapping - * @param Array columnNames column ordering - * @return Array items wrapped in arrays, corresponding to lines - */ - -function createRows(items, columns, columnNames, paddingChr) { - return items.map(item => { - let row = [] - let numLines = 0 - columnNames.forEach(columnName => { - numLines = Math.max(numLines, item[columnName].length) - }) - // combine matching lines of each rows - for (let i = 0; i < numLines; i++) { - row[i] = row[i] || [] - columnNames.forEach(columnName => { - let column = columns[columnName] - let val = item[columnName][i] || '' // || '' ensures empty columns get padded - if (column.align === 'right') row[i].push(padLeft(val, column.width, paddingChr)) - else if (column.align === 'center' || column.align === 'centre') row[i].push(padCenter(val, column.width, paddingChr)) - else row[i].push(padRight(val, column.width, paddingChr)) - }) - } - return row - }) -} - -/** - * Object.assign - * - * @return Object Object with properties mixed in. - */ - -function mixin(...args) { - if (Object.assign) return Object.assign(...args) - return ObjectAssign(...args) -} - -function ObjectAssign(target, firstSource) { - "use strict"; - if (target === undefined || target === null) - throw new TypeError("Cannot convert first argument to object"); - - var to = Object(target); - - var hasPendingException = false; - var pendingException; - - for (var i = 1; i < arguments.length; i++) { - var nextSource = arguments[i]; - if (nextSource === undefined || nextSource === null) - continue; - - var keysArray = Object.keys(Object(nextSource)); - for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { - var nextKey = keysArray[nextIndex]; - try { - var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); - if (desc !== undefined && desc.enumerable) - to[nextKey] = nextSource[nextKey]; - } catch (e) { - if (!hasPendingException) { - hasPendingException = true; - pendingException = e; - } - } - } - - if (hasPendingException) - throw pendingException; - } - return to; -} - -/** - * Adapted from String.prototype.endsWith polyfill. - */ - -function endsWith(target, searchString, position) { - position = position || target.length; - position = position - searchString.length; - let lastIndex = target.lastIndexOf(searchString); - return lastIndex !== -1 && lastIndex === position; -} - - -function toArray(items, columnNames) { - if (Array.isArray(items)) return items - let rows = [] - for (let key in items) { - let item = {} - item[columnNames[0] || 'key'] = key - item[columnNames[1] || 'value'] = items[key] - rows.push(item) - } - return rows -} diff --git a/node_modules/columnify/package.json b/node_modules/columnify/package.json deleted file mode 100644 index 29565407a8cd7..0000000000000 --- a/node_modules/columnify/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "columnify", - "version": "1.6.0", - "description": "Render data in text columns. Supports in-column text-wrap.", - "main": "columnify.js", - "scripts": { - "pretest": "npm prune", - "test": "make prepublish && tape test/*.js | tap-spec", - "bench": "npm test && node bench", - "prepublish": "make prepublish" - }, - "babel": { - "presets": [ - "es2015" - ] - }, - "author": "Tim Oxley", - "license": "MIT", - "devDependencies": { - "babel-cli": "^6.26.0", - "babel-preset-es2015": "^6.3.13", - "chalk": "^1.1.1", - "tap-spec": "^5.0.0", - "tape": "^4.4.0" - }, - "repository": { - "type": "git", - "url": "git://github.com/timoxley/columnify.git" - }, - "keywords": [ - "column", - "text", - "ansi", - "console", - "terminal", - "wrap", - "table" - ], - "bugs": { - "url": "https://github.com/timoxley/columnify/issues" - }, - "homepage": "https://github.com/timoxley/columnify", - "engines": { - "node": ">=8.0.0" - }, - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "directories": { - "test": "test" - } -} diff --git a/node_modules/columnify/utils.js b/node_modules/columnify/utils.js deleted file mode 100644 index df3e6cc44e856..0000000000000 --- a/node_modules/columnify/utils.js +++ /dev/null @@ -1,193 +0,0 @@ -"use strict" - -var wcwidth = require('./width') - -/** - * repeat string `str` up to total length of `len` - * - * @param String str string to repeat - * @param Number len total length of output string - */ - -function repeatString(str, len) { - return Array.apply(null, {length: len + 1}).join(str).slice(0, len) -} - -/** - * Pad `str` up to total length `max` with `chr`. - * If `str` is longer than `max`, padRight will return `str` unaltered. - * - * @param String str string to pad - * @param Number max total length of output string - * @param String chr optional. Character to pad with. default: ' ' - * @return String padded str - */ - -function padRight(str, max, chr) { - str = str != null ? str : '' - str = String(str) - var length = max - wcwidth(str) - if (length <= 0) return str - return str + repeatString(chr || ' ', length) -} - -/** - * Pad `str` up to total length `max` with `chr`. - * If `str` is longer than `max`, padCenter will return `str` unaltered. - * - * @param String str string to pad - * @param Number max total length of output string - * @param String chr optional. Character to pad with. default: ' ' - * @return String padded str - */ - -function padCenter(str, max, chr) { - str = str != null ? str : '' - str = String(str) - var length = max - wcwidth(str) - if (length <= 0) return str - var lengthLeft = Math.floor(length/2) - var lengthRight = length - lengthLeft - return repeatString(chr || ' ', lengthLeft) + str + repeatString(chr || ' ', lengthRight) -} - -/** - * Pad `str` up to total length `max` with `chr`, on the left. - * If `str` is longer than `max`, padRight will return `str` unaltered. - * - * @param String str string to pad - * @param Number max total length of output string - * @param String chr optional. Character to pad with. default: ' ' - * @return String padded str - */ - -function padLeft(str, max, chr) { - str = str != null ? str : '' - str = String(str) - var length = max - wcwidth(str) - if (length <= 0) return str - return repeatString(chr || ' ', length) + str -} - -/** - * Split a String `str` into lines of maxiumum length `max`. - * Splits on word boundaries. Preserves existing new lines. - * - * @param String str string to split - * @param Number max length of each line - * @return Array Array containing lines. - */ - -function splitIntoLines(str, max) { - function _splitIntoLines(str, max) { - return str.trim().split(' ').reduce(function(lines, word) { - var line = lines[lines.length - 1] - if (line && wcwidth(line.join(' ')) + wcwidth(word) < max) { - lines[lines.length - 1].push(word) // add to line - } - else lines.push([word]) // new line - return lines - }, []).map(function(l) { - return l.join(' ') - }) - } - return str.split('\n').map(function(str) { - return _splitIntoLines(str, max) - }).reduce(function(lines, line) { - return lines.concat(line) - }, []) -} - -/** - * Add spaces and `truncationChar` between words of - * `str` which are longer than `max`. - * - * @param String str string to split - * @param Number max length of each line - * @param Number truncationChar character to append to split words - * @return String - */ - -function splitLongWords(str, max, truncationChar) { - str = str.trim() - var result = [] - var words = str.split(' ') - var remainder = '' - - var truncationWidth = wcwidth(truncationChar) - - while (remainder || words.length) { - if (remainder) { - var word = remainder - remainder = '' - } else { - var word = words.shift() - } - - if (wcwidth(word) > max) { - // slice is based on length no wcwidth - var i = 0 - var wwidth = 0 - var limit = max - truncationWidth - while (i < word.length) { - var w = wcwidth(word.charAt(i)) - if (w + wwidth > limit) { - break - } - wwidth += w - ++i - } - - remainder = word.slice(i) // get remainder - // save remainder for next loop - - word = word.slice(0, i) // grab truncated word - word += truncationChar // add trailing … or whatever - } - result.push(word) - } - - return result.join(' ') -} - - -/** - * Truncate `str` into total width `max` - * If `str` is shorter than `max`, will return `str` unaltered. - * - * @param String str string to truncated - * @param Number max total wcwidth of output string - * @return String truncated str - */ - -function truncateString(str, max) { - - str = str != null ? str : '' - str = String(str) - - if(max == Infinity) return str - - var i = 0 - var wwidth = 0 - while (i < str.length) { - var w = wcwidth(str.charAt(i)) - if(w + wwidth > max) - break - wwidth += w - ++i - } - return str.slice(0, i) -} - - - -/** - * Exports - */ - -module.exports.padRight = padRight -module.exports.padCenter = padCenter -module.exports.padLeft = padLeft -module.exports.splitIntoLines = splitIntoLines -module.exports.splitLongWords = splitLongWords -module.exports.truncateString = truncateString diff --git a/node_modules/columnify/width.js b/node_modules/columnify/width.js deleted file mode 100644 index a9f5333b40b2f..0000000000000 --- a/node_modules/columnify/width.js +++ /dev/null @@ -1,6 +0,0 @@ -var stripAnsi = require('strip-ansi') -var wcwidth = require('wcwidth') - -module.exports = function(str) { - return wcwidth(stripAnsi(str)) -} diff --git a/node_modules/defaults/LICENSE b/node_modules/defaults/LICENSE deleted file mode 100644 index 11eb6fdebf3b6..0000000000000 --- a/node_modules/defaults/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2022 Sindre Sorhus -Copyright (c) 2015 Elijah Insua - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/node_modules/defaults/index.js b/node_modules/defaults/index.js deleted file mode 100644 index cb7d75c9c6beb..0000000000000 --- a/node_modules/defaults/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var clone = require('clone'); - -module.exports = function(options, defaults) { - options = options || {}; - - Object.keys(defaults).forEach(function(key) { - if (typeof options[key] === 'undefined') { - options[key] = clone(defaults[key]); - } - }); - - return options; -}; \ No newline at end of file diff --git a/node_modules/defaults/package.json b/node_modules/defaults/package.json deleted file mode 100644 index 44f72b1714ce4..0000000000000 --- a/node_modules/defaults/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "defaults", - "version": "1.0.4", - "description": "merge single level defaults over a config object", - "main": "index.js", - "funding": "https://github.com/sponsors/sindresorhus", - "scripts": { - "test": "node test.js" - }, - "repository": { - "type": "git", - "url": "git://github.com/sindresorhus/node-defaults.git" - }, - "keywords": [ - "config", - "defaults", - "options", - "object", - "merge", - "assign", - "properties", - "deep" - ], - "author": "Elijah Insua ", - "license": "MIT", - "readmeFilename": "README.md", - "dependencies": { - "clone": "^1.0.2" - }, - "devDependencies": { - "tap": "^2.0.0" - } -} diff --git a/node_modules/defaults/test.js b/node_modules/defaults/test.js deleted file mode 100644 index 60e0ffba8b4aa..0000000000000 --- a/node_modules/defaults/test.js +++ /dev/null @@ -1,34 +0,0 @@ -var defaults = require('./'), - test = require('tap').test; - -test("ensure options is an object", function(t) { - var options = defaults(false, { a : true }); - t.ok(options.a); - t.end() -}); - -test("ensure defaults override keys", function(t) { - var result = defaults({}, { a: false, b: true }); - t.ok(result.b, 'b merges over undefined'); - t.equal(result.a, false, 'a merges over undefined'); - t.end(); -}); - -test("ensure defined keys are not overwritten", function(t) { - var result = defaults({ b: false }, { a: false, b: true }); - t.equal(result.b, false, 'b not merged'); - t.equal(result.a, false, 'a merges over undefined'); - t.end(); -}); - -test("ensure defaults clone nested objects", function(t) { - var d = { a: [1,2,3], b: { hello : 'world' } }; - var result = defaults({}, d); - t.equal(result.a.length, 3, 'objects should be clones'); - t.ok(result.a !== d.a, 'objects should be clones'); - - t.equal(Object.keys(result.b).length, 1, 'objects should be clones'); - t.ok(result.b !== d.b, 'objects should be clones'); - t.end(); -}); - diff --git a/node_modules/wcwidth/LICENSE b/node_modules/wcwidth/LICENSE deleted file mode 100644 index 313ef1e888e41..0000000000000 --- a/node_modules/wcwidth/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -wcwidth.js: JavaScript Portng of Markus Kuhn's wcwidth() Implementation -======================================================================= - -Copyright (C) 2012 by Jun Woong. - -This package is a JavaScript porting of `wcwidth()` implementation -[by Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c). - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/node_modules/wcwidth/combining.js b/node_modules/wcwidth/combining.js deleted file mode 100644 index dac9789d35f0f..0000000000000 --- a/node_modules/wcwidth/combining.js +++ /dev/null @@ -1,50 +0,0 @@ -module.exports = [ - [ 0x0300, 0x036F ], [ 0x0483, 0x0486 ], [ 0x0488, 0x0489 ], - [ 0x0591, 0x05BD ], [ 0x05BF, 0x05BF ], [ 0x05C1, 0x05C2 ], - [ 0x05C4, 0x05C5 ], [ 0x05C7, 0x05C7 ], [ 0x0600, 0x0603 ], - [ 0x0610, 0x0615 ], [ 0x064B, 0x065E ], [ 0x0670, 0x0670 ], - [ 0x06D6, 0x06E4 ], [ 0x06E7, 0x06E8 ], [ 0x06EA, 0x06ED ], - [ 0x070F, 0x070F ], [ 0x0711, 0x0711 ], [ 0x0730, 0x074A ], - [ 0x07A6, 0x07B0 ], [ 0x07EB, 0x07F3 ], [ 0x0901, 0x0902 ], - [ 0x093C, 0x093C ], [ 0x0941, 0x0948 ], [ 0x094D, 0x094D ], - [ 0x0951, 0x0954 ], [ 0x0962, 0x0963 ], [ 0x0981, 0x0981 ], - [ 0x09BC, 0x09BC ], [ 0x09C1, 0x09C4 ], [ 0x09CD, 0x09CD ], - [ 0x09E2, 0x09E3 ], [ 0x0A01, 0x0A02 ], [ 0x0A3C, 0x0A3C ], - [ 0x0A41, 0x0A42 ], [ 0x0A47, 0x0A48 ], [ 0x0A4B, 0x0A4D ], - [ 0x0A70, 0x0A71 ], [ 0x0A81, 0x0A82 ], [ 0x0ABC, 0x0ABC ], - [ 0x0AC1, 0x0AC5 ], [ 0x0AC7, 0x0AC8 ], [ 0x0ACD, 0x0ACD ], - [ 0x0AE2, 0x0AE3 ], [ 0x0B01, 0x0B01 ], [ 0x0B3C, 0x0B3C ], - [ 0x0B3F, 0x0B3F ], [ 0x0B41, 0x0B43 ], [ 0x0B4D, 0x0B4D ], - [ 0x0B56, 0x0B56 ], [ 0x0B82, 0x0B82 ], [ 0x0BC0, 0x0BC0 ], - [ 0x0BCD, 0x0BCD ], [ 0x0C3E, 0x0C40 ], [ 0x0C46, 0x0C48 ], - [ 0x0C4A, 0x0C4D ], [ 0x0C55, 0x0C56 ], [ 0x0CBC, 0x0CBC ], - [ 0x0CBF, 0x0CBF ], [ 0x0CC6, 0x0CC6 ], [ 0x0CCC, 0x0CCD ], - [ 0x0CE2, 0x0CE3 ], [ 0x0D41, 0x0D43 ], [ 0x0D4D, 0x0D4D ], - [ 0x0DCA, 0x0DCA ], [ 0x0DD2, 0x0DD4 ], [ 0x0DD6, 0x0DD6 ], - [ 0x0E31, 0x0E31 ], [ 0x0E34, 0x0E3A ], [ 0x0E47, 0x0E4E ], - [ 0x0EB1, 0x0EB1 ], [ 0x0EB4, 0x0EB9 ], [ 0x0EBB, 0x0EBC ], - [ 0x0EC8, 0x0ECD ], [ 0x0F18, 0x0F19 ], [ 0x0F35, 0x0F35 ], - [ 0x0F37, 0x0F37 ], [ 0x0F39, 0x0F39 ], [ 0x0F71, 0x0F7E ], - [ 0x0F80, 0x0F84 ], [ 0x0F86, 0x0F87 ], [ 0x0F90, 0x0F97 ], - [ 0x0F99, 0x0FBC ], [ 0x0FC6, 0x0FC6 ], [ 0x102D, 0x1030 ], - [ 0x1032, 0x1032 ], [ 0x1036, 0x1037 ], [ 0x1039, 0x1039 ], - [ 0x1058, 0x1059 ], [ 0x1160, 0x11FF ], [ 0x135F, 0x135F ], - [ 0x1712, 0x1714 ], [ 0x1732, 0x1734 ], [ 0x1752, 0x1753 ], - [ 0x1772, 0x1773 ], [ 0x17B4, 0x17B5 ], [ 0x17B7, 0x17BD ], - [ 0x17C6, 0x17C6 ], [ 0x17C9, 0x17D3 ], [ 0x17DD, 0x17DD ], - [ 0x180B, 0x180D ], [ 0x18A9, 0x18A9 ], [ 0x1920, 0x1922 ], - [ 0x1927, 0x1928 ], [ 0x1932, 0x1932 ], [ 0x1939, 0x193B ], - [ 0x1A17, 0x1A18 ], [ 0x1B00, 0x1B03 ], [ 0x1B34, 0x1B34 ], - [ 0x1B36, 0x1B3A ], [ 0x1B3C, 0x1B3C ], [ 0x1B42, 0x1B42 ], - [ 0x1B6B, 0x1B73 ], [ 0x1DC0, 0x1DCA ], [ 0x1DFE, 0x1DFF ], - [ 0x200B, 0x200F ], [ 0x202A, 0x202E ], [ 0x2060, 0x2063 ], - [ 0x206A, 0x206F ], [ 0x20D0, 0x20EF ], [ 0x302A, 0x302F ], - [ 0x3099, 0x309A ], [ 0xA806, 0xA806 ], [ 0xA80B, 0xA80B ], - [ 0xA825, 0xA826 ], [ 0xFB1E, 0xFB1E ], [ 0xFE00, 0xFE0F ], - [ 0xFE20, 0xFE23 ], [ 0xFEFF, 0xFEFF ], [ 0xFFF9, 0xFFFB ], - [ 0x10A01, 0x10A03 ], [ 0x10A05, 0x10A06 ], [ 0x10A0C, 0x10A0F ], - [ 0x10A38, 0x10A3A ], [ 0x10A3F, 0x10A3F ], [ 0x1D167, 0x1D169 ], - [ 0x1D173, 0x1D182 ], [ 0x1D185, 0x1D18B ], [ 0x1D1AA, 0x1D1AD ], - [ 0x1D242, 0x1D244 ], [ 0xE0001, 0xE0001 ], [ 0xE0020, 0xE007F ], - [ 0xE0100, 0xE01EF ] -] diff --git a/node_modules/wcwidth/docs/index.md b/node_modules/wcwidth/docs/index.md deleted file mode 100644 index 5c5126d03287b..0000000000000 --- a/node_modules/wcwidth/docs/index.md +++ /dev/null @@ -1,65 +0,0 @@ -### Javascript porting of Markus Kuhn's wcwidth() implementation - -The following explanation comes from the original C implementation: - -This is an implementation of wcwidth() and wcswidth() (defined in -IEEE Std 1002.1-2001) for Unicode. - -http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html -http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html - -In fixed-width output devices, Latin characters all occupy a single -"cell" position of equal width, whereas ideographic CJK characters -occupy two such cells. Interoperability between terminal-line -applications and (teletype-style) character terminals using the -UTF-8 encoding requires agreement on which character should advance -the cursor by how many cell positions. No established formal -standards exist at present on which Unicode character shall occupy -how many cell positions on character terminals. These routines are -a first attempt of defining such behavior based on simple rules -applied to data provided by the Unicode Consortium. - -For some graphical characters, the Unicode standard explicitly -defines a character-cell width via the definition of the East Asian -FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. -In all these cases, there is no ambiguity about which width a -terminal shall use. For characters in the East Asian Ambiguous (A) -class, the width choice depends purely on a preference of backward -compatibility with either historic CJK or Western practice. -Choosing single-width for these characters is easy to justify as -the appropriate long-term solution, as the CJK practice of -displaying these characters as double-width comes from historic -implementation simplicity (8-bit encoded characters were displayed -single-width and 16-bit ones double-width, even for Greek, -Cyrillic, etc.) and not any typographic considerations. - -Much less clear is the choice of width for the Not East Asian -(Neutral) class. Existing practice does not dictate a width for any -of these characters. It would nevertheless make sense -typographically to allocate two character cells to characters such -as for instance EM SPACE or VOLUME INTEGRAL, which cannot be -represented adequately with a single-width glyph. The following -routines at present merely assign a single-cell width to all -neutral characters, in the interest of simplicity. This is not -entirely satisfactory and should be reconsidered before -establishing a formal standard in this area. At the moment, the -decision which Not East Asian (Neutral) characters should be -represented by double-width glyphs cannot yet be answered by -applying a simple rule from the Unicode database content. Setting -up a proper standard for the behavior of UTF-8 character terminals -will require a careful analysis not only of each Unicode character, -but also of each presentation form, something the author of these -routines has avoided to do so far. - -http://www.unicode.org/unicode/reports/tr11/ - -Markus Kuhn -- 2007-05-26 (Unicode 5.0) - -Permission to use, copy, modify, and distribute this software -for any purpose and without fee is hereby granted. The author -disclaims all warranties with regard to this software. - -Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c - - - diff --git a/node_modules/wcwidth/index.js b/node_modules/wcwidth/index.js deleted file mode 100644 index 48cbb6020aebe..0000000000000 --- a/node_modules/wcwidth/index.js +++ /dev/null @@ -1,99 +0,0 @@ -"use strict" - -var defaults = require('defaults') -var combining = require('./combining') - -var DEFAULTS = { - nul: 0, - control: 0 -} - -module.exports = function wcwidth(str) { - return wcswidth(str, DEFAULTS) -} - -module.exports.config = function(opts) { - opts = defaults(opts || {}, DEFAULTS) - return function wcwidth(str) { - return wcswidth(str, opts) - } -} - -/* - * The following functions define the column width of an ISO 10646 - * character as follows: - * - The null character (U+0000) has a column width of 0. - * - Other C0/C1 control characters and DEL will lead to a return value - * of -1. - * - Non-spacing and enclosing combining characters (general category - * code Mn or Me in the - * Unicode database) have a column width of 0. - * - SOFT HYPHEN (U+00AD) has a column width of 1. - * - Other format characters (general category code Cf in the Unicode - * database) and ZERO WIDTH - * SPACE (U+200B) have a column width of 0. - * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) - * have a column width of 0. - * - Spacing characters in the East Asian Wide (W) or East Asian - * Full-width (F) category as - * defined in Unicode Technical Report #11 have a column width of 2. - * - All remaining characters (including all printable ISO 8859-1 and - * WGL4 characters, Unicode control characters, etc.) have a column - * width of 1. - * This implementation assumes that characters are encoded in ISO 10646. -*/ - -function wcswidth(str, opts) { - if (typeof str !== 'string') return wcwidth(str, opts) - - var s = 0 - for (var i = 0; i < str.length; i++) { - var n = wcwidth(str.charCodeAt(i), opts) - if (n < 0) return -1 - s += n - } - - return s -} - -function wcwidth(ucs, opts) { - // test for 8-bit control characters - if (ucs === 0) return opts.nul - if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return opts.control - - // binary search in table of non-spacing characters - if (bisearch(ucs)) return 0 - - // if we arrive here, ucs is not a combining or C0/C1 control character - return 1 + - (ucs >= 0x1100 && - (ucs <= 0x115f || // Hangul Jamo init. consonants - ucs == 0x2329 || ucs == 0x232a || - (ucs >= 0x2e80 && ucs <= 0xa4cf && - ucs != 0x303f) || // CJK ... Yi - (ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables - (ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compatibility Ideographs - (ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms - (ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compatibility Forms - (ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms - (ucs >= 0xffe0 && ucs <= 0xffe6) || - (ucs >= 0x20000 && ucs <= 0x2fffd) || - (ucs >= 0x30000 && ucs <= 0x3fffd))); -} - -function bisearch(ucs) { - var min = 0 - var max = combining.length - 1 - var mid - - if (ucs < combining[0][0] || ucs > combining[max][1]) return false - - while (max >= min) { - mid = Math.floor((min + max) / 2) - if (ucs > combining[mid][1]) min = mid + 1 - else if (ucs < combining[mid][0]) max = mid - 1 - else return true - } - - return false -} diff --git a/node_modules/wcwidth/package.json b/node_modules/wcwidth/package.json deleted file mode 100644 index eb2df9d0076d2..0000000000000 --- a/node_modules/wcwidth/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "wcwidth", - "version": "1.0.1", - "description": "Port of C's wcwidth() and wcswidth()", - "author": "Tim Oxley", - "contributors": [ - "Woong Jun (http://code.woong.org/)" - ], - "main": "index.js", - "dependencies": { - "defaults": "^1.0.3" - }, - "devDependencies": { - "tape": "^4.5.1" - }, - "license": "MIT", - "keywords": [ - "wide character", - "wc", - "wide character string", - "wcs", - "terminal", - "width", - "wcwidth", - "wcswidth" - ], - "directories": { - "doc": "docs", - "test": "test" - }, - "scripts": { - "test": "tape test/*.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/timoxley/wcwidth.git" - }, - "bugs": { - "url": "https://github.com/timoxley/wcwidth/issues" - }, - "homepage": "https://github.com/timoxley/wcwidth#readme" -} diff --git a/node_modules/wcwidth/test/index.js b/node_modules/wcwidth/test/index.js deleted file mode 100644 index 5180599a2ff28..0000000000000 --- a/node_modules/wcwidth/test/index.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict" - -var wcwidth = require('../') -var test = require('tape') - -test('handles regular strings', function(t) { - t.strictEqual(wcwidth('abc'), 3) - t.end() -}) - -test('handles multibyte strings', function(t) { - t.strictEqual(wcwidth('字的模块'), 8) - t.end() -}) - -test('handles multibyte characters mixed with regular characters', function(t) { - t.strictEqual(wcwidth('abc 字的模块'), 12) - t.end() -}) - -test('ignores control characters e.g. \\n', function(t) { - t.strictEqual(wcwidth('abc\n字的模块\ndef'), 14) - t.end() -}) - -test('ignores bad input', function(t) { - t.strictEqual(wcwidth(''), 0) - t.strictEqual(wcwidth(3), 0) - t.strictEqual(wcwidth({}), 0) - t.strictEqual(wcwidth([]), 0) - t.strictEqual(wcwidth(), 0) - t.end() -}) - -test('ignores nul (charcode 0)', function(t) { - t.strictEqual(wcwidth(String.fromCharCode(0)), 0) - t.end() -}) - -test('ignores nul mixed with chars', function(t) { - t.strictEqual(wcwidth('a' + String.fromCharCode(0) + '\n字的'), 5) - t.end() -}) - -test('can have custom value for nul', function(t) { - t.strictEqual(wcwidth.config({ - nul: 10 - })(String.fromCharCode(0) + 'a字的'), 15) - t.end() -}) - -test('can have custom control char value', function(t) { - t.strictEqual(wcwidth.config({ - control: 1 - })('abc\n字的模块\ndef'), 16) - t.end() -}) - -test('negative custom control chars == -1', function(t) { - t.strictEqual(wcwidth.config({ - control: -1 - })('abc\n字的模块\ndef'), -1) - t.end() -}) diff --git a/package-lock.json b/package-lock.json index 42ae49fd161d6..7fe5ed9560d93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,6 @@ "chalk", "ci-info", "cli-columns", - "columnify", "fastest-levenshtein", "fs-minipass", "glob", @@ -104,7 +103,6 @@ "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", - "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", "glob": "^10.3.12", @@ -3375,15 +3373,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "inBundle": true, - "engines": { - "node": ">=0.8" - } - }, "node_modules/cmd-shim": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.2.tgz", @@ -3552,19 +3541,6 @@ "color-support": "bin.js" } }, - "node_modules/columnify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", - "inBundle": true, - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -4155,18 +4131,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "inBundle": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -16013,15 +15977,6 @@ "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==" }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "inBundle": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", diff --git a/package.json b/package.json index 6661e394d4185..e3a2be0fd8b7a 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", - "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", "glob": "^10.3.12", @@ -139,7 +138,6 @@ "chalk", "ci-info", "cli-columns", - "columnify", "fastest-levenshtein", "fs-minipass", "glob", From b0ca16310d9db944dd13f80ecce534c65eea42c5 Mon Sep 17 00:00:00 2001 From: Gar Date: Tue, 23 Apr 2024 12:29:12 -0700 Subject: [PATCH 06/42] deps: remove @npmcli/disparity-colors This tiny single use package can live inline with where it's used --- DEPENDENCIES.md | 7 +- node_modules/.gitignore | 4 - node_modules/@npmcli/disparity-colors/LICENSE | 15 -- .../@npmcli/disparity-colors/lib/index.js | 34 ---- .../node_modules/ansi-styles/index.js | 163 ------------------ .../node_modules/ansi-styles/license | 9 - .../node_modules/ansi-styles/package.json | 56 ------ .../@npmcli/disparity-colors/package.json | 70 -------- package-lock.json | 26 --- workspaces/libnpmdiff/package.json | 1 - 10 files changed, 1 insertion(+), 384 deletions(-) delete mode 100644 node_modules/@npmcli/disparity-colors/LICENSE delete mode 100644 node_modules/@npmcli/disparity-colors/lib/index.js delete mode 100644 node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/index.js delete mode 100644 node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/license delete mode 100644 node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/package.json delete mode 100644 node_modules/@npmcli/disparity-colors/package.json diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 5462ad11da200..9eed49020e0c2 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -24,7 +24,6 @@ graph LR; libnpmaccess-->npmcli-template-oss["@npmcli/template-oss"]; libnpmdiff-->npm-package-arg; libnpmdiff-->npmcli-arborist["@npmcli/arborist"]; - libnpmdiff-->npmcli-disparity-colors["@npmcli/disparity-colors"]; libnpmdiff-->npmcli-eslint-config["@npmcli/eslint-config"]; libnpmdiff-->npmcli-installed-package-contents["@npmcli/installed-package-contents"]; libnpmdiff-->npmcli-template-oss["@npmcli/template-oss"]; @@ -266,7 +265,6 @@ graph LR; agent-base-->debug; aggregate-error-->clean-stack; aggregate-error-->indent-string; - ansi-styles-->color-convert; bin-links-->cmd-shim; bin-links-->npm-normalize-package-bin; bin-links-->read-cmd-shim; @@ -288,7 +286,6 @@ graph LR; cidr-regex-->ip-regex; cli-columns-->string-width; cli-columns-->strip-ansi; - color-convert-->color-name; cross-spawn-->path-key; cross-spawn-->shebang-command; cross-spawn-->which; @@ -341,7 +338,6 @@ graph LR; libnpmdiff-->minimatch; libnpmdiff-->npm-package-arg; libnpmdiff-->npmcli-arborist["@npmcli/arborist"]; - libnpmdiff-->npmcli-disparity-colors["@npmcli/disparity-colors"]; libnpmdiff-->npmcli-eslint-config["@npmcli/eslint-config"]; libnpmdiff-->npmcli-installed-package-contents["@npmcli/installed-package-contents"]; libnpmdiff-->npmcli-template-oss["@npmcli/template-oss"]; @@ -638,7 +634,6 @@ graph LR; npmcli-config-->semver; npmcli-config-->tap; npmcli-config-->walk-up-path; - npmcli-disparity-colors-->ansi-styles; npmcli-docs-->front-matter; npmcli-docs-->ignore-walk; npmcli-docs-->isaacs-string-locale-compare["@isaacs/string-locale-compare"]; @@ -818,4 +813,4 @@ packages higher up the chain. - @npmcli/git, make-fetch-happen, @npmcli/config - @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, read-package-json, promzard - @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, normalize-package-data, npm-packlist, bin-links, nopt, parse-conflict-json, @npmcli/mock-globals, read - - @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, @npmcli/redact, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, proggy, minify-registry-metadata, ini, @npmcli/disparity-colors, mute-stream, npm-audit-report, npm-user-validate + - @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, @npmcli/redact, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, proggy, minify-registry-metadata, ini, mute-stream, npm-audit-report, npm-user-validate diff --git a/node_modules/.gitignore b/node_modules/.gitignore index 6e00159ec7a0f..09610fb1b697d 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -16,10 +16,6 @@ !/@npmcli/ /@npmcli/* !/@npmcli/agent -!/@npmcli/disparity-colors -!/@npmcli/disparity-colors/node_modules/ -/@npmcli/disparity-colors/node_modules/* -!/@npmcli/disparity-colors/node_modules/ansi-styles !/@npmcli/fs !/@npmcli/git !/@npmcli/installed-package-contents diff --git a/node_modules/@npmcli/disparity-colors/LICENSE b/node_modules/@npmcli/disparity-colors/LICENSE deleted file mode 100644 index dedcd7d2f9dae..0000000000000 --- a/node_modules/@npmcli/disparity-colors/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) npm Inc. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/@npmcli/disparity-colors/lib/index.js b/node_modules/@npmcli/disparity-colors/lib/index.js deleted file mode 100644 index 3d2aa56be9253..0000000000000 --- a/node_modules/@npmcli/disparity-colors/lib/index.js +++ /dev/null @@ -1,34 +0,0 @@ -const ansi = require('ansi-styles') - -const colors = { - removed: ansi.red, - added: ansi.green, - header: ansi.yellow, - section: ansi.magenta, -} - -function colorize (str, opts) { - let headerLength = (opts || {}).headerLength - if (typeof headerLength !== 'number' || Number.isNaN(headerLength)) { - headerLength = 2 - } - - const color = (colorStr, colorId) => { - const { open, close } = colors[colorId] - // avoid highlighting the "\n" (would highlight till the end of the line) - return colorStr.replace(/[^\n\r]+/g, open + '$&' + close) - } - - // this RegExp will include all the `\n` chars into the lines, easier to join - const lines = ((typeof str === 'string' && str) || '').split(/^/m) - - const start = color(lines.slice(0, headerLength).join(''), 'header') - const end = lines.slice(headerLength).join('') - .replace(/^-.*/gm, color('$&', 'removed')) - .replace(/^\+.*/gm, color('$&', 'added')) - .replace(/^@@.+@@/gm, color('$&', 'section')) - - return start + end -} - -module.exports = colorize diff --git a/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/index.js b/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/index.js deleted file mode 100644 index 5d82581a13f99..0000000000000 --- a/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/index.js +++ /dev/null @@ -1,163 +0,0 @@ -'use strict'; - -const wrapAnsi16 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${code + offset}m`; -}; - -const wrapAnsi256 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${38 + offset};5;${code}m`; -}; - -const wrapAnsi16m = (fn, offset) => (...args) => { - const rgb = fn(...args); - return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; -}; - -const ansi2ansi = n => n; -const rgb2rgb = (r, g, b) => [r, g, b]; - -const setLazyProperty = (object, property, get) => { - Object.defineProperty(object, property, { - get: () => { - const value = get(); - - Object.defineProperty(object, property, { - value, - enumerable: true, - configurable: true - }); - - return value; - }, - enumerable: true, - configurable: true - }); -}; - -/** @type {typeof import('color-convert')} */ -let colorConvert; -const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { - if (colorConvert === undefined) { - colorConvert = require('color-convert'); - } - - const offset = isBackground ? 10 : 0; - const styles = {}; - - for (const [sourceSpace, suite] of Object.entries(colorConvert)) { - const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; - if (sourceSpace === targetSpace) { - styles[name] = wrap(identity, offset); - } else if (typeof suite === 'object') { - styles[name] = wrap(suite[targetSpace], offset); - } - } - - return styles; -}; - -function assembleStyles() { - const codes = new Map(); - const styles = { - modifier: { - reset: [0, 0], - // 21 isn't widely supported and 22 does the same thing - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29] - }, - color: { - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], - - // Bright color - blackBright: [90, 39], - redBright: [91, 39], - greenBright: [92, 39], - yellowBright: [93, 39], - blueBright: [94, 39], - magentaBright: [95, 39], - cyanBright: [96, 39], - whiteBright: [97, 39] - }, - bgColor: { - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - - // Bright color - bgBlackBright: [100, 49], - bgRedBright: [101, 49], - bgGreenBright: [102, 49], - bgYellowBright: [103, 49], - bgBlueBright: [104, 49], - bgMagentaBright: [105, 49], - bgCyanBright: [106, 49], - bgWhiteBright: [107, 49] - } - }; - - // Alias bright black as gray (and grey) - styles.color.gray = styles.color.blackBright; - styles.bgColor.bgGray = styles.bgColor.bgBlackBright; - styles.color.grey = styles.color.blackBright; - styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; - - for (const [groupName, group] of Object.entries(styles)) { - for (const [styleName, style] of Object.entries(group)) { - styles[styleName] = { - open: `\u001B[${style[0]}m`, - close: `\u001B[${style[1]}m` - }; - - group[styleName] = styles[styleName]; - - codes.set(style[0], style[1]); - } - - Object.defineProperty(styles, groupName, { - value: group, - enumerable: false - }); - } - - Object.defineProperty(styles, 'codes', { - value: codes, - enumerable: false - }); - - styles.color.close = '\u001B[39m'; - styles.bgColor.close = '\u001B[49m'; - - setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); - setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); - - return styles; -} - -// Make the export immutable -Object.defineProperty(module, 'exports', { - enumerable: true, - get: assembleStyles -}); diff --git a/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/license b/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/license deleted file mode 100644 index e7af2f77107d7..0000000000000 --- a/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/license +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/package.json b/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/package.json deleted file mode 100644 index 75393284d7e47..0000000000000 --- a/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "ansi-styles", - "version": "4.3.0", - "description": "ANSI escape codes for styling strings in the terminal", - "license": "MIT", - "repository": "chalk/ansi-styles", - "funding": "https://github.com/chalk/ansi-styles?sponsor=1", - "author": { - "name": "Sindre Sorhus", - "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" - }, - "engines": { - "node": ">=8" - }, - "scripts": { - "test": "xo && ava && tsd", - "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor" - }, - "files": [ - "index.js", - "index.d.ts" - ], - "keywords": [ - "ansi", - "styles", - "color", - "colour", - "colors", - "terminal", - "console", - "cli", - "string", - "tty", - "escape", - "formatting", - "rgb", - "256", - "shell", - "xterm", - "log", - "logging", - "command-line", - "text" - ], - "dependencies": { - "color-convert": "^2.0.1" - }, - "devDependencies": { - "@types/color-convert": "^1.9.0", - "ava": "^2.3.0", - "svg-term-cli": "^2.1.1", - "tsd": "^0.11.0", - "xo": "^0.25.3" - } -} diff --git a/node_modules/@npmcli/disparity-colors/package.json b/node_modules/@npmcli/disparity-colors/package.json deleted file mode 100644 index 17eb4846c353c..0000000000000 --- a/node_modules/@npmcli/disparity-colors/package.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "@npmcli/disparity-colors", - "version": "3.0.0", - "main": "lib/index.js", - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "description": "Colorizes unified diff output", - "repository": { - "type": "git", - "url": "https://github.com/npm/disparity-colors.git" - }, - "keywords": [ - "disparity", - "npm", - "npmcli", - "diff", - "char", - "unified", - "multiline", - "string", - "color", - "ansi", - "terminal", - "cli", - "tty" - ], - "author": "GitHub Inc.", - "contributors": [ - { - "name": "Ruy Adorno", - "url": "https://ruyadorno.com", - "twitter": "ruyadorno" - } - ], - "license": "ISC", - "scripts": { - "lint": "eslint \"**/*.js\"", - "pretest": "npm run lint", - "test": "tap", - "snap": "tap", - "postlint": "template-oss-check", - "template-oss-apply": "template-oss-apply --force", - "lintfix": "npm run lint -- --fix", - "posttest": "npm run lint" - }, - "tap": { - "check-coverage": true, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "devDependencies": { - "@npmcli/eslint-config": "^3.0.1", - "@npmcli/template-oss": "4.5.1", - "tap": "^16.0.1" - }, - "dependencies": { - "ansi-styles": "^4.3.0" - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.5.1" - } -} diff --git a/package-lock.json b/package-lock.json index 7fe5ed9560d93..f3f5725153dd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1621,31 +1621,6 @@ "resolved": "workspaces/config", "link": true }, - "node_modules/@npmcli/disparity-colors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/disparity-colors/-/disparity-colors-3.0.0.tgz", - "integrity": "sha512-5R/z157/f20Fi0Ou4ZttL51V0xz0EdPEOauFtPCEYOLInDBRCj1/TxOJ5aGTrtShxEshN2d+hXb9ZKSi5RLBcg==", - "dependencies": { - "ansi-styles": "^4.3.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/disparity-colors/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@npmcli/docs": { "resolved": "docs", "link": true @@ -16477,7 +16452,6 @@ "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/disparity-colors": "^3.0.0", "@npmcli/installed-package-contents": "^2.0.2", "binary-extensions": "^2.3.0", "diff": "^5.1.0", diff --git a/workspaces/libnpmdiff/package.json b/workspaces/libnpmdiff/package.json index fc4aac936b494..d420e603b2afd 100644 --- a/workspaces/libnpmdiff/package.json +++ b/workspaces/libnpmdiff/package.json @@ -47,7 +47,6 @@ }, "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/disparity-colors": "^3.0.0", "@npmcli/installed-package-contents": "^2.0.2", "binary-extensions": "^2.3.0", "diff": "^5.1.0", From 03958c375cd8fa9ec6d84ad35b7cc5cf5e9136f6 Mon Sep 17 00:00:00 2001 From: Gar Date: Tue, 23 Apr 2024 13:19:21 -0700 Subject: [PATCH 07/42] fix: inline color selector in libnpmdiff Eventually we'll use npm to do this so we don't have to check if color is enabled --- workspaces/libnpmdiff/lib/format-diff.js | 32 ++++++++++++++++--- .../test/format-diff.js.test.cjs | 10 +++--- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/workspaces/libnpmdiff/lib/format-diff.js b/workspaces/libnpmdiff/lib/format-diff.js index 8db110fbea186..a6606d94b8b30 100644 --- a/workspaces/libnpmdiff/lib/format-diff.js +++ b/workspaces/libnpmdiff/lib/format-diff.js @@ -1,8 +1,24 @@ -const colorizeDiff = require('@npmcli/disparity-colors') const jsDiff = require('diff') const shouldPrintPatch = require('./should-print-patch.js') +const colors = { + // red + removed: { open: '\x1B[31m', close: '\x1B[39m' }, + // green + added: { open: '\x1B[32m', close: '\x1B[39m' }, + // blue + header: { open: '\x1B[34m', close: '\x1B[39m' }, + // cyan + section: { open: '\x1B[36m', close: '\x1B[39m' }, +} + +const color = (colorStr, colorId) => { + const { open, close } = colors[colorId] + // avoid highlighting the "\n" (would highlight till the end of the line) + return colorStr.replace(/[^\n\r]+/g, open + '$&' + close) +} + const formatDiff = ({ files, opts = {}, refs, versions }) => { let res = '' const srcPrefix = opts.diffNoPrefix ? '' : opts.diffSrcPrefix || 'a/' @@ -83,9 +99,17 @@ const formatDiff = ({ files, opts = {}, refs, versions }) => { header(`+++ ${names.b}`) } - res += (opts.color - ? colorizeDiff(patch, { headerLength }) - : patch) + if (opts.color) { + // this RegExp will include all the `\n` chars into the lines, easier to join + const lines = patch.split(/^/m) + res += color(lines.slice(0, headerLength).join(''), 'header') + res += lines.slice(headerLength).join('') + .replace(/^-.*/gm, color('$&', 'removed')) + .replace(/^\+.*/gm, color('$&', 'added')) + .replace(/^@@.+@@/gm, color('$&', 'section')) + } else { + res += patch + } } return res.trim() diff --git a/workspaces/libnpmdiff/tap-snapshots/test/format-diff.js.test.cjs b/workspaces/libnpmdiff/tap-snapshots/test/format-diff.js.test.cjs index f735d8925820a..a35d1f1ce55a8 100644 --- a/workspaces/libnpmdiff/tap-snapshots/test/format-diff.js.test.cjs +++ b/workspaces/libnpmdiff/tap-snapshots/test/format-diff.js.test.cjs @@ -33,11 +33,11 @@ index v1.0.0..v2.0.0 ` exports[`test/format-diff.js TAP colored output > should output expected colored diff result 1`] = ` -diff --git a/foo.js b/foo.js -index v1.0.0..v2.0.0 100644 ---- a/foo.js -+++ b/foo.js -@@ -1,2 +1,2 @@ +diff --git a/foo.js b/foo.js +index v1.0.0..v2.0.0 100644 +--- a/foo.js ++++ b/foo.js +@@ -1,2 +1,2 @@ "use strict" -module.exports = "foo" +module.exports = "foobar" From 78447d7a35fab870456ba66eee408b2baddca23e Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 24 Apr 2024 09:26:54 -0700 Subject: [PATCH 08/42] fix: prefer fs/promises over promisify (#7399) --- lib/commands/doctor.js | 7 +- lib/commands/edit.js | 26 ++--- lib/commands/init.js | 7 +- lib/commands/link.js | 8 +- lib/commands/shrinkwrap.js | 3 +- lib/commands/view.js | 5 +- lib/utils/reify-finish.js | 2 +- .../test/lib/commands/doctor.js.test.cjs | 10 +- test/lib/commands/doctor.js | 23 ++-- .../arborist/lib/arborist/isolated-reifier.js | 4 +- workspaces/arborist/scripts/benchmark.js | 6 +- .../arborist/scripts/benchmark/load-actual.js | 6 +- .../arborist/scripts/benchmark/reify.js | 3 +- workspaces/arborist/test/arborist/pruner.js | 13 ++- .../config/lib/definitions/definitions.js | 4 +- workspaces/libnpmpack/lib/index.js | 3 +- workspaces/libnpmversion/lib/read-json.js | 3 +- workspaces/libnpmversion/lib/write-json.js | 3 +- workspaces/libnpmversion/test/write-json.js | 100 ++++++++---------- 19 files changed, 105 insertions(+), 131 deletions(-) diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index 3048a123d6eb1..2c8581a4aba4d 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -1,18 +1,13 @@ const cacache = require('cacache') -const fs = require('fs') +const { access, lstat, readdir, constants: { R_OK, W_OK, X_OK } } = require('fs/promises') const fetch = require('make-fetch-happen') const which = require('which') const pacote = require('pacote') const { resolve } = require('path') const semver = require('semver') -const { promisify } = require('util') const { log, output } = require('proc-log') const ping = require('../utils/ping.js') const { defaults } = require('@npmcli/config/lib/definitions') -const lstat = promisify(fs.lstat) -const readdir = promisify(fs.readdir) -const access = promisify(fs.access) -const { R_OK, W_OK, X_OK } = fs.constants const maskLabel = mask => { const label = [] diff --git a/lib/commands/edit.js b/lib/commands/edit.js index fbc7840a39876..e6ab26278740c 100644 --- a/lib/commands/edit.js +++ b/lib/commands/edit.js @@ -2,7 +2,7 @@ // open the package folder in the $EDITOR const { resolve } = require('path') -const fs = require('graceful-fs') +const { lstat } = require('fs/promises') const cp = require('child_process') const completion = require('../utils/completion/installed-shallow.js') const BaseCommand = require('../base-command.js') @@ -50,25 +50,15 @@ class Edit extends BaseCommand { const path = splitPackageNames(args[0]) const dir = resolve(this.npm.dir, path) - // graceful-fs does not promisify + await lstat(dir) await new Promise((res, rej) => { - fs.lstat(dir, (err) => { - if (err) { - return rej(err) + const [bin, ...spawnArgs] = this.npm.config.get('editor').split(/\s+/) + const editor = cp.spawn(bin, [...spawnArgs, dir], { stdio: 'inherit' }) + editor.on('exit', async (code) => { + if (code) { + return rej(new Error(`editor process exited with code: ${code}`)) } - const [bin, ...spawnArgs] = this.npm.config.get('editor').split(/\s+/) - const editor = cp.spawn(bin, [...spawnArgs, dir], { stdio: 'inherit' }) - editor.on('exit', async (code) => { - if (code) { - return rej(new Error(`editor process exited with code: ${code}`)) - } - try { - await this.npm.exec('rebuild', [dir]) - } catch (execErr) { - rej(execErr) - } - res() - }) + await this.npm.exec('rebuild', [dir]).then(res).catch(rej) }) }) } diff --git a/lib/commands/init.js b/lib/commands/init.js index d45dbaa1fa0d7..28067e4def1d0 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -1,4 +1,4 @@ -const fs = require('fs') +const { statSync } = require('fs') const { relative, resolve } = require('path') const { mkdir } = require('fs/promises') const initJson = require('init-package-json') @@ -8,11 +8,10 @@ const mapWorkspaces = require('@npmcli/map-workspaces') const PackageJson = require('@npmcli/package-json') const { log, output } = require('proc-log') const updateWorkspaces = require('../workspaces/update-workspaces.js') +const BaseCommand = require('../base-command.js') const posixPath = p => p.split('\\').join('/') -const BaseCommand = require('../base-command.js') - class Init extends BaseCommand { static description = 'Create a package.json file' static params = [ @@ -197,7 +196,7 @@ class Init extends BaseCommand { // mapWorkspaces, so we're just going to avoid touching the // top-level package.json try { - fs.statSync(resolve(workspacePath, 'package.json')) + statSync(resolve(workspacePath, 'package.json')) } catch (err) { return } diff --git a/lib/commands/link.js b/lib/commands/link.js index cdc248569849c..0442e50dc0d83 100644 --- a/lib/commands/link.js +++ b/lib/commands/link.js @@ -1,15 +1,11 @@ -const fs = require('fs') -const util = require('util') -const readdir = util.promisify(fs.readdir) +const { readdir } = require('fs/promises') const { resolve } = require('path') - const npa = require('npm-package-arg') const pkgJson = require('@npmcli/package-json') const semver = require('semver') - const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Link extends ArboristWorkspaceCmd { static description = 'Symlink a package folder' static name = 'link' diff --git a/lib/commands/shrinkwrap.js b/lib/commands/shrinkwrap.js index 01e1d5fdc1189..56d7ffa88e99e 100644 --- a/lib/commands/shrinkwrap.js +++ b/lib/commands/shrinkwrap.js @@ -1,7 +1,8 @@ const { resolve, basename } = require('path') -const { unlink } = require('fs').promises +const { unlink } = require('fs/promises') const { log } = require('proc-log') const BaseCommand = require('../base-command.js') + class Shrinkwrap extends BaseCommand { static description = 'Lock down dependency versions for publication' static name = 'shrinkwrap' diff --git a/lib/commands/view.js b/lib/commands/view.js index 744e2badb9581..e8b102737a1e9 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -1,5 +1,5 @@ const columns = require('cli-columns') -const fs = require('fs') +const { readFile } = require('fs/promises') const jsonParse = require('json-parse-even-better-errors') const { log, output } = require('proc-log') const npa = require('npm-package-arg') @@ -7,10 +7,9 @@ const { resolve } = require('path') const formatBytes = require('../utils/format-bytes.js') const relativeDate = require('tiny-relative-date') const semver = require('semver') -const { inspect, promisify } = require('util') +const { inspect } = require('util') const { packument } = require('pacote') -const readFile = promisify(fs.readFile) const readJson = async file => jsonParse(await readFile(file, 'utf8')) const Queryable = require('../utils/queryable.js') diff --git a/lib/utils/reify-finish.js b/lib/utils/reify-finish.js index 9b43abcb7610a..0b34a37576860 100644 --- a/lib/utils/reify-finish.js +++ b/lib/utils/reify-finish.js @@ -1,6 +1,6 @@ const reifyOutput = require('./reify-output.js') const ini = require('ini') -const { writeFile } = require('fs').promises +const { writeFile } = require('fs/promises') const { resolve } = require('path') const reifyFinish = async (npm, arb) => { diff --git a/tap-snapshots/test/lib/commands/doctor.js.test.cjs b/tap-snapshots/test/lib/commands/doctor.js.test.cjs index 985d76e5d12a5..5c5b122477d81 100644 --- a/tap-snapshots/test/lib/commands/doctor.js.test.cjs +++ b/tap-snapshots/test/lib/commands/doctor.js.test.cjs @@ -731,11 +731,11 @@ Object { "warn": Array [ String( doctor getGitPath Error: test error - doctor at which ({CWD}/{TESTDIR}/doctor.js:313:15) - doctor at Doctor.getGitPath ({CWD}/lib/commands/doctor.js:286:18) - doctor at Doctor.exec ({CWD}/lib/commands/doctor.js:125:33) - doctor at processTicksAndRejections (node:internal/process/task_queues:95:5) - doctor at MockNpm.exec ({CWD}/test/fixtures/mock-npm.js:80:26) + doctor at which {STACK} + doctor at Doctor.getGitPath {STACK} + doctor at Doctor.exec {STACK} + doctor at processTicksAndRejections {STACK} + doctor at MockNpm.exec {STACK} ), ], } diff --git a/test/lib/commands/doctor.js b/test/lib/commands/doctor.js index 1682a6cccfa48..cbe74aba53ff7 100644 --- a/test/lib/commands/doctor.js +++ b/test/lib/commands/doctor.js @@ -1,5 +1,5 @@ const t = require('tap') -const fs = require('fs') +const fs = require('fs/promises') const path = require('path') const { load: loadMockNpm } = require('../../fixtures/mock-npm') @@ -11,6 +11,7 @@ const cleanCacheSha = (str) => str.replace(/content-v2\/sha512\/[^"]+/g, 'content-v2/sha512/{sha}') t.cleanSnapshot = p => cleanCacheSha(cleanDate(cleanCwd(p))) + .replace(/\s\((\{CWD\}|node:).*\d+:\d+\)$/gm, ' {STACK}') const npmManifest = (version) => { return { @@ -389,15 +390,15 @@ t.test('incorrect owner', async t => { const { joinedOutput, logs, npm } = await loadMockNpm(t, { mocks: { ...mocks, - fs: { + 'fs/promises': { ...fs, - lstat: (p, cb) => { - const stat = fs.lstatSync(p) + lstat: async (p) => { + const stat = await fs.lstat(p) if (p.endsWith('_cacache')) { stat.uid += 1 stat.gid += 1 } - return cb(null, stat) + return stat }, }, }, @@ -418,9 +419,9 @@ t.test('incorrect permissions', async t => { const { joinedOutput, logs, npm } = await loadMockNpm(t, { mocks: { ...mocks, - fs: { + 'fs/promises': { ...fs, - access: () => { + access: async () => { throw new Error('Test Error') }, }, @@ -442,9 +443,13 @@ t.test('error reading directory', async t => { const { joinedOutput, logs, npm } = await loadMockNpm(t, { mocks: { ...mocks, - fs: { + 'fs/promises': { ...fs, - readdir: () => { + readdir: async (s, ...args) => { + if (s.endsWith('_logs')) { + return fs.readdir(s, ...args) + } + // if (s.endsWith) throw new Error('Test Error') }, }, diff --git a/workspaces/arborist/lib/arborist/isolated-reifier.js b/workspaces/arborist/lib/arborist/isolated-reifier.js index f4f1bb8e44362..19e4e4a20d83a 100644 --- a/workspaces/arborist/lib/arborist/isolated-reifier.js +++ b/workspaces/arborist/lib/arborist/isolated-reifier.js @@ -1,7 +1,7 @@ const _makeIdealGraph = Symbol('makeIdealGraph') const _createIsolatedTree = Symbol.for('createIsolatedTree') const _createBundledTree = Symbol('createBundledTree') -const fs = require('fs') +const { mkdirSync } = require('fs') const pacote = require('pacote') const { join } = require('path') const { depth } = require('treeverse') @@ -108,7 +108,7 @@ module.exports = cls => class IsolatedReifier extends cls { '.store', `${node.name}@${node.version}` ) - fs.mkdirSync(dir, { recursive: true }) + mkdirSync(dir, { recursive: true }) // TODO this approach feels wrong // and shouldn't be necessary for shrinkwraps await pacote.extract(node.resolved, dir, { diff --git a/workspaces/arborist/scripts/benchmark.js b/workspaces/arborist/scripts/benchmark.js index c25140caa93c6..21f5432de76f6 100644 --- a/workspaces/arborist/scripts/benchmark.js +++ b/workspaces/arborist/scripts/benchmark.js @@ -1,14 +1,16 @@ process.env.ARBORIST_DEBUG = '0' + const { Suite } = require('benchmark') const { relative, resolve } = require('path') const { mkdir, rm } = require('fs/promises') const { execSync } = require('child_process') +const { linkSync, writeFileSync, readdirSync } = require('fs') +const registryServer = require('../test/fixtures/server.js') + const shaCmd = 'git show --no-patch --pretty=%H HEAD' const dirty = !!String(execSync('git status -s -uno')).trim() const currentSha = String(execSync(shaCmd)).trim() + (dirty ? '-dirty' : '') const lastBenchmark = resolve(__dirname, 'benchmark/saved/last-benchmark.json') -const { linkSync, writeFileSync, readdirSync } = require('fs') -const registryServer = require('../test/fixtures/server.js') const red = m => `\x1B[31m${m}\x1B[39m` const green = m => `\x1B[32m${m}\x1B[39m` diff --git a/workspaces/arborist/scripts/benchmark/load-actual.js b/workspaces/arborist/scripts/benchmark/load-actual.js index 6194098fa9e4d..ddc8145bcb60d 100644 --- a/workspaces/arborist/scripts/benchmark/load-actual.js +++ b/workspaces/arborist/scripts/benchmark/load-actual.js @@ -1,10 +1,8 @@ const Arborist = require('../..') const { resolve, basename } = require('path') const { writeFileSync } = require('fs') -const { - mkdir, - rm, -} = require('fs/promises') +const { mkdir, rm } = require('fs/promises') + const dir = resolve(__dirname, basename(__filename, '.js')) const suite = async (suite, { registry, cache }) => { diff --git a/workspaces/arborist/scripts/benchmark/reify.js b/workspaces/arborist/scripts/benchmark/reify.js index 84c7ab4b0471d..797a5cb803682 100644 --- a/workspaces/arborist/scripts/benchmark/reify.js +++ b/workspaces/arborist/scripts/benchmark/reify.js @@ -1,8 +1,7 @@ const Arborist = require('../..') const { resolve, basename } = require('path') -const { writeFileSync } = require('fs') +const { writeFileSync, rmSync } = require('fs') const { mkdir } = require('fs/promises') -const { rmSync } = require('fs') const dir = resolve(__dirname, basename(__filename, '.js')) // these are not arbitrary, the empty/full and no-* bits matter diff --git a/workspaces/arborist/test/arborist/pruner.js b/workspaces/arborist/test/arborist/pruner.js index 8de95a5a9ddd4..9be29442acdea 100644 --- a/workspaces/arborist/test/arborist/pruner.js +++ b/workspaces/arborist/test/arborist/pruner.js @@ -80,17 +80,16 @@ t.test('prune with lockfile omit dev', async t => { }) t.test('prune omit dev with bins', async t => { - const fs = require('fs') - const { promisify } = require('util') - const readdir = promisify(fs.readdir) + const { readdir } = require('fs/promises') + const { statSync, lstatSync } = require('fs') const path = fixture(t, 'prune-dev-bins') // should have bin files const reifiedBin = resolve(path, 'node_modules/.bin/yes') if (process.platform === 'win32') { - t.ok(fs.statSync(reifiedBin + '.cmd').isFile(), 'should have shim') + t.ok(statSync(reifiedBin + '.cmd').isFile(), 'should have shim') } else { - t.ok(fs.lstatSync(reifiedBin).isSymbolicLink(), 'should have symlink') + t.ok(lstatSync(reifiedBin).isSymbolicLink(), 'should have symlink') } // PRUNE things @@ -107,9 +106,9 @@ t.test('prune omit dev with bins', async t => { // should also remove ./bin/* files const bin = resolve(path, 'node_modules/.bin/yes') if (process.platform === 'win32') { - t.throws(() => fs.statSync(bin + '.cmd').isFile(), /ENOENT/, 'should not have shim') + t.throws(() => statSync(bin + '.cmd').isFile(), /ENOENT/, 'should not have shim') } else { - t.throws(() => fs.lstatSync(bin).isSymbolicLink(), /ENOENT/, 'should not have symlink') + t.throws(() => lstatSync(bin).isSymbolicLink(), /ENOENT/, 'should not have symlink') } }) diff --git a/workspaces/config/lib/definitions/definitions.js b/workspaces/config/lib/definitions/definitions.js index 3565cdb4feb44..57ab171611838 100644 --- a/workspaces/config/lib/definitions/definitions.js +++ b/workspaces/config/lib/definitions/definitions.js @@ -7,10 +7,10 @@ const { join } = require('node:path') const isWindows = process.platform === 'win32' // used by cafile flattening to flatOptions.ca -const fs = require('fs') +const { readFileSync } = require('fs') const maybeReadFile = file => { try { - return fs.readFileSync(file, 'utf8') + return readFileSync(file, 'utf8') } catch (er) { if (er.code !== 'ENOENT') { throw er diff --git a/workspaces/libnpmpack/lib/index.js b/workspaces/libnpmpack/lib/index.js index 00dc96974a968..c71716cf54428 100644 --- a/workspaces/libnpmpack/lib/index.js +++ b/workspaces/libnpmpack/lib/index.js @@ -4,9 +4,8 @@ const pacote = require('pacote') const npa = require('npm-package-arg') const runScript = require('@npmcli/run-script') const path = require('path') -const util = require('util') const Arborist = require('@npmcli/arborist') -const writeFile = util.promisify(require('fs').writeFile) +const { writeFile } = require('fs/promises') module.exports = pack async function pack (spec = 'file:.', opts = {}) { diff --git a/workspaces/libnpmversion/lib/read-json.js b/workspaces/libnpmversion/lib/read-json.js index 2dd0f7aa4902e..32c7289507697 100644 --- a/workspaces/libnpmversion/lib/read-json.js +++ b/workspaces/libnpmversion/lib/read-json.js @@ -1,7 +1,6 @@ // can't use read-package-json-fast, because we want to ensure // that we make as few changes as possible, even for safety issues. -const { promisify } = require('util') -const readFile = promisify(require('fs').readFile) +const { readFile } = require('fs/promises') const parse = require('json-parse-even-better-errors') module.exports = async path => parse(await readFile(path)) diff --git a/workspaces/libnpmversion/lib/write-json.js b/workspaces/libnpmversion/lib/write-json.js index f066d72c67e12..425be8e8e3efb 100644 --- a/workspaces/libnpmversion/lib/write-json.js +++ b/workspaces/libnpmversion/lib/write-json.js @@ -1,6 +1,5 @@ // write the json back, preserving the line breaks and indent -const { promisify } = require('util') -const writeFile = promisify(require('fs').writeFile) +const { writeFile } = require('fs/promises') const kIndent = Symbol.for('indent') const kNewline = Symbol.for('newline') diff --git a/workspaces/libnpmversion/test/write-json.js b/workspaces/libnpmversion/test/write-json.js index a8e5b15728bd7..63dccf6cf5d0e 100644 --- a/workspaces/libnpmversion/test/write-json.js +++ b/workspaces/libnpmversion/test/write-json.js @@ -1,60 +1,54 @@ const t = require('tap') -const requireInject = require('require-inject') -const fs = require('fs') -const writeJson = requireInject('../lib/write-json.js', { - fs: { - ...fs, - writeFile: (path, data, cb) => cb(null, [path, data]), - }, -}) +const path = require('path') +const writeJson = require('../lib/write-json.js') +const { readFile } = require('fs/promises') const kIndent = Symbol.for('indent') const kNewline = Symbol.for('newline') t.test('write json with newlines and indent set', async t => { - t.same(await writeJson('x', { - [kNewline]: '\r\n', - [kIndent]: 3, - a: 1, - b: [2, 3], - }), [ - 'x', - '{\r\n' + - ' "a": 1,\r\n' + - ' "b": [\r\n' + - ' 2,\r\n' + - ' 3\r\n' + - ' ]\r\n' + - '}\r\n', - ], 'numeric three space indent, CRLF line breaks') - - t.same(await writeJson('x', { - [kNewline]: 'XYZ\n', - [kIndent]: '\t', - a: 1, - b: [2, 3], - }), [ - 'x', - '{XYZ\n' + - '\t"a": 1,XYZ\n' + - '\t"b": [XYZ\n' + - '\t\t2,XYZ\n' + - '\t\t3XYZ\n' + - '\t]XYZ\n' + - '}XYZ\n', - ], 'string tap indent, CRLF line breaks') - - t.same(await writeJson('x', { - a: 1, - b: [2, 3], - }), [ - 'x', - '{\n' + - ' "a": 1,\n' + - ' "b": [\n' + - ' 2,\n' + - ' 3\n' + - ' ]\n' + - '}\n', - ], 'default newline and indent') + t.test('numeric three space indent, CRLF line breaks', async t => { + const dir = t.testdir() + const file = path.join(dir, 'x') + + await writeJson(file, { + [kNewline]: '\r\n', + [kIndent]: 3, + a: 1, + b: [2, 3], + }) + + const str = await readFile(file, 'utf-8') + t.equal(str, `{\r\n "a": 1,\r\n "b": [\r\n 2,\r\n 3\r\n ]\r\n}\r\n`) + }) + + t.test('string tap indent, CRLF line breaks', async t => { + const dir = t.testdir() + const file = path.join(dir, 'x') + + await writeJson(file, { + [kNewline]: 'XYZ\n', + [kIndent]: '\t', + a: 1, + b: [2, 3], + }) + + const str = await readFile(file, 'utf-8') + t.equal(str, `{XYZ\n\t"a": 1,XYZ\n\t"b": [XYZ\n\t\t2,XYZ\n\t\t3XYZ\n\t]XYZ\n}XYZ\n`) + }) + + t.test('default newline and indent', async t => { + const dir = t.testdir() + const file = path.join(dir, 'x') + + await writeJson(file, { + a: 1, + b: [2, 3], + }) + + const str = await readFile(file, 'utf-8') + t.match(str, `{\n "a": 1,\n "b": [\n 2,\n 3\n ]\n}\n`) + }) + + t.end() }) From 157d0aebfe5710880d0c91bddee970316b8a6612 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Tue, 23 Apr 2024 11:08:10 -0700 Subject: [PATCH 09/42] deps: @npmcli/package-json@5.1.0 --- package-lock.json | 4 ++-- package.json | 2 +- workspaces/arborist/package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f3f5725153dd0..7d1bd17da6fdf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,7 +92,7 @@ "@npmcli/config": "^8.0.2", "@npmcli/fs": "^3.1.0", "@npmcli/map-workspaces": "^3.0.6", - "@npmcli/package-json": "^5.0.3", + "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.1", "@npmcli/redact": "^1.1.0", "@npmcli/run-script": "^8.0.0", @@ -16360,7 +16360,7 @@ "@npmcli/metavuln-calculator": "^7.1.0", "@npmcli/name-from-folder": "^2.0.0", "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.3", + "@npmcli/package-json": "^5.1.0", "@npmcli/query": "^3.1.0", "@npmcli/redact": "^1.1.0", "@npmcli/run-script": "^8.0.0", diff --git a/package.json b/package.json index e3a2be0fd8b7a..044149f0674d2 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@npmcli/config": "^8.0.2", "@npmcli/fs": "^3.1.0", "@npmcli/map-workspaces": "^3.0.6", - "@npmcli/package-json": "^5.0.3", + "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.1", "@npmcli/redact": "^1.1.0", "@npmcli/run-script": "^8.0.0", diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index 9350e16352b6c..58ef87e9194e8 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -10,7 +10,7 @@ "@npmcli/metavuln-calculator": "^7.1.0", "@npmcli/name-from-folder": "^2.0.0", "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.3", + "@npmcli/package-json": "^5.1.0", "@npmcli/query": "^3.1.0", "@npmcli/redact": "^1.1.0", "@npmcli/run-script": "^8.0.0", From 486d46cd5b5678ad1ab6c23ee12cf7559477805a Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Tue, 23 Apr 2024 11:09:06 -0700 Subject: [PATCH 10/42] deps: @npmcli/installed-package-contents@2.1.0 --- .../installed-package-contents/bin/index.js | 44 +++++++ .../installed-package-contents/lib/index.js | 121 +++++------------- .../installed-package-contents/package.json | 12 +- package-lock.json | 12 +- workspaces/arborist/package.json | 2 +- workspaces/libnpmdiff/package.json | 2 +- 6 files changed, 88 insertions(+), 105 deletions(-) create mode 100755 node_modules/@npmcli/installed-package-contents/bin/index.js mode change 100755 => 100644 node_modules/@npmcli/installed-package-contents/lib/index.js diff --git a/node_modules/@npmcli/installed-package-contents/bin/index.js b/node_modules/@npmcli/installed-package-contents/bin/index.js new file mode 100755 index 0000000000000..7b83b23bf168c --- /dev/null +++ b/node_modules/@npmcli/installed-package-contents/bin/index.js @@ -0,0 +1,44 @@ +#! /usr/bin/env node + +const { relative } = require('path') +const pkgContents = require('../') + +const usage = `Usage: + installed-package-contents [-d --depth=] + +Lists the files installed for a package specified by . + +Options: + -d --depth= Provide a numeric value ("Infinity" is allowed) + to specify how deep in the file tree to traverse. + Default=1 + -h --help Show this usage information` + +const options = {} + +process.argv.slice(2).forEach(arg => { + let match + if ((match = arg.match(/^(?:--depth=|-d)([0-9]+|Infinity)/))) { + options.depth = +match[1] + } else if (arg === '-h' || arg === '--help') { + console.log(usage) + process.exit(0) + } else { + options.path = arg + } +}) + +if (!options.path) { + console.error('ERROR: no path provided') + console.error(usage) + process.exit(1) +} + +const cwd = process.cwd() + +pkgContents(options) + .then(list => list.sort().forEach(p => console.log(relative(cwd, p)))) + .catch(/* istanbul ignore next - pretty unusual */ er => { + console.error(er) + process.exit(1) + }) diff --git a/node_modules/@npmcli/installed-package-contents/lib/index.js b/node_modules/@npmcli/installed-package-contents/lib/index.js old mode 100755 new mode 100644 index 20b25c4bc8437..ab1486cd01d00 --- a/node_modules/@npmcli/installed-package-contents/lib/index.js +++ b/node_modules/@npmcli/installed-package-contents/lib/index.js @@ -1,5 +1,3 @@ -#! /usr/bin/env node - // to GET CONTENTS for folder at PATH (which may be a PACKAGE): // - if PACKAGE, read path/package.json // - if bins in ../node_modules/.bin, add those to result @@ -19,53 +17,46 @@ // - add GET CONTENTS of bundled deps, PACKAGE=true, depth + 1 const bundled = require('npm-bundled') -const { promisify } = require('util') -const fs = require('fs') -const readFile = promisify(fs.readFile) -const readdir = promisify(fs.readdir) -const stat = promisify(fs.stat) -const lstat = promisify(fs.lstat) -const { relative, resolve, basename, dirname } = require('path') +const { readFile, readdir, stat } = require('fs/promises') +const { resolve, basename, dirname } = require('path') const normalizePackageBin = require('npm-normalize-package-bin') -const readPackage = ({ path, packageJsonCache }) => - packageJsonCache.has(path) ? Promise.resolve(packageJsonCache.get(path)) +const readPackage = ({ path, packageJsonCache }) => packageJsonCache.has(path) + ? Promise.resolve(packageJsonCache.get(path)) : readFile(path).then(json => { const pkg = normalizePackageBin(JSON.parse(json)) packageJsonCache.set(path, pkg) return pkg - }) - .catch(er => null) + }).catch(() => null) // just normalize bundle deps and bin, that's all we care about here. const normalized = Symbol('package data has been normalized') -const rpj = ({ path, packageJsonCache }) => - readPackage({ path, packageJsonCache }) - .then(pkg => { - if (!pkg || pkg[normalized]) { - return pkg - } - if (pkg.bundledDependencies && !pkg.bundleDependencies) { - pkg.bundleDependencies = pkg.bundledDependencies - delete pkg.bundledDependencies - } - const bd = pkg.bundleDependencies - if (bd === true) { - pkg.bundleDependencies = [ - ...Object.keys(pkg.dependencies || {}), - ...Object.keys(pkg.optionalDependencies || {}), - ] - } - if (typeof bd === 'object' && !Array.isArray(bd)) { - pkg.bundleDependencies = Object.keys(bd) - } - pkg[normalized] = true +const rpj = ({ path, packageJsonCache }) => readPackage({ path, packageJsonCache }) + .then(pkg => { + if (!pkg || pkg[normalized]) { return pkg - }) + } + if (pkg.bundledDependencies && !pkg.bundleDependencies) { + pkg.bundleDependencies = pkg.bundledDependencies + delete pkg.bundledDependencies + } + const bd = pkg.bundleDependencies + if (bd === true) { + pkg.bundleDependencies = [ + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.optionalDependencies || {}), + ] + } + if (typeof bd === 'object' && !Array.isArray(bd)) { + pkg.bundleDependencies = Object.keys(bd) + } + pkg[normalized] = true + return pkg + }) const pkgContents = async ({ path, - depth, + depth = 1, currentDepth = 0, pkg = null, result = null, @@ -105,7 +96,7 @@ const pkgContents = async ({ }) const bins = await Promise.all( - binFiles.map(b => stat(b).then(() => b).catch((er) => null)) + binFiles.map(b => stat(b).then(() => b).catch(() => null)) ) bins.filter(b => b).forEach(b => result.add(b)) } @@ -136,18 +127,6 @@ const pkgContents = async ({ const recursePromises = [] - // if we didn't get withFileTypes support, tack that on - if (typeof dirEntries[0] === 'string') { - // use a map so we can return a promise, but we mutate dirEntries in place - // this is much slower than getting the entries from the readdir call, - // but polyfills support for node versions before 10.10 - await Promise.all(dirEntries.map(async (name, index) => { - const p = resolve(path, name) - const st = await lstat(p) - dirEntries[index] = Object.assign(st, { name }) - })) - } - for (const entry of dirEntries) { const p = resolve(path, entry.name) if (entry.isDirectory() === false) { @@ -195,48 +174,8 @@ const pkgContents = async ({ return result } -module.exports = ({ path, depth = 1, packageJsonCache }) => pkgContents({ +module.exports = ({ path, ...opts }) => pkgContents({ path: resolve(path), - depth, + ...opts, pkg: true, - packageJsonCache, }).then(results => [...results]) - -if (require.main === module) { - const options = { path: null, depth: 1 } - const usage = `Usage: - installed-package-contents [-d --depth=] - -Lists the files installed for a package specified by . - -Options: - -d --depth= Provide a numeric value ("Infinity" is allowed) - to specify how deep in the file tree to traverse. - Default=1 - -h --help Show this usage information` - - process.argv.slice(2).forEach(arg => { - let match - if ((match = arg.match(/^--depth=([0-9]+|Infinity)/)) || - (match = arg.match(/^-d([0-9]+|Infinity)/))) { - options.depth = +match[1] - } else if (arg === '-h' || arg === '--help') { - console.log(usage) - process.exit(0) - } else { - options.path = arg - } - }) - if (!options.path) { - console.error('ERROR: no path provided') - console.error(usage) - process.exit(1) - } - const cwd = process.cwd() - module.exports(options) - .then(list => list.sort().forEach(p => console.log(relative(cwd, p)))) - .catch(/* istanbul ignore next - pretty unusual */ er => { - console.error(er) - process.exit(1) - }) -} diff --git a/node_modules/@npmcli/installed-package-contents/package.json b/node_modules/@npmcli/installed-package-contents/package.json index 3554754123e61..132256430a6c1 100644 --- a/node_modules/@npmcli/installed-package-contents/package.json +++ b/node_modules/@npmcli/installed-package-contents/package.json @@ -1,17 +1,17 @@ { "name": "@npmcli/installed-package-contents", - "version": "2.0.2", + "version": "2.1.0", "description": "Get the list of files installed in a package in node_modules, including bundled dependencies", "author": "GitHub Inc.", "main": "lib/index.js", "bin": { - "installed-package-contents": "lib/index.js" + "installed-package-contents": "bin/index.js" }, "license": "ISC", "scripts": { "test": "tap", "snap": "tap", - "lint": "eslint \"**/*.js\"", + "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"", "postlint": "template-oss-check", "template-oss-apply": "template-oss-apply --force", "lintfix": "npm run lint -- --fix", @@ -19,8 +19,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.11.4", - "require-inject": "^1.4.4", + "@npmcli/template-oss": "4.21.4", "tap": "^16.3.0" }, "dependencies": { @@ -40,7 +39,8 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.11.4" + "version": "4.21.4", + "publish": true }, "tap": { "nyc-arg": [ diff --git a/package-lock.json b/package-lock.json index 7d1bd17da6fdf..553d6bc781c4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1693,16 +1693,16 @@ } }, "node_modules/@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", + "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", "inBundle": true, "dependencies": { "npm-bundled": "^3.0.0", "npm-normalize-package-bin": "^3.0.0" }, "bin": { - "installed-package-contents": "lib/index.js" + "installed-package-contents": "bin/index.js" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -16355,7 +16355,7 @@ "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^3.1.0", - "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/installed-package-contents": "^2.1.0", "@npmcli/map-workspaces": "^3.0.2", "@npmcli/metavuln-calculator": "^7.1.0", "@npmcli/name-from-folder": "^2.0.0", @@ -16452,7 +16452,7 @@ "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/installed-package-contents": "^2.1.0", "binary-extensions": "^2.3.0", "diff": "^5.1.0", "minimatch": "^9.0.4", diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index 58ef87e9194e8..ba00f05db1b4c 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -5,7 +5,7 @@ "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^3.1.0", - "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/installed-package-contents": "^2.1.0", "@npmcli/map-workspaces": "^3.0.2", "@npmcli/metavuln-calculator": "^7.1.0", "@npmcli/name-from-folder": "^2.0.0", diff --git a/workspaces/libnpmdiff/package.json b/workspaces/libnpmdiff/package.json index d420e603b2afd..04e9b90adb79f 100644 --- a/workspaces/libnpmdiff/package.json +++ b/workspaces/libnpmdiff/package.json @@ -47,7 +47,7 @@ }, "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/installed-package-contents": "^2.1.0", "binary-extensions": "^2.3.0", "diff": "^5.1.0", "minimatch": "^9.0.4", From 36adff36c41f56315fe582e1e4dda29060f7fdf7 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Tue, 23 Apr 2024 11:07:43 -0700 Subject: [PATCH 11/42] deps: pacote@18.0.2 --- DEPENDENCIES.md | 15 +- mock-registry/package.json | 2 +- node_modules/.gitignore | 1 - .../@npmcli/package-json/lib/index.js | 6 + .../@npmcli/package-json/package.json | 6 +- node_modules/pacote/lib/dir.js | 2 +- node_modules/pacote/lib/fetcher.js | 13 +- node_modules/pacote/lib/file.js | 31 +- node_modules/pacote/lib/git.js | 6 +- node_modules/pacote/lib/registry.js | 9 +- node_modules/pacote/package.json | 5 +- node_modules/read-package-json/LICENSE | 15 - .../read-package-json/lib/read-json.js | 589 ------------------ node_modules/read-package-json/package.json | 65 -- package-lock.json | 42 +- package.json | 2 +- workspaces/arborist/package.json | 2 +- workspaces/libnpmdiff/package.json | 2 +- workspaces/libnpmexec/package.json | 2 +- workspaces/libnpmpack/package.json | 2 +- 20 files changed, 65 insertions(+), 752 deletions(-) delete mode 100644 node_modules/read-package-json/LICENSE delete mode 100644 node_modules/read-package-json/lib/read-json.js delete mode 100644 node_modules/read-package-json/package.json diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 9eed49020e0c2..87abae3f85cd9 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -242,18 +242,14 @@ graph LR; pacote-->npm-registry-fetch; pacote-->npmcli-git["@npmcli/git"]; pacote-->npmcli-installed-package-contents["@npmcli/installed-package-contents"]; + pacote-->npmcli-package-json["@npmcli/package-json"]; pacote-->npmcli-promise-spawn["@npmcli/promise-spawn"]; pacote-->npmcli-run-script["@npmcli/run-script"]; pacote-->proc-log; - pacote-->read-package-json-fast; - pacote-->read-package-json; pacote-->ssri; parse-conflict-json-->json-parse-even-better-errors; promzard-->read; read-->mute-stream; - read-package-json-->json-parse-even-better-errors; - read-package-json-->normalize-package-data; - read-package-json-->npm-normalize-package-bin; read-package-json-fast-->json-parse-even-better-errors; read-package-json-fast-->npm-normalize-package-bin; unique-filename-->unique-slug; @@ -713,12 +709,11 @@ graph LR; pacote-->npm-registry-fetch; pacote-->npmcli-git["@npmcli/git"]; pacote-->npmcli-installed-package-contents["@npmcli/installed-package-contents"]; + pacote-->npmcli-package-json["@npmcli/package-json"]; pacote-->npmcli-promise-spawn["@npmcli/promise-spawn"]; pacote-->npmcli-run-script["@npmcli/run-script"]; pacote-->proc-log; pacote-->promise-retry; - pacote-->read-package-json-fast; - pacote-->read-package-json; pacote-->sigstore; pacote-->ssri; pacote-->tar; @@ -733,10 +728,6 @@ graph LR; promise-retry-->retry; promzard-->read; read-->mute-stream; - read-package-json-->glob; - read-package-json-->json-parse-even-better-errors; - read-package-json-->normalize-package-data; - read-package-json-->npm-normalize-package-bin; read-package-json-fast-->json-parse-even-better-errors; read-package-json-fast-->npm-normalize-package-bin; semver-->lru-cache; @@ -811,6 +802,6 @@ packages higher up the chain. - @npmcli/run-script, libnpmhook, libnpmorg, libnpmsearch, libnpmteam, init-package-json, npm-profile - @npmcli/package-json, npm-registry-fetch - @npmcli/git, make-fetch-happen, @npmcli/config - - @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, read-package-json, promzard + - @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, promzard - @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, normalize-package-data, npm-packlist, bin-links, nopt, parse-conflict-json, @npmcli/mock-globals, read - @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, @npmcli/redact, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, proggy, minify-registry-metadata, ini, mute-stream, npm-audit-report, npm-user-validate diff --git a/mock-registry/package.json b/mock-registry/package.json index 8be3efdb1ff8f..eaa6b63e77ad8 100644 --- a/mock-registry/package.json +++ b/mock-registry/package.json @@ -51,7 +51,7 @@ "json-stringify-safe": "^5.0.1", "nock": "^13.3.3", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "tap": "^16.3.8" } } diff --git a/node_modules/.gitignore b/node_modules/.gitignore index 09610fb1b697d..ce124e0438201 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -178,7 +178,6 @@ !/qrcode-terminal !/read-cmd-shim !/read-package-json-fast -!/read-package-json !/read !/retry !/safer-buffer diff --git a/node_modules/@npmcli/package-json/lib/index.js b/node_modules/@npmcli/package-json/lib/index.js index 0cc41c685a39e..6d1b760727ba6 100644 --- a/node_modules/@npmcli/package-json/lib/index.js +++ b/node_modules/@npmcli/package-json/lib/index.js @@ -167,6 +167,12 @@ class PackageJson { return this } + fromContent (data) { + this.#manifest = data + this.#canSave = false + return this + } + // Load data from a comment // /**package { "name": "foo", "version": "1.2.3", ... } **/ fromComment (data) { diff --git a/node_modules/@npmcli/package-json/package.json b/node_modules/@npmcli/package-json/package.json index faf9a952fe915..98236f604ecbd 100644 --- a/node_modules/@npmcli/package-json/package.json +++ b/node_modules/@npmcli/package-json/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/package-json", - "version": "5.0.3", + "version": "5.1.0", "description": "Programmatic API to update package.json", "main": "lib/index.js", "files": [ @@ -25,7 +25,7 @@ "license": "ISC", "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.21.3", + "@npmcli/template-oss": "4.21.4", "read-package-json": "^7.0.0", "read-package-json-fast": "^3.0.2", "tap": "^16.0.1" @@ -48,7 +48,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.21.3", + "version": "4.21.4", "publish": "true" }, "tap": { diff --git a/node_modules/pacote/lib/dir.js b/node_modules/pacote/lib/dir.js index 6979462ea073e..135be8e6cba83 100644 --- a/node_modules/pacote/lib/dir.js +++ b/node_modules/pacote/lib/dir.js @@ -87,7 +87,7 @@ class DirFetcher extends Fetcher { return Promise.resolve(this.package) } - return this[_readPackageJson](this.resolved + '/package.json') + return this[_readPackageJson](this.resolved) .then(mani => this.package = { ...mani, _integrity: this.integrity && String(this.integrity), diff --git a/node_modules/pacote/lib/fetcher.js b/node_modules/pacote/lib/fetcher.js index 287ec7956fc97..c4a707e7ef81e 100644 --- a/node_modules/pacote/lib/fetcher.js +++ b/node_modules/pacote/lib/fetcher.js @@ -5,7 +5,6 @@ const npa = require('npm-package-arg') const ssri = require('ssri') -const { promisify } = require('util') const { basename, dirname } = require('path') const tar = require('tar') const { log } = require('proc-log') @@ -16,12 +15,14 @@ const cacache = require('cacache') const isPackageBin = require('./util/is-package-bin.js') const removeTrailingSlashes = require('./util/trailing-slashes.js') const getContents = require('@npmcli/installed-package-contents') -const readPackageJsonFast = require('read-package-json-fast') -const readPackageJson = promisify(require('read-package-json')) +const PackageJson = require('@npmcli/package-json') const { Minipass } = require('minipass') - const cacheDir = require('./util/cache-dir.js') +// Pacote is only concerned with the package.json contents +const packageJsonPrepare = (p) => PackageJson.prepare(p).then(pkg => pkg.content) +const packageJsonNormalize = (p) => PackageJson.normalize(p).then(pkg => pkg.content) + // Private methods. // Child classes should not have to override these. // Users should never call them. @@ -93,9 +94,9 @@ class FetcherBase { this.fullMetadata = this.before ? true : !!opts.fullMetadata this.fullReadJson = !!opts.fullReadJson if (this.fullReadJson) { - this[_readPackageJson] = readPackageJson + this[_readPackageJson] = packageJsonPrepare } else { - this[_readPackageJson] = readPackageJsonFast + this[_readPackageJson] = packageJsonNormalize } // rrh is a registry hostname or 'never' or 'always' diff --git a/node_modules/pacote/lib/file.js b/node_modules/pacote/lib/file.js index bf99bb86e359e..95769de1374c9 100644 --- a/node_modules/pacote/lib/file.js +++ b/node_modules/pacote/lib/file.js @@ -1,10 +1,11 @@ -const Fetcher = require('./fetcher.js') const fsm = require('fs-minipass') const cacache = require('cacache') -const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved') -const _exeBins = Symbol('_exeBins') const { resolve } = require('path') -const fs = require('fs') +const { stat, chmod } = require('fs/promises') +const Fetcher = require('./fetcher.js') + +const _exeBins = Symbol('_exeBins') +const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved') const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson') class FileFetcher extends Fetcher { @@ -26,7 +27,7 @@ class FileFetcher extends Fetcher { // have to unpack the tarball for this. return cacache.tmp.withTmp(this.cache, this.opts, dir => this.extract(dir) - .then(() => this[_readPackageJson](dir + '/package.json')) + .then(() => this[_readPackageJson](dir)) .then(mani => this.package = { ...mani, _integrity: this.integrity && String(this.integrity), @@ -40,23 +41,23 @@ class FileFetcher extends Fetcher { return Promise.resolve() } - return Promise.all(Object.keys(pkg.bin).map(k => new Promise(res => { + return Promise.all(Object.keys(pkg.bin).map(async k => { const script = resolve(dest, pkg.bin[k]) // Best effort. Ignore errors here, the only result is that // a bin script is not executable. But if it's missing or // something, we just leave it for a later stage to trip over // when we can provide a more useful contextual error. - fs.stat(script, (er, st) => { - if (er) { - return res() - } + try { + const st = await stat(script) const mode = st.mode | 0o111 if (mode === st.mode) { - return res() + return } - fs.chmod(script, mode, res) - }) - }))) + await chmod(script, mode) + } catch { + // Ignore errors here + } + })) } extract (dest) { @@ -64,7 +65,7 @@ class FileFetcher extends Fetcher { // but if not, read the unpacked manifest and chmod properly. return super.extract(dest) .then(result => this.package ? result - : this[_readPackageJson](dest + '/package.json').then(pkg => + : this[_readPackageJson](dest).then(pkg => this[_exeBins](pkg, dest)).then(() => result)) } diff --git a/node_modules/pacote/lib/git.js b/node_modules/pacote/lib/git.js index 533d83d3d8dd3..2cac44ae528e6 100644 --- a/node_modules/pacote/lib/git.js +++ b/node_modules/pacote/lib/git.js @@ -156,11 +156,11 @@ class GitFetcher extends Fetcher { [_resolvedFromClone] () { // do a full or shallow clone, then look at the HEAD // kind of wasteful, but no other option, really - return this[_clone](dir => this.resolved) + return this[_clone](() => this.resolved) } [_prepareDir] (dir) { - return this[_readPackageJson](dir + '/package.json').then(mani => { + return this[_readPackageJson](dir).then(mani => { // no need if we aren't going to do any preparation. const scripts = mani.scripts if (!mani.workspaces && (!scripts || !( @@ -312,7 +312,7 @@ class GitFetcher extends Fetcher { return this.spec.hosted && this.resolved ? FileFetcher.prototype.manifest.apply(this) : this[_clone](dir => - this[_readPackageJson](dir + '/package.json') + this[_readPackageJson](dir) .then(mani => this.package = { ...mani, _resolved: this.resolved, diff --git a/node_modules/pacote/lib/registry.js b/node_modules/pacote/lib/registry.js index de25a11af4667..b6a8d49b84f32 100644 --- a/node_modules/pacote/lib/registry.js +++ b/node_modules/pacote/lib/registry.js @@ -3,7 +3,7 @@ const RemoteFetcher = require('./remote.js') const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved') const pacoteVersion = require('../package.json').version const removeTrailingSlashes = require('./util/trailing-slashes.js') -const rpj = require('read-package-json-fast') +const PackageJson = require('@npmcli/package-json') const pickManifest = require('npm-pick-manifest') const ssri = require('ssri') const crypto = require('crypto') @@ -127,12 +127,13 @@ class RegistryFetcher extends Fetcher { } const packument = await this.packument() - let mani = await pickManifest(packument, this.spec.fetchSpec, { + const steps = PackageJson.normalizeSteps.filter(s => s !== '_attributes') + const mani = await new PackageJson().fromContent(pickManifest(packument, this.spec.fetchSpec, { ...this.opts, defaultTag: this.defaultTag, before: this.before, - }) - mani = rpj.normalize(mani) + })).normalize({ steps }).then(p => p.content) + /* XXX add ETARGET and E403 revalidation of cached packuments here */ // add _time from packument if fetched with fullMetadata diff --git a/node_modules/pacote/package.json b/node_modules/pacote/package.json index 9fc3f2cfee960..a4048eee28510 100644 --- a/node_modules/pacote/package.json +++ b/node_modules/pacote/package.json @@ -1,6 +1,6 @@ { "name": "pacote", - "version": "18.0.0", + "version": "18.0.2", "description": "JavaScript package downloader", "author": "GitHub Inc.", "bin": { @@ -46,6 +46,7 @@ "dependencies": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.0", "@npmcli/run-script": "^8.0.0", "cacache": "^18.0.0", @@ -57,8 +58,6 @@ "npm-registry-fetch": "^16.0.0", "proc-log": "^4.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^7.0.0", - "read-package-json-fast": "^3.0.0", "sigstore": "^2.2.0", "ssri": "^10.0.0", "tar": "^6.1.11" diff --git a/node_modules/read-package-json/LICENSE b/node_modules/read-package-json/LICENSE deleted file mode 100644 index 052085c436514..0000000000000 --- a/node_modules/read-package-json/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/read-package-json/lib/read-json.js b/node_modules/read-package-json/lib/read-json.js deleted file mode 100644 index d35f09ebd208f..0000000000000 --- a/node_modules/read-package-json/lib/read-json.js +++ /dev/null @@ -1,589 +0,0 @@ -var fs = require('fs') - -var path = require('path') - -var { glob } = require('glob') -var normalizeData = require('normalize-package-data') -var safeJSON = require('json-parse-even-better-errors') -var util = require('util') -var normalizePackageBin = require('npm-normalize-package-bin') - -module.exports = readJson - -// put more stuff on here to customize. -readJson.extraSet = [ - bundleDependencies, - gypfile, - serverjs, - scriptpath, - authors, - readme, - mans, - bins, - githead, - fillTypes, -] - -var typoWarned = {} -var cache = {} - -function readJson (file, log_, strict_, cb_) { - var log, strict, cb - for (var i = 1; i < arguments.length - 1; i++) { - if (typeof arguments[i] === 'boolean') { - strict = arguments[i] - } else if (typeof arguments[i] === 'function') { - log = arguments[i] - } - } - - if (!log) { - log = function () {} - } - cb = arguments[arguments.length - 1] - - readJson_(file, log, strict, cb) -} - -function readJson_ (file, log, strict, cb) { - fs.readFile(file, 'utf8', function (er, d) { - parseJson(file, er, d, log, strict, cb) - }) -} - -function stripBOM (content) { - // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) - // because the buffer-to-string conversion in `fs.readFileSync()` - // translates it to FEFF, the UTF-16 BOM. - if (content.charCodeAt(0) === 0xFEFF) { - content = content.slice(1) - } - return content -} - -function jsonClone (obj) { - if (obj == null) { - return obj - } else if (Array.isArray(obj)) { - var newarr = new Array(obj.length) - for (var ii in obj) { - newarr[ii] = jsonClone(obj[ii]) - } - return newarr - } else if (typeof obj === 'object') { - var newobj = {} - for (var kk in obj) { - newobj[kk] = jsonClone(obj[kk]) - } - return newobj - } else { - return obj - } -} - -function parseJson (file, er, d, log, strict, cb) { - if (er && er.code === 'ENOENT') { - return fs.stat(path.dirname(file), function (err, stat) { - if (!err && stat && !stat.isDirectory()) { - // ENOTDIR isn't used on Windows, but npm expects it. - er = Object.create(er) - er.code = 'ENOTDIR' - return cb(er) - } else { - return indexjs(file, er, log, strict, cb) - } - }) - } - if (er) { - return cb(er) - } - - if (cache[d]) { - return cb(null, jsonClone(cache[d])) - } - - var data - - try { - data = safeJSON(stripBOM(d)) - for (var key in data) { - if (/^_/.test(key)) { - delete data[key] - } - } - } catch (jsonErr) { - data = parseIndex(d) - if (!data) { - return cb(parseError(jsonErr, file)) - } - } - extrasCached(file, d, data, log, strict, cb) -} - -function extrasCached (file, d, data, log, strict, cb) { - extras(file, data, log, strict, function (err, extrasData) { - if (!err) { - cache[d] = jsonClone(extrasData) - } - cb(err, extrasData) - }) -} - -function indexjs (file, er, log, strict, cb) { - if (path.basename(file) === 'index.js') { - return cb(er) - } - - var index = path.resolve(path.dirname(file), 'index.js') - fs.readFile(index, 'utf8', function (er2, d) { - if (er2) { - return cb(er) - } - - if (cache[d]) { - return cb(null, cache[d]) - } - - var data = parseIndex(d) - if (!data) { - return cb(er) - } - - extrasCached(file, d, data, log, strict, cb) - }) -} - -readJson.extras = extras -function extras (file, data, log_, strict_, cb_) { - var log, strict, cb - for (var i = 2; i < arguments.length - 1; i++) { - if (typeof arguments[i] === 'boolean') { - strict = arguments[i] - } else if (typeof arguments[i] === 'function') { - log = arguments[i] - } - } - - if (!log) { - log = function () {} - } - cb = arguments[i] - - var set = readJson.extraSet - var n = set.length - var errState = null - set.forEach(function (fn) { - fn(file, data, then) - }) - - function then (er) { - if (errState) { - return - } - if (er) { - return cb(errState = er) - } - if (--n > 0) { - return - } - final(file, data, log, strict, cb) - } -} - -function scriptpath (file, data, cb) { - if (!data.scripts) { - return cb(null, data) - } - var k = Object.keys(data.scripts) - k.forEach(scriptpath_, data.scripts) - cb(null, data) -} - -function scriptpath_ (key) { - var s = this[key] - // This is never allowed, and only causes problems - if (typeof s !== 'string') { - return delete this[key] - } - - var spre = /^(\.[/\\])?node_modules[/\\].bin[\\/]/ - if (s.match(spre)) { - this[key] = this[key].replace(spre, '') - } -} - -function gypfile (file, data, cb) { - var dir = path.dirname(file) - var s = data.scripts || {} - if (s.install || s.preinstall) { - return cb(null, data) - } - - if (data.gypfile === false) { - return cb(null, data) - } - glob('*.gyp', { cwd: dir }) - .then(files => gypfile_(file, data, files, cb)) - .catch(er => cb(er)) -} - -function gypfile_ (file, data, files, cb) { - if (!files.length) { - return cb(null, data) - } - var s = data.scripts || {} - s.install = 'node-gyp rebuild' - data.scripts = s - data.gypfile = true - return cb(null, data) -} - -function serverjs (file, data, cb) { - var dir = path.dirname(file) - var s = data.scripts || {} - if (s.start) { - return cb(null, data) - } - fs.access(path.join(dir, 'server.js'), (err) => { - if (!err) { - s.start = 'node server.js' - data.scripts = s - } - return cb(null, data) - }) -} - -function authors (file, data, cb) { - if (data.contributors) { - return cb(null, data) - } - var af = path.resolve(path.dirname(file), 'AUTHORS') - fs.readFile(af, 'utf8', function (er, ad) { - // ignore error. just checking it. - if (er) { - return cb(null, data) - } - authors_(file, data, ad, cb) - }) -} - -function authors_ (file, data, ad, cb) { - ad = ad.split(/\r?\n/g).map(function (line) { - return line.replace(/^\s*#.*$/, '').trim() - }).filter(function (line) { - return line - }) - data.contributors = ad - return cb(null, data) -} - -function readme (file, data, cb) { - if (data.readme) { - return cb(null, data) - } - var dir = path.dirname(file) - var globOpts = { cwd: dir, nocase: true, mark: true } - glob('{README,README.*}', globOpts) - .then(files => { - // don't accept directories. - files = files.filter(function (filtered) { - return !filtered.match(/\/$/) - }) - if (!files.length) { - return cb() - } - var fn = preferMarkdownReadme(files) - var rm = path.resolve(dir, fn) - return readme_(file, data, rm, cb) - }) - .catch(er => cb(er)) -} - -function preferMarkdownReadme (files) { - var fallback = 0 - var re = /\.m?a?r?k?d?o?w?n?$/i - for (var i = 0; i < files.length; i++) { - if (files[i].match(re)) { - return files[i] - } else if (files[i].match(/README$/)) { - fallback = i - } - } - // prefer README.md, followed by README; otherwise, return - // the first filename (which could be README) - return files[fallback] -} - -function readme_ (file, data, rm, cb) { - var rmfn = path.basename(rm) - fs.readFile(rm, 'utf8', function (er, rmData) { - // maybe not readable, or something. - if (er) { - return cb() - } - data.readme = rmData - data.readmeFilename = rmfn - return cb(er, data) - }) -} - -function mans (file, data, cb) { - let cwd = data.directories && data.directories.man - if (data.man || !cwd) { - return cb(null, data) - } - const dirname = path.dirname(file) - cwd = path.resolve(path.dirname(file), cwd) - glob('**/*.[0-9]', { cwd }) - .then(mansGlob => { - data.man = mansGlob.map(man => - path.relative(dirname, path.join(cwd, man)).split(path.sep).join('/') - ) - return cb(null, data) - }) - .catch(er => cb(er)) -} - -function bins (file, data, cb) { - data = normalizePackageBin(data) - - var m = data.directories && data.directories.bin - if (data.bin || !m) { - return cb(null, data) - } - - m = path.resolve(path.dirname(file), path.join('.', path.join('/', m))) - glob('**', { cwd: m }) - .then(binsGlob => bins_(file, data, binsGlob, cb)) - .catch(er => cb(er)) -} - -function bins_ (file, data, binsGlob, cb) { - var m = (data.directories && data.directories.bin) || '.' - data.bin = binsGlob.reduce(function (acc, mf) { - if (mf && mf.charAt(0) !== '.') { - var f = path.basename(mf) - acc[f] = path.join(m, mf) - } - return acc - }, {}) - return cb(null, normalizePackageBin(data)) -} - -function bundleDependencies (file, data, cb) { - var bd = 'bundleDependencies' - var bdd = 'bundledDependencies' - // normalize key name - if (data[bdd] !== undefined) { - if (data[bd] === undefined) { - data[bd] = data[bdd] - } - delete data[bdd] - } - if (data[bd] === false) { - delete data[bd] - } else if (data[bd] === true) { - data[bd] = Object.keys(data.dependencies || {}) - } else if (data[bd] !== undefined && !Array.isArray(data[bd])) { - delete data[bd] - } - return cb(null, data) -} - -function githead (file, data, cb) { - if (data.gitHead) { - return cb(null, data) - } - var dir = path.dirname(file) - var head = path.resolve(dir, '.git/HEAD') - fs.readFile(head, 'utf8', function (er, headData) { - if (er) { - var parent = path.dirname(dir) - if (parent === dir) { - return cb(null, data) - } - return githead(dir, data, cb) - } - githead_(data, dir, headData, cb) - }) -} - -function githead_ (data, dir, head, cb) { - if (!head.match(/^ref: /)) { - data.gitHead = head.trim() - return cb(null, data) - } - var headRef = head.replace(/^ref: /, '').trim() - var headFile = path.resolve(dir, '.git', headRef) - fs.readFile(headFile, 'utf8', function (er, headData) { - if (er || !headData) { - var packFile = path.resolve(dir, '.git/packed-refs') - return fs.readFile(packFile, 'utf8', function (readFileErr, refs) { - if (readFileErr || !refs) { - return cb(null, data) - } - refs = refs.split('\n') - for (var i = 0; i < refs.length; i++) { - var match = refs[i].match(/^([0-9a-f]{40}) (.+)$/) - if (match && match[2].trim() === headRef) { - data.gitHead = match[1] - break - } - } - return cb(null, data) - }) - } - headData = headData.replace(/^ref: /, '').trim() - data.gitHead = headData - return cb(null, data) - }) -} - -/** - * Warn if the bin references don't point to anything. This might be better in - * normalize-package-data if it had access to the file path. - */ -function checkBinReferences_ (file, data, warn, cb) { - if (!(data.bin instanceof Object)) { - return cb() - } - - var keys = Object.keys(data.bin) - var keysLeft = keys.length - if (!keysLeft) { - return cb() - } - - function handleExists (relName, result) { - keysLeft-- - if (!result) { - warn('No bin file found at ' + relName) - } - if (!keysLeft) { - cb() - } - } - - keys.forEach(function (key) { - var dirName = path.dirname(file) - var relName = data.bin[key] - /* istanbul ignore if - impossible, bins have been normalized */ - if (typeof relName !== 'string') { - var msg = 'Bin filename for ' + key + - ' is not a string: ' + util.inspect(relName) - warn(msg) - delete data.bin[key] - handleExists(relName, true) - return - } - var binPath = path.resolve(dirName, relName) - fs.stat(binPath, (err) => handleExists(relName, !err)) - }) -} - -function final (file, data, log, strict, cb) { - var pId = makePackageId(data) - - function warn (msg) { - if (typoWarned[pId]) { - return - } - if (log) { - log('package.json', pId, msg) - } - } - - try { - normalizeData(data, warn, strict) - } catch (error) { - return cb(error) - } - - checkBinReferences_(file, data, warn, function () { - typoWarned[pId] = true - cb(null, data) - }) -} - -function fillTypes (file, data, cb) { - var index = data.main || 'index.js' - - if (typeof index !== 'string') { - return cb(new TypeError('The "main" attribute must be of type string.')) - } - - // TODO exports is much more complicated than this in verbose format - // We need to support for instance - - // "exports": { - // ".": [ - // { - // "default": "./lib/npm.js" - // }, - // "./lib/npm.js" - // ], - // "./package.json": "./package.json" - // }, - // as well as conditional exports - - // if (data.exports && typeof data.exports === 'string') { - // index = data.exports - // } - - // if (data.exports && data.exports['.']) { - // index = data.exports['.'] - // if (typeof index !== 'string') { - // } - // } - - var extless = - path.join(path.dirname(index), path.basename(index, path.extname(index))) - var dts = `./${extless}.d.ts` - var dtsPath = path.join(path.dirname(file), dts) - var hasDTSFields = 'types' in data || 'typings' in data - if (!hasDTSFields && fs.existsSync(dtsPath)) { - data.types = dts.split(path.sep).join('/') - } - - cb(null, data) -} - -function makePackageId (data) { - var name = cleanString(data.name) - var ver = cleanString(data.version) - return name + '@' + ver -} - -function cleanString (str) { - return (!str || typeof (str) !== 'string') ? '' : str.trim() -} - -// /**package { "name": "foo", "version": "1.2.3", ... } **/ -function parseIndex (data) { - data = data.split(/^\/\*\*package(?:\s|$)/m) - - if (data.length < 2) { - return null - } - data = data[1] - data = data.split(/\*\*\/$/m) - - if (data.length < 2) { - return null - } - data = data[0] - data = data.replace(/^\s*\*/mg, '') - - try { - return safeJSON(data) - } catch (er) { - return null - } -} - -function parseError (ex, file) { - var e = new Error('Failed to parse json\n' + ex.message) - e.code = 'EJSONPARSE' - e.path = file - return e -} diff --git a/node_modules/read-package-json/package.json b/node_modules/read-package-json/package.json deleted file mode 100644 index 01061f2bc2792..0000000000000 --- a/node_modules/read-package-json/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "read-package-json", - "version": "7.0.0", - "author": "GitHub Inc.", - "description": "The thing npm uses to read package.json files with semantics and defaults and validation", - "repository": { - "type": "git", - "url": "https://github.com/npm/read-package-json.git" - }, - "main": "lib/read-json.js", - "scripts": { - "prerelease": "npm t", - "postrelease": "npm publish && git push --follow-tags", - "release": "standard-version -s", - "test": "tap", - "npmclilint": "npmcli-lint", - "lint": "eslint \"**/*.js\"", - "lintfix": "npm run lint -- --fix", - "posttest": "npm run lint", - "postsnap": "npm run lintfix --", - "postlint": "template-oss-check", - "snap": "tap", - "template-oss-apply": "template-oss-apply --force" - }, - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.18.0", - "tap": "^16.0.1" - }, - "license": "ISC", - "files": [ - "bin/", - "lib/" - ], - "engines": { - "node": "^16.14.0 || >=18.0.0" - }, - "tap": { - "branches": 73, - "functions": 77, - "lines": 77, - "statements": 77, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.18.0", - "publish": "true", - "ciVersions": [ - "16.14.0", - "16.x", - "18.0.0", - "18.x" - ] - } -} diff --git a/package-lock.json b/package-lock.json index 553d6bc781c4d..153a22e746b0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -139,7 +139,7 @@ "npm-registry-fetch": "^16.2.1", "npm-user-validate": "^2.0.0", "p-map": "^4.0.0", - "pacote": "^18.0.0", + "pacote": "^18.0.2", "parse-conflict-json": "^3.0.1", "proc-log": "^4.2.0", "proggy": "^2.0.0", @@ -237,7 +237,7 @@ "json-stringify-safe": "^5.0.1", "nock": "^13.3.3", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "tap": "^16.3.8" }, "engines": { @@ -1836,9 +1836,9 @@ } }, "node_modules/@npmcli/package-json": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.0.3.tgz", - "integrity": "sha512-cgsjCvld2wMqkUqvY+SZI+1ZJ7umGBYc9IAKfqJRKJCcs7hCQYxScUgdsyrRINk3VmdCYf9TXiLBHQ6ECTxhtg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.1.0.tgz", + "integrity": "sha512-1aL4TuVrLS9sf8quCLerU3H9J4vtCtgu8VauYozrmEyU57i/EdKleCnsQ7vpnABIH6c9mnTxcH5sFkO3BlV8wQ==", "inBundle": true, "dependencies": { "@npmcli/git": "^5.0.0", @@ -10875,13 +10875,14 @@ } }, "node_modules/pacote": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.0.tgz", - "integrity": "sha512-ma7uVt/q3Sb3XbLwUjOeClz+7feHjMOFegHn5whw++x+GzikZkAq/2auklSbRuy6EI2iJh1/ZqCpVaUcxRaeqQ==", + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.2.tgz", + "integrity": "sha512-oMxnZQCOZqFZyEh5oJtpMepoub4hoI6EfMUCdbwkBqkFuJ1Dwfz5IMQD344dKbwPPBNZWKwGL/kNvmDubZyvug==", "inBundle": true, "dependencies": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.0", "@npmcli/run-script": "^8.0.0", "cacache": "^18.0.0", @@ -10893,8 +10894,6 @@ "npm-registry-fetch": "^16.0.0", "proc-log": "^4.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^7.0.0", - "read-package-json-fast": "^3.0.0", "sigstore": "^2.2.0", "ssri": "^10.0.0", "tar": "^6.1.11" @@ -11373,21 +11372,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/read-package-json": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", - "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", - "inBundle": true, - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/read-package-json-fast": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", @@ -16376,7 +16360,7 @@ "npm-package-arg": "^11.0.2", "npm-pick-manifest": "^9.0.0", "npm-registry-fetch": "^16.2.1", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "parse-conflict-json": "^3.0.0", "proc-log": "^4.2.0", "proggy": "^2.0.0", @@ -16457,7 +16441,7 @@ "diff": "^5.1.0", "minimatch": "^9.0.4", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "tar": "^6.2.1" }, "devDependencies": { @@ -16477,7 +16461,7 @@ "@npmcli/run-script": "^8.0.0", "ci-info": "^4.0.0", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "proc-log": "^4.2.0", "read": "^3.0.1", "read-package-json-fast": "^3.0.2", @@ -16555,7 +16539,7 @@ "@npmcli/arborist": "^7.2.1", "@npmcli/run-script": "^8.0.0", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0" + "pacote": "^18.0.1" }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", diff --git a/package.json b/package.json index 044149f0674d2..299414e4b4ad4 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "npm-registry-fetch": "^16.2.1", "npm-user-validate": "^2.0.0", "p-map": "^4.0.0", - "pacote": "^18.0.0", + "pacote": "^18.0.2", "parse-conflict-json": "^3.0.1", "proc-log": "^4.2.0", "proggy": "^2.0.0", diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index ba00f05db1b4c..bca86d9451966 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -26,7 +26,7 @@ "npm-package-arg": "^11.0.2", "npm-pick-manifest": "^9.0.0", "npm-registry-fetch": "^16.2.1", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "parse-conflict-json": "^3.0.0", "proc-log": "^4.2.0", "proggy": "^2.0.0", diff --git a/workspaces/libnpmdiff/package.json b/workspaces/libnpmdiff/package.json index 04e9b90adb79f..adeb3fc09c5a7 100644 --- a/workspaces/libnpmdiff/package.json +++ b/workspaces/libnpmdiff/package.json @@ -52,7 +52,7 @@ "diff": "^5.1.0", "minimatch": "^9.0.4", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "tar": "^6.2.1" }, "templateOSS": { diff --git a/workspaces/libnpmexec/package.json b/workspaces/libnpmexec/package.json index 812d99e1a0f90..b06b983a77b7c 100644 --- a/workspaces/libnpmexec/package.json +++ b/workspaces/libnpmexec/package.json @@ -63,7 +63,7 @@ "@npmcli/run-script": "^8.0.0", "ci-info": "^4.0.0", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0", + "pacote": "^18.0.1", "proc-log": "^4.2.0", "read": "^3.0.1", "read-package-json-fast": "^3.0.2", diff --git a/workspaces/libnpmpack/package.json b/workspaces/libnpmpack/package.json index 518e95420455c..9ec7dcd15fee1 100644 --- a/workspaces/libnpmpack/package.json +++ b/workspaces/libnpmpack/package.json @@ -39,7 +39,7 @@ "@npmcli/arborist": "^7.2.1", "@npmcli/run-script": "^8.0.0", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.0" + "pacote": "^18.0.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" From ea66e9534f4b9004f8b4c53a2f8adb7688ee9b36 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 24 Apr 2024 10:17:57 -0700 Subject: [PATCH 12/42] chore: remove licensee as a devDependency (#7380) It is only used during CI and we can call it with `npx` Co-authored-by: Gar --- DEPENDENCIES.md | 1 - package-lock.json | 1618 ++++----------------------------------------- package.json | 3 +- 3 files changed, 123 insertions(+), 1499 deletions(-) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 87abae3f85cd9..730d8a35ca730 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -491,7 +491,6 @@ graph LR; npm-->libnpmsearch; npm-->libnpmteam; npm-->libnpmversion; - npm-->licensee; npm-->make-fetch-happen; npm-->minimatch; npm-->minipass-pipeline; diff --git a/package-lock.json b/package-lock.json index 153a22e746b0a..31e6c9f394223 100644 --- a/package-lock.json +++ b/package-lock.json @@ -174,7 +174,6 @@ "ajv-formats-draft2019": "^1.6.1", "cli-table3": "^0.6.4", "diff": "^5.2.0", - "licensee": "^10.0.0", "nock": "^13.4.0", "npm-packlist": "^8.0.2", "remark": "^14.0.2", @@ -686,12 +685,6 @@ "node": ">=6.9.0" } }, - "node_modules/@blueoak/list": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@blueoak/list/-/list-9.0.0.tgz", - "integrity": "sha512-ExvaAZaZEIhaCePVpqW4ZoFgixhuylQiukSSqaRNfqUtqSWKnlUMZpZWOlugRpfRLuazPkcquDVhPkeodQI5FQ==", - "dev": true - }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -1228,12 +1221,6 @@ "node": ">=14" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, "node_modules/@google-automations/git-file-utils": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@google-automations/git-file-utils/-/git-file-utils-1.2.6.tgz", @@ -1746,77 +1733,6 @@ "resolved": "mock-registry", "link": true }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@npmcli/move-file/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/move-file/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@npmcli/name-from-folder": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", @@ -2213,15 +2129,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/@tufjs/canonical-json": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", @@ -2412,18 +2319,6 @@ "node": ">= 14" } }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dev": true, - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -2542,15 +2437,6 @@ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "inBundle": true }, - "node_modules/are-we-there-yet": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz", - "integrity": "sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2669,15 +2555,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -3571,12 +3448,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, "node_modules/conventional-changelog-angular": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", @@ -3744,15 +3615,6 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/correct-license-metadata": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/correct-license-metadata/-/correct-license-metadata-1.4.0.tgz", - "integrity": "sha512-nvbNpK/aYCbztZWGi9adIPqR+ZcQmZTWNT7eMYLvkaVGroN1nTHiVuuNPl7pK6ZNx1mvDztlRBJtfUdrVwKJ5A==", - "dev": true, - "dependencies": { - "spdx-expression-validate": "^2.0.0" - } - }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -4151,12 +4013,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, "node_modules/deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", @@ -4195,15 +4051,6 @@ "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", "dev": true }, - "node_modules/docopt": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz", - "integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5578,25 +5425,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.1.tgz", - "integrity": "sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -5944,15 +5772,6 @@ "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -6027,12 +5846,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -6318,15 +6131,6 @@ "node": ">=10.17.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -6405,12 +6209,6 @@ "node": ">=8" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7379,1250 +7177,170 @@ }, "node_modules/just-extend": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true - }, - "node_modules/just-omit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/just-omit/-/just-omit-2.2.0.tgz", - "integrity": "sha512-Js7+HxDOGcB3RhI38Mird/RgyMf3t0DAJFda1QWqqlAKTa36NeSYIufJXxrZUbysFTRcTOFcoMCiFK5FwCoI7Q==", - "dev": true - }, - "node_modules/just-safe-set": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-safe-set/-/just-safe-set-4.2.1.tgz", - "integrity": "sha512-La5CP41Ycv52+E4g7w1sRV8XXk7Sp8a/TwWQAYQKn6RsQz1FD4Z/rDRRmqV3wJznS1MDF3YxK7BCudX1J8FxLg==", - "dev": true - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "peer": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libnpmaccess": { - "resolved": "workspaces/libnpmaccess", - "link": true - }, - "node_modules/libnpmdiff": { - "resolved": "workspaces/libnpmdiff", - "link": true - }, - "node_modules/libnpmexec": { - "resolved": "workspaces/libnpmexec", - "link": true - }, - "node_modules/libnpmfund": { - "resolved": "workspaces/libnpmfund", - "link": true - }, - "node_modules/libnpmhook": { - "resolved": "workspaces/libnpmhook", - "link": true - }, - "node_modules/libnpmorg": { - "resolved": "workspaces/libnpmorg", - "link": true - }, - "node_modules/libnpmpack": { - "resolved": "workspaces/libnpmpack", - "link": true - }, - "node_modules/libnpmpublish": { - "resolved": "workspaces/libnpmpublish", - "link": true - }, - "node_modules/libnpmsearch": { - "resolved": "workspaces/libnpmsearch", - "link": true - }, - "node_modules/libnpmteam": { - "resolved": "workspaces/libnpmteam", - "link": true - }, - "node_modules/libnpmversion": { - "resolved": "workspaces/libnpmversion", - "link": true - }, - "node_modules/libtap": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/libtap/-/libtap-1.4.1.tgz", - "integrity": "sha512-S9v19shLTigoMn3c02V7LZ4t09zxmVP3r3RbEAwuHFYeKgF+ESFJxoQ0PMFKW4XdgQhcjVBEwDoopG6WROq/gw==", - "dev": true, - "dependencies": { - "async-hook-domain": "^2.0.4", - "bind-obj-methods": "^3.0.0", - "diff": "^4.0.2", - "function-loop": "^2.0.1", - "minipass": "^3.1.5", - "own-or": "^1.0.0", - "own-or-env": "^1.0.2", - "signal-exit": "^3.0.4", - "stack-utils": "^2.0.4", - "tap-parser": "^11.0.0", - "tap-yaml": "^1.0.0", - "tcompare": "^5.0.6", - "trivial-deferred": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/libtap/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/libtap/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/libtap/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/licensee": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/licensee/-/licensee-10.0.0.tgz", - "integrity": "sha512-gvn5JHCNuchGGjjIm6FsK4qSOTtHkbUfo8YKW61hhEIk3osEf3fKlCH9ma0j+HaVESrOt0YUOmsi/wusKSnneQ==", - "dev": true, - "dependencies": { - "@blueoak/list": "^9.0.0", - "@npmcli/arborist": "^6.1.2", - "correct-license-metadata": "^1.4.0", - "docopt": "^0.6.2", - "has": "^1.0.3", - "npm-license-corrections": "^1.6.2", - "semver": "^7.3.8", - "spdx-expression-parse": "^3.0.1", - "spdx-expression-validate": "^2.0.0", - "spdx-osi": "^3.0.0", - "spdx-whitelisted": "^1.0.0" - }, - "bin": { - "licensee": "licensee" - }, - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/licensee/node_modules/@npmcli/arborist": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-6.5.1.tgz", - "integrity": "sha512-cdV8pGurLK0CifZRilMJbm2CZ3H4Snk8PAqOngj5qmgFLjEllMLvScSZ3XKfd+CK8fo/hrPHO9zazy9OYdvmUg==", - "dev": true, - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^3.1.0", - "@npmcli/installed-package-contents": "^2.0.2", - "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/metavuln-calculator": "^5.0.0", - "@npmcli/name-from-folder": "^2.0.0", - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^4.0.0", - "@npmcli/query": "^3.1.0", - "@npmcli/run-script": "^6.0.0", - "bin-links": "^4.0.1", - "cacache": "^17.0.4", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^6.1.1", - "json-parse-even-better-errors": "^3.0.0", - "json-stringify-nice": "^1.1.4", - "minimatch": "^9.0.0", - "nopt": "^7.0.0", - "npm-install-checks": "^6.2.0", - "npm-package-arg": "^10.1.0", - "npm-pick-manifest": "^8.0.1", - "npm-registry-fetch": "^14.0.3", - "npmlog": "^7.0.1", - "pacote": "^15.0.8", - "parse-conflict-json": "^3.0.0", - "proc-log": "^3.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^1.0.2", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^10.0.1", - "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@npmcli/git": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", - "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", - "dev": true, - "dependencies": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@npmcli/metavuln-calculator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-5.0.1.tgz", - "integrity": "sha512-qb8Q9wIIlEPj3WeA1Lba91R4ZboPL0uspzV0F9uwP+9AYMVB2zOoa7Pbk12g6D2NHAinSbHh6QYmGuRyHZ874Q==", - "dev": true, - "dependencies": { - "cacache": "^17.0.0", - "json-parse-even-better-errors": "^3.0.0", - "pacote": "^15.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@npmcli/package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q==", - "dev": true, - "dependencies": { - "@npmcli/git": "^4.1.0", - "glob": "^10.2.2", - "hosted-git-info": "^6.1.1", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "proc-log": "^3.0.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@npmcli/promise-spawn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", - "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", - "dev": true, - "dependencies": { - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@npmcli/run-script": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", - "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", - "dev": true, - "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@sigstore/bundle": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", - "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", - "dev": true, - "dependencies": { - "@sigstore/protobuf-specs": "^0.2.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@sigstore/protobuf-specs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", - "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@sigstore/sign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", - "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", - "dev": true, - "dependencies": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "make-fetch-happen": "^11.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@sigstore/sign/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@sigstore/sign/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/licensee/node_modules/@sigstore/tuf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", - "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", - "dev": true, - "dependencies": { - "@sigstore/protobuf-specs": "^0.2.0", - "tuf-js": "^1.1.7" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@tufjs/canonical-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", - "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/@tufjs/models": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", - "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", - "dev": true, - "dependencies": { - "@tufjs/canonical-json": "1.0.0", - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/licensee/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/licensee/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", - "dev": true, - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/licensee/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/licensee/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/make-fetch-happen/node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/licensee/node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/licensee/node_modules/node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/licensee/node_modules/node-gyp/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/licensee/node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/licensee/node_modules/node-gyp/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/licensee/node_modules/node-gyp/node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/licensee/node_modules/node-gyp/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/licensee/node_modules/normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", - "dev": true, - "dependencies": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/npm-packlist": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", - "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", - "dev": true, - "dependencies": { - "ignore-walk": "^6.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/npm-pick-manifest": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", - "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", - "dev": true, - "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/npm-registry-fetch": { - "version": "14.0.5", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", - "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", - "dev": true, - "dependencies": { - "make-fetch-happen": "^11.0.0", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^10.0.0", - "proc-log": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/npm-registry-fetch/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/licensee/node_modules/pacote": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", - "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", - "dev": true, - "dependencies": { - "@npmcli/git": "^4.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^5.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^1.3.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/pacote/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/licensee/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/promise-call-limit": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.2.tgz", - "integrity": "sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/licensee/node_modules/read-package-json": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", - "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", - "dev": true, - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/licensee/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/licensee/node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/licensee/node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true }, - "node_modules/licensee/node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } + "node_modules/just-omit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/just-omit/-/just-omit-2.2.0.tgz", + "integrity": "sha512-Js7+HxDOGcB3RhI38Mird/RgyMf3t0DAJFda1QWqqlAKTa36NeSYIufJXxrZUbysFTRcTOFcoMCiFK5FwCoI7Q==", + "dev": true }, - "node_modules/licensee/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/just-safe-set": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-safe-set/-/just-safe-set-4.2.1.tgz", + "integrity": "sha512-La5CP41Ycv52+E4g7w1sRV8XXk7Sp8a/TwWQAYQKn6RsQz1FD4Z/rDRRmqV3wJznS1MDF3YxK7BCudX1J8FxLg==", "dev": true }, - "node_modules/licensee/node_modules/sigstore": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", - "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "peer": true, "dependencies": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "@sigstore/sign": "^1.0.0", - "@sigstore/tuf": "^1.0.3", - "make-fetch-happen": "^11.0.1" - }, - "bin": { - "sigstore": "bin/sigstore.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "json-buffer": "3.0.1" } }, - "node_modules/licensee/node_modules/sigstore/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/licensee/node_modules/sigstore/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/licensee/node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, "engines": { - "node": ">= 10" - } - }, - "node_modules/licensee/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "node": ">=0.10.0" } }, - "node_modules/licensee/node_modules/tuf-js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", - "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "peer": true, "dependencies": { - "@tufjs/models": "1.0.4", - "debug": "^4.3.4", - "make-fetch-happen": "^11.1.1" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 0.8.0" } }, - "node_modules/licensee/node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "node_modules/libnpmaccess": { + "resolved": "workspaces/libnpmaccess", + "link": true + }, + "node_modules/libnpmdiff": { + "resolved": "workspaces/libnpmdiff", + "link": true + }, + "node_modules/libnpmexec": { + "resolved": "workspaces/libnpmexec", + "link": true + }, + "node_modules/libnpmfund": { + "resolved": "workspaces/libnpmfund", + "link": true + }, + "node_modules/libnpmhook": { + "resolved": "workspaces/libnpmhook", + "link": true + }, + "node_modules/libnpmorg": { + "resolved": "workspaces/libnpmorg", + "link": true + }, + "node_modules/libnpmpack": { + "resolved": "workspaces/libnpmpack", + "link": true + }, + "node_modules/libnpmpublish": { + "resolved": "workspaces/libnpmpublish", + "link": true + }, + "node_modules/libnpmsearch": { + "resolved": "workspaces/libnpmsearch", + "link": true + }, + "node_modules/libnpmteam": { + "resolved": "workspaces/libnpmteam", + "link": true + }, + "node_modules/libnpmversion": { + "resolved": "workspaces/libnpmversion", + "link": true + }, + "node_modules/libtap": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/libtap/-/libtap-1.4.1.tgz", + "integrity": "sha512-S9v19shLTigoMn3c02V7LZ4t09zxmVP3r3RbEAwuHFYeKgF+ESFJxoQ0PMFKW4XdgQhcjVBEwDoopG6WROq/gw==", "dev": true, "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" + "async-hook-domain": "^2.0.4", + "bind-obj-methods": "^3.0.0", + "diff": "^4.0.2", + "function-loop": "^2.0.1", + "minipass": "^3.1.5", + "own-or": "^1.0.0", + "own-or-env": "^1.0.2", + "signal-exit": "^3.0.4", + "stack-utils": "^2.0.4", + "tap-parser": "^11.0.0", + "tap-yaml": "^1.0.0", + "tcompare": "^5.0.6", + "trivial-deferred": "^1.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/licensee/node_modules/tuf-js/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/libtap/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.3.1" } }, - "node_modules/licensee/node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "node_modules/libtap/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "imurmurhash": "^0.1.4" + "yallist": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/licensee/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/libtap/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -10243,12 +8961,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-license-corrections": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/npm-license-corrections/-/npm-license-corrections-1.6.2.tgz", - "integrity": "sha512-U66tDCdutNSdzbbPu3IWpgUwcrekT3XW+5fPdRleQmW2kiDqCnurRJnI2kQswRYng1dg/GpgxXE8mT6r6s40rg==", - "dev": true - }, "node_modules/npm-normalize-package-bin": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", @@ -10353,21 +9065,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npmlog": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", - "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -12504,27 +11201,6 @@ "node": ">= 8" } }, - "node_modules/spdx-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", - "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", - "dev": true, - "dependencies": { - "array-find-index": "^1.0.2", - "spdx-expression-parse": "^3.0.0", - "spdx-ranges": "^2.0.0" - } - }, - "node_modules/spdx-compare/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -12561,53 +11237,12 @@ "spdx-license-ids": "^3.0.0" } }, - "node_modules/spdx-expression-validate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz", - "integrity": "sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/spdx-expression-validate/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, "node_modules/spdx-license-ids": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "inBundle": true }, - "node_modules/spdx-osi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-osi/-/spdx-osi-3.0.0.tgz", - "integrity": "sha512-7DZMaD/rNHWGf82qWOazBsLXQsaLsoJb9RRjhEUQr5o86kw3A1ErGzSdvaXl+KalZyKkkU5T2a5NjCCutAKQSw==", - "dev": true - }, - "node_modules/spdx-ranges": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", - "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", - "dev": true - }, - "node_modules/spdx-whitelisted": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/spdx-whitelisted/-/spdx-whitelisted-1.0.0.tgz", - "integrity": "sha512-X4FOpUCvZuo42MdB1zAZ/wdX4N0lLcWDozf2KYFVDgtLv8Lx+f31LOYLP2/FcwTzsPi64bS/VwKqklI4RBletg==", - "dev": true, - "dependencies": { - "spdx-compare": "^1.0.0", - "spdx-ranges": "^2.0.0" - } - }, "node_modules/split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", @@ -16050,15 +14685,6 @@ "node": ">=16" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index 299414e4b4ad4..9bb9b3a16ee43 100644 --- a/package.json +++ b/package.json @@ -205,7 +205,6 @@ "ajv-formats-draft2019": "^1.6.1", "cli-table3": "^0.6.4", "diff": "^5.2.0", - "licensee": "^10.0.0", "nock": "^13.4.0", "npm-packlist": "^8.0.2", "remark": "^14.0.2", @@ -218,7 +217,7 @@ "scripts": { "dependencies": "node scripts/bundle-and-gitignore-deps.js && node scripts/dependency-graph.js", "dumpconf": "env | grep npm | sort | uniq", - "licenses": "licensee --production --errors-only", + "licenses": "npx licensee --production --errors-only", "test": "tap", "test:nocolor": "CI=true tap -Rclassic", "test-all": "node . run test -ws -iwr --if-present", From dd39de7d1da743cbd33b671fa96f66667109b451 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 24 Apr 2024 10:32:25 -0700 Subject: [PATCH 13/42] chore: disable selflink test on apple silicon (#7411) Arborist CI has started failing on `macos-latest` now that those runners default to `arm64` machines (aka Apple Silicon). I am able to reproduce the failures locally on a Macbook Pro M1. After spending some time debugging the issue I believe it has to do with the timing of `Node` vs `Link` creation. I was able to bisect and find https://github.com/npm/cli/pull/5376 which removed the ability for nodes to possibly take longer to create than their link targets. Going back to the commit before that PR the flaky test passes locally for me and fails starting with the first commit in that PR. I'm just running the offending test in a loop and seeing if it fails, so not a perfect metric. But when it fails, I get a failure at least 10% of the time. On the old commit I was able to run it 50x with no failures. Here's what I was running locally to observe failures: ```sh COUNT="0" while true; do COUNT=$((COUNT+1)) echo "Start $COUNT" if ! npm test -w workspaces/arborist --ignore-scripts -- test/arborist/load-actual.js --no-coverage -Rtap --grep selflink; then echo "Failed on run $COUNT" exit 1 fi done ``` This is definitely an edge case, but one I would like to fix in the future. Disabling this test is to temporarily get CI green while we release and make more substantial changes that are hard to do with CI flaking. We've had other issues with symlinks and I would feel much better knowing we have defined behavior in this specific case when tracking down future potential symlink bugs. One fix that worked locally is iterating over `node.target.children` sequentially instead of in `Promise.all`] but that is probably only a side effect of the dep ordering in the test. A fix will have to account for any order of links and node taking different amount of time. https://github.com/npm/cli/blob/c1152e9d2e325bc87176d3d9788605107d109b7b/workspaces/arborist/lib/arborist/load-actual.js#L337 --- workspaces/arborist/test/fixtures/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/workspaces/arborist/test/fixtures/index.js b/workspaces/arborist/test/fixtures/index.js index fdc5592c7dd8d..2317d3f4b0515 100644 --- a/workspaces/arborist/test/fixtures/index.js +++ b/workspaces/arborist/test/fixtures/index.js @@ -20,7 +20,11 @@ const roots = [ 'optofdev', 'other', 'root', - 'selflink', + // This test flakes out on Apple Silicon + // https://github.com/npm/cli/pull/7411 + process.platform === 'darwin' && process.arch === 'arm64' + ? null + : 'selflink', 'symlinked-node-modules/example', 'workspace', 'workspace2', @@ -35,7 +39,7 @@ const roots = [ 'link-dep-nested', 'link-dep-nested/root', 'external-link-cached-dummy-dep/root', -] +].filter(Boolean) const symlinks = { 'selflink/node_modules/@scope/z/node_modules/glob': From 4ab64013236925e7bceb9f88cfcc81f4a65f292f Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 14:18:18 -0700 Subject: [PATCH 14/42] fix(cleanup): dont nest files utils dir --- lib/base-command.js | 2 +- lib/commands/edit.js | 2 +- lib/commands/explain.js | 2 +- lib/commands/explore.js | 2 +- lib/commands/fund.js | 2 +- lib/commands/init.js | 2 +- lib/commands/ls.js | 2 +- lib/commands/rebuild.js | 2 +- lib/commands/uninstall.js | 2 +- lib/commands/update.js | 2 +- lib/commands/version.js | 2 +- lib/{workspaces => utils}/get-workspaces.js | 0 lib/utils/{completion => }/installed-deep.js | 0 lib/utils/{completion => }/installed-shallow.js | 0 lib/{workspaces => utils}/update-workspaces.js | 0 test/lib/arborist-cmd.js | 2 +- test/lib/{workspaces => utils}/get-workspaces.js | 2 +- test/lib/utils/{completion => }/installed-deep.js | 2 +- test/lib/utils/{completion => }/installed-shallow.js | 2 +- 19 files changed, 15 insertions(+), 15 deletions(-) rename lib/{workspaces => utils}/get-workspaces.js (100%) rename lib/utils/{completion => }/installed-deep.js (100%) rename lib/utils/{completion => }/installed-shallow.js (100%) rename lib/{workspaces => utils}/update-workspaces.js (100%) rename test/lib/{workspaces => utils}/get-workspaces.js (98%) rename test/lib/utils/{completion => }/installed-deep.js (97%) rename test/lib/utils/{completion => }/installed-shallow.js (93%) diff --git a/lib/base-command.js b/lib/base-command.js index cfaa0bb394460..fb33005cc901b 100644 --- a/lib/base-command.js +++ b/lib/base-command.js @@ -167,7 +167,7 @@ class BaseCommand { const relativeFrom = prefixInsideCwd ? this.npm.localPrefix : process.cwd() const filters = this.npm.config.get('workspace') - const getWorkspaces = require('./workspaces/get-workspaces.js') + const getWorkspaces = require('./utils/get-workspaces.js') const ws = await getWorkspaces(filters, { path: this.npm.localPrefix, includeWorkspaceRoot, diff --git a/lib/commands/edit.js b/lib/commands/edit.js index e6ab26278740c..eca4fad6fe24c 100644 --- a/lib/commands/edit.js +++ b/lib/commands/edit.js @@ -4,7 +4,7 @@ const { resolve } = require('path') const { lstat } = require('fs/promises') const cp = require('child_process') -const completion = require('../utils/completion/installed-shallow.js') +const completion = require('../utils/installed-shallow.js') const BaseCommand = require('../base-command.js') const splitPackageNames = (path) => { diff --git a/lib/commands/explain.js b/lib/commands/explain.js index 98ef356bfc1b3..1e09ea0ee61cb 100644 --- a/lib/commands/explain.js +++ b/lib/commands/explain.js @@ -20,7 +20,7 @@ class Explain extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } diff --git a/lib/commands/explore.js b/lib/commands/explore.js index ef4743e62197d..ae29262071555 100644 --- a/lib/commands/explore.js +++ b/lib/commands/explore.js @@ -5,7 +5,7 @@ const pkgJson = require('@npmcli/package-json') const runScript = require('@npmcli/run-script') const { join, relative } = require('path') const { log, output } = require('proc-log') -const completion = require('../utils/completion/installed-shallow.js') +const completion = require('../utils/installed-shallow.js') const BaseCommand = require('../base-command.js') class Explore extends BaseCommand { diff --git a/lib/commands/fund.js b/lib/commands/fund.js index 6fa2c467a35eb..5aaab2df746a5 100644 --- a/lib/commands/fund.js +++ b/lib/commands/fund.js @@ -38,7 +38,7 @@ class Fund extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } diff --git a/lib/commands/init.js b/lib/commands/init.js index 28067e4def1d0..cee56e7b91ba5 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -7,7 +7,7 @@ const libexec = require('libnpmexec') const mapWorkspaces = require('@npmcli/map-workspaces') const PackageJson = require('@npmcli/package-json') const { log, output } = require('proc-log') -const updateWorkspaces = require('../workspaces/update-workspaces.js') +const updateWorkspaces = require('../utils/update-workspaces.js') const BaseCommand = require('../base-command.js') const posixPath = p => p.split('\\').join('/') diff --git a/lib/commands/ls.js b/lib/commands/ls.js index a81e69fe40e89..cf086924092fe 100644 --- a/lib/commands/ls.js +++ b/lib/commands/ls.js @@ -42,7 +42,7 @@ class LS extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } diff --git a/lib/commands/rebuild.js b/lib/commands/rebuild.js index 8858edd1da349..d9e22de7cf048 100644 --- a/lib/commands/rebuild.js +++ b/lib/commands/rebuild.js @@ -20,7 +20,7 @@ class Rebuild extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } diff --git a/lib/commands/uninstall.js b/lib/commands/uninstall.js index 07775efb9cf2f..51df355d5a899 100644 --- a/lib/commands/uninstall.js +++ b/lib/commands/uninstall.js @@ -2,7 +2,7 @@ const { resolve } = require('path') const pkgJson = require('@npmcli/package-json') const reifyFinish = require('../utils/reify-finish.js') -const completion = require('../utils/completion/installed-shallow.js') +const completion = require('../utils/installed-shallow.js') const ArboristWorkspaceCmd = require('../arborist-cmd.js') class Uninstall extends ArboristWorkspaceCmd { diff --git a/lib/commands/update.js b/lib/commands/update.js index 12b6ac153a588..63711c05e5b97 100644 --- a/lib/commands/update.js +++ b/lib/commands/update.js @@ -33,7 +33,7 @@ class Update extends ArboristWorkspaceCmd { // TODO /* istanbul ignore next */ static async completion (opts, npm) { - const completion = require('../utils/completion/installed-deep.js') + const completion = require('../utils/installed-deep.js') return completion(npm, opts) } diff --git a/lib/commands/version.js b/lib/commands/version.js index 376cd88480d65..0e1916d7af7fb 100644 --- a/lib/commands/version.js +++ b/lib/commands/version.js @@ -81,7 +81,7 @@ class Version extends BaseCommand { } async changeWorkspaces (args) { - const updateWorkspaces = require('../workspaces/update-workspaces.js') + const updateWorkspaces = require('../utils/update-workspaces.js') const libnpmversion = require('libnpmversion') const prefix = this.npm.config.get('tag-version-prefix') const { diff --git a/lib/workspaces/get-workspaces.js b/lib/utils/get-workspaces.js similarity index 100% rename from lib/workspaces/get-workspaces.js rename to lib/utils/get-workspaces.js diff --git a/lib/utils/completion/installed-deep.js b/lib/utils/installed-deep.js similarity index 100% rename from lib/utils/completion/installed-deep.js rename to lib/utils/installed-deep.js diff --git a/lib/utils/completion/installed-shallow.js b/lib/utils/installed-shallow.js similarity index 100% rename from lib/utils/completion/installed-shallow.js rename to lib/utils/installed-shallow.js diff --git a/lib/workspaces/update-workspaces.js b/lib/utils/update-workspaces.js similarity index 100% rename from lib/workspaces/update-workspaces.js rename to lib/utils/update-workspaces.js diff --git a/test/lib/arborist-cmd.js b/test/lib/arborist-cmd.js index 79ff8c6c24601..3c3f44f75d89f 100644 --- a/test/lib/arborist-cmd.js +++ b/test/lib/arborist-cmd.js @@ -127,7 +127,7 @@ t.test('arborist-cmd', async t => { t.test('handle getWorkspaces raising an error', async t => { const { cmd } = await mockArboristCmd(t, null, 'a', { mocks: { - '{LIB}/workspaces/get-workspaces.js': async () => { + '{LIB}/utils/get-workspaces.js': async () => { throw new Error('oopsie') }, }, diff --git a/test/lib/workspaces/get-workspaces.js b/test/lib/utils/get-workspaces.js similarity index 98% rename from test/lib/workspaces/get-workspaces.js rename to test/lib/utils/get-workspaces.js index 4e48b1c4b7707..931f90d13046f 100644 --- a/test/lib/workspaces/get-workspaces.js +++ b/test/lib/utils/get-workspaces.js @@ -1,6 +1,6 @@ const { resolve } = require('path') const t = require('tap') -const getWorkspaces = require('../../../lib/workspaces/get-workspaces.js') +const getWorkspaces = require('../../../lib/utils/get-workspaces.js') const normalizePath = p => p .replace(/\\+/g, '/') diff --git a/test/lib/utils/completion/installed-deep.js b/test/lib/utils/installed-deep.js similarity index 97% rename from test/lib/utils/completion/installed-deep.js rename to test/lib/utils/installed-deep.js index 0af26861ff83a..4d212746cba89 100644 --- a/test/lib/utils/completion/installed-deep.js +++ b/test/lib/utils/installed-deep.js @@ -1,5 +1,5 @@ const t = require('tap') -const installedDeep = require('../../../../lib/utils/completion/installed-deep.js') +const installedDeep = require('../../../lib/utils/installed-deep.js') const mockNpm = require('../../../fixtures/mock-npm') const fixture = { diff --git a/test/lib/utils/completion/installed-shallow.js b/test/lib/utils/installed-shallow.js similarity index 93% rename from test/lib/utils/completion/installed-shallow.js rename to test/lib/utils/installed-shallow.js index 3666803979cb3..43ccda4daea69 100644 --- a/test/lib/utils/completion/installed-shallow.js +++ b/test/lib/utils/installed-shallow.js @@ -1,5 +1,5 @@ const t = require('tap') -const installed = require('../../../../lib/utils/completion/installed-shallow.js') +const installed = require('../../../lib/utils/installed-shallow.js') const mockNpm = require('../../../fixtures/mock-npm') const mockShallow = async (t, config) => { From 469f7885ca47f79bbd3c7171dc56a471a3e422a2 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 14:28:58 -0700 Subject: [PATCH 15/42] fix(cleanup): newlines and whitespace --- lib/base-command.js | 1 + lib/commands/access.js | 1 - lib/commands/adduser.js | 2 +- lib/commands/audit.js | 388 +------------------------------ lib/commands/ci.js | 1 - lib/commands/completion.js | 11 +- lib/commands/config.js | 2 +- lib/commands/dedupe.js | 3 +- lib/commands/dist-tag.js | 1 + lib/commands/docs.js | 2 + lib/commands/doctor.js | 3 +- lib/commands/edit.js | 42 ++-- lib/commands/explain.js | 1 + lib/commands/explore.js | 6 +- lib/commands/find-dupes.js | 3 +- lib/commands/fund.js | 1 + lib/commands/get.js | 1 + lib/commands/help-search.js | 1 + lib/commands/help.js | 3 +- lib/commands/hook.js | 3 +- lib/commands/install-ci-test.js | 6 +- lib/commands/install-test.js | 6 +- lib/commands/install.js | 3 +- lib/commands/link.js | 1 + lib/commands/login.js | 2 +- lib/commands/logout.js | 1 + lib/commands/ls.js | 9 +- lib/commands/org.js | 1 + lib/commands/outdated.js | 2 +- lib/commands/pack.js | 1 + lib/commands/ping.js | 1 + lib/commands/prefix.js | 1 + lib/commands/profile.js | 6 +- lib/commands/prune.js | 5 +- lib/commands/publish.js | 5 +- lib/commands/query.js | 2 - lib/commands/rebuild.js | 3 +- lib/commands/repo.js | 3 +- lib/commands/root.js | 2 + lib/commands/run-script.js | 2 +- lib/commands/sbom.js | 2 - lib/commands/search.js | 2 +- lib/commands/set.js | 1 + lib/commands/shrinkwrap.js | 1 + lib/commands/star.js | 3 +- lib/commands/stars.js | 3 +- lib/commands/team.js | 2 +- lib/commands/token.js | 4 +- lib/commands/uninstall.js | 4 +- lib/commands/unpublish.js | 3 +- lib/commands/unstar.js | 1 + lib/commands/update.js | 5 +- lib/commands/version.js | 1 - lib/commands/view.js | 5 +- lib/commands/whoami.js | 3 +- lib/lifecycle-cmd.js | 1 + lib/npm.js | 1 + lib/package-url-cmd.js | 1 + lib/utils/did-you-mean.js | 1 + lib/utils/verify-signatures.js | 389 ++++++++++++++++++++++++++++++++ 60 files changed, 499 insertions(+), 472 deletions(-) create mode 100644 lib/utils/verify-signatures.js diff --git a/lib/base-command.js b/lib/base-command.js index fb33005cc901b..9c30ef8a4b44e 100644 --- a/lib/base-command.js +++ b/lib/base-command.js @@ -179,4 +179,5 @@ class BaseCommand { this.workspacePaths = [...ws.values()] } } + module.exports = BaseCommand diff --git a/lib/commands/access.js b/lib/commands/access.js index 20565e274398e..1d0161cadc91e 100644 --- a/lib/commands/access.js +++ b/lib/commands/access.js @@ -3,7 +3,6 @@ const npa = require('npm-package-arg') const { output } = require('proc-log') const pkgJson = require('@npmcli/package-json') const localeCompare = require('@isaacs/string-locale-compare')('en') - const otplease = require('../utils/otplease.js') const getIdentity = require('../utils/get-identity.js') const BaseCommand = require('../base-command.js') diff --git a/lib/commands/adduser.js b/lib/commands/adduser.js index 842819f2bf44b..d896272bf7ed5 100644 --- a/lib/commands/adduser.js +++ b/lib/commands/adduser.js @@ -1,7 +1,6 @@ const { log, output } = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') - const BaseCommand = require('../base-command.js') class AddUser extends BaseCommand { @@ -47,4 +46,5 @@ class AddUser extends BaseCommand { output.standard(message) } } + module.exports = AddUser diff --git a/lib/commands/audit.js b/lib/commands/audit.js index 7eada9f617e70..aed1be7a82906 100644 --- a/lib/commands/audit.js +++ b/lib/commands/audit.js @@ -1,395 +1,9 @@ const npmAuditReport = require('npm-audit-report') -const fetch = require('npm-registry-fetch') -const localeCompare = require('@isaacs/string-locale-compare')('en') -const npa = require('npm-package-arg') -const pacote = require('pacote') -const pMap = require('p-map') -const tufClient = require('@sigstore/tuf') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') const auditError = require('../utils/audit-error.js') const { log, output } = require('proc-log') const reifyFinish = require('../utils/reify-finish.js') - -const sortAlphabetically = (a, b) => localeCompare(a.name, b.name) - -class VerifySignatures { - constructor (tree, filterSet, npm, opts) { - this.tree = tree - this.filterSet = filterSet - this.npm = npm - this.opts = opts - this.keys = new Map() - this.invalid = [] - this.missing = [] - this.checkedPackages = new Set() - this.auditedWithKeysCount = 0 - this.verifiedSignatureCount = 0 - this.verifiedAttestationCount = 0 - this.exitCode = 0 - } - - async run () { - const start = process.hrtime.bigint() - - // Find all deps in tree - const { edges, registries } = this.getEdgesOut(this.tree.inventory.values(), this.filterSet) - if (edges.size === 0) { - throw new Error('found no installed dependencies to audit') - } - - const tuf = await tufClient.initTUF({ - cachePath: this.opts.tufCache, - retry: this.opts.retry, - timeout: this.opts.timeout, - }) - await Promise.all([...registries].map(registry => this.setKeys({ registry, tuf }))) - - log.verbose('verifying registry signatures') - await pMap(edges, (e) => this.getVerifiedInfo(e), { concurrency: 20, stopOnError: true }) - - // Didn't find any dependencies that could be verified, e.g. only local - // deps, missing version, not on a registry etc. - if (!this.auditedWithKeysCount) { - throw new Error('found no dependencies to audit that were installed from ' + - 'a supported registry') - } - - const invalid = this.invalid.sort(sortAlphabetically) - const missing = this.missing.sort(sortAlphabetically) - - const hasNoInvalidOrMissing = invalid.length === 0 && missing.length === 0 - - if (!hasNoInvalidOrMissing) { - process.exitCode = 1 - } - - if (this.npm.config.get('json')) { - output.standard(JSON.stringify({ - invalid, - missing, - }, null, 2)) - return - } - const end = process.hrtime.bigint() - const elapsed = end - start - - const auditedPlural = this.auditedWithKeysCount > 1 ? 's' : '' - const timing = `audited ${this.auditedWithKeysCount} package${auditedPlural} in ` + - `${Math.floor(Number(elapsed) / 1e9)}s` - output.standard(timing) - output.standard('') - - const verifiedBold = this.npm.chalk.bold('verified') - if (this.verifiedSignatureCount) { - if (this.verifiedSignatureCount === 1) { - /* eslint-disable-next-line max-len */ - output.standard(`${this.verifiedSignatureCount} package has a ${verifiedBold} registry signature`) - } else { - /* eslint-disable-next-line max-len */ - output.standard(`${this.verifiedSignatureCount} packages have ${verifiedBold} registry signatures`) - } - output.standard('') - } - - if (this.verifiedAttestationCount) { - if (this.verifiedAttestationCount === 1) { - /* eslint-disable-next-line max-len */ - output.standard(`${this.verifiedAttestationCount} package has a ${verifiedBold} attestation`) - } else { - /* eslint-disable-next-line max-len */ - output.standard(`${this.verifiedAttestationCount} packages have ${verifiedBold} attestations`) - } - output.standard('') - } - - if (missing.length) { - const missingClr = this.npm.chalk.redBright('missing') - if (missing.length === 1) { - /* eslint-disable-next-line max-len */ - output.standard(`1 package has a ${missingClr} registry signature but the registry is providing signing keys:`) - } else { - /* eslint-disable-next-line max-len */ - output.standard(`${missing.length} packages have ${missingClr} registry signatures but the registry is providing signing keys:`) - } - output.standard('') - missing.map(m => - output.standard(`${this.npm.chalk.red(`${m.name}@${m.version}`)} (${m.registry})`) - ) - } - - if (invalid.length) { - if (missing.length) { - output.standard('') - } - const invalidClr = this.npm.chalk.redBright('invalid') - // We can have either invalid signatures or invalid provenance - const invalidSignatures = this.invalid.filter(i => i.code === 'EINTEGRITYSIGNATURE') - if (invalidSignatures.length) { - if (invalidSignatures.length === 1) { - output.standard(`1 package has an ${invalidClr} registry signature:`) - } else { - /* eslint-disable-next-line max-len */ - output.standard(`${invalidSignatures.length} packages have ${invalidClr} registry signatures:`) - } - output.standard('') - invalidSignatures.map(i => - output.standard(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) - ) - output.standard('') - } - - const invalidAttestations = this.invalid.filter(i => i.code === 'EATTESTATIONVERIFY') - if (invalidAttestations.length) { - if (invalidAttestations.length === 1) { - output.standard(`1 package has an ${invalidClr} attestation:`) - } else { - /* eslint-disable-next-line max-len */ - output.standard(`${invalidAttestations.length} packages have ${invalidClr} attestations:`) - } - output.standard('') - invalidAttestations.map(i => - output.standard(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) - ) - output.standard('') - } - - if (invalid.length === 1) { - /* eslint-disable-next-line max-len */ - output.standard(`Someone might have tampered with this package since it was published on the registry!`) - } else { - /* eslint-disable-next-line max-len */ - output.standard(`Someone might have tampered with these packages since they were published on the registry!`) - } - output.standard('') - } - } - - getEdgesOut (nodes, filterSet) { - const edges = new Set() - const registries = new Set() - for (const node of nodes) { - for (const edge of node.edgesOut.values()) { - const filteredOut = - edge.from - && filterSet - && filterSet.size > 0 - && !filterSet.has(edge.from.target) - - if (!filteredOut) { - const spec = this.getEdgeSpec(edge) - if (spec) { - // Prefetch and cache public keys from used registries - registries.add(this.getSpecRegistry(spec)) - } - edges.add(edge) - } - } - } - return { edges, registries } - } - - async setKeys ({ registry, tuf }) { - const { host, pathname } = new URL(registry) - // Strip any trailing slashes from pathname - const regKey = `${host}${pathname.replace(/\/$/, '')}/keys.json` - let keys = await tuf.getTarget(regKey) - .then((target) => JSON.parse(target)) - .then(({ keys: ks }) => ks.map((key) => ({ - ...key, - keyid: key.keyId, - pemkey: `-----BEGIN PUBLIC KEY-----\n${key.publicKey.rawBytes}\n-----END PUBLIC KEY-----`, - expires: key.publicKey.validFor.end || null, - }))).catch(err => { - if (err.code === 'TUF_FIND_TARGET_ERROR') { - return null - } else { - throw err - } - }) - - // If keys not found in Sigstore TUF repo, fallback to registry keys API - if (!keys) { - keys = await fetch.json('/-/npm/v1/keys', { - ...this.npm.flatOptions, - registry, - }).then(({ keys: ks }) => ks.map((key) => ({ - ...key, - pemkey: `-----BEGIN PUBLIC KEY-----\n${key.key}\n-----END PUBLIC KEY-----`, - }))).catch(err => { - if (err.code === 'E404' || err.code === 'E400') { - return null - } else { - throw err - } - }) - } - - if (keys) { - this.keys.set(registry, keys) - } - } - - getEdgeType (edge) { - return edge.optional ? 'optionalDependencies' - : edge.peer ? 'peerDependencies' - : edge.dev ? 'devDependencies' - : 'dependencies' - } - - getEdgeSpec (edge) { - let name = edge.name - try { - name = npa(edge.spec).subSpec.name - } catch { - // leave it as edge.name - } - try { - return npa(`${name}@${edge.spec}`) - } catch { - // Skip packages with invalid spec - } - } - - buildRegistryConfig (registry) { - const keys = this.keys.get(registry) || [] - const parsedRegistry = new URL(registry) - const regKey = `//${parsedRegistry.host}${parsedRegistry.pathname}` - return { - [`${regKey}:_keys`]: keys, - } - } - - getSpecRegistry (spec) { - return fetch.pickRegistry(spec, this.npm.flatOptions) - } - - getValidPackageInfo (edge) { - const type = this.getEdgeType(edge) - // Skip potentially optional packages that are not on disk, as these could - // be omitted during install - if (edge.error === 'MISSING' && type !== 'dependencies') { - return - } - - const spec = this.getEdgeSpec(edge) - // Skip invalid version requirements - if (!spec) { - return - } - const node = edge.to || edge - const { version } = node.package || {} - - if (node.isWorkspace || // Skip local workspaces packages - !version || // Skip packages that don't have a installed version, e.g. optonal dependencies - !spec.registry) { // Skip if not from registry, e.g. git package - return - } - - for (const omitType of this.npm.config.get('omit')) { - if (node[omitType]) { - return - } - } - - return { - name: spec.name, - version, - type, - location: node.location, - registry: this.getSpecRegistry(spec), - } - } - - async verifySignatures (name, version, registry) { - const { - _integrity: integrity, - _signatures, - _attestations, - _resolved: resolved, - } = await pacote.manifest(`${name}@${version}`, { - verifySignatures: true, - verifyAttestations: true, - ...this.buildRegistryConfig(registry), - ...this.npm.flatOptions, - }) - const signatures = _signatures || [] - const result = { - integrity, - signatures, - attestations: _attestations, - resolved, - } - return result - } - - async getVerifiedInfo (edge) { - const info = this.getValidPackageInfo(edge) - if (!info) { - return - } - const { name, version, location, registry, type } = info - if (this.checkedPackages.has(location)) { - // we already did or are doing this one - return - } - this.checkedPackages.add(location) - - // We only "audit" or verify the signature, or the presence of it, on - // packages whose registry returns signing keys - const keys = this.keys.get(registry) || [] - if (keys.length) { - this.auditedWithKeysCount += 1 - } - - try { - const { integrity, signatures, attestations, resolved } = await this.verifySignatures( - name, version, registry - ) - - // Currently we only care about missing signatures on registries that provide a public key - // We could make this configurable in the future with a strict/paranoid mode - if (signatures.length) { - this.verifiedSignatureCount += 1 - } else if (keys.length) { - this.missing.push({ - integrity, - location, - name, - registry, - resolved, - version, - }) - } - - // Track verified attestations separately to registry signatures, as all - // packages on registries with signing keys are expected to have registry - // signatures, but not all packages have provenance and publish attestations. - if (attestations) { - this.verifiedAttestationCount += 1 - } - } catch (e) { - if (e.code === 'EINTEGRITYSIGNATURE' || e.code === 'EATTESTATIONVERIFY') { - this.invalid.push({ - code: e.code, - message: e.message, - integrity: e.integrity, - keyid: e.keyid, - location, - name, - registry, - resolved: e.resolved, - signature: e.signature, - predicateType: e.predicateType, - type, - version, - }) - } else { - throw e - } - } - } -} +const VerifySignatures = require('../utils/verify-signatures.js') class Audit extends ArboristWorkspaceCmd { static description = 'Run a security audit' diff --git a/lib/commands/ci.js b/lib/commands/ci.js index ff559b6d801d7..a8b4a845126f5 100644 --- a/lib/commands/ci.js +++ b/lib/commands/ci.js @@ -3,7 +3,6 @@ const runScript = require('@npmcli/run-script') const fs = require('fs/promises') const { log, time } = require('proc-log') const validateLockfile = require('../utils/validate-lockfile.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') class CI extends ArboristWorkspaceCmd { diff --git a/lib/commands/completion.js b/lib/commands/completion.js index 677d7fa2ec3fe..20ff3ea76e98b 100644 --- a/lib/commands/completion.js +++ b/lib/commands/completion.js @@ -27,23 +27,22 @@ // Matches are wrapped with ' to escape them, if necessary, and then printed // one per line for the shell completion method to consume in IFS=$'\n' mode // as an array. -// const fs = require('fs/promises') const nopt = require('nopt') const { resolve } = require('path') const { output } = require('proc-log') - const Npm = require('../npm.js') const { definitions, shorthands } = require('@npmcli/config/lib/definitions') const { commands, aliases, deref } = require('../utils/cmd-list.js') -const configNames = Object.keys(definitions) -const shorthandNames = Object.keys(shorthands) -const allConfs = configNames.concat(shorthandNames) const { isWindowsShell } = require('../utils/is-windows.js') +const BaseCommand = require('../base-command.js') + const fileExists = (file) => fs.stat(file).then(s => s.isFile()).catch(() => false) -const BaseCommand = require('../base-command.js') +const configNames = Object.keys(definitions) +const shorthandNames = Object.keys(shorthands) +const allConfs = configNames.concat(shorthandNames) class Completion extends BaseCommand { static description = 'Tab Completion for npm' diff --git a/lib/commands/config.js b/lib/commands/config.js index 21faa8838c593..56315208e232f 100644 --- a/lib/commands/config.js +++ b/lib/commands/config.js @@ -6,6 +6,7 @@ const localeCompare = require('@isaacs/string-locale-compare')('en') const pkgJson = require('@npmcli/package-json') const { defaults, definitions } = require('@npmcli/config/lib/definitions') const { log, output } = require('proc-log') +const BaseCommand = require('../base-command.js') // These are the configs that we can nerf-dart. Not all of them currently even // *have* config definitions so we have to explicitly validate them here @@ -46,7 +47,6 @@ const publicVar = k => { return true } -const BaseCommand = require('../base-command.js') class Config extends BaseCommand { static description = 'Manage the npm configuration files' static name = 'config' diff --git a/lib/commands/dedupe.js b/lib/commands/dedupe.js index 0d0e26621b227..f9785fd66bb49 100644 --- a/lib/commands/dedupe.js +++ b/lib/commands/dedupe.js @@ -1,8 +1,7 @@ -// dedupe duplicated packages, or find them in the tree const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') +// dedupe duplicated packages, or find them in the tree class Dedupe extends ArboristWorkspaceCmd { static description = 'Reduce duplication in the package tree' static name = 'dedupe' diff --git a/lib/commands/dist-tag.js b/lib/commands/dist-tag.js index 741890fc9cec7..7eeeae571bc1c 100644 --- a/lib/commands/dist-tag.js +++ b/lib/commands/dist-tag.js @@ -205,4 +205,5 @@ class DistTag extends BaseCommand { return data } } + module.exports = DistTag diff --git a/lib/commands/docs.js b/lib/commands/docs.js index 5d20215b56a07..2259b49f79617 100644 --- a/lib/commands/docs.js +++ b/lib/commands/docs.js @@ -1,4 +1,5 @@ const PackageUrlCmd = require('../package-url-cmd.js') + class Docs extends PackageUrlCmd { static description = 'Open documentation for a package in a web browser' static name = 'docs' @@ -16,4 +17,5 @@ class Docs extends PackageUrlCmd { return `https://www.npmjs.com/package/${mani.name}` } } + module.exports = Docs diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index 2c8581a4aba4d..a9f24bd62e0f0 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -8,6 +8,7 @@ const semver = require('semver') const { log, output } = require('proc-log') const ping = require('../utils/ping.js') const { defaults } = require('@npmcli/config/lib/definitions') +const BaseCommand = require('../base-command.js') const maskLabel = mask => { const label = [] @@ -93,7 +94,7 @@ const subcommands = [ // - verify all local packages have bins linked // What is the fix for these? ] -const BaseCommand = require('../base-command.js') + class Doctor extends BaseCommand { static description = 'Check the health of your npm environment' static name = 'doctor' diff --git a/lib/commands/edit.js b/lib/commands/edit.js index eca4fad6fe24c..12c9f759589e7 100644 --- a/lib/commands/edit.js +++ b/lib/commands/edit.js @@ -1,34 +1,31 @@ -// npm edit -// open the package folder in the $EDITOR - const { resolve } = require('path') const { lstat } = require('fs/promises') const cp = require('child_process') const completion = require('../utils/installed-shallow.js') const BaseCommand = require('../base-command.js') -const splitPackageNames = (path) => { - return path.split('/') - // combine scoped parts - .reduce((parts, part) => { - if (parts.length === 0) { - return [part] - } +const splitPackageNames = (path) => path.split('/') +// combine scoped parts + .reduce((parts, part) => { + if (parts.length === 0) { + return [part] + } - const lastPart = parts[parts.length - 1] - // check if previous part is the first part of a scoped package - if (lastPart[0] === '@' && !lastPart.includes('/')) { - parts[parts.length - 1] += '/' + part - } else { - parts.push(part) - } + const lastPart = parts[parts.length - 1] + // check if previous part is the first part of a scoped package + if (lastPart[0] === '@' && !lastPart.includes('/')) { + parts[parts.length - 1] += '/' + part + } else { + parts.push(part) + } - return parts - }, []) - .join('/node_modules/') - .replace(/(\/node_modules)+/, '/node_modules') -} + return parts + }, []) + .join('/node_modules/') + .replace(/(\/node_modules)+/, '/node_modules') +// npm edit +// open the package folder in the $EDITOR class Edit extends BaseCommand { static description = 'Edit an installed package' static name = 'edit' @@ -63,4 +60,5 @@ class Edit extends BaseCommand { }) } } + module.exports = Edit diff --git a/lib/commands/explain.js b/lib/commands/explain.js index 1e09ea0ee61cb..2e7d07df729a8 100644 --- a/lib/commands/explain.js +++ b/lib/commands/explain.js @@ -126,4 +126,5 @@ class Explain extends ArboristWorkspaceCmd { }) } } + module.exports = Explain diff --git a/lib/commands/explore.js b/lib/commands/explore.js index ae29262071555..a4acc821eabf9 100644 --- a/lib/commands/explore.js +++ b/lib/commands/explore.js @@ -1,6 +1,3 @@ -// npm explore [@] -// open a subshell to the package folder. - const pkgJson = require('@npmcli/package-json') const runScript = require('@npmcli/run-script') const { join, relative } = require('path') @@ -8,6 +5,8 @@ const { log, output } = require('proc-log') const completion = require('../utils/installed-shallow.js') const BaseCommand = require('../base-command.js') +// npm explore [@] +// open a subshell to the package folder. class Explore extends BaseCommand { static description = 'Browse an installed package' static name = 'explore' @@ -71,4 +70,5 @@ class Explore extends BaseCommand { }) } } + module.exports = Explore diff --git a/lib/commands/find-dupes.js b/lib/commands/find-dupes.js index 2e06e8b6bd93f..0945089c74b7c 100644 --- a/lib/commands/find-dupes.js +++ b/lib/commands/find-dupes.js @@ -1,6 +1,6 @@ -// dedupe duplicated packages, or find them in the tree const ArboristWorkspaceCmd = require('../arborist-cmd.js') +// dedupe duplicated packages, or find them in the tree class FindDupes extends ArboristWorkspaceCmd { static description = 'Find duplication in the package tree' static name = 'find-dupes' @@ -24,4 +24,5 @@ class FindDupes extends ArboristWorkspaceCmd { return this.npm.exec('dedupe', []) } } + module.exports = FindDupes diff --git a/lib/commands/fund.js b/lib/commands/fund.js index 5aaab2df746a5..8bcd184e70968 100644 --- a/lib/commands/fund.js +++ b/lib/commands/fund.js @@ -222,4 +222,5 @@ class Fund extends ArboristWorkspaceCmd { return [url, message] } } + module.exports = Fund diff --git a/lib/commands/get.js b/lib/commands/get.js index 4bf5d2caf8264..43eca7389ec90 100644 --- a/lib/commands/get.js +++ b/lib/commands/get.js @@ -19,4 +19,5 @@ class Get extends BaseCommand { return this.npm.exec('config', ['get'].concat(args)) } } + module.exports = Get diff --git a/lib/commands/help-search.js b/lib/commands/help-search.js index 8821d932525dc..1bbff2df6cc16 100644 --- a/lib/commands/help-search.js +++ b/lib/commands/help-search.js @@ -191,4 +191,5 @@ class HelpSearch extends BaseCommand { return finalOut.trim() } } + module.exports = HelpSearch diff --git a/lib/commands/help.js b/lib/commands/help.js index 1f51713a8d051..fd84d3f8546ef 100644 --- a/lib/commands/help.js +++ b/lib/commands/help.js @@ -5,9 +5,9 @@ const { glob } = require('glob') const { output } = require('proc-log') const localeCompare = require('@isaacs/string-locale-compare')('en') const { deref } = require('../utils/cmd-list.js') +const BaseCommand = require('../base-command.js') const globify = pattern => pattern.split('\\').join('/') -const BaseCommand = require('../base-command.js') // Strips out the number from foo.7 or foo.7. or foo.7.tgz // We don't currently compress our man pages but if we ever did this would @@ -111,4 +111,5 @@ class Help extends BaseCommand { return 'file:///' + path.resolve(this.npm.npmRoot, `docs/output/${sect}/${f}.html`) } } + module.exports = Help diff --git a/lib/commands/hook.js b/lib/commands/hook.js index 7ec95e079d660..557d04e7a035a 100644 --- a/lib/commands/hook.js +++ b/lib/commands/hook.js @@ -2,8 +2,8 @@ const hookApi = require('libnpmhook') const otplease = require('../utils/otplease.js') const relativeDate = require('tiny-relative-date') const { output } = require('proc-log') - const BaseCommand = require('../base-command.js') + class Hook extends BaseCommand { static description = 'Manage registry hooks' static name = 'hook' @@ -105,4 +105,5 @@ class Hook extends BaseCommand { return `${hook.type === 'owner' ? '~' : ''}${hook.name}` } } + module.exports = Hook diff --git a/lib/commands/install-ci-test.js b/lib/commands/install-ci-test.js index f7a357ba6e124..4b9dd269f8c74 100644 --- a/lib/commands/install-ci-test.js +++ b/lib/commands/install-ci-test.js @@ -1,8 +1,7 @@ -// npm install-ci-test -// Runs `npm ci` and then runs `npm test` - const CI = require('./ci.js') +// npm install-ci-test +// Runs `npm ci` and then runs `npm test` class InstallCITest extends CI { static description = 'Install a project with a clean slate and run tests' static name = 'install-ci-test' @@ -12,4 +11,5 @@ class InstallCITest extends CI { return this.npm.exec('test', []) } } + module.exports = InstallCITest diff --git a/lib/commands/install-test.js b/lib/commands/install-test.js index 11f22e535403c..e21ca7c929c55 100644 --- a/lib/commands/install-test.js +++ b/lib/commands/install-test.js @@ -1,8 +1,7 @@ -// npm install-test -// Runs `npm install` and then runs `npm test` - const Install = require('./install.js') +// npm install-test +// Runs `npm install` and then runs `npm test` class InstallTest extends Install { static description = 'Install package(s) and run tests' static name = 'install-test' @@ -12,4 +11,5 @@ class InstallTest extends Install { return this.npm.exec('test', []) } } + module.exports = InstallTest diff --git a/lib/commands/install.js b/lib/commands/install.js index 6573b4d65555d..24e5f6819b314 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -5,8 +5,8 @@ const runScript = require('@npmcli/run-script') const pacote = require('pacote') const checks = require('npm-install-checks') const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Install extends ArboristWorkspaceCmd { static description = 'Install a package' static name = 'install' @@ -172,4 +172,5 @@ class Install extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Install diff --git a/lib/commands/link.js b/lib/commands/link.js index 0442e50dc0d83..bde761c4226dc 100644 --- a/lib/commands/link.js +++ b/lib/commands/link.js @@ -185,4 +185,5 @@ class Link extends ArboristWorkspaceCmd { return missing } } + module.exports = Link diff --git a/lib/commands/login.js b/lib/commands/login.js index d38aec51289cc..0801af9726f78 100644 --- a/lib/commands/login.js +++ b/lib/commands/login.js @@ -1,7 +1,6 @@ const { log, output } = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') - const BaseCommand = require('../base-command.js') class Login extends BaseCommand { @@ -47,4 +46,5 @@ class Login extends BaseCommand { output.standard(message) } } + module.exports = Login diff --git a/lib/commands/logout.js b/lib/commands/logout.js index 338081cccd457..63a8154cd3fdf 100644 --- a/lib/commands/logout.js +++ b/lib/commands/logout.js @@ -46,4 +46,5 @@ class Logout extends BaseCommand { await this.npm.config.save(level) } } + module.exports = Logout diff --git a/lib/commands/ls.js b/lib/commands/ls.js index cf086924092fe..51e99f429816a 100644 --- a/lib/commands/ls.js +++ b/lib/commands/ls.js @@ -1,10 +1,12 @@ const { resolve, relative, sep } = require('path') -const relativePrefix = `.${sep}` - const archy = require('archy') const { breadth } = require('treeverse') const npa = require('npm-package-arg') const { output } = require('proc-log') +const ArboristWorkspaceCmd = require('../arborist-cmd.js') +const localeCompare = require('@isaacs/string-locale-compare')('en') + +const relativePrefix = `.${sep}` const _depth = Symbol('depth') const _dedupe = Symbol('dedupe') @@ -17,8 +19,6 @@ const _parent = Symbol('parent') const _problems = Symbol('problems') const _required = Symbol('required') const _type = Symbol('type') -const ArboristWorkspaceCmd = require('../arborist-cmd.js') -const localeCompare = require('@isaacs/string-locale-compare')('en') class LS extends ArboristWorkspaceCmd { static description = 'List installed packages' @@ -219,6 +219,7 @@ class LS extends ArboristWorkspaceCmd { return tree } } + module.exports = LS const isGitNode = (node) => { diff --git a/lib/commands/org.js b/lib/commands/org.js index f1e5b0e09c62c..f06c537d3f3f7 100644 --- a/lib/commands/org.js +++ b/lib/commands/org.js @@ -149,4 +149,5 @@ class Org extends BaseCommand { } } } + module.exports = Org diff --git a/lib/commands/outdated.js b/lib/commands/outdated.js index 1600315cac642..ceef86be950c5 100644 --- a/lib/commands/outdated.js +++ b/lib/commands/outdated.js @@ -6,7 +6,6 @@ const npa = require('npm-package-arg') const pickManifest = require('npm-pick-manifest') const { output } = require('proc-log') const localeCompare = require('@isaacs/string-locale-compare')('en') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') class Outdated extends ArboristWorkspaceCmd { @@ -369,4 +368,5 @@ class Outdated extends ArboristWorkspaceCmd { return JSON.stringify(out, null, 2) } } + module.exports = Outdated diff --git a/lib/commands/pack.js b/lib/commands/pack.js index 463329235d417..e679377fa7970 100644 --- a/lib/commands/pack.js +++ b/lib/commands/pack.js @@ -83,4 +83,5 @@ class Pack extends BaseCommand { return this.exec([...this.workspacePaths, ...args.filter(a => a !== '.')]) } } + module.exports = Pack diff --git a/lib/commands/ping.js b/lib/commands/ping.js index 3ae4ed80a22cb..2d8f6f91a9111 100644 --- a/lib/commands/ping.js +++ b/lib/commands/ping.js @@ -26,4 +26,5 @@ class Ping extends BaseCommand { } } } + module.exports = Ping diff --git a/lib/commands/prefix.js b/lib/commands/prefix.js index 6c3d6f886f12c..edd5595d09b41 100644 --- a/lib/commands/prefix.js +++ b/lib/commands/prefix.js @@ -11,4 +11,5 @@ class Prefix extends BaseCommand { return output.standard(this.npm.prefix) } } + module.exports = Prefix diff --git a/lib/commands/profile.js b/lib/commands/profile.js index 8bb19e69fd484..a0676e47889af 100644 --- a/lib/commands/profile.js +++ b/lib/commands/profile.js @@ -1,11 +1,11 @@ -const inspect = require('util').inspect +const { inspect } = require('util') const { URL } = require('url') const { log, output } = require('proc-log') const npmProfile = require('npm-profile') const qrcodeTerminal = require('qrcode-terminal') - const otplease = require('../utils/otplease.js') const readUserInfo = require('../utils/read-user-info.js') +const BaseCommand = require('../base-command.js') const qrcode = url => new Promise((resolve) => qrcodeTerminal.generate(url, resolve)) @@ -33,7 +33,6 @@ const writableProfileKeys = [ 'github', ] -const BaseCommand = require('../base-command.js') class Profile extends BaseCommand { static description = 'Change settings on your registry profile' static name = 'profile' @@ -387,4 +386,5 @@ class Profile extends BaseCommand { } } } + module.exports = Profile diff --git a/lib/commands/prune.js b/lib/commands/prune.js index 189fc29cb8bc3..1bcf8a9576316 100644 --- a/lib/commands/prune.js +++ b/lib/commands/prune.js @@ -1,7 +1,7 @@ -// prune extraneous packages const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + +// prune extraneous packages class Prune extends ArboristWorkspaceCmd { static description = 'Remove extraneous packages' static name = 'prune' @@ -30,4 +30,5 @@ class Prune extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Prune diff --git a/lib/commands/publish.js b/lib/commands/publish.js index db4cb7f5dc61e..f174d338b6392 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -7,18 +7,16 @@ const pacote = require('pacote') const npa = require('npm-package-arg') const npmFetch = require('npm-registry-fetch') const { redactLog: replaceInfo } = require('@npmcli/redact') - const otplease = require('../utils/otplease.js') const { getContents, logTar } = require('../utils/tar.js') - // for historical reasons, publishConfig in package.json can contain ANY config // keys that npm supports in .npmrc files and elsewhere. We *may* want to // revisit this at some point, and have a minimal set that's a SemVer-major // change that ought to get a RFC written on it. const { flatten } = require('@npmcli/config/lib/definitions') const pkgJson = require('@npmcli/package-json') - const BaseCommand = require('../base-command.js') + class Publish extends BaseCommand { static description = 'Publish a package' static name = 'publish' @@ -226,4 +224,5 @@ class Publish extends BaseCommand { return manifest } } + module.exports = Publish diff --git a/lib/commands/query.js b/lib/commands/query.js index a25180d6c38d8..1e9dee4ef1fda 100644 --- a/lib/commands/query.js +++ b/lib/commands/query.js @@ -1,5 +1,3 @@ -'use strict' - const { resolve } = require('node:path') const BaseCommand = require('../base-command.js') const { log, output } = require('proc-log') diff --git a/lib/commands/rebuild.js b/lib/commands/rebuild.js index d9e22de7cf048..3894f0aa290cc 100644 --- a/lib/commands/rebuild.js +++ b/lib/commands/rebuild.js @@ -2,8 +2,8 @@ const { resolve } = require('path') const { output } = require('proc-log') const npa = require('npm-package-arg') const semver = require('semver') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Rebuild extends ArboristWorkspaceCmd { static description = 'Rebuild a package' static name = 'rebuild' @@ -80,4 +80,5 @@ class Rebuild extends ArboristWorkspaceCmd { }) } } + module.exports = Rebuild diff --git a/lib/commands/repo.js b/lib/commands/repo.js index b89b74c0bf1ba..8e2fef24771d9 100644 --- a/lib/commands/repo.js +++ b/lib/commands/repo.js @@ -1,6 +1,6 @@ const { URL } = require('url') - const PackageUrlCmd = require('../package-url-cmd.js') + class Repo extends PackageUrlCmd { static description = 'Open package repository page in the browser' static name = 'repo' @@ -30,6 +30,7 @@ class Repo extends PackageUrlCmd { return url } } + module.exports = Repo const unknownHostedUrl = url => { diff --git a/lib/commands/root.js b/lib/commands/root.js index f1f9579d103fd..f7c330a004169 100644 --- a/lib/commands/root.js +++ b/lib/commands/root.js @@ -1,5 +1,6 @@ const { output } = require('proc-log') const BaseCommand = require('../base-command.js') + class Root extends BaseCommand { static description = 'Display npm root' static name = 'root' @@ -9,4 +10,5 @@ class Root extends BaseCommand { output.standard(this.npm.dir) } } + module.exports = Root diff --git a/lib/commands/run-script.js b/lib/commands/run-script.js index 34c0b00fe95b5..f048996e66354 100644 --- a/lib/commands/run-script.js +++ b/lib/commands/run-script.js @@ -1,7 +1,7 @@ const { log, output } = require('proc-log') const pkgJson = require('@npmcli/package-json') - const BaseCommand = require('../base-command.js') + class RunScript extends BaseCommand { static description = 'Run arbitrary package scripts' static params = [ diff --git a/lib/commands/sbom.js b/lib/commands/sbom.js index 4b20bf5ea1f76..4ee21ec1954fd 100644 --- a/lib/commands/sbom.js +++ b/lib/commands/sbom.js @@ -1,5 +1,3 @@ -'use strict' - const localeCompare = require('@isaacs/string-locale-compare')('en') const BaseCommand = require('../base-command.js') const { log, output } = require('proc-log') diff --git a/lib/commands/search.js b/lib/commands/search.js index 2b338ed4d39b8..cffc4cdacc846 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -1,7 +1,6 @@ const Pipeline = require('minipass-pipeline') const libSearch = require('libnpmsearch') const { log, output } = require('proc-log') - const formatSearchStream = require('../utils/format-search-stream.js') const BaseCommand = require('../base-command.js') @@ -68,4 +67,5 @@ class Search extends BaseCommand { log.silly('search', 'search completed') } } + module.exports = Search diff --git a/lib/commands/set.js b/lib/commands/set.js index f315d183845c5..509da1956bf1f 100644 --- a/lib/commands/set.js +++ b/lib/commands/set.js @@ -22,4 +22,5 @@ class Set extends BaseCommand { return this.npm.exec('config', ['set'].concat(args)) } } + module.exports = Set diff --git a/lib/commands/shrinkwrap.js b/lib/commands/shrinkwrap.js index 56d7ffa88e99e..008244e9760f3 100644 --- a/lib/commands/shrinkwrap.js +++ b/lib/commands/shrinkwrap.js @@ -69,4 +69,5 @@ class Shrinkwrap extends BaseCommand { } } } + module.exports = Shrinkwrap diff --git a/lib/commands/star.js b/lib/commands/star.js index 39165d8c3d8dc..fbf81e64bf21d 100644 --- a/lib/commands/star.js +++ b/lib/commands/star.js @@ -2,8 +2,8 @@ const fetch = require('npm-registry-fetch') const npa = require('npm-package-arg') const { log, output } = require('proc-log') const getIdentity = require('../utils/get-identity') - const BaseCommand = require('../base-command.js') + class Star extends BaseCommand { static description = 'Mark your favorite packages' static name = 'star' @@ -68,4 +68,5 @@ class Star extends BaseCommand { } } } + module.exports = Star diff --git a/lib/commands/stars.js b/lib/commands/stars.js index 1d92d97d7760a..628b22fdb8808 100644 --- a/lib/commands/stars.js +++ b/lib/commands/stars.js @@ -1,8 +1,8 @@ const fetch = require('npm-registry-fetch') const { log, output } = require('proc-log') const getIdentity = require('../utils/get-identity.js') - const BaseCommand = require('../base-command.js') + class Stars extends BaseCommand { static description = 'View packages marked as favorites' static name = 'stars' @@ -35,4 +35,5 @@ class Stars extends BaseCommand { } } } + module.exports = Stars diff --git a/lib/commands/team.js b/lib/commands/team.js index 4ffaa5ff86ab9..f7bada28a611e 100644 --- a/lib/commands/team.js +++ b/lib/commands/team.js @@ -1,7 +1,6 @@ const columns = require('cli-columns') const libteam = require('libnpmteam') const { output } = require('proc-log') - const otplease = require('../utils/otplease.js') const BaseCommand = require('../base-command.js') @@ -152,4 +151,5 @@ class Team extends BaseCommand { } } } + module.exports = Team diff --git a/lib/commands/token.js b/lib/commands/token.js index 70ff0a332b18a..4429a20319f7e 100644 --- a/lib/commands/token.js +++ b/lib/commands/token.js @@ -1,10 +1,9 @@ const { log, output } = require('proc-log') const profile = require('npm-profile') - const otplease = require('../utils/otplease.js') const readUserInfo = require('../utils/read-user-info.js') - const BaseCommand = require('../base-command.js') + class Token extends BaseCommand { static description = 'Manage your authentication tokens' static name = 'token' @@ -194,4 +193,5 @@ class Token extends BaseCommand { return list } } + module.exports = Token diff --git a/lib/commands/uninstall.js b/lib/commands/uninstall.js index 51df355d5a899..7496c02deb28f 100644 --- a/lib/commands/uninstall.js +++ b/lib/commands/uninstall.js @@ -1,10 +1,9 @@ const { resolve } = require('path') const pkgJson = require('@npmcli/package-json') - const reifyFinish = require('../utils/reify-finish.js') const completion = require('../utils/installed-shallow.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Uninstall extends ArboristWorkspaceCmd { static description = 'Remove a package' static name = 'uninstall' @@ -53,4 +52,5 @@ class Uninstall extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Uninstall diff --git a/lib/commands/unpublish.js b/lib/commands/unpublish.js index 3e7e8c8b624a2..e8b7de8395ea9 100644 --- a/lib/commands/unpublish.js +++ b/lib/commands/unpublish.js @@ -7,12 +7,12 @@ const pkgJson = require('@npmcli/package-json') const { flatten } = require('@npmcli/config/lib/definitions') const getIdentity = require('../utils/get-identity.js') const otplease = require('../utils/otplease.js') +const BaseCommand = require('../base-command.js') const LAST_REMAINING_VERSION_ERROR = 'Refusing to delete the last version of the package. ' + 'It will block from republishing a new version for 24 hours.\n' + 'Run with --force to do this.' -const BaseCommand = require('../base-command.js') class Unpublish extends BaseCommand { static description = 'Remove a package from the registry' static name = 'unpublish' @@ -172,4 +172,5 @@ class Unpublish extends BaseCommand { } } } + module.exports = Unpublish diff --git a/lib/commands/unstar.js b/lib/commands/unstar.js index cbcb73636c638..c72966866669a 100644 --- a/lib/commands/unstar.js +++ b/lib/commands/unstar.js @@ -4,4 +4,5 @@ class Unstar extends Star { static description = 'Remove an item from your favorite packages' static name = 'unstar' } + module.exports = Unstar diff --git a/lib/commands/update.js b/lib/commands/update.js index 63711c05e5b97..ddc3e4a47f38a 100644 --- a/lib/commands/update.js +++ b/lib/commands/update.js @@ -1,10 +1,8 @@ const path = require('path') - const { log } = require('proc-log') - const reifyFinish = require('../utils/reify-finish.js') - const ArboristWorkspaceCmd = require('../arborist-cmd.js') + class Update extends ArboristWorkspaceCmd { static description = 'Update packages' static name = 'update' @@ -66,4 +64,5 @@ class Update extends ArboristWorkspaceCmd { await reifyFinish(this.npm, arb) } } + module.exports = Update diff --git a/lib/commands/version.js b/lib/commands/version.js index 0e1916d7af7fb..4d7b971fa6fbf 100644 --- a/lib/commands/version.js +++ b/lib/commands/version.js @@ -1,7 +1,6 @@ const { resolve } = require('node:path') const { readFile } = require('node:fs/promises') const { output } = require('proc-log') - const BaseCommand = require('../base-command.js') class Version extends BaseCommand { diff --git a/lib/commands/view.js b/lib/commands/view.js index e8b102737a1e9..9c8630bef154e 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -9,11 +9,11 @@ const relativeDate = require('tiny-relative-date') const semver = require('semver') const { inspect } = require('util') const { packument } = require('pacote') +const Queryable = require('../utils/queryable.js') +const BaseCommand = require('../base-command.js') const readJson = async file => jsonParse(await readFile(file, 'utf8')) -const Queryable = require('../utils/queryable.js') -const BaseCommand = require('../base-command.js') class View extends BaseCommand { static description = 'View registry info' static name = 'view' @@ -406,6 +406,7 @@ class View extends BaseCommand { } } } + module.exports = View function cleanBlanks (obj) { diff --git a/lib/commands/whoami.js b/lib/commands/whoami.js index e05993abdd5bf..03d7bb24991cf 100644 --- a/lib/commands/whoami.js +++ b/lib/commands/whoami.js @@ -1,7 +1,7 @@ const { output } = require('proc-log') const getIdentity = require('../utils/get-identity.js') - const BaseCommand = require('../base-command.js') + class Whoami extends BaseCommand { static description = 'Display npm username' static name = 'whoami' @@ -14,4 +14,5 @@ class Whoami extends BaseCommand { ) } } + module.exports = Whoami diff --git a/lib/lifecycle-cmd.js b/lib/lifecycle-cmd.js index 848771a38355e..26e04b12af272 100644 --- a/lib/lifecycle-cmd.js +++ b/lib/lifecycle-cmd.js @@ -16,4 +16,5 @@ class LifecycleCmd extends BaseCommand { return this.npm.exec('run-script', [this.constructor.name, ...args]) } } + module.exports = LifecycleCmd diff --git a/lib/npm.js b/lib/npm.js index 509c2fa2abd36..e76317e905ea3 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -445,4 +445,5 @@ class Npm { this.#display.flushOutput(jsonError) } } + module.exports = Npm diff --git a/lib/package-url-cmd.js b/lib/package-url-cmd.js index c81b933f69254..5ab7cb87a2cd3 100644 --- a/lib/package-url-cmd.js +++ b/lib/package-url-cmd.js @@ -62,4 +62,5 @@ class PackageUrlCommand extends BaseCommand { return (rurl && hostedGitInfo.fromUrl(rurl.replace(/^git\+/, ''))) || null } } + module.exports = PackageUrlCommand diff --git a/lib/utils/did-you-mean.js b/lib/utils/did-you-mean.js index ff3c812b46c3c..499c27c74e1de 100644 --- a/lib/utils/did-you-mean.js +++ b/lib/utils/did-you-mean.js @@ -37,4 +37,5 @@ const didYouMean = async (path, scmd) => { : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` return suggestion } + module.exports = didYouMean diff --git a/lib/utils/verify-signatures.js b/lib/utils/verify-signatures.js new file mode 100644 index 0000000000000..f2973316c9b76 --- /dev/null +++ b/lib/utils/verify-signatures.js @@ -0,0 +1,389 @@ +const fetch = require('npm-registry-fetch') +const localeCompare = require('@isaacs/string-locale-compare')('en') +const npa = require('npm-package-arg') +const pacote = require('pacote') +const pMap = require('p-map') +const tufClient = require('@sigstore/tuf') +const { log, output } = require('proc-log') + +const sortAlphabetically = (a, b) => localeCompare(a.name, b.name) + +class VerifySignatures { + constructor (tree, filterSet, npm, opts) { + this.tree = tree + this.filterSet = filterSet + this.npm = npm + this.opts = opts + this.keys = new Map() + this.invalid = [] + this.missing = [] + this.checkedPackages = new Set() + this.auditedWithKeysCount = 0 + this.verifiedSignatureCount = 0 + this.verifiedAttestationCount = 0 + this.exitCode = 0 + } + + async run () { + const start = process.hrtime.bigint() + + // Find all deps in tree + const { edges, registries } = this.getEdgesOut(this.tree.inventory.values(), this.filterSet) + if (edges.size === 0) { + throw new Error('found no installed dependencies to audit') + } + + const tuf = await tufClient.initTUF({ + cachePath: this.opts.tufCache, + retry: this.opts.retry, + timeout: this.opts.timeout, + }) + await Promise.all([...registries].map(registry => this.setKeys({ registry, tuf }))) + + log.verbose('verifying registry signatures') + await pMap(edges, (e) => this.getVerifiedInfo(e), { concurrency: 20, stopOnError: true }) + + // Didn't find any dependencies that could be verified, e.g. only local + // deps, missing version, not on a registry etc. + if (!this.auditedWithKeysCount) { + throw new Error('found no dependencies to audit that were installed from ' + + 'a supported registry') + } + + const invalid = this.invalid.sort(sortAlphabetically) + const missing = this.missing.sort(sortAlphabetically) + + const hasNoInvalidOrMissing = invalid.length === 0 && missing.length === 0 + + if (!hasNoInvalidOrMissing) { + process.exitCode = 1 + } + + if (this.npm.config.get('json')) { + output.standard(JSON.stringify({ + invalid, + missing, + }, null, 2)) + return + } + const end = process.hrtime.bigint() + const elapsed = end - start + + const auditedPlural = this.auditedWithKeysCount > 1 ? 's' : '' + const timing = `audited ${this.auditedWithKeysCount} package${auditedPlural} in ` + + `${Math.floor(Number(elapsed) / 1e9)}s` + output.standard(timing) + output.standard('') + + const verifiedBold = this.npm.chalk.bold('verified') + if (this.verifiedSignatureCount) { + if (this.verifiedSignatureCount === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedSignatureCount} package has a ${verifiedBold} registry signature`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedSignatureCount} packages have ${verifiedBold} registry signatures`) + } + output.standard('') + } + + if (this.verifiedAttestationCount) { + if (this.verifiedAttestationCount === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedAttestationCount} package has a ${verifiedBold} attestation`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${this.verifiedAttestationCount} packages have ${verifiedBold} attestations`) + } + output.standard('') + } + + if (missing.length) { + const missingClr = this.npm.chalk.redBright('missing') + if (missing.length === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`1 package has a ${missingClr} registry signature but the registry is providing signing keys:`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${missing.length} packages have ${missingClr} registry signatures but the registry is providing signing keys:`) + } + output.standard('') + missing.map(m => + output.standard(`${this.npm.chalk.red(`${m.name}@${m.version}`)} (${m.registry})`) + ) + } + + if (invalid.length) { + if (missing.length) { + output.standard('') + } + const invalidClr = this.npm.chalk.redBright('invalid') + // We can have either invalid signatures or invalid provenance + const invalidSignatures = this.invalid.filter(i => i.code === 'EINTEGRITYSIGNATURE') + if (invalidSignatures.length) { + if (invalidSignatures.length === 1) { + output.standard(`1 package has an ${invalidClr} registry signature:`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${invalidSignatures.length} packages have ${invalidClr} registry signatures:`) + } + output.standard('') + invalidSignatures.map(i => + output.standard(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) + ) + output.standard('') + } + + const invalidAttestations = this.invalid.filter(i => i.code === 'EATTESTATIONVERIFY') + if (invalidAttestations.length) { + if (invalidAttestations.length === 1) { + output.standard(`1 package has an ${invalidClr} attestation:`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`${invalidAttestations.length} packages have ${invalidClr} attestations:`) + } + output.standard('') + invalidAttestations.map(i => + output.standard(`${this.npm.chalk.red(`${i.name}@${i.version}`)} (${i.registry})`) + ) + output.standard('') + } + + if (invalid.length === 1) { + /* eslint-disable-next-line max-len */ + output.standard(`Someone might have tampered with this package since it was published on the registry!`) + } else { + /* eslint-disable-next-line max-len */ + output.standard(`Someone might have tampered with these packages since they were published on the registry!`) + } + output.standard('') + } + } + + getEdgesOut (nodes, filterSet) { + const edges = new Set() + const registries = new Set() + for (const node of nodes) { + for (const edge of node.edgesOut.values()) { + const filteredOut = + edge.from + && filterSet + && filterSet.size > 0 + && !filterSet.has(edge.from.target) + + if (!filteredOut) { + const spec = this.getEdgeSpec(edge) + if (spec) { + // Prefetch and cache public keys from used registries + registries.add(this.getSpecRegistry(spec)) + } + edges.add(edge) + } + } + } + return { edges, registries } + } + + async setKeys ({ registry, tuf }) { + const { host, pathname } = new URL(registry) + // Strip any trailing slashes from pathname + const regKey = `${host}${pathname.replace(/\/$/, '')}/keys.json` + let keys = await tuf.getTarget(regKey) + .then((target) => JSON.parse(target)) + .then(({ keys: ks }) => ks.map((key) => ({ + ...key, + keyid: key.keyId, + pemkey: `-----BEGIN PUBLIC KEY-----\n${key.publicKey.rawBytes}\n-----END PUBLIC KEY-----`, + expires: key.publicKey.validFor.end || null, + }))).catch(err => { + if (err.code === 'TUF_FIND_TARGET_ERROR') { + return null + } else { + throw err + } + }) + + // If keys not found in Sigstore TUF repo, fallback to registry keys API + if (!keys) { + keys = await fetch.json('/-/npm/v1/keys', { + ...this.npm.flatOptions, + registry, + }).then(({ keys: ks }) => ks.map((key) => ({ + ...key, + pemkey: `-----BEGIN PUBLIC KEY-----\n${key.key}\n-----END PUBLIC KEY-----`, + }))).catch(err => { + if (err.code === 'E404' || err.code === 'E400') { + return null + } else { + throw err + } + }) + } + + if (keys) { + this.keys.set(registry, keys) + } + } + + getEdgeType (edge) { + return edge.optional ? 'optionalDependencies' + : edge.peer ? 'peerDependencies' + : edge.dev ? 'devDependencies' + : 'dependencies' + } + + getEdgeSpec (edge) { + let name = edge.name + try { + name = npa(edge.spec).subSpec.name + } catch { + // leave it as edge.name + } + try { + return npa(`${name}@${edge.spec}`) + } catch { + // Skip packages with invalid spec + } + } + + buildRegistryConfig (registry) { + const keys = this.keys.get(registry) || [] + const parsedRegistry = new URL(registry) + const regKey = `//${parsedRegistry.host}${parsedRegistry.pathname}` + return { + [`${regKey}:_keys`]: keys, + } + } + + getSpecRegistry (spec) { + return fetch.pickRegistry(spec, this.npm.flatOptions) + } + + getValidPackageInfo (edge) { + const type = this.getEdgeType(edge) + // Skip potentially optional packages that are not on disk, as these could + // be omitted during install + if (edge.error === 'MISSING' && type !== 'dependencies') { + return + } + + const spec = this.getEdgeSpec(edge) + // Skip invalid version requirements + if (!spec) { + return + } + const node = edge.to || edge + const { version } = node.package || {} + + if (node.isWorkspace || // Skip local workspaces packages + !version || // Skip packages that don't have a installed version, e.g. optonal dependencies + !spec.registry) { // Skip if not from registry, e.g. git package + return + } + + for (const omitType of this.npm.config.get('omit')) { + if (node[omitType]) { + return + } + } + + return { + name: spec.name, + version, + type, + location: node.location, + registry: this.getSpecRegistry(spec), + } + } + + async verifySignatures (name, version, registry) { + const { + _integrity: integrity, + _signatures, + _attestations, + _resolved: resolved, + } = await pacote.manifest(`${name}@${version}`, { + verifySignatures: true, + verifyAttestations: true, + ...this.buildRegistryConfig(registry), + ...this.npm.flatOptions, + }) + const signatures = _signatures || [] + const result = { + integrity, + signatures, + attestations: _attestations, + resolved, + } + return result + } + + async getVerifiedInfo (edge) { + const info = this.getValidPackageInfo(edge) + if (!info) { + return + } + const { name, version, location, registry, type } = info + if (this.checkedPackages.has(location)) { + // we already did or are doing this one + return + } + this.checkedPackages.add(location) + + // We only "audit" or verify the signature, or the presence of it, on + // packages whose registry returns signing keys + const keys = this.keys.get(registry) || [] + if (keys.length) { + this.auditedWithKeysCount += 1 + } + + try { + const { integrity, signatures, attestations, resolved } = await this.verifySignatures( + name, version, registry + ) + + // Currently we only care about missing signatures on registries that provide a public key + // We could make this configurable in the future with a strict/paranoid mode + if (signatures.length) { + this.verifiedSignatureCount += 1 + } else if (keys.length) { + this.missing.push({ + integrity, + location, + name, + registry, + resolved, + version, + }) + } + + // Track verified attestations separately to registry signatures, as all + // packages on registries with signing keys are expected to have registry + // signatures, but not all packages have provenance and publish attestations. + if (attestations) { + this.verifiedAttestationCount += 1 + } + } catch (e) { + if (e.code === 'EINTEGRITYSIGNATURE' || e.code === 'EATTESTATIONVERIFY') { + this.invalid.push({ + code: e.code, + message: e.message, + integrity: e.integrity, + keyid: e.keyid, + location, + name, + registry, + resolved: e.resolved, + signature: e.signature, + predicateType: e.predicateType, + type, + version, + }) + } else { + throw e + } + } + } +} + +module.exports = VerifySignatures From 28019d50fdb1b2395199516694180edc7b4f8dd6 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 14:45:45 -0700 Subject: [PATCH 16/42] fix(cleanup): move cli specific files to separate dir --- .eslintrc.local.js | 4 +-- lib/cli.js | 4 +-- lib/{cli-entry.js => cli/entry.js} | 27 ++++++++++++++-- lib/{utils => cli}/exit-handler.js | 2 +- lib/{utils => cli}/update-notifier.js | 0 lib/{es6 => cli}/validate-engines.js | 0 lib/npm.js | 31 +------------------ smoke-tests/test/npm-replace-global.js | 2 +- .../update-notifier.js.test.cjs | 24 +++++++------- test/fixtures/mock-npm.js | 6 +--- test/lib/cli.js | 2 +- test/lib/{cli-entry.js => cli/entry.js} | 23 +++++++++++--- test/lib/{utils => cli}/update-notifier.js | 2 +- test/lib/{es6 => cli}/validate-engines.js | 2 +- test/lib/npm.js | 5 ++- test/lib/utils/exit-handler.js | 2 +- test/lib/utils/installed-deep.js | 2 +- test/lib/utils/installed-shallow.js | 2 +- 18 files changed, 70 insertions(+), 70 deletions(-) rename lib/{cli-entry.js => cli/entry.js} (71%) rename lib/{utils => cli}/exit-handler.js (99%) rename lib/{utils => cli}/update-notifier.js (100%) rename lib/{es6 => cli}/validate-engines.js (100%) rename tap-snapshots/test/lib/{utils => cli}/update-notifier.js.test.cjs (64%) rename test/lib/{cli-entry.js => cli/entry.js} (88%) rename test/lib/{utils => cli}/update-notifier.js (99%) rename test/lib/{es6 => cli}/validate-engines.js (94%) diff --git a/.eslintrc.local.js b/.eslintrc.local.js index 6d94f64614fb8..2dce9d2badc08 100644 --- a/.eslintrc.local.js +++ b/.eslintrc.local.js @@ -25,8 +25,8 @@ module.exports = { overrides: es6Files({ 'index.js': ['lib/cli.js'], 'bin/npm-cli.js': ['lib/cli.js'], - 'lib/cli.js': ['lib/es6/validate-engines.js'], - 'lib/es6/validate-engines.js': ['package.json'], + 'lib/cli.js': ['lib/cli/validate-engines.js'], + 'lib/cli/validate-engines.js': ['package.json'], // TODO: This file should also have its requires restricted as well since it // is an entry point but it currently pulls in config definitions which have // a large require graph, so that is not currently feasible. A future config diff --git a/lib/cli.js b/lib/cli.js index 84d5471ad5e91..e11729fe3205b 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,4 +1,4 @@ -const validateEngines = require('./es6/validate-engines.js') -const cliEntry = require('node:path').resolve(__dirname, 'cli-entry.js') +const validateEngines = require('./cli/validate-engines.js') +const cliEntry = require('node:path').resolve(__dirname, 'cli/entry.js') module.exports = (process) => validateEngines(process, () => require(cliEntry)) diff --git a/lib/cli-entry.js b/lib/cli/entry.js similarity index 71% rename from lib/cli-entry.js rename to lib/cli/entry.js index 9a5994aec19a3..1c5f7e0dc1545 100644 --- a/lib/cli-entry.js +++ b/lib/cli/entry.js @@ -11,9 +11,12 @@ module.exports = async (process, validateEngines) => { process.argv.splice(1, 1, 'npm', '-g') } + // Patch the global fs module here at the app level + require('graceful-fs').gracefulify(require('fs')) + const satisfies = require('semver/functions/satisfies') - const exitHandler = require('./utils/exit-handler.js') - const Npm = require('./npm.js') + const exitHandler = require('./exit-handler.js') + const Npm = require('../npm.js') const npm = new Npm() exitHandler.setNpm(npm) @@ -58,11 +61,29 @@ module.exports = async (process, validateEngines) => { return exitHandler() } + // this is async but we dont await it, since its ok if it doesnt + // finish before the command finishes running. it uses command and argv + // so it must be initiated here, after the command name is set + const updateNotifier = require('./update-notifier.js') + // eslint-disable-next-line promise/catch-or-return + updateNotifier(npm).then((msg) => (npm.updateNotification = msg)) + + // Options are prefixed by a hyphen-minus (-, \u2d). + // Other dash-type chars look similar but are invalid. + const nonDashArgs = npm.argv.filter(a => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(a)) + if (nonDashArgs.length) { + log.error( + 'arg', + 'Argument starts with non-ascii dash, this is probably invalid:', + nonDashArgs.join(', ') + ) + } + await npm.exec(cmd) return exitHandler() } catch (err) { if (err.code === 'EUNKNOWNCOMMAND') { - const didYouMean = require('./utils/did-you-mean.js') + const didYouMean = require('../utils/did-you-mean.js') const suggestions = await didYouMean(npm.localPrefix, cmd) output.standard(`Unknown command: "${cmd}"${suggestions}\n`) output.standard('To see a list of supported npm commands, run:\n npm help') diff --git a/lib/utils/exit-handler.js b/lib/cli/exit-handler.js similarity index 99% rename from lib/utils/exit-handler.js rename to lib/cli/exit-handler.js index 76d7d6036e072..6dc44de1f003a 100644 --- a/lib/utils/exit-handler.js +++ b/lib/cli/exit-handler.js @@ -1,5 +1,5 @@ const { log, output, time } = require('proc-log') -const errorMessage = require('./error-message.js') +const errorMessage = require('../utils/error-message.js') const { redactLog: replaceInfo } = require('@npmcli/redact') let npm = null // set by the cli diff --git a/lib/utils/update-notifier.js b/lib/cli/update-notifier.js similarity index 100% rename from lib/utils/update-notifier.js rename to lib/cli/update-notifier.js diff --git a/lib/es6/validate-engines.js b/lib/cli/validate-engines.js similarity index 100% rename from lib/es6/validate-engines.js rename to lib/cli/validate-engines.js diff --git a/lib/npm.js b/lib/npm.js index e76317e905ea3..d52f8bdc1c480 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -2,10 +2,6 @@ const { resolve, dirname, join } = require('node:path') const Config = require('@npmcli/config') const which = require('which') const fs = require('node:fs/promises') - -// Patch the global fs module here at the app level -require('graceful-fs').gracefulify(require('fs')) - const { definitions, flatten, shorthands } = require('@npmcli/config/lib/definitions') const usage = require('./utils/npm-usage.js') const LogFile = require('./utils/log-file.js') @@ -13,7 +9,6 @@ const Timers = require('./utils/timers.js') const Display = require('./utils/display.js') const { log, time } = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') -const updateNotifier = require('./utils/update-notifier.js') const pkg = require('../package.json') const { deref } = require('./utils/cmd-list.js') @@ -42,7 +37,6 @@ class Npm { #title = 'npm' #argvClean = [] #npmRoot = null - #warnedNonDashArg = false #chalk = null #logChalk = null @@ -109,30 +103,7 @@ class Npm { // passed in directly. async exec (cmd, args = this.argv) { const command = this.setCmd(cmd) - - const timeEnd = time.start(`command:${cmd}`) - - // this is async but we dont await it, since its ok if it doesnt - // finish before the command finishes running. it uses command and argv - // so it must be initiated here, after the command name is set - // eslint-disable-next-line promise/catch-or-return - updateNotifier(this).then((msg) => (this.updateNotification = msg)) - - // Options are prefixed by a hyphen-minus (-, \u2d). - // Other dash-type chars look similar but are invalid. - if (!this.#warnedNonDashArg) { - const nonDashArgs = args.filter(a => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(a)) - if (nonDashArgs.length) { - this.#warnedNonDashArg = true - log.error( - 'arg', - 'Argument starts with non-ascii dash, this is probably invalid:', - nonDashArgs.join(', ') - ) - } - } - - return command.cmdExec(args).finally(timeEnd) + return time.start(`command:${cmd}`, () => command.cmdExec(args)) } async load () { diff --git a/smoke-tests/test/npm-replace-global.js b/smoke-tests/test/npm-replace-global.js index 5b84daf356ce2..c0accf6ba53b5 100644 --- a/smoke-tests/test/npm-replace-global.js +++ b/smoke-tests/test/npm-replace-global.js @@ -190,7 +190,7 @@ t.test('fail when updating with lazy require', async t => { // exit-handler is the last thing called in the code // so an uncached lazy require within the exit handler will always throw await fs.writeFile( - join(paths.globalNodeModules, 'npm/lib/utils/exit-handler.js'), + join(paths.globalNodeModules, 'npm/lib/cli/exit-handler.js'), `module.exports = () => require('./LAZY_REQUIRE_CANARY');module.exports.setNpm = () => {}`, 'utf-8' ) diff --git a/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs b/tap-snapshots/test/lib/cli/update-notifier.js.test.cjs similarity index 64% rename from tap-snapshots/test/lib/utils/update-notifier.js.test.cjs rename to tap-snapshots/test/lib/cli/update-notifier.js.test.cjs index 5693b3f3a9097..244d5216340f8 100644 --- a/tap-snapshots/test/lib/utils/update-notifier.js.test.cjs +++ b/tap-snapshots/test/lib/cli/update-notifier.js.test.cjs @@ -5,7 +5,7 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' -exports[`test/lib/utils/update-notifier.js TAP notification situations 122.420.69 - color=always > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 122.420.69 - color=always > must match snapshot 1`] = ` New major version of npm available! 122.420.69 -> 123.420.69 Changelog: https://github.com/npm/cli/releases/tag/v123.420.69 @@ -13,7 +13,7 @@ To update run: npm install -g npm@123.420.69 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 122.420.69 - color=false > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 122.420.69 - color=false > must match snapshot 1`] = ` New major version of npm available! 122.420.69 -> 123.420.69 Changelog: https://github.com/npm/cli/releases/tag/v123.420.69 @@ -21,7 +21,7 @@ To update run: npm install -g npm@123.420.69 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.419.69 - color=always > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.419.69 - color=always > must match snapshot 1`] = ` New minor version of npm available! 123.419.69 -> 123.420.69 Changelog: https://github.com/npm/cli/releases/tag/v123.420.69 @@ -29,7 +29,7 @@ To update run: npm install -g npm@123.420.69 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.419.69 - color=false > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.419.69 - color=false > must match snapshot 1`] = ` New minor version of npm available! 123.419.69 -> 123.420.69 Changelog: https://github.com/npm/cli/releases/tag/v123.420.69 @@ -37,7 +37,7 @@ To update run: npm install -g npm@123.420.69 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.420.68 - color=always > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.420.68 - color=always > must match snapshot 1`] = ` New patch version of npm available! 123.420.68 -> 123.420.69 Changelog: https://github.com/npm/cli/releases/tag/v123.420.69 @@ -45,7 +45,7 @@ To update run: npm install -g npm@123.420.69 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.420.68 - color=false > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.420.68 - color=false > must match snapshot 1`] = ` New patch version of npm available! 123.420.68 -> 123.420.69 Changelog: https://github.com/npm/cli/releases/tag/v123.420.69 @@ -53,7 +53,7 @@ To update run: npm install -g npm@123.420.69 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.420.70 - color=always > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.420.70 - color=always > must match snapshot 1`] = ` New minor version of npm available! 123.420.70 -> 123.421.70 Changelog: https://github.com/npm/cli/releases/tag/v123.421.70 @@ -61,7 +61,7 @@ To update run: npm install -g npm@123.421.70 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.420.70 - color=false > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.420.70 - color=false > must match snapshot 1`] = ` New minor version of npm available! 123.420.70 -> 123.421.70 Changelog: https://github.com/npm/cli/releases/tag/v123.421.70 @@ -69,7 +69,7 @@ To update run: npm install -g npm@123.421.70 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.421.69 - color=always > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.421.69 - color=always > must match snapshot 1`] = ` New patch version of npm available! 123.421.69 -> 123.421.70 Changelog: https://github.com/npm/cli/releases/tag/v123.421.70 @@ -77,7 +77,7 @@ To update run: npm install -g npm@123.421.70 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 123.421.69 - color=false > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 123.421.69 - color=false > must match snapshot 1`] = ` New patch version of npm available! 123.421.69 -> 123.421.70 Changelog: https://github.com/npm/cli/releases/tag/v123.421.70 @@ -85,7 +85,7 @@ To update run: npm install -g npm@123.421.70 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 124.0.0-beta.0 - color=always > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 124.0.0-beta.0 - color=always > must match snapshot 1`] = ` New prerelease version of npm available! 124.0.0-beta.0 -> 124.0.0-beta.99999 Changelog: https://github.com/npm/cli/releases/tag/v124.0.0-beta.99999 @@ -93,7 +93,7 @@ To update run: npm install -g npm@124.0.0-beta.99999 ` -exports[`test/lib/utils/update-notifier.js TAP notification situations 124.0.0-beta.0 - color=false > must match snapshot 1`] = ` +exports[`test/lib/cli/update-notifier.js TAP notification situations 124.0.0-beta.0 - color=false > must match snapshot 1`] = ` New prerelease version of npm available! 124.0.0-beta.0 -> 124.0.0-beta.99999 Changelog: https://github.com/npm/cli/releases/tag/v124.0.0-beta.99999 diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index 6bb3123d2b091..466b9b2a0ba46 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -48,17 +48,13 @@ const setGlobalNodeModules = (globalDir) => { } const buildMocks = (t, mocks) => { - const allMocks = { - '{LIB}/utils/update-notifier.js': async () => {}, - ...mocks, - } + const allMocks = { ...mocks } // The definitions must be mocked since they are a singleton that reads from // process and environs to build defaults in order to break the requiure // cache. We also need to mock them with any mocks that were passed in for the // test in case those mocks are for things like ci-info which is used there. const definitions = '@npmcli/config/lib/definitions' allMocks[definitions] = tmock(t, definitions, allMocks) - return allMocks } diff --git a/test/lib/cli.js b/test/lib/cli.js index a6cb576e886ee..6c3079b8efe31 100644 --- a/test/lib/cli.js +++ b/test/lib/cli.js @@ -3,7 +3,7 @@ const tmock = require('../fixtures/tmock') t.test('returns cli-entry function', async t => { const cli = tmock(t, '{LIB}/cli.js', { - '{LIB}/cli-entry.js': () => 'ENTRY', + '{LIB}/cli/entry.js': () => 'ENTRY', }) t.equal(cli(process), 'ENTRY') diff --git a/test/lib/cli-entry.js b/test/lib/cli/entry.js similarity index 88% rename from test/lib/cli-entry.js rename to test/lib/cli/entry.js index 3a8d3321c4b64..66a417e7d269a 100644 --- a/test/lib/cli-entry.js +++ b/test/lib/cli/entry.js @@ -1,7 +1,7 @@ const t = require('tap') -const { load: loadMockNpm } = require('../fixtures/mock-npm.js') -const tmock = require('../fixtures/tmock.js') -const validateEngines = require('../../lib/es6/validate-engines.js') +const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') +const tmock = require('../../fixtures/tmock.js') +const validateEngines = require('../../../lib/cli/validate-engines.js') const cliMock = async (t, opts) => { let exitHandlerArgs = null @@ -13,9 +13,9 @@ const cliMock = async (t, opts) => { exitHandlerMock.setNpm = _npm => npm = _npm const { Npm, ...mock } = await loadMockNpm(t, { ...opts, init: false }) - const cli = tmock(t, '{LIB}/cli-entry.js', { + const cli = tmock(t, '{LIB}/cli/entry.js', { '{LIB}/npm.js': Npm, - '{LIB}/utils/exit-handler.js': exitHandlerMock, + '{LIB}/cli/exit-handler.js': exitHandlerMock, }) return { @@ -159,3 +159,16 @@ t.test('unsupported node version', async t => { /npm v.* does not support Node\.js 12\.6\.0\./ ) }) + +t.test('non-ascii dash', async t => { + const { cli, logs } = await cliMock(t, { + globals: { + 'process.argv': ['node', 'npm', 'scope', '\u2010not-a-dash'], + }, + }) + await cli(process) + t.equal( + logs.error[0], + 'arg Argument starts with non-ascii dash, this is probably invalid: \u2010not-a-dash' + ) +}) diff --git a/test/lib/utils/update-notifier.js b/test/lib/cli/update-notifier.js similarity index 99% rename from test/lib/utils/update-notifier.js rename to test/lib/cli/update-notifier.js index 052367c60dadb..2d29868b792a1 100644 --- a/test/lib/utils/update-notifier.js +++ b/test/lib/cli/update-notifier.js @@ -83,7 +83,7 @@ const runUpdateNotifier = async (t, { prefixDir, argv, }) - const updateNotifier = tmock(t, '{LIB}/utils/update-notifier.js', mocks) + const updateNotifier = tmock(t, '{LIB}/cli/update-notifier.js', mocks) const result = await updateNotifier(mock.npm) diff --git a/test/lib/es6/validate-engines.js b/test/lib/cli/validate-engines.js similarity index 94% rename from test/lib/es6/validate-engines.js rename to test/lib/cli/validate-engines.js index 0e6bce726af96..1c0b59700a773 100644 --- a/test/lib/es6/validate-engines.js +++ b/test/lib/cli/validate-engines.js @@ -3,7 +3,7 @@ const mockGlobals = require('@npmcli/mock-globals') const tmock = require('../../fixtures/tmock') const mockValidateEngines = (t) => { - const validateEngines = tmock(t, '{LIB}/es6/validate-engines.js', { + const validateEngines = tmock(t, '{LIB}/cli/validate-engines.js', { '{ROOT}/package.json': { version: '1.2.3', engines: { node: '>=0' } }, }) mockGlobals(t, { 'process.version': 'v4.5.6' }) diff --git a/test/lib/npm.js b/test/lib/npm.js index a0dec04caa137..bc9042365abea 100644 --- a/test/lib/npm.js +++ b/test/lib/npm.js @@ -178,17 +178,16 @@ t.test('npm.load', async t => { outputs.length = 0 logs.length = 0 - await npm.exec('get', ['scope', '\u2010not-a-dash']) + await npm.exec('get', ['scope', 'usage']) t.strictSame([npm.command, npm.flatOptions.npmCommand], ['ll', 'll'], 'does not change npm.command when another command is called') t.match(logs, [ - 'error arg Argument starts with non-ascii dash, this is probably invalid: \u2010not-a-dash', /timing command:config Completed in [0-9.]+ms/, /timing command:get Completed in [0-9.]+ms/, ]) - t.same(outputs, ['scope=@foo\n\u2010not-a-dash=undefined']) + t.same(outputs, ['scope=@foo\nusage=false']) }) await t.test('--no-workspaces with --workspace', async t => { diff --git a/test/lib/utils/exit-handler.js b/test/lib/utils/exit-handler.js index af92611de0594..b1f4d9c272533 100644 --- a/test/lib/utils/exit-handler.js +++ b/test/lib/utils/exit-handler.js @@ -72,7 +72,7 @@ const mockExitHandler = async (t, { config, mocks, files, ...opts } = {}) => { }, }) - const exitHandler = tmock(t, '{LIB}/utils/exit-handler.js', { + const exitHandler = tmock(t, '{LIB}/cli/exit-handler.js', { '{LIB}/utils/error-message.js': (err) => ({ summary: [['ERR SUMMARY', err.message]], detail: [['ERR DETAIL', err.message]], diff --git a/test/lib/utils/installed-deep.js b/test/lib/utils/installed-deep.js index 4d212746cba89..20e001aaec751 100644 --- a/test/lib/utils/installed-deep.js +++ b/test/lib/utils/installed-deep.js @@ -1,6 +1,6 @@ const t = require('tap') const installedDeep = require('../../../lib/utils/installed-deep.js') -const mockNpm = require('../../../fixtures/mock-npm') +const mockNpm = require('../../fixtures/mock-npm') const fixture = { 'package.json': JSON.stringify({ diff --git a/test/lib/utils/installed-shallow.js b/test/lib/utils/installed-shallow.js index 43ccda4daea69..67b49292a64c7 100644 --- a/test/lib/utils/installed-shallow.js +++ b/test/lib/utils/installed-shallow.js @@ -1,6 +1,6 @@ const t = require('tap') const installed = require('../../../lib/utils/installed-shallow.js') -const mockNpm = require('../../../fixtures/mock-npm') +const mockNpm = require('../../fixtures/mock-npm') const mockShallow = async (t, config) => { const res = await mockNpm(t, { From 03634be50fd1159e42f73ef4aa71bf5f06eb5ada Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 15:12:25 -0700 Subject: [PATCH 17/42] fix: remove granular config timers --- workspaces/config/lib/index.js | 26 +++++++--------- workspaces/config/test/index.js | 54 +++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/workspaces/config/lib/index.js b/workspaces/config/lib/index.js index c3e73dc761c57..49c4f0a18115c 100644 --- a/workspaces/config/lib/index.js +++ b/workspaces/config/lib/index.js @@ -233,27 +233,24 @@ class Config { throw new Error('attempting to load npm config multiple times') } - const timeEnd = time.start('config:load') - // first load the defaults, which sets the global prefix - time.start('config:load:defaults', () => this.loadDefaults()) + this.loadDefaults() // next load the builtin config, as this sets new effective defaults - await time.start('config:load:builtin', () => this.loadBuiltinConfig()) + await this.loadBuiltinConfig() // cli and env are not async, and can set the prefix, relevant to project - time.start('config:load:cli', () => this.loadCLI()) - - time.start('config:load:env', () => this.loadEnv()) + this.loadCLI() + this.loadEnv() // next project config, which can affect userconfig location - await time.start('config:load:project', () => this.loadProjectConfig()) + await this.loadProjectConfig() // then user config, which can affect globalconfig location - await time.start('config:load:user', () => this.loadUserConfig()) + await this.loadUserConfig() // last but not least, global config file - await time.start('config:load:global', () => this.loadGlobalConfig()) + await this.loadGlobalConfig() // set this before calling setEnvs, so that we don't have to share // private attributes, as that module also does a bunch of get operations @@ -262,9 +259,7 @@ class Config { // set proper globalPrefix now that everything is loaded this.globalPrefix = this.get('prefix') - time.start('config:load:setEnvs', () => this.setEnvs()) - - timeEnd() + this.setEnvs() } loadDefaults () { @@ -590,7 +585,8 @@ class Config { async #loadFile (file, type) { // only catch the error from readFile, not from the loadObject call - await time.start(`config:load:file:${file}`, () => readFile(file, 'utf8').then( + log.silly(`config:load:file:${file}`) + await readFile(file, 'utf8').then( data => { const parsedConfig = ini.parse(data) if (type === 'project' && parsedConfig.prefix) { @@ -601,7 +597,7 @@ class Config { return this.#loadObject(parsedConfig, type, file) }, er => this.#loadObject(null, type, file, er) - )) + ) } loadBuiltinConfig () { diff --git a/workspaces/config/test/index.js b/workspaces/config/test/index.js index 9e9fac4f6dc34..e1c976e2e52d0 100644 --- a/workspaces/config/test/index.js +++ b/workspaces/config/test/index.js @@ -237,9 +237,10 @@ loglevel = yolo }) logs.length = 0 await config.load() - t.match(logs, [['verbose', 'config', 'error loading user config', { - message: 'weird error', - }]]) + t.match(logs.find(l => l[0] === 'verbose'), + ['verbose', 'config', 'error loading user config', { + message: 'weird error', + }]) logs.length = 0 }) @@ -375,7 +376,7 @@ loglevel = yolo // warn logs are emitted as a side effect of validate config.validate() - t.strictSame(logs, [ + t.strictSame(logs.filter(l => l[0] === 'warn'), [ ['warn', 'invalid config', 'registry="hello"', 'set in command line options'], ['warn', 'invalid config', 'Must be', 'full url with "http://"'], ['warn', 'invalid config', 'proxy="hello"', 'set in command line options'], @@ -392,8 +393,7 @@ loglevel = yolo ['warn', 'invalid config', 'prefix=true', 'set in command line options'], ['warn', 'invalid config', 'Must be', 'valid filesystem path'], ['warn', 'config', 'also', 'Please use --include=dev instead.'], - ['warn', 'invalid config', 'loglevel="yolo"', - `set in ${resolve(path, 'project/.npmrc')}`], + ['warn', 'invalid config', 'loglevel="yolo"', `set in ${resolve(path, 'project/.npmrc')}`], ['warn', 'invalid config', 'Must be one of:', ['silent', 'error', 'warn', 'notice', 'http', 'info', 'verbose', 'silly'].join(', '), ], @@ -570,7 +570,7 @@ loglevel = yolo all: config.get('all'), }) - t.strictSame(logs, [ + t.strictSame(logs.filter(l => l[0] === 'warn'), [ ['warn', 'invalid config', 'registry="hello"', 'set in command line options'], ['warn', 'invalid config', 'Must be', 'full url with "http://"'], ['warn', 'invalid config', 'proxy="hello"', 'set in command line options'], @@ -1183,8 +1183,9 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, path, 'localPrefix is the root') t.same(config.get('workspace'), [join(path, 'workspaces', 'one')], 'set the workspace') - t.equal(logs.length, 1, 'got one log message') - t.match(logs[0], ['info', /^found workspace root at/], 'logged info about workspace root') + const info = logs.filter(l => l[0] === 'info') + t.equal(info.length, 1, 'got one log message') + t.match(info[0], ['info', /^found workspace root at/], 'logged info about workspace root') }) t.test('finds other workspace parent', async (t) => { @@ -1204,8 +1205,9 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, path, 'localPrefix is the root') t.same(config.get('workspace'), ['../two'], 'kept the specified workspace') - t.equal(logs.length, 1, 'got one log message') - t.match(logs[0], ['info', /^found workspace root at/], 'logged info about workspace root') + const info = logs.filter(l => l[0] === 'info') + t.equal(info.length, 1, 'got one log message') + t.match(info[0], ['info', /^found workspace root at/], 'logged info about workspace root') }) t.test('warns when workspace has .npmrc', async (t) => { @@ -1225,9 +1227,10 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, path, 'localPrefix is the root') t.same(config.get('workspace'), [join(path, 'workspaces', 'three')], 'kept the workspace') - t.equal(logs.length, 2, 'got two log messages') - t.match(logs[0], ['warn', /^ignoring workspace config/], 'warned about ignored config') - t.match(logs[1], ['info', /^found workspace root at/], 'logged info about workspace root') + const filtered = logs.filter(l => l[0] === 'info' || l[0] === 'warn') + t.equal(filtered.length, 2, 'got two log messages') + t.match(filtered[0], ['warn', /^ignoring workspace config/], 'warned about ignored config') + t.match(filtered[1], ['info', /^found workspace root at/], 'logged info about workspace root') }) t.test('prefix skips auto detect', async (t) => { @@ -1247,7 +1250,8 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, join(path, 'workspaces', 'one'), 'localPrefix is the root') t.same(config.get('workspace'), [], 'did not set workspace') - t.equal(logs.length, 0, 'got no log messages') + const filtered = logs.filter(l => l[0] !== 'silly') + t.equal(filtered.length, 0, 'got no log messages') }) t.test('no-workspaces skips auto detect', async (t) => { @@ -1267,7 +1271,8 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, join(path, 'workspaces', 'one'), 'localPrefix is the root') t.same(config.get('workspace'), [], 'did not set workspace') - t.equal(logs.length, 0, 'got no log messages') + const filtered = logs.filter(l => l[0] !== 'silly') + t.equal(filtered.length, 0, 'got no log messages') }) t.test('global skips auto detect', async (t) => { @@ -1287,7 +1292,8 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, join(path, 'workspaces', 'one'), 'localPrefix is the root') t.same(config.get('workspace'), [], 'did not set workspace') - t.equal(logs.length, 0, 'got no log messages') + const filtered = logs.filter(l => l[0] !== 'silly') + t.equal(filtered.length, 0, 'got no log messages') }) t.test('location=global skips auto detect', async (t) => { @@ -1307,7 +1313,8 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, join(path, 'workspaces', 'one'), 'localPrefix is the root') t.same(config.get('workspace'), [], 'did not set workspace') - t.equal(logs.length, 0, 'got no log messages') + const filtered = logs.filter(l => l[0] !== 'silly') + t.equal(filtered.length, 0, 'got no log messages') }) t.test('excludeNpmCwd skips auto detect', async (t) => { @@ -1328,7 +1335,8 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, join(path, 'workspaces', 'one'), 'localPrefix is the root') t.same(config.get('workspace'), [], 'did not set workspace') - t.equal(logs.length, 0, 'got no log messages') + const filtered = logs.filter(l => l[0] !== 'silly') + t.equal(filtered.length, 0, 'got no log messages') }) t.test('does not error for invalid package.json', async (t) => { @@ -1354,8 +1362,9 @@ t.test('workspaces', async (t) => { await config.load() t.equal(config.localPrefix, path, 'localPrefix is the root') t.same(config.get('workspace'), [join(path, 'workspaces', 'one')], 'set the workspace') - t.equal(logs.length, 1, 'got one log message') - t.match(logs[0], ['info', /^found workspace root at/], 'logged info about workspace root') + const filtered = logs.filter(l => l[0] !== 'silly') + t.equal(filtered.length, 1, 'got one log message') + t.match(filtered[0], ['info', /^found workspace root at/], 'logged info about workspace root') }) }) @@ -1474,7 +1483,8 @@ t.test('catch project config prefix error', async t => { logs.length = 0 // config.load() triggers the error to be logged await config.load() - t.match(logs, [[ + const filtered = logs.filter(l => l[0] !== 'silly') + t.match(filtered, [[ 'error', 'config', `prefix cannot be changed from project config: ${path}`, ]], 'Expected error logged') }) From fc68547eb9b06a1a6a2a0feb7e422accec50230d Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 15:13:13 -0700 Subject: [PATCH 18/42] fix: remove some npm.load timers and exit earlier for --versions --- lib/cli/entry.js | 12 +- lib/npm.js | 103 ++++++--------- lib/utils/display.js | 32 ++++- lib/utils/log-file.js | 4 +- .../test/lib/cli/exit-handler.js.test.cjs | 66 ++++++++++ .../test/lib/utils/log-file.js.test.cjs | 119 +++++++++--------- test/lib/cli/entry.js | 16 ++- test/lib/{utils => cli}/exit-handler.js | 0 test/lib/npm.js | 16 +-- test/lib/utils/display.js | 9 +- 10 files changed, 208 insertions(+), 169 deletions(-) create mode 100644 tap-snapshots/test/lib/cli/exit-handler.js.test.cjs rename test/lib/{utils => cli}/exit-handler.js (100%) diff --git a/lib/cli/entry.js b/lib/cli/entry.js index 1c5f7e0dc1545..9b3e29ec336a6 100644 --- a/lib/cli/entry.js +++ b/lib/cli/entry.js @@ -40,20 +40,12 @@ module.exports = async (process, validateEngines) => { // Now actually fire up npm and run the command. // This is how to use npm programmatically: try { - await npm.load() + const { exec } = await npm.load() - // npm -v - if (npm.config.get('version', 'cli')) { - output.standard(npm.version) + if (!exec) { return exitHandler() } - // npm --versions - if (npm.config.get('versions', 'cli')) { - npm.argv = ['version'] - npm.config.set('usage', false, 'cli') - } - cmd = npm.argv.shift() if (!cmd) { output.standard(npm.usage) diff --git a/lib/npm.js b/lib/npm.js index d52f8bdc1c480..c801b33cf7adb 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -7,7 +7,7 @@ const usage = require('./utils/npm-usage.js') const LogFile = require('./utils/log-file.js') const Timers = require('./utils/timers.js') const Display = require('./utils/display.js') -const { log, time } = require('proc-log') +const { log, time, output } = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const pkg = require('../package.json') const { deref } = require('./utils/cmd-list.js') @@ -28,20 +28,14 @@ class Npm { } updateNotification = null - loadErr = null argv = [] #command = null #runId = new Date().toISOString().replace(/[.:]/g, '_') - #loadPromise = null #title = 'npm' #argvClean = [] #npmRoot = null - #chalk = null - #logChalk = null - #noColorChalk = null - #display = null #logFile = new LogFile() #timers = new Timers({ start: 'npm' }) @@ -107,13 +101,7 @@ class Npm { } async load () { - if (!this.#loadPromise) { - this.#loadPromise = time.start('npm:load', () => this.#load().catch((er) => { - this.loadErr = er - throw er - })) - } - return this.#loadPromise + return time.start('npm:load', () => this.#load().then(r => r || { exec: true })) } get loaded () { @@ -160,19 +148,24 @@ class Npm { await time.start('npm:load:configload', () => this.config.load()) - // get createSupportsColor from chalk directly if this lands - // https://github.com/chalk/chalk/pull/600 - const [{ Chalk }, { createSupportsColor }] = await Promise.all([ - import('chalk'), - import('supports-color'), - ]) - this.#noColorChalk = new Chalk({ level: 0 }) - // we get the chalk level based on a null stream meaning chalk will only use - // what it knows about the environment to get color support since we already - // determined in our definitions that we want to show colors. - const level = Math.max(createSupportsColor(null).level, 1) - this.#chalk = this.color ? new Chalk({ level }) : this.#noColorChalk - this.#logChalk = this.logColor ? new Chalk({ level }) : this.#noColorChalk + await this.#display.load({ + loglevel: this.config.get('loglevel'), + stdoutColor: this.color, + stderrColor: this.logColor, + timing: this.config.get('timing'), + unicode: this.config.get('unicode'), + progress: this.flatOptions.progress, + json: this.config.get('json'), + heading: this.config.get('heading'), + }) + process.env.COLOR = this.color ? '1' : '0' + + // npm -v + // return from here early so we dont create any caches/logfiles/timers etc + if (this.config.get('version', 'cli')) { + output.standard(this.version) + return { exec: false } + } // mkdir this separately since the logs dir can be set to // a different location. if this fails, then we don't have @@ -208,49 +201,29 @@ class Npm { log.verbose('argv', this.#argvClean.map(JSON.stringify).join(' ')) }) - time.start('npm:load:display', () => { - this.#display.load({ - loglevel: this.config.get('loglevel'), - // TODO: only pass in logColor and color and create chalk instances - // in display load method. Then remove chalk getters from npm and - // producers should emit chalk-templates (or something else). - stdoutChalk: this.#chalk, - stdoutColor: this.color, - stderrChalk: this.#logChalk, - stderrColor: this.logColor, - timing: this.config.get('timing'), - unicode: this.config.get('unicode'), - progress: this.flatOptions.progress, - json: this.config.get('json'), - heading: this.config.get('heading'), - }) - process.env.COLOR = this.color ? '1' : '0' + this.#logFile.load({ + path: this.logPath, + logsMax: this.config.get('logs-max'), }) - time.start('npm:load:logFile', () => { - this.#logFile.load({ - path: this.logPath, - logsMax: this.config.get('logs-max'), - }) - log.verbose('logfile', this.#logFile.files[0] || 'no logfile created') + this.#timers.load({ + path: this.config.get('timing') ? this.logPath : null, }) - time.start('npm:load:timers', () => - this.#timers.load({ - path: this.config.get('timing') ? this.logPath : null, - }) - ) - - time.start('npm:load:configScope', () => { - const configScope = this.config.get('scope') - if (configScope && !/^@/.test(configScope)) { - this.config.set('scope', `@${configScope}`, this.config.find('scope')) - } - }) + const configScope = this.config.get('scope') + if (configScope && !/^@/.test(configScope)) { + this.config.set('scope', `@${configScope}`, this.config.find('scope')) + } if (this.config.get('force')) { log.warn('using --force', 'Recommended protections disabled.') } + + // npm --versions + if (this.config.get('versions', 'cli')) { + this.argv = ['version'] + this.config.set('usage', false, 'cli') + } } get isShellout () { @@ -283,15 +256,15 @@ class Npm { } get noColorChalk () { - return this.#noColorChalk + return this.#display.chalk.noColor } get chalk () { - return this.#chalk + return this.#display.chalk.stdout } get logChalk () { - return this.#logChalk + return this.#display.chalk.stderr } get global () { diff --git a/lib/utils/display.js b/lib/utils/display.js index d9642fa374adf..1cc906083b5a9 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -121,6 +121,7 @@ class Display { } // colors + #noColorChalk #stdoutChalk #stdoutColor #stderrChalk @@ -161,25 +162,44 @@ class Display { } } - load ({ + get chalk () { + return { + noColor: this.#noColorChalk, + stdout: this.#stdoutChalk, + stderr: this.#stderrChalk, + } + } + + async load ({ heading, json, loglevel, progress, - stderrChalk, stderrColor, - stdoutChalk, stdoutColor, timing, unicode, }) { + // get createSupportsColor from chalk directly if this lands + // https://github.com/chalk/chalk/pull/600 + const [{ Chalk }, { createSupportsColor }] = await Promise.all([ + import('chalk'), + import('supports-color'), + ]) + // we get the chalk level based on a null stream meaning chalk will only use + // what it knows about the environment to get color support since we already + // determined in our definitions that we want to show colors. + const level = Math.max(createSupportsColor(null).level, 1) + + this.#noColorChalk = new Chalk({ level: 0 }) + this.#stdoutColor = stdoutColor - this.#stdoutChalk = stdoutChalk + this.#stdoutChalk = stdoutColor ? new Chalk({ level }) : this.#noColorChalk this.#stderrColor = stderrColor - this.#stderrChalk = stderrChalk + this.#stderrChalk = stderrColor ? new Chalk({ level }) : this.#noColorChalk - this.#logColors = COLOR_PALETTE({ chalk: stderrChalk }) + this.#logColors = COLOR_PALETTE({ chalk: this.#stderrChalk }) this.#levelIndex = LEVEL_OPTIONS[loglevel].index this.#timing = timing diff --git a/lib/utils/log-file.js b/lib/utils/log-file.js index a3792abf91951..80fd9d9636dbc 100644 --- a/lib/utils/log-file.js +++ b/lib/utils/log-file.js @@ -72,6 +72,8 @@ class LogFiles { } } + log.verbose('logfile', this.files[0] || 'no logfile created') + // Kickoff cleaning process, even if we aren't writing a logfile. // This is async but it will always ignore the current logfile // Return the result so it can be awaited in tests @@ -234,7 +236,7 @@ class LogFiles { } catch (e) { // Disable cleanup failure warnings when log writing is disabled if (this.#logsMax > 0) { - log.warn('logfile', 'error cleaning log files', e) + log.verbose('logfile', 'error cleaning log files', e) } } finally { log.silly('logfile', 'done cleaning log files') diff --git a/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs b/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs new file mode 100644 index 0000000000000..3a510647ece8e --- /dev/null +++ b/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs @@ -0,0 +1,66 @@ +/* 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/cli/exit-handler.js TAP handles unknown error with logs and debug file > debug file contents 1`] = ` +XX timing npm:load:whichnode Completed in {TIME}ms +XX silly config:load:file:{CWD}/npmrc +XX silly config:load:file:{CWD}/prefix/.npmrc +XX silly config:load:file:{CWD}/home/.npmrc +XX silly config:load:file:{CWD}/global/etc/npmrc +XX timing npm:load:configload Completed in {TIME}ms +XX timing npm:load:mkdirpcache Completed in {TIME}ms +XX timing npm:load:mkdirplogs Completed in {TIME}ms +XX verbose title npm +XX verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "silly" "--color" "false" "--timing" "true" +XX timing npm:load:setTitle Completed in {TIME}ms +XX verbose logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}- +XX verbose logfile {CWD}/cache/_logs/{DATE}-debug-0.log +XX timing npm:load Completed in {TIME}ms +XX verbose stack Error: Unknown error +XX verbose cwd {CWD}/prefix +XX verbose {OS} +XX verbose {NODE-VERSION} +XX verbose npm {NPM-VERSION} +XX error code ECODE +XX error ERR SUMMARY Unknown error +XX error ERR DETAIL Unknown error +XX verbose exit 1 +XX timing npm Completed in {TIME}ms +XX verbose code 1 +XX error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json +XX error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log +` + +exports[`test/lib/cli/exit-handler.js TAP handles unknown error with logs and debug file > logs 1`] = ` +timing npm:load:whichnode Completed in {TIME}ms +silly config:load:file:{CWD}/npmrc +silly config:load:file:{CWD}/prefix/.npmrc +silly config:load:file:{CWD}/home/.npmrc +silly config:load:file:{CWD}/global/etc/npmrc +timing npm:load:configload Completed in {TIME}ms +timing npm:load:mkdirpcache Completed in {TIME}ms +timing npm:load:mkdirplogs Completed in {TIME}ms +verbose title npm +verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "silly" "--color" "false" "--timing" "true" +timing npm:load:setTitle Completed in {TIME}ms +verbose logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}- +verbose logfile {CWD}/cache/_logs/{DATE}-debug-0.log +timing npm:load Completed in {TIME}ms +verbose stack Error: Unknown error +verbose cwd {CWD}/prefix +verbose {OS} +verbose {NODE-VERSION} +verbose npm {NPM-VERSION} +error code ECODE +error ERR SUMMARY Unknown error +error ERR DETAIL Unknown error +verbose exit 1 +timing npm Completed in {TIME}ms +verbose code 1 +error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json +error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log +` diff --git a/tap-snapshots/test/lib/utils/log-file.js.test.cjs b/tap-snapshots/test/lib/utils/log-file.js.test.cjs index 0a4af7cadf060..34002b8133e22 100644 --- a/tap-snapshots/test/lib/utils/log-file.js.test.cjs +++ b/tap-snapshots/test/lib/utils/log-file.js.test.cjs @@ -7,64 +7,65 @@ 'use strict' exports[`test/lib/utils/log-file.js TAP snapshot > must match snapshot 1`] = ` 0 verbose logfile logs-max:10 dir:{CWD}/{DATE}- -1 silly logfile done cleaning log files -2 error no prefix -3 error prefix with prefix -4 error prefix 1 2 3 -5 verbose { obj: { with: { many: [Object] } } } -6 verbose {"obj":{"with":{"many":{"props":1}}}} -7 verbose { -7 verbose "obj": { -7 verbose "with": { -7 verbose "many": { -7 verbose "props": 1 -7 verbose } -7 verbose } -7 verbose } -7 verbose } -8 verbose [ 'test', 'with', 'an', 'array' ] -9 verbose ["test","with","an","array"] -10 verbose [ -10 verbose "test", -10 verbose "with", -10 verbose "an", -10 verbose "array" -10 verbose ] -11 verbose [ 'test', [ 'with', [ 'an', [Array] ] ] ] -12 verbose ["test",["with",["an",["array"]]]] -13 verbose [ -13 verbose "test", -13 verbose [ -13 verbose "with", -13 verbose [ -13 verbose "an", -13 verbose [ -13 verbose "array" -13 verbose ] -13 verbose ] -13 verbose ] -13 verbose ] -14 error pre has many errors Error: message -14 error pre at stack trace line 0 -14 error pre at stack trace line 1 -14 error pre at stack trace line 2 -14 error pre at stack trace line 3 -14 error pre at stack trace line 4 -14 error pre at stack trace line 5 -14 error pre at stack trace line 6 -14 error pre at stack trace line 7 -14 error pre at stack trace line 8 -14 error pre at stack trace line 9 Error: message2 -14 error pre at stack trace line 0 -14 error pre at stack trace line 1 -14 error pre at stack trace line 2 -14 error pre at stack trace line 3 -14 error pre at stack trace line 4 -14 error pre at stack trace line 5 -14 error pre at stack trace line 6 -14 error pre at stack trace line 7 -14 error pre at stack trace line 8 -14 error pre at stack trace line 9 -15 error nostack [Error: message] +1 verbose logfile {CWD}/{DATE}-debug-0.log +2 silly logfile done cleaning log files +3 error no prefix +4 error prefix with prefix +5 error prefix 1 2 3 +6 verbose { obj: { with: { many: [Object] } } } +7 verbose {"obj":{"with":{"many":{"props":1}}}} +8 verbose { +8 verbose "obj": { +8 verbose "with": { +8 verbose "many": { +8 verbose "props": 1 +8 verbose } +8 verbose } +8 verbose } +8 verbose } +9 verbose [ 'test', 'with', 'an', 'array' ] +10 verbose ["test","with","an","array"] +11 verbose [ +11 verbose "test", +11 verbose "with", +11 verbose "an", +11 verbose "array" +11 verbose ] +12 verbose [ 'test', [ 'with', [ 'an', [Array] ] ] ] +13 verbose ["test",["with",["an",["array"]]]] +14 verbose [ +14 verbose "test", +14 verbose [ +14 verbose "with", +14 verbose [ +14 verbose "an", +14 verbose [ +14 verbose "array" +14 verbose ] +14 verbose ] +14 verbose ] +14 verbose ] +15 error pre has many errors Error: message +15 error pre at stack trace line 0 +15 error pre at stack trace line 1 +15 error pre at stack trace line 2 +15 error pre at stack trace line 3 +15 error pre at stack trace line 4 +15 error pre at stack trace line 5 +15 error pre at stack trace line 6 +15 error pre at stack trace line 7 +15 error pre at stack trace line 8 +15 error pre at stack trace line 9 Error: message2 +15 error pre at stack trace line 0 +15 error pre at stack trace line 1 +15 error pre at stack trace line 2 +15 error pre at stack trace line 3 +15 error pre at stack trace line 4 +15 error pre at stack trace line 5 +15 error pre at stack trace line 6 +15 error pre at stack trace line 7 +15 error pre at stack trace line 8 +15 error pre at stack trace line 9 +16 error nostack [Error: message] ` diff --git a/test/lib/cli/entry.js b/test/lib/cli/entry.js index 66a417e7d269a..feb6692704d2a 100644 --- a/test/lib/cli/entry.js +++ b/test/lib/cli/entry.js @@ -1,4 +1,5 @@ const t = require('tap') +const { dirname } = require('path') const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') const tmock = require('../../fixtures/tmock.js') const validateEngines = require('../../../lib/cli/validate-engines.js') @@ -29,20 +30,17 @@ const cliMock = async (t, opts) => { t.test('print the version, and treat npm_g as npm -g', async t => { const { logs, cli, Npm, outputs, exitHandlerCalled } = await cliMock(t, { - globals: { 'process.argv': ['node', 'npm_g', '-v'] }, + globals: { 'process.argv': ['node', 'npm_g', 'root'] }, }) await cli(process) - t.strictSame(process.argv, ['node', 'npm', '-g', '-v'], 'system process.argv was rewritten') + t.strictSame(process.argv, ['node', 'npm', '-g', 'root'], 'system process.argv was rewritten') t.strictSame(logs.verbose.byTitle('cli'), ['cli node npm']) - t.strictSame(logs.verbose.byTitle('title'), ['title npm']) - t.match(logs.verbose.byTitle('argv'), ['argv "--global" "--version"']) - t.strictSame(logs.info, [ - `using npm@${Npm.version}`, - `using node@${process.version}`, - ]) + t.strictSame(logs.verbose.byTitle('title'), ['title npm root']) + t.match(logs.verbose.byTitle('argv'), ['argv "--global" "root"']) + t.strictSame(logs.info, [`using npm@${Npm.version}`, `using node@${process.version}`]) t.equal(outputs.length, 1) - t.strictSame(outputs, [Npm.version]) + t.match(outputs[0], dirname(process.cwd())) t.strictSame(exitHandlerCalled(), []) }) diff --git a/test/lib/utils/exit-handler.js b/test/lib/cli/exit-handler.js similarity index 100% rename from test/lib/utils/exit-handler.js rename to test/lib/cli/exit-handler.js diff --git a/test/lib/npm.js b/test/lib/npm.js index bc9042365abea..915e63d0060bc 100644 --- a/test/lib/npm.js +++ b/test/lib/npm.js @@ -26,25 +26,13 @@ t.test('not yet loaded', async t => { t.test('npm.load', async t => { await t.test('load error', async t => { const { npm } = await loadMockNpm(t, { load: false }) - const loadError = new Error('load error') npm.config.load = async () => { - throw loadError + throw new Error('load error') } await t.rejects( () => npm.load(), /load error/ ) - - t.equal(npm.loadErr, loadError) - npm.config.load = async () => { - throw new Error('different error') - } - await t.rejects( - () => npm.load(), - /load error/, - 'loading again returns the original error' - ) - t.equal(npm.loadErr, loadError) }) await t.test('basic loading', async t => { @@ -416,7 +404,7 @@ t.test('timings', async t => { t.match(logs.timing.byTitle('npm'), [ /Completed in [0-9]+ms/, ]) - t.match(logs.silly, [ + t.match(logs.silly.byTitle('timing'), [ `timing Tried to end timer that doesn't exist: baz`, ]) t.notOk(npm.unfinishedTimers.has('foo'), 'foo timer is gone') diff --git a/test/lib/utils/display.js b/test/lib/utils/display.js index 31ea7bbed8add..b05690ebd8179 100644 --- a/test/lib/utils/display.js +++ b/test/lib/utils/display.js @@ -5,23 +5,22 @@ const mockGlobals = require('@npmcli/mock-globals') const { inspect } = require('util') const mockDisplay = async (t, { mocks, load } = {}) => { - const { Chalk } = await import('chalk') const { log, output } = require('proc-log') const logs = mockLogs() const Display = tmock(t, '{LIB}/utils/display', mocks) const display = new Display(logs.streams) - const displayLoad = (opts) => display.load({ + const displayLoad = async (opts) => display.load({ loglevel: 'silly', - stderrChalk: new Chalk({ level: 0 }), stderrColor: false, + stdoutColot: false, heading: 'npm', ...opts, }) if (load !== false) { - displayLoad(load) + await displayLoad(load) } t.teardown(() => display.off()) @@ -68,7 +67,7 @@ t.test('can buffer output when paused', async t => { output.standard('Message 2') t.strictSame(outputs, []) - displayLoad() + await displayLoad() t.strictSame(outputs, ['Message 1', 'Message 2']) }) From 08e0c0ed1ad7bc2f12b4f358eb3e6b18bdbca053 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 15:36:18 -0700 Subject: [PATCH 19/42] chore: move sigstore json files to fixtures dir --- .../sigstore/valid-sigstore-attestations.json | 0 .../sigstore/valid-tuf-js-attestations.json | 0 test/lib/commands/audit.js | 14 +++++++------- 3 files changed, 7 insertions(+), 7 deletions(-) rename test/{lib => }/fixtures/sigstore/valid-sigstore-attestations.json (100%) rename test/{lib => }/fixtures/sigstore/valid-tuf-js-attestations.json (100%) diff --git a/test/lib/fixtures/sigstore/valid-sigstore-attestations.json b/test/fixtures/sigstore/valid-sigstore-attestations.json similarity index 100% rename from test/lib/fixtures/sigstore/valid-sigstore-attestations.json rename to test/fixtures/sigstore/valid-sigstore-attestations.json diff --git a/test/lib/fixtures/sigstore/valid-tuf-js-attestations.json b/test/fixtures/sigstore/valid-tuf-js-attestations.json similarity index 100% rename from test/lib/fixtures/sigstore/valid-tuf-js-attestations.json rename to test/fixtures/sigstore/valid-tuf-js-attestations.json diff --git a/test/lib/commands/audit.js b/test/lib/commands/audit.js index 51abae13322cc..701d374ade985 100644 --- a/test/lib/commands/audit.js +++ b/test/lib/commands/audit.js @@ -1892,7 +1892,7 @@ t.test('audit signatures', async t => { const registry = new MockRegistry({ tap: t, registry: npm.config.get('registry') }) await manifestWithValidAttestations({ registry }) const fixture = fs.readFileSync( - path.join(__dirname, '..', 'fixtures', 'sigstore/valid-sigstore-attestations.json'), + path.resolve(__dirname, '../../fixtures/sigstore/valid-sigstore-attestations.json'), 'utf8' ) registry.nock.get('/-/npm/v1/attestations/sigstore@1.0.0').reply(200, fixture) @@ -1918,11 +1918,11 @@ t.test('audit signatures', async t => { await manifestWithValidAttestations({ registry }) await manifestWithMultipleValidAttestations({ registry }) const fixture1 = fs.readFileSync( - path.join(__dirname, '..', 'fixtures', 'sigstore/valid-sigstore-attestations.json'), + path.join(__dirname, '../../fixtures/sigstore/valid-sigstore-attestations.json'), 'utf8' ) const fixture2 = fs.readFileSync( - path.join(__dirname, '..', 'fixtures', 'sigstore/valid-tuf-js-attestations.json'), + path.join(__dirname, '../../fixtures/sigstore/valid-tuf-js-attestations.json'), 'utf8' ) registry.nock.get('/-/npm/v1/attestations/sigstore@1.0.0').reply(200, fixture1) @@ -1951,7 +1951,7 @@ t.test('audit signatures', async t => { const registry = new MockRegistry({ tap: t, registry: npm.config.get('registry') }) await manifestWithValidAttestations({ registry }) const fixture = fs.readFileSync( - path.join(__dirname, '..', 'fixtures', 'sigstore/valid-sigstore-attestations.json'), + path.join(__dirname, '../../fixtures/sigstore/valid-sigstore-attestations.json'), 'utf8' ) registry.nock.get('/-/npm/v1/attestations/sigstore@1.0.0').reply(200, fixture) @@ -1986,7 +1986,7 @@ t.test('audit signatures', async t => { const registry = new MockRegistry({ tap: t, registry: npm.config.get('registry') }) await manifestWithValidAttestations({ registry }) const fixture = fs.readFileSync( - path.join(__dirname, '..', 'fixtures', 'sigstore/valid-sigstore-attestations.json'), + path.join(__dirname, '../../fixtures/sigstore/valid-sigstore-attestations.json'), 'utf8' ) registry.nock.get('/-/npm/v1/attestations/sigstore@1.0.0').reply(200, fixture) @@ -2016,11 +2016,11 @@ t.test('audit signatures', async t => { await manifestWithValidAttestations({ registry }) await manifestWithMultipleValidAttestations({ registry }) const fixture1 = fs.readFileSync( - path.join(__dirname, '..', 'fixtures', 'sigstore/valid-sigstore-attestations.json'), + path.join(__dirname, '../../fixtures/sigstore/valid-sigstore-attestations.json'), 'utf8' ) const fixture2 = fs.readFileSync( - path.join(__dirname, '..', 'fixtures', 'sigstore/valid-tuf-js-attestations.json'), + path.join(__dirname, '../../fixtures/sigstore/valid-tuf-js-attestations.json'), 'utf8' ) registry.nock.get('/-/npm/v1/attestations/sigstore@1.0.0').reply(200, fixture1) From 7e04417d4b084043300d1cdd5b4dce8ea7184d9e Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 15:39:50 -0700 Subject: [PATCH 20/42] fix: rename base-cmd to match other commands --- lib/arborist-cmd.js | 3 +-- lib/{base-command.js => base-cmd.js} | 0 lib/commands/access.js | 2 +- lib/commands/adduser.js | 2 +- lib/commands/cache.js | 2 +- lib/commands/completion.js | 2 +- lib/commands/config.js | 2 +- lib/commands/deprecate.js | 2 +- lib/commands/diff.js | 2 +- lib/commands/dist-tag.js | 2 +- lib/commands/doctor.js | 2 +- lib/commands/edit.js | 2 +- lib/commands/exec.js | 2 +- lib/commands/explore.js | 2 +- lib/commands/get.js | 2 +- lib/commands/help-search.js | 2 +- lib/commands/help.js | 2 +- lib/commands/hook.js | 2 +- lib/commands/init.js | 2 +- lib/commands/login.js | 2 +- lib/commands/logout.js | 2 +- lib/commands/org.js | 2 +- lib/commands/owner.js | 2 +- lib/commands/pack.js | 2 +- lib/commands/ping.js | 2 +- lib/commands/pkg.js | 2 +- lib/commands/prefix.js | 2 +- lib/commands/profile.js | 2 +- lib/commands/publish.js | 2 +- lib/commands/query.js | 2 +- lib/commands/root.js | 2 +- lib/commands/run-script.js | 2 +- lib/commands/sbom.js | 2 +- lib/commands/search.js | 2 +- lib/commands/set.js | 2 +- lib/commands/shrinkwrap.js | 2 +- lib/commands/star.js | 2 +- lib/commands/stars.js | 2 +- lib/commands/team.js | 2 +- lib/commands/token.js | 2 +- lib/commands/unpublish.js | 2 +- lib/commands/version.js | 2 +- lib/commands/view.js | 2 +- lib/commands/whoami.js | 2 +- lib/lifecycle-cmd.js | 4 ++-- lib/package-url-cmd.js | 6 ++---- test/lib/load-all-commands.js | 2 +- 47 files changed, 48 insertions(+), 51 deletions(-) rename lib/{base-command.js => base-cmd.js} (100%) diff --git a/lib/arborist-cmd.js b/lib/arborist-cmd.js index d8cb25baf487e..9d247d02fa181 100644 --- a/lib/arborist-cmd.js +++ b/lib/arborist-cmd.js @@ -1,10 +1,9 @@ const { log } = require('proc-log') +const BaseCommand = require('./base-cmd.js') // This is the base for all commands whose execWorkspaces just gets // a list of workspace names and passes it on to new Arborist() to // be able to run a filtered Arborist.reify() at some point. - -const BaseCommand = require('./base-command.js') class ArboristCmd extends BaseCommand { get isArboristCmd () { return true diff --git a/lib/base-command.js b/lib/base-cmd.js similarity index 100% rename from lib/base-command.js rename to lib/base-cmd.js diff --git a/lib/commands/access.js b/lib/commands/access.js index 1d0161cadc91e..d35699e839109 100644 --- a/lib/commands/access.js +++ b/lib/commands/access.js @@ -5,7 +5,7 @@ const pkgJson = require('@npmcli/package-json') const localeCompare = require('@isaacs/string-locale-compare')('en') const otplease = require('../utils/otplease.js') const getIdentity = require('../utils/get-identity.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const commands = [ 'get', diff --git a/lib/commands/adduser.js b/lib/commands/adduser.js index d896272bf7ed5..5299ebaca41aa 100644 --- a/lib/commands/adduser.js +++ b/lib/commands/adduser.js @@ -1,7 +1,7 @@ const { log, output } = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class AddUser extends BaseCommand { static description = 'Add a registry user account' diff --git a/lib/commands/cache.js b/lib/commands/cache.js index 8e9b33b3d1a49..108c261ffe57d 100644 --- a/lib/commands/cache.js +++ b/lib/commands/cache.js @@ -3,7 +3,7 @@ const pacote = require('pacote') const fs = require('fs/promises') const { join } = require('path') const semver = require('semver') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const npa = require('npm-package-arg') const jsonParse = require('json-parse-even-better-errors') const localeCompare = require('@isaacs/string-locale-compare')('en') diff --git a/lib/commands/completion.js b/lib/commands/completion.js index 20ff3ea76e98b..a4cf1d77c5e3a 100644 --- a/lib/commands/completion.js +++ b/lib/commands/completion.js @@ -36,7 +36,7 @@ const Npm = require('../npm.js') const { definitions, shorthands } = require('@npmcli/config/lib/definitions') const { commands, aliases, deref } = require('../utils/cmd-list.js') const { isWindowsShell } = require('../utils/is-windows.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const fileExists = (file) => fs.stat(file).then(s => s.isFile()).catch(() => false) diff --git a/lib/commands/config.js b/lib/commands/config.js index 56315208e232f..7fb8476276937 100644 --- a/lib/commands/config.js +++ b/lib/commands/config.js @@ -6,7 +6,7 @@ const localeCompare = require('@isaacs/string-locale-compare')('en') const pkgJson = require('@npmcli/package-json') const { defaults, definitions } = require('@npmcli/config/lib/definitions') const { log, output } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') // These are the configs that we can nerf-dart. Not all of them currently even // *have* config definitions so we have to explicitly validate them here diff --git a/lib/commands/deprecate.js b/lib/commands/deprecate.js index bdce313923cff..58856538fe23f 100644 --- a/lib/commands/deprecate.js +++ b/lib/commands/deprecate.js @@ -4,7 +4,7 @@ const npa = require('npm-package-arg') const semver = require('semver') const getIdentity = require('../utils/get-identity.js') const libaccess = require('libnpmaccess') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Deprecate extends BaseCommand { static description = 'Deprecate a version of a package' diff --git a/lib/commands/diff.js b/lib/commands/diff.js index e188a38505867..6b5adf633acd7 100644 --- a/lib/commands/diff.js +++ b/lib/commands/diff.js @@ -6,7 +6,7 @@ const pacote = require('pacote') const pickManifest = require('npm-pick-manifest') const { log, output } = require('proc-log') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Diff extends BaseCommand { static description = 'The registry diff command' diff --git a/lib/commands/dist-tag.js b/lib/commands/dist-tag.js index 7eeeae571bc1c..e13f9ecf59c7f 100644 --- a/lib/commands/dist-tag.js +++ b/lib/commands/dist-tag.js @@ -4,7 +4,7 @@ const semver = require('semver') const { log, output } = require('proc-log') const otplease = require('../utils/otplease.js') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class DistTag extends BaseCommand { static description = 'Modify package distribution tags' diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index a9f24bd62e0f0..339dcf15f70f2 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -8,7 +8,7 @@ const semver = require('semver') const { log, output } = require('proc-log') const ping = require('../utils/ping.js') const { defaults } = require('@npmcli/config/lib/definitions') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const maskLabel = mask => { const label = [] diff --git a/lib/commands/edit.js b/lib/commands/edit.js index 12c9f759589e7..4110a1db55e82 100644 --- a/lib/commands/edit.js +++ b/lib/commands/edit.js @@ -2,7 +2,7 @@ const { resolve } = require('path') const { lstat } = require('fs/promises') const cp = require('child_process') const completion = require('../utils/installed-shallow.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const splitPackageNames = (path) => path.split('/') // combine scoped parts diff --git a/lib/commands/exec.js b/lib/commands/exec.js index f181bbb2ef6fe..9bb4b15e0c5a3 100644 --- a/lib/commands/exec.js +++ b/lib/commands/exec.js @@ -1,6 +1,6 @@ const { resolve } = require('path') const libexec = require('libnpmexec') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Exec extends BaseCommand { static description = 'Run a command from a local or remote npm package' diff --git a/lib/commands/explore.js b/lib/commands/explore.js index a4acc821eabf9..d9dd9a9931f56 100644 --- a/lib/commands/explore.js +++ b/lib/commands/explore.js @@ -3,7 +3,7 @@ const runScript = require('@npmcli/run-script') const { join, relative } = require('path') const { log, output } = require('proc-log') const completion = require('../utils/installed-shallow.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') // npm explore [@] // open a subshell to the package folder. diff --git a/lib/commands/get.js b/lib/commands/get.js index 43eca7389ec90..4191f2c973e7d 100644 --- a/lib/commands/get.js +++ b/lib/commands/get.js @@ -1,5 +1,5 @@ const Npm = require('../npm.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Get extends BaseCommand { static description = 'Get a value from the npm configuration' diff --git a/lib/commands/help-search.js b/lib/commands/help-search.js index 1bbff2df6cc16..67d381dd94565 100644 --- a/lib/commands/help-search.js +++ b/lib/commands/help-search.js @@ -2,7 +2,7 @@ const { readFile } = require('node:fs/promises') const path = require('node:path') const { glob } = require('glob') const { output } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const globify = pattern => pattern.split('\\').join('/') diff --git a/lib/commands/help.js b/lib/commands/help.js index fd84d3f8546ef..fb3fe664e017d 100644 --- a/lib/commands/help.js +++ b/lib/commands/help.js @@ -5,7 +5,7 @@ const { glob } = require('glob') const { output } = require('proc-log') const localeCompare = require('@isaacs/string-locale-compare')('en') const { deref } = require('../utils/cmd-list.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const globify = pattern => pattern.split('\\').join('/') diff --git a/lib/commands/hook.js b/lib/commands/hook.js index 557d04e7a035a..3b91ff539081a 100644 --- a/lib/commands/hook.js +++ b/lib/commands/hook.js @@ -2,7 +2,7 @@ const hookApi = require('libnpmhook') const otplease = require('../utils/otplease.js') const relativeDate = require('tiny-relative-date') const { output } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Hook extends BaseCommand { static description = 'Manage registry hooks' diff --git a/lib/commands/init.js b/lib/commands/init.js index cee56e7b91ba5..1847e19a9560f 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -8,7 +8,7 @@ const mapWorkspaces = require('@npmcli/map-workspaces') const PackageJson = require('@npmcli/package-json') const { log, output } = require('proc-log') const updateWorkspaces = require('../utils/update-workspaces.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const posixPath = p => p.split('\\').join('/') diff --git a/lib/commands/login.js b/lib/commands/login.js index 0801af9726f78..fa82ecaa2c207 100644 --- a/lib/commands/login.js +++ b/lib/commands/login.js @@ -1,7 +1,7 @@ const { log, output } = require('proc-log') const { redactLog: replaceInfo } = require('@npmcli/redact') const auth = require('../utils/auth.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Login extends BaseCommand { static description = 'Login to a registry user account' diff --git a/lib/commands/logout.js b/lib/commands/logout.js index 63a8154cd3fdf..39b4b176bf966 100644 --- a/lib/commands/logout.js +++ b/lib/commands/logout.js @@ -1,7 +1,7 @@ const npmFetch = require('npm-registry-fetch') const { getAuth } = npmFetch const { log } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Logout extends BaseCommand { static description = 'Log out of the registry' diff --git a/lib/commands/org.js b/lib/commands/org.js index f06c537d3f3f7..af67547a643db 100644 --- a/lib/commands/org.js +++ b/lib/commands/org.js @@ -1,6 +1,6 @@ const liborg = require('libnpmorg') const otplease = require('../utils/otplease.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const { output } = require('proc-log') class Org extends BaseCommand { diff --git a/lib/commands/owner.js b/lib/commands/owner.js index cfd40df2151e6..188065583198d 100644 --- a/lib/commands/owner.js +++ b/lib/commands/owner.js @@ -4,7 +4,7 @@ const pacote = require('pacote') const { log, output } = require('proc-log') const otplease = require('../utils/otplease.js') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const { redact } = require('@npmcli/redact') const readJson = async (path) => { diff --git a/lib/commands/pack.js b/lib/commands/pack.js index e679377fa7970..f64a21dcc0d9d 100644 --- a/lib/commands/pack.js +++ b/lib/commands/pack.js @@ -3,7 +3,7 @@ const libpack = require('libnpmpack') const npa = require('npm-package-arg') const { log, output } = require('proc-log') const { getContents, logTar } = require('../utils/tar.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Pack extends BaseCommand { static description = 'Create a tarball from a package' diff --git a/lib/commands/ping.js b/lib/commands/ping.js index 2d8f6f91a9111..8ade46ac8f82a 100644 --- a/lib/commands/ping.js +++ b/lib/commands/ping.js @@ -1,7 +1,7 @@ const { redact } = require('@npmcli/redact') const { log, output } = require('proc-log') const pingUtil = require('../utils/ping.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Ping extends BaseCommand { static description = 'Ping npm registry' diff --git a/lib/commands/pkg.js b/lib/commands/pkg.js index 26e60fec48786..62553b15103e3 100644 --- a/lib/commands/pkg.js +++ b/lib/commands/pkg.js @@ -1,6 +1,6 @@ const { output } = require('proc-log') const PackageJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const Queryable = require('../utils/queryable.js') class Pkg extends BaseCommand { diff --git a/lib/commands/prefix.js b/lib/commands/prefix.js index edd5595d09b41..d1f56cb190bd7 100644 --- a/lib/commands/prefix.js +++ b/lib/commands/prefix.js @@ -1,5 +1,5 @@ const { output } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Prefix extends BaseCommand { static description = 'Display prefix' diff --git a/lib/commands/profile.js b/lib/commands/profile.js index a0676e47889af..66bb3d118e6b7 100644 --- a/lib/commands/profile.js +++ b/lib/commands/profile.js @@ -5,7 +5,7 @@ const npmProfile = require('npm-profile') const qrcodeTerminal = require('qrcode-terminal') const otplease = require('../utils/otplease.js') const readUserInfo = require('../utils/read-user-info.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const qrcode = url => new Promise((resolve) => qrcodeTerminal.generate(url, resolve)) diff --git a/lib/commands/publish.js b/lib/commands/publish.js index f174d338b6392..fba7b7a120953 100644 --- a/lib/commands/publish.js +++ b/lib/commands/publish.js @@ -15,7 +15,7 @@ const { getContents, logTar } = require('../utils/tar.js') // change that ought to get a RFC written on it. const { flatten } = require('@npmcli/config/lib/definitions') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Publish extends BaseCommand { static description = 'Publish a package' diff --git a/lib/commands/query.js b/lib/commands/query.js index 1e9dee4ef1fda..fe84469b88fe0 100644 --- a/lib/commands/query.js +++ b/lib/commands/query.js @@ -1,5 +1,5 @@ const { resolve } = require('node:path') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const { log, output } = require('proc-log') class QuerySelectorItem { diff --git a/lib/commands/root.js b/lib/commands/root.js index f7c330a004169..180f4c4ed0720 100644 --- a/lib/commands/root.js +++ b/lib/commands/root.js @@ -1,5 +1,5 @@ const { output } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Root extends BaseCommand { static description = 'Display npm root' diff --git a/lib/commands/run-script.js b/lib/commands/run-script.js index f048996e66354..0bf517f77efb4 100644 --- a/lib/commands/run-script.js +++ b/lib/commands/run-script.js @@ -1,6 +1,6 @@ const { log, output } = require('proc-log') const pkgJson = require('@npmcli/package-json') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class RunScript extends BaseCommand { static description = 'Run arbitrary package scripts' diff --git a/lib/commands/sbom.js b/lib/commands/sbom.js index 4ee21ec1954fd..ff7377581dfa5 100644 --- a/lib/commands/sbom.js +++ b/lib/commands/sbom.js @@ -1,5 +1,5 @@ const localeCompare = require('@isaacs/string-locale-compare')('en') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const { log, output } = require('proc-log') const { cyclonedxOutput } = require('../utils/sbom-cyclonedx.js') const { spdxOutput } = require('../utils/sbom-spdx.js') diff --git a/lib/commands/search.js b/lib/commands/search.js index cffc4cdacc846..93005398480d1 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -2,8 +2,8 @@ const Pipeline = require('minipass-pipeline') const libSearch = require('libnpmsearch') const { log, output } = require('proc-log') const formatSearchStream = require('../utils/format-search-stream.js') +const BaseCommand = require('../base-cmd.js') -const BaseCommand = require('../base-command.js') class Search extends BaseCommand { static description = 'Search for packages' static name = 'search' diff --git a/lib/commands/set.js b/lib/commands/set.js index 509da1956bf1f..2e61762ba9dcd 100644 --- a/lib/commands/set.js +++ b/lib/commands/set.js @@ -1,5 +1,5 @@ const Npm = require('../npm.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Set extends BaseCommand { static description = 'Set a value in the npm configuration' diff --git a/lib/commands/shrinkwrap.js b/lib/commands/shrinkwrap.js index 008244e9760f3..d7866bdb91dce 100644 --- a/lib/commands/shrinkwrap.js +++ b/lib/commands/shrinkwrap.js @@ -1,7 +1,7 @@ const { resolve, basename } = require('path') const { unlink } = require('fs/promises') const { log } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Shrinkwrap extends BaseCommand { static description = 'Lock down dependency versions for publication' diff --git a/lib/commands/star.js b/lib/commands/star.js index fbf81e64bf21d..1b76955810c72 100644 --- a/lib/commands/star.js +++ b/lib/commands/star.js @@ -2,7 +2,7 @@ const fetch = require('npm-registry-fetch') const npa = require('npm-package-arg') const { log, output } = require('proc-log') const getIdentity = require('../utils/get-identity') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Star extends BaseCommand { static description = 'Mark your favorite packages' diff --git a/lib/commands/stars.js b/lib/commands/stars.js index 628b22fdb8808..1059569979daf 100644 --- a/lib/commands/stars.js +++ b/lib/commands/stars.js @@ -1,7 +1,7 @@ const fetch = require('npm-registry-fetch') const { log, output } = require('proc-log') const getIdentity = require('../utils/get-identity.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Stars extends BaseCommand { static description = 'View packages marked as favorites' diff --git a/lib/commands/team.js b/lib/commands/team.js index f7bada28a611e..22af61863851a 100644 --- a/lib/commands/team.js +++ b/lib/commands/team.js @@ -3,7 +3,7 @@ const libteam = require('libnpmteam') const { output } = require('proc-log') const otplease = require('../utils/otplease.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Team extends BaseCommand { static description = 'Manage organization teams and team memberships' static name = 'team' diff --git a/lib/commands/token.js b/lib/commands/token.js index 4429a20319f7e..aa9bd0fce24f8 100644 --- a/lib/commands/token.js +++ b/lib/commands/token.js @@ -2,7 +2,7 @@ const { log, output } = require('proc-log') const profile = require('npm-profile') const otplease = require('../utils/otplease.js') const readUserInfo = require('../utils/read-user-info.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Token extends BaseCommand { static description = 'Manage your authentication tokens' diff --git a/lib/commands/unpublish.js b/lib/commands/unpublish.js index e8b7de8395ea9..47a5db8206244 100644 --- a/lib/commands/unpublish.js +++ b/lib/commands/unpublish.js @@ -7,7 +7,7 @@ const pkgJson = require('@npmcli/package-json') const { flatten } = require('@npmcli/config/lib/definitions') const getIdentity = require('../utils/get-identity.js') const otplease = require('../utils/otplease.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const LAST_REMAINING_VERSION_ERROR = 'Refusing to delete the last version of the package. ' + 'It will block from republishing a new version for 24 hours.\n' + diff --git a/lib/commands/version.js b/lib/commands/version.js index 4d7b971fa6fbf..549ba9b9f9c77 100644 --- a/lib/commands/version.js +++ b/lib/commands/version.js @@ -1,7 +1,7 @@ const { resolve } = require('node:path') const { readFile } = require('node:fs/promises') const { output } = require('proc-log') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Version extends BaseCommand { static description = 'Bump a package version' diff --git a/lib/commands/view.js b/lib/commands/view.js index 9c8630bef154e..c0d5bf552eee0 100644 --- a/lib/commands/view.js +++ b/lib/commands/view.js @@ -10,7 +10,7 @@ const semver = require('semver') const { inspect } = require('util') const { packument } = require('pacote') const Queryable = require('../utils/queryable.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') const readJson = async file => jsonParse(await readFile(file, 'utf8')) diff --git a/lib/commands/whoami.js b/lib/commands/whoami.js index 03d7bb24991cf..df749e9db7e91 100644 --- a/lib/commands/whoami.js +++ b/lib/commands/whoami.js @@ -1,6 +1,6 @@ const { output } = require('proc-log') const getIdentity = require('../utils/get-identity.js') -const BaseCommand = require('../base-command.js') +const BaseCommand = require('../base-cmd.js') class Whoami extends BaseCommand { static description = 'Display npm username' diff --git a/lib/lifecycle-cmd.js b/lib/lifecycle-cmd.js index 26e04b12af272..a509a9380f668 100644 --- a/lib/lifecycle-cmd.js +++ b/lib/lifecycle-cmd.js @@ -1,7 +1,7 @@ +const BaseCommand = require('./base-cmd.js') + // The implementation of commands that are just "run a script" // restart, start, stop, test - -const BaseCommand = require('./base-command.js') class LifecycleCmd extends BaseCommand { static usage = ['[-- ]'] static isShellout = true diff --git a/lib/package-url-cmd.js b/lib/package-url-cmd.js index 5ab7cb87a2cd3..bcefd17af4492 100644 --- a/lib/package-url-cmd.js +++ b/lib/package-url-cmd.js @@ -1,11 +1,9 @@ -// Base command for opening urls from a package manifest (bugs, docs, repo) - const pacote = require('pacote') - const openUrl = require('./utils/open-url.js') const { log } = require('proc-log') +const BaseCommand = require('./base-cmd.js') -const BaseCommand = require('./base-command.js') +// Base command for opening urls from a package manifest (bugs, docs, repo) class PackageUrlCommand extends BaseCommand { static params = [ 'browser', diff --git a/test/lib/load-all-commands.js b/test/lib/load-all-commands.js index 9fa6995cfb1ad..c00da37eff3fc 100644 --- a/test/lib/load-all-commands.js +++ b/test/lib/load-all-commands.js @@ -6,7 +6,7 @@ const t = require('tap') const util = require('util') const { load: loadMockNpm } = require('../fixtures/mock-npm.js') const { commands } = require('../../lib/utils/cmd-list.js') -const BaseCommand = require('../../lib/base-command.js') +const BaseCommand = require('../../lib/base-cmd.js') const isAsyncFn = (v) => typeof v === 'function' && /^\[AsyncFunction:/.test(util.inspect(v)) From 25384388e01d1c9d6c4cae4a49149407b0024176 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 16:04:58 -0700 Subject: [PATCH 21/42] fix: dont write timing logs to file unless requested --- lib/npm.js | 1 + lib/utils/log-file.js | 42 +++++++++++++++++++++++--------------- test/lib/utils/log-file.js | 2 ++ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/npm.js b/lib/npm.js index c801b33cf7adb..fcccdbf7381a0 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -204,6 +204,7 @@ class Npm { this.#logFile.load({ path: this.logPath, logsMax: this.config.get('logs-max'), + timing: this.config.get('timing'), }) this.#timers.load({ diff --git a/lib/utils/log-file.js b/lib/utils/log-file.js index 80fd9d9636dbc..09e3873f2dce6 100644 --- a/lib/utils/log-file.js +++ b/lib/utils/log-file.js @@ -1,6 +1,5 @@ const os = require('os') const { join, dirname, basename } = require('path') -const { Minipass } = require('minipass') const fsMiniPass = require('fs-minipass') const fs = require('fs/promises') const { log } = require('proc-log') @@ -9,9 +8,9 @@ const { formatWithOptions } = require('./format') const padZero = (n, length) => n.toString().padStart(length.toString().length, '0') class LogFiles { - // Default to a plain minipass stream so we can buffer + // Default to an array so we can buffer // initial writes before we know the cache location - #logStream = null + #logStream = [] // We cap log files at a certain number of log events per file. // Note that each log event can write more than one line to the @@ -29,6 +28,7 @@ class LogFiles { #path = null #logsMax = null #files = [] + #timing = false constructor ({ maxLogsPerFile = 50_000, @@ -40,7 +40,6 @@ class LogFiles { } on () { - this.#logStream = new Minipass() process.on('log', this.#logHandler) } @@ -49,11 +48,12 @@ class LogFiles { this.#endStream() } - load ({ path, logsMax = Infinity } = {}) { + load ({ path, logsMax = Infinity, timing } = {}) { // dir is user configurable and is required to exist so // this can error if the dir is missing or not configured correctly this.#path = path this.#logsMax = logsMax + this.#timing = timing // Log stream has already ended if (!this.#logStream) { @@ -62,13 +62,19 @@ class LogFiles { log.verbose('logfile', `logs-max:${logsMax} dir:${this.#path}`) - // Pipe our initial stream to our new file stream and + // Write the contents of our array buffer to our new file stream and // set that as the new log logstream for future writes // if logs max is 0 then the user does not want a log file if (this.#logsMax > 0) { const initialFile = this.#openLogFile() if (initialFile) { - this.#logStream = this.#logStream.pipe(initialFile) + for (const item of this.#logStream) { + const formatted = this.#formatLogItem(...item) + if (formatted !== null) { + initialFile.write(formatted) + } + } + this.#logStream = initialFile } } @@ -80,20 +86,16 @@ class LogFiles { return this.#cleanLogs() } - log (...args) { - this.#logHandler(...args) - } - get files () { return this.#files } get #isBuffered () { - return this.#logStream instanceof Minipass + return Array.isArray(this.#logStream) } #endStream (output) { - if (this.#logStream) { + if (this.#logStream && !this.#isBuffered) { this.#logStream.end(output) this.#logStream = null } @@ -111,12 +113,15 @@ class LogFiles { return } - const logOutput = this.#formatLogItem(level, ...args) - if (this.#isBuffered) { // Cant do anything but buffer the output if we dont // have a file stream yet - this.#logStream.write(logOutput) + this.#logStream.push([level, ...args]) + return + } + + const logOutput = this.#formatLogItem(level, ...args) + if (logOutput === null) { return } @@ -137,6 +142,11 @@ class LogFiles { } #formatLogItem (level, title, ...args) { + // Only right timing logs to logfile if explicitly requests + if (level === log.KEYS.timing && !this.#timing) { + return null + } + this.#fileLogCount += 1 const prefix = [this.#totalLogCount++, level, title || null] return formatWithOptions({ prefix, eol: os.EOL, colors: false }, ...args) diff --git a/test/lib/utils/log-file.js b/test/lib/utils/log-file.js index f34dda8f52433..a4cf8a256a634 100644 --- a/test/lib/utils/log-file.js +++ b/test/lib/utils/log-file.js @@ -46,6 +46,8 @@ const loadLogFile = async (t, { buffer = [], mocks, testdir = {}, ...options } = const MockLogFile = tmock(t, '{LIB}/utils/log-file.js', mocks) const logFile = new MockLogFile(Object.keys(options).length ? options : undefined) + // Create a fake public method since there is not one on logFile anymore + logFile.log = (...b) => process.emit('log', ...b) buffer.forEach((b) => logFile.log(...b)) const id = getId() From 7ca6d8490b675c9d4c402ae8e41c9afd5871aa35 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 16:39:27 -0700 Subject: [PATCH 22/42] fix: use proc-log META for flush and force --- lib/cli/exit-handler.js | 15 ++--- lib/npm.js | 10 --- lib/utils/display.js | 122 ++++++++++++++--------------------- lib/utils/error-message.js | 8 +-- test/fixtures/mock-npm.js | 4 +- test/lib/cli/exit-handler.js | 8 +-- 6 files changed, 64 insertions(+), 103 deletions(-) diff --git a/lib/cli/exit-handler.js b/lib/cli/exit-handler.js index 6dc44de1f003a..8d1d5a3e0ef34 100644 --- a/lib/cli/exit-handler.js +++ b/lib/cli/exit-handler.js @@ -1,4 +1,4 @@ -const { log, output, time } = require('proc-log') +const { log, output, time, META } = require('proc-log') const errorMessage = require('../utils/error-message.js') const { redactLog: replaceInfo } = require('@npmcli/redact') @@ -32,9 +32,10 @@ process.on('exit', code => { log.error('', 'This is an error with npm itself. Please report this error at:') log.error('', ' ') - // This gets logged regardless of silent mode - // eslint-disable-next-line no-console - console.error('') + if (!npm || !npm.silent) { + // eslint-disable-next-line no-console + console.error('') + } showLogFileError = true } @@ -120,8 +121,7 @@ const exitHandler = err => { // only show the notification if it finished. if (typeof npm.updateNotification === 'string') { - // TODO: use proc-log to send `force: true` along with event - npm.forceLog('notice', '', npm.updateNotification) + log.notice('', npm.updateNotification, { [META]: true, force: true }) } let exitCode = process.exitCode || 0 @@ -200,8 +200,7 @@ const exitHandler = err => { } if (hasLoadedNpm) { - // TODO: use proc-log.output.flush() once it exists - npm.flushOutput(jsonError) + output.flush({ [META]: true, jsonError }) } log.verbose('exit', exitCode || 0) diff --git a/lib/npm.js b/lib/npm.js index fcccdbf7381a0..e0f3f40a72874 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -379,16 +379,6 @@ class Npm { get usage () { return usage(this) } - - // TODO: move to proc-log and remove - forceLog (...args) { - this.#display.forceLog(...args) - } - - // TODO: move to proc-log and remove - flushOutput (jsonError) { - this.#display.flushOutput(jsonError) - } } module.exports = Npm diff --git a/lib/utils/display.js b/lib/utils/display.js index 1cc906083b5a9..32399a7bf5329 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -1,5 +1,5 @@ const proggy = require('proggy') -const { log, output } = require('proc-log') +const { log, output, META } = require('proc-log') const { explain } = require('./explain-eresolve.js') const { formatWithOptions } = require('./format') @@ -32,17 +32,6 @@ const COLOR_PALETTE = ({ chalk: c }) => ({ silly: c.blue.dim, }) -const LOG_LEVELS = log.LEVELS.reduce((acc, key) => { - acc[key] = key - return acc -}, {}) - -// TODO: move flush to proc-log -const OUTPUT_LEVELS = ['flush', ...output.LEVELS].reduce((acc, key) => { - acc[key] = key - return acc -}, {}) - const LEVEL_OPTIONS = { silent: { index: 0, @@ -76,7 +65,7 @@ const LEVEL_OPTIONS = { const LEVEL_METHODS = { ...LEVEL_OPTIONS, - [LOG_LEVELS.timing]: { + [log.KEYS.timing]: { show: ({ timing, index }) => !!timing && index !== 0, }, } @@ -102,11 +91,13 @@ const setBlocking = (stream) => { return stream } -const getLevel = (stringOrLevelObject) => { - if (typeof stringOrLevelObject === 'string') { - return { level: stringOrLevelObject } +const withMeta = (handler) => (level, ...args) => { + let meta = {} + const last = args.at(-1) + if (last && typeof last === 'object' && Object.hasOwn(last, META)) { + meta = args.pop() } - return stringOrLevelObject + return handler(level, meta, ...args) } class Display { @@ -136,6 +127,7 @@ class Display { #timing #json #heading + #silent // display streams #stdout @@ -205,19 +197,11 @@ class Display { this.#timing = timing this.#json = json this.#heading = heading - - // In silent mode we remove all the handlers - if (this.#levelIndex <= 0) { - this.off() - return - } + this.#silent = this.#levelIndex <= 0 // Emit resume event on the logs which will flush output log.resume() - - // TODO: this should be a proc-log method `proc-log.output.flush`? - this.#outputHandler(OUTPUT_LEVELS.flush) - + output.flush() this.#startProgress({ progress, unicode }) } @@ -236,107 +220,98 @@ class Display { // Arrow function assigned to a private class field so it can be passed // directly as a listener and still reference "this" - #logHandler = (...args) => { - if (args[0] === LOG_LEVELS.resume) { + #logHandler = withMeta((level, meta, ...args) => { + if (level === log.KEYS.resume) { this.#logState.buffering = false this.#logState.buffer.forEach((item) => this.#tryWriteLog(...item)) this.#logState.buffer.length = 0 return } - if (args[0] === LOG_LEVELS.pause) { + if (level === log.KEYS.pause) { this.#logState.buffering = true return } if (this.#logState.buffering) { - this.#logState.buffer.push(args) + this.#logState.buffer.push([level, meta, ...args]) return } - this.#tryWriteLog(...args) - } + this.#tryWriteLog(level, meta, ...args) + }) // Arrow function assigned to a private class field so it can be passed // directly as a listener and still reference "this" - #outputHandler = (...args) => { - if (args[0] === OUTPUT_LEVELS.flush) { + #outputHandler = withMeta((level, meta, ...args) => { + if (level === output.KEYS.flush) { this.#outputState.buffering = false - if (args[1] && this.#json) { + + if (meta.jsonError && this.#json) { const json = {} - for (const [, item] of this.#outputState.buffer) { - Object.assign(json, tryJsonParse(item)) + for (const item of this.#outputState.buffer) { + // index 2 skips the level and meta + Object.assign(json, tryJsonParse(item[2])) } - this.#writeOutput('standard', JSON.stringify({ ...json, ...args[1] }, null, 2)) + this.#writeOutput( + output.KEYS.standard, + meta, + JSON.stringify({ ...json, error: meta.jsonError }, null, 2) + ) } else { this.#outputState.buffer.forEach((item) => this.#writeOutput(...item)) } + this.#outputState.buffer.length = 0 return } - if (args[0] === OUTPUT_LEVELS.buffer) { - this.#outputState.buffer.push(['standard', ...args.slice(1)]) + if (level === output.KEYS.buffer) { + this.#outputState.buffer.push([output.KEYS.standard, meta, ...args]) return } if (this.#outputState.buffering) { - this.#outputState.buffer.push(args) + this.#outputState.buffer.push([level, meta, ...args]) return } - this.#writeOutput(...args) - } + this.#writeOutput(level, meta, ...args) + }) // OUTPUT - #writeOutput (...args) { - const { level } = getLevel(args.shift()) - - if (level === OUTPUT_LEVELS.standard) { + #writeOutput (level, meta, ...args) { + if (level === output.KEYS.standard) { this.#stdoutWrite({}, ...args) return } - if (level === OUTPUT_LEVELS.error) { + if (level === output.KEYS.error) { this.#stderrWrite({}, ...args) } } - // TODO: move this to proc-log and remove this public method - flushOutput (jsonError) { - this.#outputHandler(OUTPUT_LEVELS.flush, jsonError) - } - // LOGS - // TODO: make proc-log able to send signal data like `force` - // when that happens, remove this public method - forceLog (level, ...args) { - // This will show the log regardless of the current loglevel except when silent - if (this.#levelIndex !== 0) { - this.#logHandler({ level, force: true }, ...args) - } - } - - #tryWriteLog (...args) { + #tryWriteLog (level, meta, ...args) { try { // Also (and this is a really inexcusable kludge), we patch the // log.warn() method so that when we see a peerDep override // explanation from Arborist, we can replace the object with a // highly abbreviated explanation of what's being overridden. // TODO: this could probably be moved to arborist now that display is refactored - const [level, heading, message, expl] = args - if (level === LOG_LEVELS.warn && heading === 'ERESOLVE' && expl && typeof expl === 'object') { - this.#writeLog(level, heading, message) - this.#writeLog(level, '', explain(expl, this.#stderrChalk, 2)) + const [heading, message, expl] = args + if (level === log.KEYS.warn && heading === 'ERESOLVE' && expl && typeof expl === 'object') { + this.#writeLog(level, meta, heading, message) + this.#writeLog(level, meta, '', explain(expl, this.#stderrChalk, 2)) return } - this.#writeLog(...args) + this.#writeLog(level, meta, ...args) } catch (ex) { try { // if it crashed once, it might again! - this.#writeLog(LOG_LEVELS.verbose, null, `attempt to log crashed`, ...args, ex) + this.#writeLog(log.KEYS.verbose, meta, '', `attempt to log crashed`, ...args, ex) } catch (ex2) { // This happens if the object has an inspect method that crashes so just console.error // with the errors but don't do anything else that might error again. @@ -346,11 +321,10 @@ class Display { } } - #writeLog (...args) { - const { level, force = false } = getLevel(args.shift()) - + #writeLog (level, meta, ...args) { const levelOpts = LEVEL_METHODS[level] const show = levelOpts.show ?? (({ index }) => levelOpts.index <= index) + const force = meta.force && !this.#silent if (force || show({ index: this.#levelIndex, timing: this.#timing })) { // this mutates the array so we can pass args directly to format later @@ -369,7 +343,7 @@ class Display { // PROGRESS #startProgress ({ progress, unicode }) { - if (!progress) { + if (!progress || this.#silent) { return } this.#progress = proggy.createClient({ normalize: true }) diff --git a/lib/utils/error-message.js b/lib/utils/error-message.js index 5d25734f08ad1..969e56636dfe8 100644 --- a/lib/utils/error-message.js +++ b/lib/utils/error-message.js @@ -8,11 +8,9 @@ const messageText = msg => msg.map(line => line.slice(1).join(' ')).join('\n') const jsonError = (er, npm, { summary, detail }) => { if (npm?.config.loaded && npm.config.get('json')) { return { - error: { - code: er.code, - summary: messageText(summary), - detail: messageText(detail), - }, + code: er.code, + summary: messageText(summary), + detail: messageText(detail), } } } diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index 466b9b2a0ba46..d1879da7f845e 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -2,6 +2,7 @@ const os = require('os') const fs = require('fs').promises const path = require('path') const tap = require('tap') +const { output, META } = require('proc-log') const errorMessage = require('../../lib/utils/error-message') const mockLogs = require('./mock-logs.js') const mockGlobals = require('@npmcli/mock-globals') @@ -79,7 +80,8 @@ const getMockNpm = async (t, { mocks, init, load, npm: npmOpts }) => { // error message fn. This is necessary for commands with buffered output // to read the output after exec is called. This is not *exactly* how it // works in practice, but it is close enough for now. - this.flushOutput(err ? errorMessage(err, this).json : null) + const jsonError = err && errorMessage(err, this).json + output.flush({ [META]: true, jsonError }) if (err) { throw err } diff --git a/test/lib/cli/exit-handler.js b/test/lib/cli/exit-handler.js index b1f4d9c272533..d7bedd7341632 100644 --- a/test/lib/cli/exit-handler.js +++ b/test/lib/cli/exit-handler.js @@ -78,11 +78,9 @@ const mockExitHandler = async (t, { config, mocks, files, ...opts } = {}) => { detail: [['ERR DETAIL', err.message]], ...(files ? { files } : {}), json: { - error: { - code: err.code, - summary: err.message, - detail: err.message, - }, + code: err.code, + summary: err.message, + detail: err.message, }, }), ...mocks, From 3cbc25800bbd14a8b22ee3feddad715b3a6436d7 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 16:48:19 -0700 Subject: [PATCH 23/42] chore: test for early version exit --- test/lib/cli/entry.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/lib/cli/entry.js b/test/lib/cli/entry.js index feb6692704d2a..bca3315a5d76e 100644 --- a/test/lib/cli/entry.js +++ b/test/lib/cli/entry.js @@ -1,4 +1,5 @@ const t = require('tap') +const { readdirSync } = require('fs') const { dirname } = require('path') const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') const tmock = require('../../fixtures/tmock.js') @@ -170,3 +171,14 @@ t.test('non-ascii dash', async t => { 'arg Argument starts with non-ascii dash, this is probably invalid: \u2010not-a-dash' ) }) + +t.test('exit early for --version', async t => { + const { cli, outputs, Npm, cache } = await cliMock(t, { + globals: { + 'process.argv': ['node', 'npm', '-v'], + }, + }) + await cli(process) + t.strictSame(readdirSync(cache), [], 'nothing created in cache') + t.equal(outputs[0], Npm.version) +}) From 694dba9fd9a8d71facc7b832bf8f00ca9468e68a Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 17:02:29 -0700 Subject: [PATCH 24/42] fix: dont expose as many public properties of timers --- lib/cli/exit-handler.js | 2 +- lib/npm.js | 7 +++-- lib/utils/timers.js | 61 ++++++++++++++++++++------------------- test/fixtures/mock-npm.js | 2 +- test/lib/npm.js | 41 ++------------------------ test/lib/utils/timers.js | 45 ++++++++--------------------- 6 files changed, 53 insertions(+), 105 deletions(-) diff --git a/lib/cli/exit-handler.js b/lib/cli/exit-handler.js index 8d1d5a3e0ef34..7d81e79356748 100644 --- a/lib/cli/exit-handler.js +++ b/lib/cli/exit-handler.js @@ -45,7 +45,7 @@ process.on('exit', code => { // write the timing file now, this might do nothing based on the configs set. // we need to call it here in case it errors so we dont tell the user // about a timing file that doesn't exist - npm.writeTimingFile() + npm.finish() const logsDir = npm.logsDir const logFiles = npm.logFiles diff --git a/lib/npm.js b/lib/npm.js index e0f3f40a72874..1deae661bc100 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -38,7 +38,7 @@ class Npm { #display = null #logFile = new LogFile() - #timers = new Timers({ start: 'npm' }) + #timers = new Timers() // all these options are only used by tests in order to make testing more // closely resemble real world usage. for now, npm has no programmatic API so @@ -117,8 +117,8 @@ class Npm { this.#logFile.off() } - writeTimingFile () { - this.#timers.writeFile({ + finish () { + this.#timers.finish({ id: this.#runId, command: this.#argvClean, logfiles: this.logFiles, @@ -209,6 +209,7 @@ class Npm { this.#timers.load({ path: this.config.get('timing') ? this.logPath : null, + timing: this.config.get('timing'), }) const configScope = this.config.get('scope') diff --git a/lib/utils/timers.js b/lib/utils/timers.js index b27ddd588db06..16a255961fee3 100644 --- a/lib/utils/timers.js +++ b/lib/utils/timers.js @@ -5,7 +5,8 @@ const { log, time } = require('proc-log') const INITIAL_TIMER = 'npm' class Timers extends EE { - file = null + #file + #timing #unfinished = new Map() #finished = {} @@ -17,14 +18,6 @@ class Timers extends EE { this.started = this.#unfinished.get(INITIAL_TIMER) } - get unfinished () { - return this.#unfinished - } - - get finished () { - return this.#finished - } - on () { process.on('time', this.#timeHandler) } @@ -33,36 +26,46 @@ class Timers extends EE { process.off('time', this.#timeHandler) } - load ({ path } = {}) { - if (path) { - this.file = `${path}timing.json` - } + load ({ path, timing } = {}) { + this.#timing = timing + this.#file = `${path}timing.json` } - writeFile (metadata) { - if (!this.file) { + finish (metadata) { + time.end(INITIAL_TIMER) + + for (const [name, timer] of this.#unfinished) { + log.silly('unfinished npm timer', name, timer) + } + + if (!this.#timing) { + // Not in timing mode, nothing else to do here return } try { - const globalStart = this.started - const globalEnd = this.#finished[INITIAL_TIMER] || Date.now() - const content = { - metadata, - timers: this.#finished, - // add any unfinished timers with their relative start/end - unfinishedTimers: [...this.#unfinished.entries()].reduce((acc, [name, start]) => { - acc[name] = [start - globalStart, globalEnd - globalStart] - return acc - }, {}), - } - fs.writeFileSync(this.file, JSON.stringify(content) + '\n') + this.#writeFile(metadata) + log.info('timing', `Timing info written to: ${this.#file}`) } catch (e) { - this.file = null log.warn('timing', `could not write timing file: ${e}`) } } + #writeFile (metadata) { + const globalStart = this.started + const globalEnd = this.#finished[INITIAL_TIMER] + const content = { + metadata, + timers: this.#finished, + // add any unfinished timers with their relative start/end + unfinishedTimers: [...this.#unfinished.entries()].reduce((acc, [name, start]) => { + acc[name] = [start - globalStart, globalEnd - globalStart] + return acc + }, {}), + } + fs.writeFileSync(this.#file, JSON.stringify(content) + '\n') + } + #timeHandler = (level, name) => { const now = Date.now() switch (level) { @@ -76,7 +79,7 @@ class Timers extends EE { this.#unfinished.delete(name) log.timing(name, `Completed in ${ms}ms`) } else { - log.silly('timing', "Tried to end timer that doesn't exist:", name) + log.silly('timing', `Tried to end timer that doesn't exist: ${name}`) } } } diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index d1879da7f845e..4a58b869858fd 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -295,7 +295,7 @@ const setupMockNpm = async (t, { .join('\n') }, timingFile: async () => { - const data = await fs.readFile(npm.timingFile, 'utf8') + const data = await fs.readFile(npm.logPath + 'timing.json', 'utf8') return JSON.parse(data) }, } diff --git a/test/lib/npm.js b/test/lib/npm.js index 915e63d0060bc..63ac48958cf44 100644 --- a/test/lib/npm.js +++ b/test/lib/npm.js @@ -380,48 +380,14 @@ t.test('cache dir', async t => { }) t.test('timings', async t => { - t.test('gets/sets timers', async t => { - const { npm, logs } = await loadMockNpm(t, { - config: { - timing: true, - }, - }) - time.start('foo') - time.start('bar') - t.match(npm.unfinishedTimers.get('foo'), Number, 'foo timer is a number') - t.match(npm.unfinishedTimers.get('bar'), Number, 'foo timer is a number') - time.end('foo') - time.end('bar') - time.end('baz') - // npm timer is started by default - time.end('npm') - t.match(logs.timing.byTitle('foo'), [ - /Completed in [0-9]+ms/, - ]) - t.match(logs.timing.byTitle('bar'), [ - /Completed in [0-9]+ms/, - ]) - t.match(logs.timing.byTitle('npm'), [ - /Completed in [0-9]+ms/, - ]) - t.match(logs.silly.byTitle('timing'), [ - `timing Tried to end timer that doesn't exist: baz`, - ]) - t.notOk(npm.unfinishedTimers.has('foo'), 'foo timer is gone') - t.notOk(npm.unfinishedTimers.has('bar'), 'bar timer is gone') - t.match(npm.finishedTimers, { foo: Number, bar: Number, npm: Number }) - }) - t.test('writes timings file', async t => { - const { npm, cache, timingFile } = await loadMockNpm(t, { + const { npm, timingFile } = await loadMockNpm(t, { config: { timing: true }, }) time.start('foo') time.end('foo') time.start('bar') - npm.writeTimingFile() - t.match(npm.timingFile, cache) - t.match(npm.timingFile, /-timing.json$/) + npm.finish() const timings = await timingFile() t.match(timings, { metadata: { @@ -431,7 +397,6 @@ t.test('timings', async t => { }, unfinishedTimers: { bar: [Number, Number], - npm: [Number, Number], }, timers: { foo: Number, @@ -444,7 +409,7 @@ t.test('timings', async t => { const { npm, timingFile } = await loadMockNpm(t, { config: { timing: false }, }) - npm.writeTimingFile() + npm.finish() await t.rejects(() => timingFile()) }) diff --git a/test/lib/utils/timers.js b/test/lib/utils/timers.js index 1901738feb975..4e5bfb104db97 100644 --- a/test/lib/utils/timers.js +++ b/test/lib/utils/timers.js @@ -4,7 +4,7 @@ const fs = require('graceful-fs') const { log, time } = require('proc-log') const tmock = require('../../fixtures/tmock') -const mockTimers = (t, options) => { +const mockTimers = (t) => { const logs = log.LEVELS.reduce((acc, l) => { acc[l] = [] return acc @@ -14,7 +14,7 @@ const mockTimers = (t, options) => { } process.on('log', logHandler) const Timers = tmock(t, '{LIB}/utils/timers') - const timers = new Timers(options) + const timers = new Timers() t.teardown(() => { timers.off() process.off('log', logHandler) @@ -22,32 +22,12 @@ const mockTimers = (t, options) => { return { timers, logs } } -t.test('listens/stops on process', async (t) => { - const { timers } = mockTimers(t) - time.start('foo') - time.start('bar') - time.end('bar') - t.match(timers.unfinished, new Map([['foo', Number]])) - t.match(timers.finished, { bar: Number }) - timers.off() - time.start('baz') - t.notOk(timers.unfinished.get('baz')) -}) - -t.test('initial timer is named npm', async (t) => { - const { timers } = mockTimers(t) - time.end('npm') - t.match(timers.finished, { npm: Number }) -}) - t.test('logs timing events', async (t) => { - const events = [] - const listener = (...args) => events.push(args) - const { timers, logs } = mockTimers(t, { listener }) + const { timers, logs } = mockTimers(t) time.start('foo') time.start('bar') time.end('bar') - timers.off(listener) + timers.off() time.end('foo') t.equal(logs.timing.length, 1) t.match(logs.timing[0], /^bar Completed in [0-9]ms/) @@ -64,14 +44,15 @@ t.test('writes file', async (t) => { const dir = t.testdir() time.start('foo') time.end('foo') - timers.load({ path: resolve(dir, `TIMING_FILE-`) }) - timers.writeFile({ some: 'data' }) + time.start('ohno') + timers.load({ timing: true, path: resolve(dir, `TIMING_FILE-`) }) + timers.finish({ some: 'data' }) const data = JSON.parse(fs.readFileSync(resolve(dir, 'TIMING_FILE-timing.json'))) t.match(data, { metadata: { some: 'data' }, - timers: { foo: Number }, + timers: { foo: Number, npm: Number }, unfinishedTimers: { - npm: [Number, Number], + ohno: [Number, Number], }, }) }) @@ -80,20 +61,18 @@ t.test('fails to write file', async (t) => { const { logs, timers } = mockTimers(t) const dir = t.testdir() - timers.load({ path: join(dir, 'does', 'not', 'exist') }) - timers.writeFile() + timers.load({ timing: true, path: join(dir, 'does', 'not', 'exist') }) + timers.finish() t.match(logs.warn, ['timing could not write timing file:']) - t.equal(timers.file, null) }) t.test('no dir and no file', async (t) => { const { logs, timers } = mockTimers(t) timers.load() - timers.writeFile() + timers.finish() t.strictSame(logs.warn, []) t.strictSame(logs.silly, []) - t.equal(timers.file, null) }) From 43e619480568493433af78208e2b3c48843185ef Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 19:32:56 -0700 Subject: [PATCH 25/42] fix: dont show run script banners in silent --- lib/utils/display.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/utils/display.js b/lib/utils/display.js index 32399a7bf5329..4e0ba81ca956e 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -276,6 +276,13 @@ class Display { return } + // HACK: if it looks like the banner and we are silent do not print it. + // There's no other way to do this right now :( + // eslint-disable-next-line max-len + if (this.#silent && args.length === 1 && args[0].startsWith('\n> ') && args[0].endsWith('\n')) { + return + } + this.#writeOutput(level, meta, ...args) }) From f309c1cd8ab26b9cdc3b1224499aba345edfc582 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 19:33:45 -0700 Subject: [PATCH 26/42] fix(refactor): move timer and error logfile messages to lib/npm --- lib/cli/exit-handler.js | 70 ++----------------- lib/npm.js | 44 +++++++----- .../test/lib/cli/exit-handler.js.test.cjs | 8 +-- .../test/lib/utils/exit-handler.js.test.cjs | 68 ------------------ test/lib/cli/exit-handler.js | 17 ++--- 5 files changed, 39 insertions(+), 168 deletions(-) delete mode 100644 tap-snapshots/test/lib/utils/exit-handler.js.test.cjs diff --git a/lib/cli/exit-handler.js b/lib/cli/exit-handler.js index 7d81e79356748..5866c46b57c5f 100644 --- a/lib/cli/exit-handler.js +++ b/lib/cli/exit-handler.js @@ -1,4 +1,4 @@ -const { log, output, time, META } = require('proc-log') +const { log, output, META } = require('proc-log') const errorMessage = require('../utils/error-message.js') const { redactLog: replaceInfo } = require('@npmcli/redact') @@ -7,19 +7,8 @@ let exitHandlerCalled = false let showLogFileError = false process.on('exit', code => { - // process.emit is synchronous, so the timeEnd handler will run before the - // unfinished timer check below - time.end('npm') - const hasLoadedNpm = npm?.config.loaded - // Unfinished timers can be read before config load - if (npm) { - for (const [name, timer] of npm.unfinishedTimers) { - log.silly('unfinished npm timer', name, timer) - } - } - if (!code) { log.info('ok') } else { @@ -31,65 +20,14 @@ process.on('exit', code => { log.error('', 'Exit handler never called!') log.error('', 'This is an error with npm itself. Please report this error at:') log.error('', ' ') - - if (!npm || !npm.silent) { - // eslint-disable-next-line no-console - console.error('') - } - + // eslint-disable-next-line no-console + console.error('') showLogFileError = true } // npm must be loaded to know where the log file was written if (hasLoadedNpm) { - // write the timing file now, this might do nothing based on the configs set. - // we need to call it here in case it errors so we dont tell the user - // about a timing file that doesn't exist - npm.finish() - - const logsDir = npm.logsDir - const logFiles = npm.logFiles - - const timingDir = npm.timingDir - const timingFile = npm.timingFile - - const timing = npm.config.get('timing') - const logsMax = npm.config.get('logs-max') - - // Determine whether to show log file message and why it is - // being shown since in timing mode we always show the log file message - const logMethod = showLogFileError ? 'error' : timing ? 'info' : null - - if (logMethod) { - // just a line break, will be ignored in silent mode - output.error('') - - const message = [] - - if (timingFile) { - message.push(`Timing info written to: ${timingFile}`) - } else if (timing) { - message.push( - `The timing file was not written due to an error writing to the directory: ${timingDir}` - ) - } - - if (logFiles.length) { - message.push(`A complete log of this run can be found in: ${logFiles}`) - } else if (logsMax <= 0) { - // user specified no log file - message.push(`Log files were not written due to the config logs-max=${logsMax}`) - } else { - // could be an error writing to the directory - message.push( - `Log files were not written due to an error writing to the directory: ${logsDir}`, - 'You can rerun the command with `--loglevel=verbose` to see the logs in your terminal' - ) - } - - log[logMethod]('', message.join('\n')) - } - + npm.finish({ showLogFileError }) // This removes any listeners npm setup, mostly for tests to avoid max listener warnings npm.unload() } diff --git a/lib/npm.js b/lib/npm.js index 1deae661bc100..691d13ef1be99 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -117,13 +117,35 @@ class Npm { this.#logFile.off() } - finish () { + finish ({ showLogFileError } = {}) { this.#timers.finish({ id: this.#runId, command: this.#argvClean, logfiles: this.logFiles, version: this.version, }) + + if (showLogFileError) { + if (!this.silent) { + // just a line break if not in silent mode + output.error('') + } + + const logsMax = this.config.get('logs-max') + + if (this.logFiles.length) { + log.error('', `A complete log of this run can be found in: ${this.logFiles}`) + } else if (logsMax <= 0) { + // user specified no log file + log.error('', `Log files were not written due to the config logs-max=${logsMax}`) + } else { + // could be an error writing to the directory + log.error('', + `Log files were not written due to an error writing to the directory: ${this.#logsDir}` + + '\nYou can rerun the command with `--loglevel=verbose` to see the logs in your terminal' + ) + } + } } get title () { @@ -179,7 +201,7 @@ class Npm { // which we will tell them about at the end if (this.config.get('logs-max') > 0) { await time.start('npm:load:mkdirplogs', () => - fs.mkdir(this.logsDir, { recursive: true }) + fs.mkdir(this.#logsDir, { recursive: true }) .catch((e) => log.verbose('logfile', `could not create logs-dir: ${e}`))) } @@ -208,7 +230,7 @@ class Npm { }) this.#timers.load({ - path: this.config.get('timing') ? this.logPath : null, + path: this.logPath, timing: this.config.get('timing'), }) @@ -281,14 +303,6 @@ class Npm { return 2 } - get unfinishedTimers () { - return this.#timers.unfinished - } - - get finishedTimers () { - return this.#timers.finished - } - get started () { return this.#timers.started } @@ -297,16 +311,12 @@ class Npm { return this.#logFile.files } - get logsDir () { + get #logsDir () { return this.config.get('logs-dir') || join(this.cache, '_logs') } get logPath () { - return resolve(this.logsDir, `${this.#runId}-`) - } - - get timingFile () { - return this.#timers.file + return resolve(this.#logsDir, `${this.#runId}-`) } get npmRoot () { diff --git a/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs b/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs index 3a510647ece8e..cedb56642f26d 100644 --- a/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs +++ b/tap-snapshots/test/lib/cli/exit-handler.js.test.cjs @@ -29,9 +29,9 @@ XX error code ECODE XX error ERR SUMMARY Unknown error XX error ERR DETAIL Unknown error XX verbose exit 1 -XX timing npm Completed in {TIME}ms XX verbose code 1 -XX error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json +XX timing npm Completed in {TIME}ms +XX info timing Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json XX error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log ` @@ -59,8 +59,8 @@ error code ECODE error ERR SUMMARY Unknown error error ERR DETAIL Unknown error verbose exit 1 -timing npm Completed in {TIME}ms verbose code 1 -error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json +timing npm Completed in {TIME}ms +info timing Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log ` diff --git a/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs b/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs deleted file mode 100644 index 3fa13309d6249..0000000000000 --- a/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs +++ /dev/null @@ -1,68 +0,0 @@ -/* 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/utils/exit-handler.js TAP handles unknown error with logs and debug file > debug file contents 1`] = ` -XX timing npm:load:whichnode Completed in {TIME}ms -XX timing config:load Completed in {TIME}ms -XX timing npm:load:configload Completed in {TIME}ms -XX timing npm:load:mkdirpcache Completed in {TIME}ms -XX timing npm:load:mkdirplogs Completed in {TIME}ms -XX verbose title npm -XX verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "silly" "--color" "false" "--timing" "true" -XX timing npm:load:setTitle Completed in {TIME}ms -XX timing npm:load:display Completed in {TIME}ms -XX verbose logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}- -XX verbose logfile {CWD}/cache/_logs/{DATE}-debug-0.log -XX timing npm:load:logFile Completed in {TIME}ms -XX timing npm:load:timers Completed in {TIME}ms -XX timing npm:load:configScope Completed in {TIME}ms -XX timing npm:load Completed in {TIME}ms -XX verbose stack Error: Unknown error -XX verbose cwd {CWD}/prefix -XX verbose {OS} -XX verbose {NODE-VERSION} -XX verbose npm {NPM-VERSION} -XX error code ECODE -XX error ERR SUMMARY Unknown error -XX error ERR DETAIL Unknown error -XX verbose exit 1 -XX timing npm Completed in {TIME}ms -XX verbose code 1 -XX error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json -XX error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log -` - -exports[`test/lib/utils/exit-handler.js TAP handles unknown error with logs and debug file > logs 1`] = ` -timing npm:load:whichnode Completed in {TIME}ms -timing config:load Completed in {TIME}ms -timing npm:load:configload Completed in {TIME}ms -timing npm:load:mkdirpcache Completed in {TIME}ms -timing npm:load:mkdirplogs Completed in {TIME}ms -verbose title npm -verbose argv "--fetch-retries" "0" "--cache" "{CWD}/cache" "--loglevel" "silly" "--color" "false" "--timing" "true" -timing npm:load:setTitle Completed in {TIME}ms -timing npm:load:display Completed in {TIME}ms -verbose logfile logs-max:10 dir:{CWD}/cache/_logs/{DATE}- -verbose logfile {CWD}/cache/_logs/{DATE}-debug-0.log -timing npm:load:logFile Completed in {TIME}ms -timing npm:load:timers Completed in {TIME}ms -timing npm:load:configScope Completed in {TIME}ms -timing npm:load Completed in {TIME}ms -verbose stack Error: Unknown error -verbose cwd {CWD}/prefix -verbose {OS} -verbose {NODE-VERSION} -verbose npm {NPM-VERSION} -error code ECODE -error ERR SUMMARY Unknown error -error ERR DETAIL Unknown error -verbose exit 1 -timing npm Completed in {TIME}ms -verbose code 1 -error Timing info written to: {CWD}/cache/_logs/{DATE}-timing.json -error A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log -` diff --git a/test/lib/cli/exit-handler.js b/test/lib/cli/exit-handler.js index d7bedd7341632..3cb4523b3ee51 100644 --- a/test/lib/cli/exit-handler.js +++ b/test/lib/cli/exit-handler.js @@ -382,7 +382,7 @@ t.test('timers fail to write', async (t) => { await exitHandler(new Error()) - t.match(logs.error[2], `error writing to the directory`) + t.match(logs.warn[0], `timing could not write timing file: Error: err`) }) t.test('log files fail to write', async (t) => { @@ -455,7 +455,7 @@ t.test('files from error message with error', async (t) => { t.test('timing with no error', async (t) => { const { exitHandler, timingFile, npm, logs } = await mockExitHandler(t, { - config: { timing: true, loglevel: 'info' }, + config: { timing: true, loglevel: 'silly' }, }) await exitHandler() @@ -463,18 +463,9 @@ t.test('timing with no error', async (t) => { t.equal(process.exitCode, 0) - const msg = logs.info[1] - t.match(msg, /A complete log of this run can be found in:/) + const msg = logs.info.byTitle('timing')[0] t.match(msg, /Timing info written to:/) - t.match( - timingFileData.timers, - Object.keys(npm.finishedTimers).reduce((acc, k) => { - acc[k] = Number - return acc - }, {}) - ) - t.strictSame(npm.unfinishedTimers, new Map()) t.match(timingFileData, { metadata: { command: [], @@ -482,6 +473,7 @@ t.test('timing with no error', async (t) => { logfiles: [String], }, timers: { + 'npm:load': Number, npm: Number, }, }) @@ -511,7 +503,6 @@ t.test('unfinished timers', async (t) => { const timingFileData = await timingFile() t.equal(process.exitCode, 0) - t.match(npm.unfinishedTimers, new Map([['foo', Number], ['bar', Number]])) t.match(timingFileData, { metadata: { command: [], From e5f1948a569224c59a9a4fdeb0e3b82312fb87c6 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 19:49:13 -0700 Subject: [PATCH 27/42] fix: run update notifier after exec but before waiting --- lib/cli/entry.js | 29 ++++++++++++++++------------- lib/npm.js | 13 +++++++------ lib/utils/did-you-mean.js | 16 +++++++--------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/lib/cli/entry.js b/lib/cli/entry.js index 9b3e29ec336a6..db61dd74f56b0 100644 --- a/lib/cli/entry.js +++ b/lib/cli/entry.js @@ -36,7 +36,6 @@ module.exports = async (process, validateEngines) => { log.warn('cli', validateEngines.unsupportedMessage) } - let cmd // Now actually fire up npm and run the command. // This is how to use npm programmatically: try { @@ -46,20 +45,15 @@ module.exports = async (process, validateEngines) => { return exitHandler() } - cmd = npm.argv.shift() - if (!cmd) { + const command = npm.argv.shift() + const args = npm.argv + + if (!command) { output.standard(npm.usage) process.exitCode = 1 return exitHandler() } - // this is async but we dont await it, since its ok if it doesnt - // finish before the command finishes running. it uses command and argv - // so it must be initiated here, after the command name is set - const updateNotifier = require('./update-notifier.js') - // eslint-disable-next-line promise/catch-or-return - updateNotifier(npm).then((msg) => (npm.updateNotification = msg)) - // Options are prefixed by a hyphen-minus (-, \u2d). // Other dash-type chars look similar but are invalid. const nonDashArgs = npm.argv.filter(a => /^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(a)) @@ -71,13 +65,22 @@ module.exports = async (process, validateEngines) => { ) } - await npm.exec(cmd) + const execPromise = npm.exec(command, args) + + // this is async but we dont await it, since its ok if it doesnt + // finish before the command finishes running. it uses command and argv + // so it must be initiated here, after the command name is set + const updateNotifier = require('./update-notifier.js') + // eslint-disable-next-line promise/catch-or-return + updateNotifier(npm).then((msg) => (npm.updateNotification = msg)) + + await execPromise return exitHandler() } catch (err) { if (err.code === 'EUNKNOWNCOMMAND') { const didYouMean = require('../utils/did-you-mean.js') - const suggestions = await didYouMean(npm.localPrefix, cmd) - output.standard(`Unknown command: "${cmd}"${suggestions}\n`) + const suggestions = await didYouMean(npm.localPrefix, err.command) + output.standard(`Unknown command: "${err.command}"${suggestions}\n`) output.standard('To see a list of supported npm commands, run:\n npm help') process.exitCode = 1 return exitHandler() diff --git a/lib/npm.js b/lib/npm.js index 691d13ef1be99..9b00321556a44 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -22,6 +22,7 @@ class Npm { if (!command) { throw Object.assign(new Error(`Unknown command ${c}`), { code: 'EUNKNOWNCOMMAND', + command: c, }) } return require(`./commands/${command}.js`) @@ -90,18 +91,18 @@ class Npm { } // Call an npm command - // TODO: tests are currently the only time the second - // parameter of args is used. When called via `lib/cli.js` the config is - // loaded and this.argv is set to the remaining command line args. We should - // consider testing the CLI the same way it is used and not allow args to be - // passed in directly. async exec (cmd, args = this.argv) { const command = this.setCmd(cmd) return time.start(`command:${cmd}`, () => command.cmdExec(args)) } async load () { - return time.start('npm:load', () => this.#load().then(r => r || { exec: true })) + return time.start('npm:load', async () => { + const { exec = true } = await this.#load().then(r => r ?? {}) + return { + exec, + } + }) } get loaded () { diff --git a/lib/utils/did-you-mean.js b/lib/utils/did-you-mean.js index 499c27c74e1de..54c8ff2e35aa6 100644 --- a/lib/utils/did-you-mean.js +++ b/lib/utils/did-you-mean.js @@ -8,7 +8,7 @@ const didYouMean = async (path, scmd) => { let best = [] for (const str of close) { const cmd = Npm.cmd(str) - best.push(` npm ${str} # ${cmd.description}`) + best.push(` npm ${str} # ${cmd.description}`) } // We would already be suggesting this in `npm x` so omit them here const runScripts = ['stop', 'start', 'test', 'restart'] @@ -17,13 +17,13 @@ const didYouMean = async (path, scmd) => { best = best.concat( Object.keys(scripts || {}) .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4 && !runScripts.includes(cmd)) - .map(str => ` npm run ${str} # run the "${str}" package script`), + .map(str => ` npm run ${str} # run the "${str}" package script`), Object.keys(bin || {}) .filter(cmd => distance(scmd, cmd) < scmd.length * 0.4) /* eslint-disable-next-line max-len */ - .map(str => ` npm exec ${str} # run the "${str}" command from either this or a remote npm package`) + .map(str => ` npm exec ${str} # run the "${str}" command from either this or a remote npm package`) ) - } catch (_) { + } catch { // gracefully ignore not being in a folder w/ a package.json } @@ -31,11 +31,9 @@ const didYouMean = async (path, scmd) => { return '' } - const suggestion = - best.length === 1 - ? `\n\nDid you mean this?\n${best[0]}` - : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` - return suggestion + return best.length === 1 + ? `\n\nDid you mean this?\n${best[0]}` + : `\n\nDid you mean one of these?\n${best.slice(0, 3).join('\n')}` } module.exports = didYouMean From 06202f0e13d91f5ee6edfe2da6ee21bafbf18cca Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 22 Apr 2024 19:52:03 -0700 Subject: [PATCH 28/42] fix: store unref promises for awaiting in tests --- lib/npm.js | 10 ++++++++-- test/fixtures/mock-npm.js | 11 +++++++++++ test/lib/cli/exit-handler.js | 9 +-------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/npm.js b/lib/npm.js index 9b00321556a44..892cf4b96c8a0 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -28,6 +28,7 @@ class Npm { return require(`./commands/${command}.js`) } + unrefPromises = [] updateNotification = null argv = [] @@ -224,11 +225,16 @@ class Npm { log.verbose('argv', this.#argvClean.map(JSON.stringify).join(' ')) }) - this.#logFile.load({ + // logFile.load returns a promise that resolves when old logs are done being cleaned. + // We save this promise to an array so that we can await it in tests to ensure more + // deterministic logging behavior. The process will also hang open if this were to + // take a long time to resolve, but that is why process.exit is called explicitly + // in the exit-handler. + this.unrefPromises.push(this.#logFile.load({ path: this.logPath, logsMax: this.config.get('logs-max'), timing: this.config.get('timing'), - }) + })) this.#timers.load({ path: this.logPath, diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index 4a58b869858fd..5618a12566003 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -73,6 +73,17 @@ const getMockNpm = async (t, { mocks, init, load, npm: npmOpts }) => { }) } + async load () { + const res = await super.load() + // Wait for any promises (currently only log file cleaning) to be + // done before returning from load in tests. This helps create more + // deterministic testing behavior because in reality that promise + // is left hanging on purpose as a best-effort and the process gets + // closed regardless of if it has finished or not. + await Promise.all(this.unrefPromises) + return res + } + async exec (...args) { const [res, err] = await super.exec(...args).then((r) => [r]).catch(e => [null, e]) // This mimics how the exit handler flushes output for commands that have diff --git a/test/lib/cli/exit-handler.js b/test/lib/cli/exit-handler.js index 3cb4523b3ee51..fd6754b30096e 100644 --- a/test/lib/cli/exit-handler.js +++ b/test/lib/cli/exit-handler.js @@ -129,8 +129,6 @@ t.test('handles unknown error with logs and debug file', async (t) => { }) await exitHandler(err('Unknown error', 'ECODE')) - // force logfile cleaning logs to happen since those are purposefully not awaited - await require('timers/promises').setTimeout(200) const fileLogs = await debugFile() const fileLines = fileLogs.split('\n') @@ -140,19 +138,14 @@ t.test('handles unknown error with logs and debug file', async (t) => { t.equal(process.exitCode, 1) - let skippedLogs = 0 logs.forEach((logItem, i) => { const logLines = logItem.split('\n').map(l => `${i} ${l}`) for (const line of logLines) { - if (line.includes('logfile') && line.includes('cleaning')) { - skippedLogs++ - continue - } t.match(fileLogs.trim(), line, 'log appears in debug file') } }) - t.equal(logs.length - skippedLogs, parseInt(lastLog) + 1) + t.equal(logs.length, parseInt(lastLog) + 1) t.match(logs.error, [ 'code ECODE', 'ERR SUMMARY Unknown error', From 7f4e66772ee631158b47fcfcd8e22b7b6b9b9cce Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 24 Apr 2024 13:49:51 -0700 Subject: [PATCH 29/42] fix: redact when displaying non-ascii arguments --- lib/cli/entry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli/entry.js b/lib/cli/entry.js index db61dd74f56b0..fc196b8e234fc 100644 --- a/lib/cli/entry.js +++ b/lib/cli/entry.js @@ -61,7 +61,7 @@ module.exports = async (process, validateEngines) => { log.error( 'arg', 'Argument starts with non-ascii dash, this is probably invalid:', - nonDashArgs.join(', ') + require('@npmcli/redact').redactLog(nonDashArgs.join(', ')) ) } From 0708b3b2dbfc811b0e692133557b6b2e698519fd Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 24 Apr 2024 15:02:04 -0700 Subject: [PATCH 30/42] fix: use name of level instead of label for logging prefixes (#7414) --- lib/utils/display.js | 6 +-- .../tap-snapshots/test/index.js.test.cjs | 50 +++++++++---------- test/fixtures/mock-logs.js | 14 ++---- 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/lib/utils/display.js b/lib/utils/display.js index 4e0ba81ca956e..67c745f310415 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -38,11 +38,9 @@ const LEVEL_OPTIONS = { }, error: { index: 1, - label: 'ERR!', }, warn: { index: 2, - label: 'WARN', }, notice: { index: 3, @@ -55,11 +53,9 @@ const LEVEL_OPTIONS = { }, verbose: { index: 6, - label: 'verb', }, silly: { index: 7, - label: 'sill', }, } @@ -338,7 +334,7 @@ class Display { const title = args.shift() const prefix = [ this.#logColors.heading(this.#heading), - this.#logColors[level](levelOpts.label ?? level), + this.#logColors[level](level), title ? this.#logColors.title(title) : null, ] this.#stderrWrite({ prefix }, ...args) diff --git a/smoke-tests/tap-snapshots/test/index.js.test.cjs b/smoke-tests/tap-snapshots/test/index.js.test.cjs index c90e376dee20e..c889c830e845a 100644 --- a/smoke-tests/tap-snapshots/test/index.js.test.cjs +++ b/smoke-tests/tap-snapshots/test/index.js.test.cjs @@ -43,31 +43,31 @@ npm {NPM} ` exports[`test/index.js TAP basic npm ci > should throw mismatch deps in lock file error 1`] = ` -npm ERR! code EUSAGE -npm ERR! -npm ERR! \`npm ci\` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with \`npm install\` before continuing. -npm ERR! -npm ERR! Invalid: lock file's abbrev@1.0.4 does not satisfy abbrev@1.1.1 -npm ERR! -npm ERR! Clean install a project -npm ERR! -npm ERR! Usage: -npm ERR! npm ci -npm ERR! -npm ERR! Options: -npm ERR! [--install-strategy ] [--legacy-bundling] -npm ERR! [--global-style] [--omit [--omit ...]] -npm ERR! [--include [--include ...]] -npm ERR! [--strict-peer-deps] [--foreground-scripts] [--ignore-scripts] [--no-audit] -npm ERR! [--no-bin-links] [--no-fund] [--dry-run] -npm ERR! [-w|--workspace [-w|--workspace ...]] -npm ERR! [-ws|--workspaces] [--include-workspace-root] [--install-links] -npm ERR! -npm ERR! aliases: clean-install, ic, install-clean, isntall-clean -npm ERR! -npm ERR! Run "npm help ci" for more info - -npm ERR! A complete log of this run can be found in: {NPM}/{TESTDIR}/cache/_logs/{LOG} +npm error code EUSAGE +npm error +npm error \`npm ci\` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with \`npm install\` before continuing. +npm error +npm error Invalid: lock file's abbrev@1.0.4 does not satisfy abbrev@1.1.1 +npm error +npm error Clean install a project +npm error +npm error Usage: +npm error npm ci +npm error +npm error Options: +npm error [--install-strategy ] [--legacy-bundling] +npm error [--global-style] [--omit [--omit ...]] +npm error [--include [--include ...]] +npm error [--strict-peer-deps] [--foreground-scripts] [--ignore-scripts] [--no-audit] +npm error [--no-bin-links] [--no-fund] [--dry-run] +npm error [-w|--workspace [-w|--workspace ...]] +npm error [-ws|--workspaces] [--include-workspace-root] [--install-links] +npm error +npm error aliases: clean-install, ic, install-clean, isntall-clean +npm error +npm error Run "npm help ci" for more info + +npm error A complete log of this run can be found in: {NPM}/{TESTDIR}/cache/_logs/{LOG} ` exports[`test/index.js TAP basic npm diff > should have expected diff output 1`] = ` diff --git a/test/fixtures/mock-logs.js b/test/fixtures/mock-logs.js index c29928130088c..346944d7405b0 100644 --- a/test/fixtures/mock-logs.js +++ b/test/fixtures/mock-logs.js @@ -1,13 +1,7 @@ const { log: { LEVELS } } = require('proc-log') const { stripVTControlCharacters: stripAnsi } = require('util') -const labels = new Map([ - ['error', 'ERR!'], - ['warn', 'WARN'], - ['verbose', 'verb'], - ['silly', 'sill'], -].reduce((acc, v) => acc.concat([v, v.slice(0).reverse()]), [])) -const logPrefix = new RegExp(`^npm (${LEVELS.map(l => labels.get(l) ?? l).join('|')})\\s`) +const logPrefix = new RegExp(`^npm (${LEVELS.join('|')})\\s`) const isLog = (str) => logPrefix.test(stripAnsi(str)) // We only strip trailing newlines since some output will @@ -63,15 +57,15 @@ module.exports = () => { // Split on spaces for the heading and level/label. We know that // none of those have spaces but could be colorized so there's no // other good way to get each of those including control chars - const [rawHeading, rawLabel] = str.split(' ') - const rawPrefix = `${rawHeading} ${rawLabel} ` + const [rawHeading, rawLevel] = str.split(' ') + const rawPrefix = `${rawHeading} ${rawLevel} ` // If message is colorized we can just replaceAll with the string since // it will be unique due to control chars. Otherwise we create a regex // that will only match the beginning of each line. const prefix = stripAnsi(str) !== str ? rawPrefix : new RegExp(`^${rawPrefix}`, 'gm') // The level needs color stripped always because we use it to filter logs - const level = labels.get(stripAnsi(rawLabel)) ?? stripAnsi(rawLabel) + const level = stripAnsi(rawLevel) logs.push(str.replaceAll(prefix, `${level} `)) levelLogs.push({ level, message: str.replaceAll(prefix, '') }) From 180b919d2322e55ec5d58bbd476c3ecc31880479 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 24 Apr 2024 15:48:19 -0700 Subject: [PATCH 31/42] fix: remove unused npm.setCmd method --- lib/npm.js | 9 ++------- test/fixtures/mock-npm.js | 11 ----------- test/lib/utils/reify-output.js | 13 ++++++++++++- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/lib/npm.js b/lib/npm.js index 892cf4b96c8a0..54bb4f9a47b0a 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -77,7 +77,8 @@ class Npm { return this.constructor.version } - setCmd (cmd) { + // Call an npm command + async exec (cmd, args = this.argv) { const Command = Npm.cmd(cmd) const command = new Command(this) @@ -88,12 +89,6 @@ class Npm { process.env.npm_command = this.command } - return command - } - - // Call an npm command - async exec (cmd, args = this.argv) { - const command = this.setCmd(cmd) return time.start(`command:${cmd}`, () => command.cmdExec(args)) } diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index 5618a12566003..6fd94b8f0e038 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -120,7 +120,6 @@ const setupMockNpm = async (t, { // preload a command command = null, // string name of the command exec = null, // optionally exec the command before returning - setCmd = false, // test dirs prefixDir = {}, homeDir = {}, @@ -267,16 +266,6 @@ const setupMockNpm = async (t, { const mockCommand = {} if (command) { const Cmd = mockNpm.Npm.cmd(command) - if (setCmd) { - // XXX(hack): This is a hack to allow fake-ish tests to set the currently - // running npm command without running exec. Generally, we should rely on - // actually exec-ing the command to asserting the state of the world - // through what is printed/on disk/etc. This is a stop-gap to allow tests - // that are time intensive to convert to continue setting the npm command - // this way. TODO: remove setCmd from all tests and remove the setCmd - // method from `lib/npm.js` - npm.setCmd(command) - } mockCommand.cmd = new Cmd(npm) mockCommand[command] = { usage: Cmd.describeUsage, diff --git a/test/lib/utils/reify-output.js b/test/lib/utils/reify-output.js index fd15e25a74984..205b7baf421f7 100644 --- a/test/lib/utils/reify-output.js +++ b/test/lib/utils/reify-output.js @@ -8,7 +8,18 @@ const mockReify = async (t, reify, { command, ...config } = {}) => { const mock = await mockNpm(t, { command, config, - setCmd: true, + }) + + // Hack to adapt existing fake test. Make npm.command + // return whatever was passed in to this function. + // What it should be doing is npm.exec(command) but that + // breaks most of these tests because they dont expect + // a command to actually run. + Object.defineProperty(mock.npm, 'command', { + get () { + return command + }, + enumerable: true, }) reifyOutput(mock.npm, reify) From c060e60a7ce767f6fdb32782c0d373e717df7856 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 24 Apr 2024 16:15:51 -0700 Subject: [PATCH 32/42] fix: return command and argv from load --- lib/cli/entry.js | 5 +---- lib/npm.js | 2 ++ test/fixtures/mock-npm.js | 6 +++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/cli/entry.js b/lib/cli/entry.js index fc196b8e234fc..5d676c3f0a8a1 100644 --- a/lib/cli/entry.js +++ b/lib/cli/entry.js @@ -39,15 +39,12 @@ module.exports = async (process, validateEngines) => { // Now actually fire up npm and run the command. // This is how to use npm programmatically: try { - const { exec } = await npm.load() + const { exec, command, args } = await npm.load() if (!exec) { return exitHandler() } - const command = npm.argv.shift() - const args = npm.argv - if (!command) { output.standard(npm.usage) process.exitCode = 1 diff --git a/lib/npm.js b/lib/npm.js index 54bb4f9a47b0a..eb715fa803508 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -97,6 +97,8 @@ class Npm { const { exec = true } = await this.#load().then(r => r ?? {}) return { exec, + command: this.argv.shift(), + args: this.argv, } }) } diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index 6fd94b8f0e038..d8a4834a9abff 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -241,7 +241,11 @@ const setupMockNpm = async (t, { init, load, mocks: withDirs(mocks), - npm: { argv, excludeNpmCwd: true, ...withDirs(npmOpts) }, + npm: { + argv: command ? [command, ...argv] : argv, + excludeNpmCwd: true, + ...withDirs(npmOpts), + }, }) if (config.omit?.includes('prod')) { From 0e74ee42cbd2cbe438e64a2426767dad1868e70d Mon Sep 17 00:00:00 2001 From: Gar Date: Thu, 25 Apr 2024 09:25:28 -0700 Subject: [PATCH 33/42] fix: clean up npm object (#7416) Removed all the setters, they were dangerous and not the right way to set those values. Tweaked `this.#init` so it always returns an object so the coerce in `this.load` didn't need to happen. --- lib/npm.js | 40 +++++++++++---------------------------- test/lib/arborist-cmd.js | 3 ++- test/lib/commands/exec.js | 2 +- test/lib/npm.js | 29 +++------------------------- 4 files changed, 17 insertions(+), 57 deletions(-) diff --git a/lib/npm.js b/lib/npm.js index eb715fa803508..84b22f2db5a80 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -94,7 +94,7 @@ class Npm { async load () { return time.start('npm:load', async () => { - const { exec = true } = await this.#load().then(r => r ?? {}) + const { exec } = await this.#load() return { exec, command: this.argv.shift(), @@ -130,11 +130,12 @@ class Npm { output.error('') } - const logsMax = this.config.get('logs-max') - if (this.logFiles.length) { - log.error('', `A complete log of this run can be found in: ${this.logFiles}`) - } else if (logsMax <= 0) { + return log.error('', `A complete log of this run can be found in: ${this.logFiles}`) + } + + const logsMax = this.config.get('logs-max') + if (logsMax <= 0) { // user specified no log file log.error('', `Log files were not written due to the config logs-max=${logsMax}`) } else { @@ -151,11 +152,6 @@ class Npm { return this.#title } - set title (t) { - process.title = t - this.#title = t - } - async #load () { await time.start('npm:load:whichnode', async () => { // TODO should we throw here? @@ -210,8 +206,9 @@ class Npm { const { parsedArgv: { cooked, remain } } = this.config this.argv = remain // Secrets are mostly in configs, so title is set using only the positional args - // to keep those from being leaked. - this.title = ['npm'].concat(replaceInfo(remain)).join(' ').trim() + // to keep those from being leaked. We still do a best effort replaceInfo. + this.#title = ['npm'].concat(replaceInfo(remain)).join(' ').trim() + process.title = this.#title // The cooked argv is also logged separately for debugging purposes. It is // cleaned as a best effort by replacing known secrets like basic auth // password and strings that look like npm tokens. XXX: for this to be @@ -252,6 +249,8 @@ class Npm { this.argv = ['version'] this.config.set('usage', false, 'cli') } + + return { exec: true } } get isShellout () { @@ -331,26 +330,14 @@ class Npm { return this.config.get('cache') } - set cache (r) { - this.config.set('cache', r) - } - get globalPrefix () { return this.config.globalPrefix } - set globalPrefix (r) { - this.config.globalPrefix = r - } - get localPrefix () { return this.config.localPrefix } - set localPrefix (r) { - this.config.localPrefix = r - } - get localPackage () { return this.config.localPackage } @@ -386,11 +373,6 @@ class Npm { return this.global ? this.globalPrefix : this.localPrefix } - set prefix (r) { - const k = this.global ? 'globalPrefix' : 'localPrefix' - this[k] = r - } - get usage () { return usage(this) } diff --git a/test/lib/arborist-cmd.js b/test/lib/arborist-cmd.js index 3c3f44f75d89f..dd90d47b9a000 100644 --- a/test/lib/arborist-cmd.js +++ b/test/lib/arborist-cmd.js @@ -117,7 +117,8 @@ t.test('arborist-cmd', async t => { chdir: (dirs) => dirs.testdir, }) - npm.localPrefix = prefix + // TODO there has to be a better way to do this + npm.config.localPrefix = prefix await cmd.execWorkspaces([]) t.same(cmd.workspaceNames, ['a', 'c'], 'should set array with single ws name') diff --git a/test/lib/commands/exec.js b/test/lib/commands/exec.js index 094cb7113d07a..d0aa5f9a33974 100644 --- a/test/lib/commands/exec.js +++ b/test/lib/commands/exec.js @@ -76,7 +76,7 @@ t.test('--prefix', async t => { }) // This is what `--prefix` does - npm.globalPrefix = npm.localPrefix + npm.config.globalPrefix = npm.config.localPrefix await registry.package({ manifest, diff --git a/test/lib/npm.js b/test/lib/npm.js index 63ac48958cf44..a965a79a3f528 100644 --- a/test/lib/npm.js +++ b/test/lib/npm.js @@ -36,11 +36,8 @@ t.test('npm.load', async t => { }) await t.test('basic loading', async t => { - const { npm, logs, prefix: dir, cache, other } = await loadMockNpm(t, { + const { npm, logs, cache } = await loadMockNpm(t, { prefixDir: { node_modules: {} }, - otherDirs: { - newCache: {}, - }, config: { timing: true, }, @@ -61,25 +58,11 @@ t.test('npm.load', async t => { mockGlobals(t, { process: { platform: 'posix' } }) t.equal(resolve(npm.cache), resolve(cache), 'cache is cache') - npm.cache = other.newCache - t.equal(npm.config.get('cache'), other.newCache, 'cache setter sets config') - t.equal(npm.cache, other.newCache, 'cache getter gets new config') t.equal(npm.lockfileVersion, 2, 'lockfileVersion getter') t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix') t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix') - npm.globalPrefix = npm.prefix - t.equal(npm.prefix, npm.globalPrefix, 'globalPrefix setter') - npm.localPrefix = dir + '/extra/prefix' - t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after localPrefix setter') - t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after localPrefix setter') - - npm.prefix = dir + '/some/prefix' - t.equal(npm.prefix, npm.localPrefix, 'prefix is local prefix after prefix setter') - t.not(npm.prefix, npm.globalPrefix, 'prefix is not global prefix after prefix setter') - t.equal(npm.bin, npm.localBin, 'bin is local bin after prefix setter') - t.not(npm.bin, npm.globalBin, 'bin is not global bin after prefix setter') - t.equal(npm.dir, npm.localDir, 'dir is local dir after prefix setter') - t.not(npm.dir, npm.globalDir, 'dir is not global dir after prefix setter') + t.equal(npm.bin, npm.localBin, 'bin is local bin') + t.not(npm.bin, npm.globalBin, 'bin is not global bin') npm.config.set('global', true) t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after setting global') @@ -89,12 +72,6 @@ t.test('npm.load', async t => { t.equal(npm.dir, npm.globalDir, 'dir is global dir after setting global') t.not(npm.dir, npm.localDir, 'dir is not local dir after setting global') - npm.prefix = dir + '/new/global/prefix' - t.equal(npm.prefix, npm.globalPrefix, 'prefix is global prefix after prefix setter') - t.not(npm.prefix, npm.localPrefix, 'prefix is not local prefix after prefix setter') - t.equal(npm.bin, npm.globalBin, 'bin is global bin after prefix setter') - t.not(npm.bin, npm.localBin, 'bin is not local bin after prefix setter') - mockGlobals(t, { process: { platform: 'win32' } }) t.equal(npm.bin, npm.globalBin, 'bin is global bin in windows mode') t.equal(npm.dir, npm.globalDir, 'dir is global dir in windows mode') From 9fea38399141a79a688b87fc16e2d1adeacd75f7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:27:11 +0000 Subject: [PATCH 34/42] chore: release 10.6.0 --- .release-please-manifest.json | 28 ++++----- AUTHORS | 2 + CHANGELOG.md | 82 +++++++++++++++++++++++++++ package-lock.json | 30 +++++----- package.json | 2 +- workspaces/arborist/CHANGELOG.md | 32 +++++++++++ workspaces/arborist/package.json | 2 +- workspaces/config/CHANGELOG.md | 19 +++++++ workspaces/config/package.json | 2 +- workspaces/libnpmaccess/CHANGELOG.md | 7 +++ workspaces/libnpmaccess/package.json | 2 +- workspaces/libnpmdiff/CHANGELOG.md | 19 +++++++ workspaces/libnpmdiff/package.json | 2 +- workspaces/libnpmexec/CHANGELOG.md | 22 +++++++ workspaces/libnpmexec/package.json | 2 +- workspaces/libnpmfund/CHANGELOG.md | 6 ++ workspaces/libnpmfund/package.json | 2 +- workspaces/libnpmhook/CHANGELOG.md | 6 ++ workspaces/libnpmhook/package.json | 2 +- workspaces/libnpmorg/CHANGELOG.md | 6 ++ workspaces/libnpmorg/package.json | 2 +- workspaces/libnpmpack/CHANGELOG.md | 22 +++++++ workspaces/libnpmpack/package.json | 2 +- workspaces/libnpmpublish/CHANGELOG.md | 10 ++++ workspaces/libnpmpublish/package.json | 2 +- workspaces/libnpmsearch/CHANGELOG.md | 6 ++ workspaces/libnpmsearch/package.json | 2 +- workspaces/libnpmteam/CHANGELOG.md | 6 ++ workspaces/libnpmteam/package.json | 2 +- workspaces/libnpmversion/CHANGELOG.md | 22 +++++++ workspaces/libnpmversion/package.json | 2 +- 31 files changed, 310 insertions(+), 43 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index af5e2e905d552..324a735ade2f2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,16 +1,16 @@ { - ".": "10.5.2", - "workspaces/arborist": "7.4.2", - "workspaces/libnpmaccess": "8.0.3", - "workspaces/libnpmdiff": "6.0.9", - "workspaces/libnpmexec": "7.0.10", - "workspaces/libnpmfund": "5.0.7", - "workspaces/libnpmhook": "10.0.2", - "workspaces/libnpmorg": "6.0.3", - "workspaces/libnpmpack": "6.0.9", - "workspaces/libnpmpublish": "9.0.5", - "workspaces/libnpmsearch": "7.0.2", - "workspaces/libnpmteam": "6.0.2", - "workspaces/libnpmversion": "5.0.2", - "workspaces/config": "8.2.2" + ".": "10.6.0", + "workspaces/arborist": "7.5.0", + "workspaces/libnpmaccess": "8.0.4", + "workspaces/libnpmdiff": "6.1.0", + "workspaces/libnpmexec": "8.0.0", + "workspaces/libnpmfund": "5.0.8", + "workspaces/libnpmhook": "10.0.3", + "workspaces/libnpmorg": "6.0.4", + "workspaces/libnpmpack": "7.0.0", + "workspaces/libnpmpublish": "9.0.6", + "workspaces/libnpmsearch": "7.0.3", + "workspaces/libnpmteam": "6.0.3", + "workspaces/libnpmversion": "6.0.0", + "workspaces/config": "8.3.0" } diff --git a/AUTHORS b/AUTHORS index 76fc1839629f1..06c916e430792 100644 --- a/AUTHORS +++ b/AUTHORS @@ -930,3 +930,5 @@ David LJ Uiolee <22849383+uiolee@users.noreply.github.com> Vinicius Lourenço <12551007+H4ad@users.noreply.github.com> roni-berlin <72336831+roni-berlin@users.noreply.github.com> +Marc Bernard <59966492+mbtools@users.noreply.github.com> +Erik Williamson diff --git a/CHANGELOG.md b/CHANGELOG.md index 9578e0278acc3..cf11230bc20bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,87 @@ # Changelog +## [10.6.0](https://github.com/npm/cli/compare/v10.5.2...v10.6.0) (2024-04-25) + +### Features + +* [`9123de4`](https://github.com/npm/cli/commit/9123de4d282bfd19ea17ad613f5a2acab0e0e162) [#7373](https://github.com/npm/cli/pull/7373) do all ouput over proc-log events (@lukekarrys) +* [`9622597`](https://github.com/npm/cli/commit/9622597399ec93224fddf90a9209a98dbcfd6b2f) [#7339](https://github.com/npm/cli/pull/7339) refactor terminal display (#7339) (@lukekarrys) + +### Bug Fixes + +* [`0e74ee4`](https://github.com/npm/cli/commit/0e74ee42cbd2cbe438e64a2426767dad1868e70d) [#7416](https://github.com/npm/cli/pull/7416) clean up npm object (#7416) (@wraithgar) +* [`c060e60`](https://github.com/npm/cli/commit/c060e60a7ce767f6fdb32782c0d373e717df7856) [#7415](https://github.com/npm/cli/pull/7415) return command and argv from load (@lukekarrys) +* [`180b919`](https://github.com/npm/cli/commit/180b919d2322e55ec5d58bbd476c3ecc31880479) [#7415](https://github.com/npm/cli/pull/7415) remove unused npm.setCmd method (@lukekarrys) +* [`0708b3b`](https://github.com/npm/cli/commit/0708b3b2dbfc811b0e692133557b6b2e698519fd) [#7414](https://github.com/npm/cli/pull/7414) use name of level instead of label for logging prefixes (#7414) (@lukekarrys) +* [`7f4e667`](https://github.com/npm/cli/commit/7f4e66772ee631158b47fcfcd8e22b7b6b9b9cce) [#7403](https://github.com/npm/cli/pull/7403) redact when displaying non-ascii arguments (@lukekarrys) +* [`06202f0`](https://github.com/npm/cli/commit/06202f0e13d91f5ee6edfe2da6ee21bafbf18cca) [#7403](https://github.com/npm/cli/pull/7403) store unref promises for awaiting in tests (@lukekarrys) +* [`e5f1948`](https://github.com/npm/cli/commit/e5f1948a569224c59a9a4fdeb0e3b82312fb87c6) [#7403](https://github.com/npm/cli/pull/7403) run update notifier after exec but before waiting (@lukekarrys) +* [`f309c1c`](https://github.com/npm/cli/commit/f309c1cd8ab26b9cdc3b1224499aba345edfc582) [#7403](https://github.com/npm/cli/pull/7403) refactor: move timer and error logfile messages to lib/npm (@lukekarrys) +* [`43e6194`](https://github.com/npm/cli/commit/43e619480568493433af78208e2b3c48843185ef) [#7403](https://github.com/npm/cli/pull/7403) dont show run script banners in silent (@lukekarrys) +* [`694dba9`](https://github.com/npm/cli/commit/694dba9fd9a8d71facc7b832bf8f00ca9468e68a) [#7403](https://github.com/npm/cli/pull/7403) dont expose as many public properties of timers (@lukekarrys) +* [`7ca6d84`](https://github.com/npm/cli/commit/7ca6d8490b675c9d4c402ae8e41c9afd5871aa35) [#7403](https://github.com/npm/cli/pull/7403) use proc-log META for flush and force (@lukekarrys) +* [`2538438`](https://github.com/npm/cli/commit/25384388e01d1c9d6c4cae4a49149407b0024176) [#7403](https://github.com/npm/cli/pull/7403) dont write timing logs to file unless requested (@lukekarrys) +* [`7e04417`](https://github.com/npm/cli/commit/7e04417d4b084043300d1cdd5b4dce8ea7184d9e) [#7403](https://github.com/npm/cli/pull/7403) rename base-cmd to match other commands (@lukekarrys) +* [`fc68547`](https://github.com/npm/cli/commit/fc68547eb9b06a1a6a2a0feb7e422accec50230d) [#7403](https://github.com/npm/cli/pull/7403) remove some npm.load timers and exit earlier for --versions (@lukekarrys) +* [`28019d5`](https://github.com/npm/cli/commit/28019d50fdb1b2395199516694180edc7b4f8dd6) [#7403](https://github.com/npm/cli/pull/7403) cleanup: move cli specific files to separate dir (@lukekarrys) +* [`469f788`](https://github.com/npm/cli/commit/469f7885ca47f79bbd3c7171dc56a471a3e422a2) [#7403](https://github.com/npm/cli/pull/7403) cleanup: newlines and whitespace (@lukekarrys) +* [`4ab6401`](https://github.com/npm/cli/commit/4ab64013236925e7bceb9f88cfcc81f4a65f292f) [#7403](https://github.com/npm/cli/pull/7403) cleanup: dont nest files utils dir (@lukekarrys) +* [`78447d7`](https://github.com/npm/cli/commit/78447d7a35fab870456ba66eee408b2baddca23e) [#7399](https://github.com/npm/cli/pull/7399) prefer fs/promises over promisify (#7399) (@lukekarrys) +* [`d531f8b`](https://github.com/npm/cli/commit/d531f8b9237fabf640d421a8c4ea3c4284e00f0a) [#7407](https://github.com/npm/cli/pull/7407) Remove table output from search and tar summary (@wraithgar) +* [`c209e98`](https://github.com/npm/cli/commit/c209e989b405fa3e86df7015c22e6840e18313b8) [#7401](https://github.com/npm/cli/pull/7401) Remove table output from many commands (@wraithgar) +* [`ad7ab8c`](https://github.com/npm/cli/commit/ad7ab8c19994c1d2a452278edba65968185d3871) [#7388](https://github.com/npm/cli/pull/7388) perf: lazy loading optimizations (#7388) (@wraithgar) +* [`8eae4b3`](https://github.com/npm/cli/commit/8eae4b3b30a7375f0f9dd4172a8b683efe0bb354) [#7385](https://github.com/npm/cli/pull/7385) token: properly await registry request (#7385) (@wraithgar) +* [`9216d59`](https://github.com/npm/cli/commit/9216d5985fb3e2a2754be5bf0b1d43fc321cf723) [#7377](https://github.com/npm/cli/pull/7377) better output colors (#7377) (@wraithgar) +* [`6512112`](https://github.com/npm/cli/commit/65121122d99855541f63aa787f8ee8bb4eea4a3f) [#7378](https://github.com/npm/cli/pull/7378) use proc-log for all timers (@lukekarrys) +* [`2a80dab`](https://github.com/npm/cli/commit/2a80dab2ed1feedf3cd3af8ff7f41846567b2fd3) [#7370](https://github.com/npm/cli/pull/7370) typo in `npm access` usage (#7370) (@mbtools) + +### Documentation + +* [`dfa4cab`](https://github.com/npm/cli/commit/dfa4cabdccdd1c82cc160bb435c29c45ed05fdf4) [#7401](https://github.com/npm/cli/pull/7401) update output examples (@wraithgar) +* [`140b9c9`](https://github.com/npm/cli/commit/140b9c988d08beb6c3cd95b67cd4135ed32a19e6) [#7382](https://github.com/npm/cli/pull/7382) package-json: note that line endings are inferred (#7382) (@ertw) +* [`c16dd4e`](https://github.com/npm/cli/commit/c16dd4e46b58d6c4490284e6edc5c255862e322b) [#7367](https://github.com/npm/cli/pull/7367) Document that overrides only work in the root `package.json` (#7367) (@s100) + +### Dependencies + +* [`36adff3`](https://github.com/npm/cli/commit/36adff36c41f56315fe582e1e4dda29060f7fdf7) [#7408](https://github.com/npm/cli/pull/7408) `pacote@18.0.2` +* [`486d46c`](https://github.com/npm/cli/commit/486d46cd5b5678ad1ab6c23ee12cf7559477805a) [#7408](https://github.com/npm/cli/pull/7408) `@npmcli/installed-package-contents@2.1.0` +* [`157d0ae`](https://github.com/npm/cli/commit/157d0aebfe5710880d0c91bddee970316b8a6612) [#7408](https://github.com/npm/cli/pull/7408) `@npmcli/package-json@5.1.0` +* [`b0ca163`](https://github.com/npm/cli/commit/b0ca16310d9db944dd13f80ecce534c65eea42c5) [#7409](https://github.com/npm/cli/pull/7409) remove @npmcli/disparity-colors +* [`c77f035`](https://github.com/npm/cli/commit/c77f035fc18fdc0a9eb3ef0a7d1faf2c7aec6af3) [#7407](https://github.com/npm/cli/pull/7407) remove columnify +* [`2ec690d`](https://github.com/npm/cli/commit/2ec690da99fb441cdd7069480b42b6302e098005) [#7401](https://github.com/npm/cli/pull/7401) move cli-table3 to devDependencies +* [`fc6e291`](https://github.com/npm/cli/commit/fc6e291e9c2154c2e76636cb7ebf0a17be307585) [#7392](https://github.com/npm/cli/pull/7392) `proc-log@4.2.0` (#7392) +* [`38ed048`](https://github.com/npm/cli/commit/38ed048ac0d7a36785dbff0eeca3618cb7f084c5) [#7378](https://github.com/npm/cli/pull/7378) `@npmcli/metavuln-calculator@7.1.0` +* [`7678a3d`](https://github.com/npm/cli/commit/7678a3d92835457bb402c82e4ca7ea3fa734d23b) [#7378](https://github.com/npm/cli/pull/7378) `proc-log@4.1.0` +* [`87f6c09`](https://github.com/npm/cli/commit/87f6c094ac47f4e6eb5d5d6a03a0ad97711b51e9) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/metavuln-calculator@7.0.1` +* [`b8f8b41`](https://github.com/npm/cli/commit/b8f8b414d8ad9635e3efedc6e491c8c6e3df0973) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/run-script@8.0.0` +* [`79f79c7`](https://github.com/npm/cli/commit/79f79c7460be8a74f2b77c647100bcefd89b2efa) [#7373](https://github.com/npm/cli/pull/7373) `proc-log@4.0.0` +* [`9027266`](https://github.com/npm/cli/commit/90272661b16d861a5926af8ec394d32ec0f307fd) [#7373](https://github.com/npm/cli/pull/7373) `pacote@18.0.0` +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` +* [`0e7789b`](https://github.com/npm/cli/commit/0e7789b7d9ec88c89edcdade9fc898c131ed492a) [#7373](https://github.com/npm/cli/pull/7373) `npm-profile@9.0.1` +* [`ac98fd3`](https://github.com/npm/cli/commit/ac98fd3a8514f2552555d2b8af74a52e64888797) [#7373](https://github.com/npm/cli/pull/7373) `npm-package-arg@11.0.2` +* [`9351570`](https://github.com/npm/cli/commit/93515700efbb2147a6e929cf117da9e6e87c0aca) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/package-json@5.0.3` +* [`d3a0cfa`](https://github.com/npm/cli/commit/d3a0cfad06ddffe6a3d4968257b7993aea68fc7c) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/git@5.0.6` +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v7.5.0): `@npmcli/arborist@7.5.0` +* [workspace](https://github.com/npm/cli/releases/tag/config-v8.3.0): `@npmcli/config@8.3.0` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmaccess-v8.0.4): `libnpmaccess@8.0.4` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmdiff-v6.1.0): `libnpmdiff@6.1.0` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmexec-v8.0.0): `libnpmexec@8.0.0` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmfund-v5.0.8): `libnpmfund@5.0.8` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmhook-v10.0.3): `libnpmhook@10.0.3` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmorg-v6.0.4): `libnpmorg@6.0.4` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmpack-v7.0.0): `libnpmpack@7.0.0` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmpublish-v9.0.6): `libnpmpublish@9.0.6` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmsearch-v7.0.3): `libnpmsearch@7.0.3` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmteam-v6.0.3): `libnpmteam@6.0.3` +* [workspace](https://github.com/npm/cli/releases/tag/libnpmversion-v6.0.0): `libnpmversion@6.0.0` + +### Chores + +* [`3cbc258`](https://github.com/npm/cli/commit/3cbc25800bbd14a8b22ee3feddad715b3a6436d7) [#7403](https://github.com/npm/cli/pull/7403) test for early version exit (@lukekarrys) +* [`08e0c0e`](https://github.com/npm/cli/commit/08e0c0ed1ad7bc2f12b4f358eb3e6b18bdbca053) [#7403](https://github.com/npm/cli/pull/7403) move sigstore json files to fixtures dir (@lukekarrys) +* [`ea66e95`](https://github.com/npm/cli/commit/ea66e9534f4b9004f8b4c53a2f8adb7688ee9b36) [#7380](https://github.com/npm/cli/pull/7380) remove licensee as a devDependency (#7380) (@lukekarrys, @wraithgar) +* [`9333e9d`](https://github.com/npm/cli/commit/9333e9df9b6ad3143f084a25b0e7ea347c8094d3) [#7386](https://github.com/npm/cli/pull/7386) reduce windows shim test flakes (#7386) (@lukekarrys) + ## [10.5.2](https://github.com/npm/cli/compare/v10.5.1...v10.5.2) (2024-04-10) ### Bug Fixes diff --git a/package-lock.json b/package-lock.json index 31e6c9f394223..4838840d521da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm", - "version": "10.5.2", + "version": "10.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "npm", - "version": "10.5.2", + "version": "10.6.0", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -14960,7 +14960,7 @@ }, "workspaces/arborist": { "name": "@npmcli/arborist", - "version": "7.4.2", + "version": "7.5.0", "license": "ISC", "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", @@ -15017,7 +15017,7 @@ }, "workspaces/config": { "name": "@npmcli/config", - "version": "8.2.2", + "version": "8.3.0", "license": "ISC", "dependencies": { "@npmcli/map-workspaces": "^3.0.2", @@ -15040,7 +15040,7 @@ } }, "workspaces/libnpmaccess": { - "version": "8.0.3", + "version": "8.0.4", "license": "ISC", "dependencies": { "npm-package-arg": "^11.0.2", @@ -15058,7 +15058,7 @@ } }, "workspaces/libnpmdiff": { - "version": "6.0.9", + "version": "6.1.0", "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1", @@ -15080,7 +15080,7 @@ } }, "workspaces/libnpmexec": { - "version": "7.0.10", + "version": "8.0.0", "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1", @@ -15109,7 +15109,7 @@ } }, "workspaces/libnpmfund": { - "version": "5.0.7", + "version": "5.0.8", "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1" @@ -15124,7 +15124,7 @@ } }, "workspaces/libnpmhook": { - "version": "10.0.2", + "version": "10.0.3", "license": "ISC", "dependencies": { "aproba": "^2.0.0", @@ -15141,7 +15141,7 @@ } }, "workspaces/libnpmorg": { - "version": "6.0.3", + "version": "6.0.4", "license": "ISC", "dependencies": { "aproba": "^2.0.0", @@ -15159,7 +15159,7 @@ } }, "workspaces/libnpmpack": { - "version": "6.0.9", + "version": "7.0.0", "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1", @@ -15179,7 +15179,7 @@ } }, "workspaces/libnpmpublish": { - "version": "9.0.5", + "version": "9.0.6", "license": "ISC", "dependencies": { "ci-info": "^4.0.0", @@ -15204,7 +15204,7 @@ } }, "workspaces/libnpmsearch": { - "version": "7.0.2", + "version": "7.0.3", "license": "ISC", "dependencies": { "npm-registry-fetch": "^16.2.1" @@ -15220,7 +15220,7 @@ } }, "workspaces/libnpmteam": { - "version": "6.0.2", + "version": "6.0.3", "license": "ISC", "dependencies": { "aproba": "^2.0.0", @@ -15237,7 +15237,7 @@ } }, "workspaces/libnpmversion": { - "version": "5.0.2", + "version": "6.0.0", "license": "ISC", "dependencies": { "@npmcli/git": "^5.0.6", diff --git a/package.json b/package.json index 9bb9b3a16ee43..29ac300c41250 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "10.5.2", + "version": "10.6.0", "name": "npm", "description": "a package manager for JavaScript", "workspaces": [ diff --git a/workspaces/arborist/CHANGELOG.md b/workspaces/arborist/CHANGELOG.md index 7fc3a74fb11a3..f2a087b3e47af 100644 --- a/workspaces/arborist/CHANGELOG.md +++ b/workspaces/arborist/CHANGELOG.md @@ -1,5 +1,37 @@ # Changelog +## [7.5.0](https://github.com/npm/cli/compare/arborist-v7.4.2...arborist-v7.5.0) (2024-04-25) + +### Features + +* [`9123de4`](https://github.com/npm/cli/commit/9123de4d282bfd19ea17ad613f5a2acab0e0e162) [#7373](https://github.com/npm/cli/pull/7373) do all ouput over proc-log events (@lukekarrys) +* [`9622597`](https://github.com/npm/cli/commit/9622597399ec93224fddf90a9209a98dbcfd6b2f) [#7339](https://github.com/npm/cli/pull/7339) refactor terminal display (#7339) (@lukekarrys) + +### Bug Fixes + +* [`78447d7`](https://github.com/npm/cli/commit/78447d7a35fab870456ba66eee408b2baddca23e) [#7399](https://github.com/npm/cli/pull/7399) prefer fs/promises over promisify (#7399) (@lukekarrys) +* [`6512112`](https://github.com/npm/cli/commit/65121122d99855541f63aa787f8ee8bb4eea4a3f) [#7378](https://github.com/npm/cli/pull/7378) use proc-log for all timers (@lukekarrys) + +### Dependencies + +* [`36adff3`](https://github.com/npm/cli/commit/36adff36c41f56315fe582e1e4dda29060f7fdf7) [#7408](https://github.com/npm/cli/pull/7408) `pacote@18.0.2` +* [`486d46c`](https://github.com/npm/cli/commit/486d46cd5b5678ad1ab6c23ee12cf7559477805a) [#7408](https://github.com/npm/cli/pull/7408) `@npmcli/installed-package-contents@2.1.0` +* [`157d0ae`](https://github.com/npm/cli/commit/157d0aebfe5710880d0c91bddee970316b8a6612) [#7408](https://github.com/npm/cli/pull/7408) `@npmcli/package-json@5.1.0` +* [`fc6e291`](https://github.com/npm/cli/commit/fc6e291e9c2154c2e76636cb7ebf0a17be307585) [#7392](https://github.com/npm/cli/pull/7392) `proc-log@4.2.0` (#7392) +* [`38ed048`](https://github.com/npm/cli/commit/38ed048ac0d7a36785dbff0eeca3618cb7f084c5) [#7378](https://github.com/npm/cli/pull/7378) `@npmcli/metavuln-calculator@7.1.0` +* [`7678a3d`](https://github.com/npm/cli/commit/7678a3d92835457bb402c82e4ca7ea3fa734d23b) [#7378](https://github.com/npm/cli/pull/7378) `proc-log@4.1.0` +* [`87f6c09`](https://github.com/npm/cli/commit/87f6c094ac47f4e6eb5d5d6a03a0ad97711b51e9) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/metavuln-calculator@7.0.1` +* [`b8f8b41`](https://github.com/npm/cli/commit/b8f8b414d8ad9635e3efedc6e491c8c6e3df0973) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/run-script@8.0.0` +* [`79f79c7`](https://github.com/npm/cli/commit/79f79c7460be8a74f2b77c647100bcefd89b2efa) [#7373](https://github.com/npm/cli/pull/7373) `proc-log@4.0.0` +* [`9027266`](https://github.com/npm/cli/commit/90272661b16d861a5926af8ec394d32ec0f307fd) [#7373](https://github.com/npm/cli/pull/7373) `pacote@18.0.0` +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` +* [`ac98fd3`](https://github.com/npm/cli/commit/ac98fd3a8514f2552555d2b8af74a52e64888797) [#7373](https://github.com/npm/cli/pull/7373) `npm-package-arg@11.0.2` +* [`9351570`](https://github.com/npm/cli/commit/93515700efbb2147a6e929cf117da9e6e87c0aca) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/package-json@5.0.3` + +### Chores + +* [`dd39de7`](https://github.com/npm/cli/commit/dd39de7d1da743cbd33b671fa96f66667109b451) [#7411](https://github.com/npm/cli/pull/7411) disable selflink test on apple silicon (#7411) (@lukekarrys) + ## [7.4.2](https://github.com/npm/cli/compare/arborist-v7.4.1...arborist-v7.4.2) (2024-04-10) ### Bug Fixes diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index bca86d9451966..a8eec08783ddf 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/arborist", - "version": "7.4.2", + "version": "7.5.0", "description": "Manage node_modules trees", "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", diff --git a/workspaces/config/CHANGELOG.md b/workspaces/config/CHANGELOG.md index 2321f5e0ac26e..935738761d07f 100644 --- a/workspaces/config/CHANGELOG.md +++ b/workspaces/config/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [8.3.0](https://github.com/npm/cli/compare/config-v8.2.2...config-v8.3.0) (2024-04-25) + +### Features + +* [`9123de4`](https://github.com/npm/cli/commit/9123de4d282bfd19ea17ad613f5a2acab0e0e162) [#7373](https://github.com/npm/cli/pull/7373) do all ouput over proc-log events (@lukekarrys) + +### Bug Fixes + +* [`03634be`](https://github.com/npm/cli/commit/03634be50fd1159e42f73ef4aa71bf5f06eb5ada) [#7403](https://github.com/npm/cli/pull/7403) remove granular config timers (@lukekarrys) +* [`78447d7`](https://github.com/npm/cli/commit/78447d7a35fab870456ba66eee408b2baddca23e) [#7399](https://github.com/npm/cli/pull/7399) prefer fs/promises over promisify (#7399) (@lukekarrys) +* [`6512112`](https://github.com/npm/cli/commit/65121122d99855541f63aa787f8ee8bb4eea4a3f) [#7378](https://github.com/npm/cli/pull/7378) use proc-log for all timers (@lukekarrys) + +### Dependencies + +* [`fc6e291`](https://github.com/npm/cli/commit/fc6e291e9c2154c2e76636cb7ebf0a17be307585) [#7392](https://github.com/npm/cli/pull/7392) `proc-log@4.2.0` (#7392) +* [`7678a3d`](https://github.com/npm/cli/commit/7678a3d92835457bb402c82e4ca7ea3fa734d23b) [#7378](https://github.com/npm/cli/pull/7378) `proc-log@4.1.0` +* [`79f79c7`](https://github.com/npm/cli/commit/79f79c7460be8a74f2b77c647100bcefd89b2efa) [#7373](https://github.com/npm/cli/pull/7373) `proc-log@4.0.0` +* [`9027266`](https://github.com/npm/cli/commit/90272661b16d861a5926af8ec394d32ec0f307fd) [#7373](https://github.com/npm/cli/pull/7373) `pacote@18.0.0` + ## [8.2.2](https://github.com/npm/cli/compare/config-v8.2.1...config-v8.2.2) (2024-04-10) ### Bug Fixes diff --git a/workspaces/config/package.json b/workspaces/config/package.json index 3fee07cd55fb0..140640587339d 100644 --- a/workspaces/config/package.json +++ b/workspaces/config/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/config", - "version": "8.2.2", + "version": "8.3.0", "files": [ "bin/", "lib/" diff --git a/workspaces/libnpmaccess/CHANGELOG.md b/workspaces/libnpmaccess/CHANGELOG.md index 1ffe80855ad07..d426edcb44e3f 100644 --- a/workspaces/libnpmaccess/CHANGELOG.md +++ b/workspaces/libnpmaccess/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [8.0.4](https://github.com/npm/cli/compare/libnpmaccess-v8.0.3...libnpmaccess-v8.0.4) (2024-04-25) + +### Dependencies + +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` +* [`ac98fd3`](https://github.com/npm/cli/commit/ac98fd3a8514f2552555d2b8af74a52e64888797) [#7373](https://github.com/npm/cli/pull/7373) `npm-package-arg@11.0.2` + ## [8.0.3](https://github.com/npm/cli/compare/libnpmaccess-v8.0.2...libnpmaccess-v8.0.3) (2024-04-03) ### Dependencies diff --git a/workspaces/libnpmaccess/package.json b/workspaces/libnpmaccess/package.json index de40271c06c21..75f164048c412 100644 --- a/workspaces/libnpmaccess/package.json +++ b/workspaces/libnpmaccess/package.json @@ -1,6 +1,6 @@ { "name": "libnpmaccess", - "version": "8.0.3", + "version": "8.0.4", "description": "programmatic library for `npm access` commands", "author": "GitHub Inc.", "license": "ISC", diff --git a/workspaces/libnpmdiff/CHANGELOG.md b/workspaces/libnpmdiff/CHANGELOG.md index aeb0839c25d05..e8207b62c38a6 100644 --- a/workspaces/libnpmdiff/CHANGELOG.md +++ b/workspaces/libnpmdiff/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [6.1.0](https://github.com/npm/cli/compare/libnpmdiff-v6.0.9...libnpmdiff-v6.1.0) (2024-04-25) + +### Features + +* [`9622597`](https://github.com/npm/cli/commit/9622597399ec93224fddf90a9209a98dbcfd6b2f) [#7339](https://github.com/npm/cli/pull/7339) refactor terminal display (#7339) (@lukekarrys) + +### Bug Fixes + +* [`03958c3`](https://github.com/npm/cli/commit/03958c375cd8fa9ec6d84ad35b7cc5cf5e9136f6) [#7409](https://github.com/npm/cli/pull/7409) inline color selector in libnpmdiff (@wraithgar) + +### Dependencies + +* [`36adff3`](https://github.com/npm/cli/commit/36adff36c41f56315fe582e1e4dda29060f7fdf7) [#7408](https://github.com/npm/cli/pull/7408) `pacote@18.0.2` +* [`486d46c`](https://github.com/npm/cli/commit/486d46cd5b5678ad1ab6c23ee12cf7559477805a) [#7408](https://github.com/npm/cli/pull/7408) `@npmcli/installed-package-contents@2.1.0` +* [`b0ca163`](https://github.com/npm/cli/commit/b0ca16310d9db944dd13f80ecce534c65eea42c5) [#7409](https://github.com/npm/cli/pull/7409) remove @npmcli/disparity-colors +* [`9027266`](https://github.com/npm/cli/commit/90272661b16d861a5926af8ec394d32ec0f307fd) [#7373](https://github.com/npm/cli/pull/7373) `pacote@18.0.0` +* [`ac98fd3`](https://github.com/npm/cli/commit/ac98fd3a8514f2552555d2b8af74a52e64888797) [#7373](https://github.com/npm/cli/pull/7373) `npm-package-arg@11.0.2` +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v7.5.0): `@npmcli/arborist@7.5.0` + ## [6.0.9](https://github.com/npm/cli/compare/libnpmdiff-v6.0.8...libnpmdiff-v6.0.9) (2024-04-10) ### Dependencies diff --git a/workspaces/libnpmdiff/package.json b/workspaces/libnpmdiff/package.json index adeb3fc09c5a7..5ae0e86e7aba0 100644 --- a/workspaces/libnpmdiff/package.json +++ b/workspaces/libnpmdiff/package.json @@ -1,6 +1,6 @@ { "name": "libnpmdiff", - "version": "6.0.9", + "version": "6.1.0", "description": "The registry diff", "repository": { "type": "git", diff --git a/workspaces/libnpmexec/CHANGELOG.md b/workspaces/libnpmexec/CHANGELOG.md index c251326801edf..80ccbc544eba0 100644 --- a/workspaces/libnpmexec/CHANGELOG.md +++ b/workspaces/libnpmexec/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [8.0.0](https://github.com/npm/cli/compare/libnpmexec-v7.0.10...libnpmexec-v8.0.0) (2024-04-25) + +### ⚠️ BREAKING CHANGES + +* libnpmexec now emits an output event on process instead of invoking the output function passed in + +### Features + +* [`39e4da0`](https://github.com/npm/cli/commit/39e4da0358ce44858117921b2aabe271ebcee797) [#7373](https://github.com/npm/cli/pull/7373) libnpmexec: no longer accept output function (@lukekarrys) +* [`9622597`](https://github.com/npm/cli/commit/9622597399ec93224fddf90a9209a98dbcfd6b2f) [#7339](https://github.com/npm/cli/pull/7339) refactor terminal display (#7339) (@lukekarrys) + +### Dependencies + +* [`36adff3`](https://github.com/npm/cli/commit/36adff36c41f56315fe582e1e4dda29060f7fdf7) [#7408](https://github.com/npm/cli/pull/7408) `pacote@18.0.2` +* [`fc6e291`](https://github.com/npm/cli/commit/fc6e291e9c2154c2e76636cb7ebf0a17be307585) [#7392](https://github.com/npm/cli/pull/7392) `proc-log@4.2.0` (#7392) +* [`7678a3d`](https://github.com/npm/cli/commit/7678a3d92835457bb402c82e4ca7ea3fa734d23b) [#7378](https://github.com/npm/cli/pull/7378) `proc-log@4.1.0` +* [`b8f8b41`](https://github.com/npm/cli/commit/b8f8b414d8ad9635e3efedc6e491c8c6e3df0973) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/run-script@8.0.0` +* [`79f79c7`](https://github.com/npm/cli/commit/79f79c7460be8a74f2b77c647100bcefd89b2efa) [#7373](https://github.com/npm/cli/pull/7373) `proc-log@4.0.0` +* [`9027266`](https://github.com/npm/cli/commit/90272661b16d861a5926af8ec394d32ec0f307fd) [#7373](https://github.com/npm/cli/pull/7373) `pacote@18.0.0` +* [`ac98fd3`](https://github.com/npm/cli/commit/ac98fd3a8514f2552555d2b8af74a52e64888797) [#7373](https://github.com/npm/cli/pull/7373) `npm-package-arg@11.0.2` +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v7.5.0): `@npmcli/arborist@7.5.0` + ## [7.0.10](https://github.com/npm/cli/compare/libnpmexec-v7.0.9...libnpmexec-v7.0.10) (2024-04-10) ### Dependencies diff --git a/workspaces/libnpmexec/package.json b/workspaces/libnpmexec/package.json index b06b983a77b7c..ec90878667520 100644 --- a/workspaces/libnpmexec/package.json +++ b/workspaces/libnpmexec/package.json @@ -1,6 +1,6 @@ { "name": "libnpmexec", - "version": "7.0.10", + "version": "8.0.0", "files": [ "bin/", "lib/" diff --git a/workspaces/libnpmfund/CHANGELOG.md b/workspaces/libnpmfund/CHANGELOG.md index 4e11712af9ab0..f316593d4ffcc 100644 --- a/workspaces/libnpmfund/CHANGELOG.md +++ b/workspaces/libnpmfund/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [5.0.8](https://github.com/npm/cli/compare/libnpmfund-v5.0.7...libnpmfund-v5.0.8) (2024-04-25) + +### Dependencies + +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v7.5.0): `@npmcli/arborist@7.5.0` + ## [5.0.7](https://github.com/npm/cli/compare/libnpmfund-v5.0.6...libnpmfund-v5.0.7) (2024-04-10) ### Dependencies diff --git a/workspaces/libnpmfund/package.json b/workspaces/libnpmfund/package.json index 978252999e92e..84363d55efdb5 100644 --- a/workspaces/libnpmfund/package.json +++ b/workspaces/libnpmfund/package.json @@ -1,6 +1,6 @@ { "name": "libnpmfund", - "version": "5.0.7", + "version": "5.0.8", "main": "lib/index.js", "files": [ "bin/", diff --git a/workspaces/libnpmhook/CHANGELOG.md b/workspaces/libnpmhook/CHANGELOG.md index 814f3ae553e9b..f0ca57a117ed4 100644 --- a/workspaces/libnpmhook/CHANGELOG.md +++ b/workspaces/libnpmhook/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [10.0.3](https://github.com/npm/cli/compare/libnpmhook-v10.0.2...libnpmhook-v10.0.3) (2024-04-25) + +### Dependencies + +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` + ## [10.0.2](https://github.com/npm/cli/compare/libnpmhook-v10.0.1...libnpmhook-v10.0.2) (2024-04-03) ### Dependencies diff --git a/workspaces/libnpmhook/package.json b/workspaces/libnpmhook/package.json index 31745cd7583aa..dde9aed6eb7f1 100644 --- a/workspaces/libnpmhook/package.json +++ b/workspaces/libnpmhook/package.json @@ -1,6 +1,6 @@ { "name": "libnpmhook", - "version": "10.0.2", + "version": "10.0.3", "description": "programmatic API for managing npm registry hooks", "main": "lib/index.js", "files": [ diff --git a/workspaces/libnpmorg/CHANGELOG.md b/workspaces/libnpmorg/CHANGELOG.md index f956c048d2c97..dafad98ef5671 100644 --- a/workspaces/libnpmorg/CHANGELOG.md +++ b/workspaces/libnpmorg/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [6.0.4](https://github.com/npm/cli/compare/libnpmorg-v6.0.3...libnpmorg-v6.0.4) (2024-04-25) + +### Dependencies + +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` + ## [6.0.3](https://github.com/npm/cli/compare/libnpmorg-v6.0.2...libnpmorg-v6.0.3) (2024-04-03) ### Dependencies diff --git a/workspaces/libnpmorg/package.json b/workspaces/libnpmorg/package.json index 626da4c72bb18..b41689ba765fe 100644 --- a/workspaces/libnpmorg/package.json +++ b/workspaces/libnpmorg/package.json @@ -1,6 +1,6 @@ { "name": "libnpmorg", - "version": "6.0.3", + "version": "6.0.4", "description": "Programmatic api for `npm org` commands", "author": "GitHub Inc.", "main": "lib/index.js", diff --git a/workspaces/libnpmpack/CHANGELOG.md b/workspaces/libnpmpack/CHANGELOG.md index bc1e0e1b5dcbd..f640cfabcb793 100644 --- a/workspaces/libnpmpack/CHANGELOG.md +++ b/workspaces/libnpmpack/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [7.0.0](https://github.com/npm/cli/compare/libnpmpack-v6.0.9...libnpmpack-v7.0.0) (2024-04-25) + +### ⚠️ BREAKING CHANGES + +* libnpmpack no longer takes a `silent` option to suppress output from `@npmcli/run-script`. That output is now emitted via an `output` event on `process`. + +### Features + +* [`ee9bf6e`](https://github.com/npm/cli/commit/ee9bf6eded4c339366bb76af3cb5adab3305d5f3) [#7373](https://github.com/npm/cli/pull/7373) libnpmpack: remove silent option (@lukekarrys) + +### Bug Fixes + +* [`78447d7`](https://github.com/npm/cli/commit/78447d7a35fab870456ba66eee408b2baddca23e) [#7399](https://github.com/npm/cli/pull/7399) prefer fs/promises over promisify (#7399) (@lukekarrys) + +### Dependencies + +* [`36adff3`](https://github.com/npm/cli/commit/36adff36c41f56315fe582e1e4dda29060f7fdf7) [#7408](https://github.com/npm/cli/pull/7408) `pacote@18.0.2` +* [`b8f8b41`](https://github.com/npm/cli/commit/b8f8b414d8ad9635e3efedc6e491c8c6e3df0973) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/run-script@8.0.0` +* [`9027266`](https://github.com/npm/cli/commit/90272661b16d861a5926af8ec394d32ec0f307fd) [#7373](https://github.com/npm/cli/pull/7373) `pacote@18.0.0` +* [`ac98fd3`](https://github.com/npm/cli/commit/ac98fd3a8514f2552555d2b8af74a52e64888797) [#7373](https://github.com/npm/cli/pull/7373) `npm-package-arg@11.0.2` +* [workspace](https://github.com/npm/cli/releases/tag/arborist-v7.5.0): `@npmcli/arborist@7.5.0` + ## [6.0.9](https://github.com/npm/cli/compare/libnpmpack-v6.0.8...libnpmpack-v6.0.9) (2024-04-10) ### Dependencies diff --git a/workspaces/libnpmpack/package.json b/workspaces/libnpmpack/package.json index 9ec7dcd15fee1..0f0e2e328d535 100644 --- a/workspaces/libnpmpack/package.json +++ b/workspaces/libnpmpack/package.json @@ -1,6 +1,6 @@ { "name": "libnpmpack", - "version": "6.0.9", + "version": "7.0.0", "description": "Programmatic API for the bits behind npm pack", "author": "GitHub Inc.", "main": "lib/index.js", diff --git a/workspaces/libnpmpublish/CHANGELOG.md b/workspaces/libnpmpublish/CHANGELOG.md index 33cbbc884f827..87faa4e52b9ee 100644 --- a/workspaces/libnpmpublish/CHANGELOG.md +++ b/workspaces/libnpmpublish/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [9.0.6](https://github.com/npm/cli/compare/libnpmpublish-v9.0.5...libnpmpublish-v9.0.6) (2024-04-25) + +### Dependencies + +* [`fc6e291`](https://github.com/npm/cli/commit/fc6e291e9c2154c2e76636cb7ebf0a17be307585) [#7392](https://github.com/npm/cli/pull/7392) `proc-log@4.2.0` (#7392) +* [`7678a3d`](https://github.com/npm/cli/commit/7678a3d92835457bb402c82e4ca7ea3fa734d23b) [#7378](https://github.com/npm/cli/pull/7378) `proc-log@4.1.0` +* [`79f79c7`](https://github.com/npm/cli/commit/79f79c7460be8a74f2b77c647100bcefd89b2efa) [#7373](https://github.com/npm/cli/pull/7373) `proc-log@4.0.0` +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` +* [`ac98fd3`](https://github.com/npm/cli/commit/ac98fd3a8514f2552555d2b8af74a52e64888797) [#7373](https://github.com/npm/cli/pull/7373) `npm-package-arg@11.0.2` + ## [9.0.5](https://github.com/npm/cli/compare/libnpmpublish-v9.0.4...libnpmpublish-v9.0.5) (2024-04-03) ### Dependencies diff --git a/workspaces/libnpmpublish/package.json b/workspaces/libnpmpublish/package.json index b79d130a3317f..0376bb359c7fd 100644 --- a/workspaces/libnpmpublish/package.json +++ b/workspaces/libnpmpublish/package.json @@ -1,6 +1,6 @@ { "name": "libnpmpublish", - "version": "9.0.5", + "version": "9.0.6", "description": "Programmatic API for the bits behind npm publish and unpublish", "author": "GitHub Inc.", "main": "lib/index.js", diff --git a/workspaces/libnpmsearch/CHANGELOG.md b/workspaces/libnpmsearch/CHANGELOG.md index 5ac7260e79d27..8ec158d618283 100644 --- a/workspaces/libnpmsearch/CHANGELOG.md +++ b/workspaces/libnpmsearch/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [7.0.3](https://github.com/npm/cli/compare/libnpmsearch-v7.0.2...libnpmsearch-v7.0.3) (2024-04-25) + +### Dependencies + +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` + ## [7.0.2](https://github.com/npm/cli/compare/libnpmsearch-v7.0.1...libnpmsearch-v7.0.2) (2024-04-03) ### Dependencies diff --git a/workspaces/libnpmsearch/package.json b/workspaces/libnpmsearch/package.json index 9edcd98913d3a..b9e29322c3301 100644 --- a/workspaces/libnpmsearch/package.json +++ b/workspaces/libnpmsearch/package.json @@ -1,6 +1,6 @@ { "name": "libnpmsearch", - "version": "7.0.2", + "version": "7.0.3", "description": "Programmatic API for searching in npm and compatible registries.", "author": "GitHub Inc.", "main": "lib/index.js", diff --git a/workspaces/libnpmteam/CHANGELOG.md b/workspaces/libnpmteam/CHANGELOG.md index 4e52f3e6098ea..4d08c78d64e11 100644 --- a/workspaces/libnpmteam/CHANGELOG.md +++ b/workspaces/libnpmteam/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [6.0.3](https://github.com/npm/cli/compare/libnpmteam-v6.0.2...libnpmteam-v6.0.3) (2024-04-25) + +### Dependencies + +* [`ee4b3e0`](https://github.com/npm/cli/commit/ee4b3e0e741545045dc03741c7147560961d867d) [#7373](https://github.com/npm/cli/pull/7373) `npm-registry-fetch@16.2.1` + ## [6.0.2](https://github.com/npm/cli/compare/libnpmteam-v6.0.1...libnpmteam-v6.0.2) (2024-04-03) ### Dependencies diff --git a/workspaces/libnpmteam/package.json b/workspaces/libnpmteam/package.json index b44847cc43a6a..e882a86c27c6d 100644 --- a/workspaces/libnpmteam/package.json +++ b/workspaces/libnpmteam/package.json @@ -1,7 +1,7 @@ { "name": "libnpmteam", "description": "npm Team management APIs", - "version": "6.0.2", + "version": "6.0.3", "author": "GitHub Inc.", "license": "ISC", "main": "lib/index.js", diff --git a/workspaces/libnpmversion/CHANGELOG.md b/workspaces/libnpmversion/CHANGELOG.md index 857476c430f8e..39ae411e3c87d 100644 --- a/workspaces/libnpmversion/CHANGELOG.md +++ b/workspaces/libnpmversion/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [6.0.0](https://github.com/npm/cli/compare/libnpmversion-v5.0.2...libnpmversion-v6.0.0) (2024-04-25) + +### ⚠️ BREAKING CHANGES + +* libnpmversion no longer takes a `silent` option to suppress output from `@npmcli/run-script`. That output is now emitted via an `output` event on `process`. + +### Features + +* [`60faa90`](https://github.com/npm/cli/commit/60faa9052a74d7a6ac8db59dae2d7017542310d7) [#7373](https://github.com/npm/cli/pull/7373) libnpmversion: remove silent option (@lukekarrys) + +### Bug Fixes + +* [`78447d7`](https://github.com/npm/cli/commit/78447d7a35fab870456ba66eee408b2baddca23e) [#7399](https://github.com/npm/cli/pull/7399) prefer fs/promises over promisify (#7399) (@lukekarrys) + +### Dependencies + +* [`fc6e291`](https://github.com/npm/cli/commit/fc6e291e9c2154c2e76636cb7ebf0a17be307585) [#7392](https://github.com/npm/cli/pull/7392) `proc-log@4.2.0` (#7392) +* [`7678a3d`](https://github.com/npm/cli/commit/7678a3d92835457bb402c82e4ca7ea3fa734d23b) [#7378](https://github.com/npm/cli/pull/7378) `proc-log@4.1.0` +* [`b8f8b41`](https://github.com/npm/cli/commit/b8f8b414d8ad9635e3efedc6e491c8c6e3df0973) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/run-script@8.0.0` +* [`79f79c7`](https://github.com/npm/cli/commit/79f79c7460be8a74f2b77c647100bcefd89b2efa) [#7373](https://github.com/npm/cli/pull/7373) `proc-log@4.0.0` +* [`d3a0cfa`](https://github.com/npm/cli/commit/d3a0cfad06ddffe6a3d4968257b7993aea68fc7c) [#7373](https://github.com/npm/cli/pull/7373) `@npmcli/git@5.0.6` + ## [5.0.2](https://github.com/npm/cli/compare/libnpmversion-v5.0.1...libnpmversion-v5.0.2) (2023-12-06) ### Chores diff --git a/workspaces/libnpmversion/package.json b/workspaces/libnpmversion/package.json index f6680955d29a0..7ec3866703b98 100644 --- a/workspaces/libnpmversion/package.json +++ b/workspaces/libnpmversion/package.json @@ -1,6 +1,6 @@ { "name": "libnpmversion", - "version": "5.0.2", + "version": "6.0.0", "main": "lib/index.js", "files": [ "bin/", From 57ebebf03d55d4eda2b6439149a97b595a191aaf Mon Sep 17 00:00:00 2001 From: Gar Date: Thu, 25 Apr 2024 13:22:26 -0700 Subject: [PATCH 35/42] fix: update repository.url in package.json (#7418) This is what npm changes it do during publish anyways --- docs/package.json | 2 +- mock-globals/package.json | 2 +- mock-registry/package.json | 2 +- package.json | 2 +- smoke-tests/package.json | 2 +- workspaces/arborist/package.json | 2 +- workspaces/config/package.json | 2 +- workspaces/libnpmaccess/package.json | 2 +- workspaces/libnpmdiff/package.json | 2 +- workspaces/libnpmexec/package.json | 2 +- workspaces/libnpmfund/package.json | 2 +- workspaces/libnpmhook/package.json | 2 +- workspaces/libnpmorg/package.json | 2 +- workspaces/libnpmpack/package.json | 2 +- workspaces/libnpmpublish/package.json | 2 +- workspaces/libnpmsearch/package.json | 2 +- workspaces/libnpmteam/package.json | 2 +- workspaces/libnpmversion/package.json | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/package.json b/docs/package.json index 95b96ce20ff08..5dd5904cf5636 100644 --- a/docs/package.json +++ b/docs/package.json @@ -16,7 +16,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "docs" }, "devDependencies": { diff --git a/mock-globals/package.json b/mock-globals/package.json index dfa33c0638018..778d324fd3d32 100644 --- a/mock-globals/package.json +++ b/mock-globals/package.json @@ -15,7 +15,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "mock-globals" }, "keywords": [], diff --git a/mock-registry/package.json b/mock-registry/package.json index eaa6b63e77ad8..3e6979dc3f42c 100644 --- a/mock-registry/package.json +++ b/mock-registry/package.json @@ -15,7 +15,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "mock-registry" }, "keywords": [], diff --git a/package.json b/package.json index 29ac300c41250..09d8817304a74 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "author": "GitHub Inc.", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git" + "url": "git+https://github.com/npm/cli.git" }, "bugs": { "url": "https://github.com/npm/cli/issues" diff --git a/smoke-tests/package.json b/smoke-tests/package.json index 85b33edeb8b94..1fe8f63819d36 100644 --- a/smoke-tests/package.json +++ b/smoke-tests/package.json @@ -14,7 +14,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "smoke-tests" }, "devDependencies": { diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index a8eec08783ddf..4b089fd967b3a 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -62,7 +62,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/arborist" }, "author": "GitHub Inc.", diff --git a/workspaces/config/package.json b/workspaces/config/package.json index 140640587339d..380b9ceb35864 100644 --- a/workspaces/config/package.json +++ b/workspaces/config/package.json @@ -9,7 +9,7 @@ "description": "Configuration management for the npm cli", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/config" }, "author": "GitHub Inc.", diff --git a/workspaces/libnpmaccess/package.json b/workspaces/libnpmaccess/package.json index 75f164048c412..5c925784f0cab 100644 --- a/workspaces/libnpmaccess/package.json +++ b/workspaces/libnpmaccess/package.json @@ -23,7 +23,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmaccess" }, "bugs": "https://github.com/npm/libnpmaccess/issues", diff --git a/workspaces/libnpmdiff/package.json b/workspaces/libnpmdiff/package.json index 5ae0e86e7aba0..3069fa118a623 100644 --- a/workspaces/libnpmdiff/package.json +++ b/workspaces/libnpmdiff/package.json @@ -4,7 +4,7 @@ "description": "The registry diff", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmdiff" }, "main": "lib/index.js", diff --git a/workspaces/libnpmexec/package.json b/workspaces/libnpmexec/package.json index ec90878667520..89cd0a35bdbbd 100644 --- a/workspaces/libnpmexec/package.json +++ b/workspaces/libnpmexec/package.json @@ -12,7 +12,7 @@ "description": "npm exec (npx) programmatic API", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmexec" }, "keywords": [ diff --git a/workspaces/libnpmfund/package.json b/workspaces/libnpmfund/package.json index 84363d55efdb5..450d331d88fea 100644 --- a/workspaces/libnpmfund/package.json +++ b/workspaces/libnpmfund/package.json @@ -9,7 +9,7 @@ "description": "Programmatic API for npm fund", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmfund" }, "keywords": [ diff --git a/workspaces/libnpmhook/package.json b/workspaces/libnpmhook/package.json index dde9aed6eb7f1..a2adca517cc96 100644 --- a/workspaces/libnpmhook/package.json +++ b/workspaces/libnpmhook/package.json @@ -18,7 +18,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmhook" }, "keywords": [ diff --git a/workspaces/libnpmorg/package.json b/workspaces/libnpmorg/package.json index b41689ba765fe..ce206c626ce68 100644 --- a/workspaces/libnpmorg/package.json +++ b/workspaces/libnpmorg/package.json @@ -35,7 +35,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmorg" }, "bugs": "https://github.com/npm/libnpmorg/issues", diff --git a/workspaces/libnpmpack/package.json b/workspaces/libnpmpack/package.json index 0f0e2e328d535..d25029101ef39 100644 --- a/workspaces/libnpmpack/package.json +++ b/workspaces/libnpmpack/package.json @@ -30,7 +30,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmpack" }, "bugs": "https://github.com/npm/libnpmpack/issues", diff --git a/workspaces/libnpmpublish/package.json b/workspaces/libnpmpublish/package.json index 0376bb359c7fd..0c3a38c566f64 100644 --- a/workspaces/libnpmpublish/package.json +++ b/workspaces/libnpmpublish/package.json @@ -32,7 +32,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmpublish" }, "bugs": "https://github.com/npm/cli/issues", diff --git a/workspaces/libnpmsearch/package.json b/workspaces/libnpmsearch/package.json index b9e29322c3301..7c7261a7b848e 100644 --- a/workspaces/libnpmsearch/package.json +++ b/workspaces/libnpmsearch/package.json @@ -32,7 +32,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmsearch" }, "bugs": "https://github.com/npm/libnpmsearch/issues", diff --git a/workspaces/libnpmteam/package.json b/workspaces/libnpmteam/package.json index e882a86c27c6d..a7943acb5e7ae 100644 --- a/workspaces/libnpmteam/package.json +++ b/workspaces/libnpmteam/package.json @@ -22,7 +22,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmteam" }, "files": [ diff --git a/workspaces/libnpmversion/package.json b/workspaces/libnpmversion/package.json index 7ec3866703b98..5a504acb237ad 100644 --- a/workspaces/libnpmversion/package.json +++ b/workspaces/libnpmversion/package.json @@ -9,7 +9,7 @@ "description": "library to do the things that 'npm version' does", "repository": { "type": "git", - "url": "https://github.com/npm/cli.git", + "url": "git+https://github.com/npm/cli.git", "directory": "workspaces/libnpmversion" }, "author": "GitHub Inc.", From 71cbd91b6f01875a99eeae989ea67489bdd0178d Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Thu, 25 Apr 2024 15:19:15 -0700 Subject: [PATCH 36/42] fix: hide banner for exec and explore (#7421) Fixes https://github.com/npm/cli/issues/7419 --- lib/npm.js | 39 +++++++++++++++++++++++---------------- lib/utils/display.js | 15 +++++++++++---- test/lib/docs.js | 2 +- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/lib/npm.js b/lib/npm.js index 84b22f2db5a80..df2297b215da7 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -93,14 +93,7 @@ class Npm { } async load () { - return time.start('npm:load', async () => { - const { exec } = await this.#load() - return { - exec, - command: this.argv.shift(), - args: this.argv, - } - }) + return time.start('npm:load', () => this.#load()) } get loaded () { @@ -165,7 +158,26 @@ class Npm { await time.start('npm:load:configload', () => this.config.load()) + // npm --versions + if (this.config.get('versions', 'cli')) { + this.argv = ['version'] + this.config.set('usage', false, 'cli') + } else { + this.argv = [...this.config.parsedArgv.remain] + } + + // Remove first argv since that is our command as typed + // Note that this might not be the actual name of the command + // due to aliases, etc. But we use the raw form of it later + // in user output so it must be preserved as is. + const commandArg = this.argv.shift() + + // This is the actual name of the command that will be run or + // undefined if deref could not find a match + const command = deref(commandArg) + await this.#display.load({ + command, loglevel: this.config.get('loglevel'), stdoutColor: this.color, stderrColor: this.logColor, @@ -202,9 +214,10 @@ class Npm { // note: this MUST be shorter than the actual argv length, because it // uses the same memory, so node will truncate it if it's too long. + // We time this because setting process.title is slow sometimes but we + // have to do it for security reasons. But still helpful to know how slow it is. time.start('npm:load:setTitle', () => { const { parsedArgv: { cooked, remain } } = this.config - this.argv = remain // Secrets are mostly in configs, so title is set using only the positional args // to keep those from being leaked. We still do a best effort replaceInfo. this.#title = ['npm'].concat(replaceInfo(remain)).join(' ').trim() @@ -244,13 +257,7 @@ class Npm { log.warn('using --force', 'Recommended protections disabled.') } - // npm --versions - if (this.config.get('versions', 'cli')) { - this.argv = ['version'] - this.config.set('usage', false, 'cli') - } - - return { exec: true } + return { exec: true, command: commandArg, args: this.argv } } get isShellout () { diff --git a/lib/utils/display.js b/lib/utils/display.js index 67c745f310415..299edc797aaf3 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -119,6 +119,7 @@ class Display { #progress // options + #command #levelIndex #timing #json @@ -159,6 +160,7 @@ class Display { } async load ({ + command, heading, json, loglevel, @@ -168,6 +170,7 @@ class Display { timing, unicode, }) { + this.#command = command // get createSupportsColor from chalk directly if this lands // https://github.com/chalk/chalk/pull/600 const [{ Chalk }, { createSupportsColor }] = await Promise.all([ @@ -272,10 +275,14 @@ class Display { return } - // HACK: if it looks like the banner and we are silent do not print it. - // There's no other way to do this right now :( - // eslint-disable-next-line max-len - if (this.#silent && args.length === 1 && args[0].startsWith('\n> ') && args[0].endsWith('\n')) { + // HACK: if it looks like the banner and we are in a state where we hide the + // banner then dont write any output. This hack can be replaced with proc-log.META + const isBanner = args.length === 1 && + typeof args[0] === 'string' && + args[0].startsWith('\n> ') && + args[0].endsWith('\n') + const hideBanner = this.#silent || ['exec', 'explore'].includes(this.#command) + if (isBanner && hideBanner) { return } diff --git a/test/lib/docs.js b/test/lib/docs.js index 7ace9b9995701..e074d556bb360 100644 --- a/test/lib/docs.js +++ b/test/lib/docs.js @@ -74,7 +74,7 @@ t.test('basic usage', async t => { // are generated in the following test const { npm } = await loadMockNpm(t, { mocks: { - '{LIB}/utils/cmd-list.js': { commands: [] }, + '{LIB}/utils/cmd-list.js': { ...cmdList, commands: [] }, }, config: { userconfig: '/some/config/file/.npmrc' }, globals: { process: { platform: 'posix' } }, From 762888a3b603704c7c53a94a704b8a7f3edea918 Mon Sep 17 00:00:00 2001 From: Gar Date: Fri, 26 Apr 2024 09:05:17 -0700 Subject: [PATCH 37/42] deps: update dependencies for workspaces (#7429) Fixes https://github.com/npm/cli/issues/7423 --- package-lock.json | 6 +++--- package.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4838840d521da..1493bbe5ca16f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -114,15 +114,15 @@ "json-parse-even-better-errors": "^3.0.1", "libnpmaccess": "^8.0.1", "libnpmdiff": "^6.0.3", - "libnpmexec": "^7.0.4", + "libnpmexec": "^8.0.0", "libnpmfund": "^5.0.1", "libnpmhook": "^10.0.0", "libnpmorg": "^6.0.1", - "libnpmpack": "^6.0.3", + "libnpmpack": "^7.0.0", "libnpmpublish": "^9.0.2", "libnpmsearch": "^7.0.0", "libnpmteam": "^6.0.0", - "libnpmversion": "^5.0.1", + "libnpmversion": "^6.0.0", "make-fetch-happen": "^13.0.0", "minimatch": "^9.0.4", "minipass": "^7.0.4", diff --git a/package.json b/package.json index 09d8817304a74..76debeb79dca0 100644 --- a/package.json +++ b/package.json @@ -78,15 +78,15 @@ "json-parse-even-better-errors": "^3.0.1", "libnpmaccess": "^8.0.1", "libnpmdiff": "^6.0.3", - "libnpmexec": "^7.0.4", + "libnpmexec": "^8.0.0", "libnpmfund": "^5.0.1", "libnpmhook": "^10.0.0", "libnpmorg": "^6.0.1", - "libnpmpack": "^6.0.3", + "libnpmpack": "^7.0.0", "libnpmpublish": "^9.0.2", "libnpmsearch": "^7.0.0", "libnpmteam": "^6.0.0", - "libnpmversion": "^5.0.1", + "libnpmversion": "^6.0.0", "make-fetch-happen": "^13.0.0", "minimatch": "^9.0.4", "minipass": "^7.0.4", From 52306473da03123ef5623e9e152e10285c8097f3 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 29 Apr 2024 10:05:24 -0700 Subject: [PATCH 38/42] fix: rewrite powershell scripts to use PSScriptRoot (#7422) Fixes #7417 Ref https://github.com/nodejs/node/issues/52682 --- bin/npm.ps1 | 35 ++++++++++++++--------------------- bin/npx.ps1 | 35 ++++++++++++++--------------------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/bin/npm.ps1 b/bin/npm.ps1 index 399e33360e853..797004fd3dc42 100644 --- a/bin/npm.ps1 +++ b/bin/npm.ps1 @@ -1,35 +1,28 @@ #!/usr/bin/env pwsh -$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent -$exe="" -if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { - # Fix case when both the Windows and Linux builds of Node - # are installed in the same directory - $exe=".exe" +$NODE_EXE="$PSScriptRoot/node.exe" +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="$PSScriptRoot/node" } -$ret=0 - -$nodeexe = "node$exe" -$nodebin = $(Get-Command $nodeexe -ErrorAction SilentlyContinue -ErrorVariable F).Source -if ($nodebin -eq $null) { - Write-Host "$nodeexe not found." - exit 1 +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="node" } -$nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path -$npmprefixjs="$nodedir/node_modules/npm/bin/npm-prefix.js" -$npmprefix=(& $nodeexe $npmprefixjs) +$NPM_PREFIX_JS="$PSScriptRoot/node_modules/npm/bin/npm-prefix.js" +$NPM_PREFIX=(& $NODE_EXE $NPM_PREFIX_JS) + if ($LASTEXITCODE -ne 0) { Write-Host "Could not determine Node.js install directory" exit 1 } -$npmprefixclijs="$npmprefix/node_modules/npm/bin/npm-cli.js" + +$NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js" # Support pipeline input if ($MyInvocation.ExpectingInput) { - $input | & $nodeexe $npmprefixclijs $args + $input | & $NODE_EXE $NPM_CLI_JS $args } else { - & $nodeexe $npmprefixclijs $args + & $NODE_EXE $NPM_CLI_JS $args } -$ret=$LASTEXITCODE -exit $ret + +exit $LASTEXITCODE diff --git a/bin/npx.ps1 b/bin/npx.ps1 index 1d59fc52083d7..01b851a82e8bb 100644 --- a/bin/npx.ps1 +++ b/bin/npx.ps1 @@ -1,35 +1,28 @@ #!/usr/bin/env pwsh -$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent -$exe="" -if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { - # Fix case when both the Windows and Linux builds of Node - # are installed in the same directory - $exe=".exe" +$NODE_EXE="$PSScriptRoot/node.exe" +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="$PSScriptRoot/node" } -$ret=0 - -$nodeexe = "node$exe" -$nodebin = $(Get-Command $nodeexe -ErrorAction SilentlyContinue -ErrorVariable F).Source -if ($nodebin -eq $null) { - Write-Host "$nodeexe not found." - exit 1 +if (-not (Test-Path $NODE_EXE)) { + $NODE_EXE="node" } -$nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path -$npmprefixjs="$nodedir/node_modules/npm/bin/npm-prefix.js" -$npmprefix=(& $nodeexe $npmprefixjs) +$NPM_PREFIX_JS="$PSScriptRoot/node_modules/npm/bin/npm-prefix.js" +$NPM_PREFIX=(& $NODE_EXE $NPM_PREFIX_JS) + if ($LASTEXITCODE -ne 0) { Write-Host "Could not determine Node.js install directory" exit 1 } -$npmprefixclijs="$npmprefix/node_modules/npm/bin/npx-cli.js" + +$NPX_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npx-cli.js" # Support pipeline input if ($MyInvocation.ExpectingInput) { - $input | & $nodeexe $npmprefixclijs $args + $input | & $NODE_EXE $NPX_CLI_JS $args } else { - & $nodeexe $npmprefixclijs $args + & $NODE_EXE $NPX_CLI_JS $args } -$ret=$LASTEXITCODE -exit $ret + +exit $LASTEXITCODE From 9da57388ebd5c643c2a95bbf63abc745cad45ccc Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 29 Apr 2024 10:06:04 -0700 Subject: [PATCH 39/42] deps: @npmcli/run-script@8.1.0 (#7437) --- .../@npmcli/run-script/lib/run-script-pkg.js | 6 ++++-- node_modules/@npmcli/run-script/package.json | 6 +++--- package-lock.json | 16 ++++++++-------- package.json | 2 +- workspaces/arborist/package.json | 2 +- workspaces/libnpmexec/package.json | 2 +- workspaces/libnpmpack/package.json | 2 +- workspaces/libnpmversion/package.json | 2 +- 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/node_modules/@npmcli/run-script/lib/run-script-pkg.js b/node_modules/@npmcli/run-script/lib/run-script-pkg.js index a4f27b500718c..9900c96315f85 100644 --- a/node_modules/@npmcli/run-script/lib/run-script-pkg.js +++ b/node_modules/@npmcli/run-script/lib/run-script-pkg.js @@ -44,6 +44,7 @@ const runScriptPkg = async options => { return { code: 0, signal: null } } + let inputEnd = () => {} if (stdio === 'inherit') { let banner if (pkg._id) { @@ -56,8 +57,9 @@ const runScriptPkg = async options => { banner += ` ${args.join(' ')}` } banner += '\n' - const { output } = require('proc-log') + const { output, input } = require('proc-log') output.standard(banner) + inputEnd = input.start() } const [spawnShell, spawnArgs, spawnOpts] = makeSpawnArgs({ @@ -104,7 +106,7 @@ const runScriptPkg = async options => { } else { throw er } - }) + }).finally(inputEnd) } module.exports = runScriptPkg diff --git a/node_modules/@npmcli/run-script/package.json b/node_modules/@npmcli/run-script/package.json index dc780ad3ecbec..8a83e726fbeb2 100644 --- a/node_modules/@npmcli/run-script/package.json +++ b/node_modules/@npmcli/run-script/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/run-script", - "version": "8.0.0", + "version": "8.1.0", "description": "Run a lifecycle script for a package (descendant of npm-lifecycle)", "author": "GitHub Inc.", "license": "ISC", @@ -16,7 +16,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.21.3", + "@npmcli/template-oss": "4.21.4", "spawk": "^1.8.1", "tap": "^16.0.1" }, @@ -42,7 +42,7 @@ }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.21.3", + "version": "4.21.4", "publish": "true" }, "tap": { diff --git a/package-lock.json b/package-lock.json index 1493bbe5ca16f..fe21cfb258713 100644 --- a/package-lock.json +++ b/package-lock.json @@ -95,7 +95,7 @@ "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.1", "@npmcli/redact": "^1.1.0", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "@sigstore/tuf": "^2.3.2", "abbrev": "^2.0.0", "archy": "~1.0.0", @@ -1802,9 +1802,9 @@ } }, "node_modules/@npmcli/run-script": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-8.0.0.tgz", - "integrity": "sha512-5noc+eCQmX1W9nlFUe65n5MIteikd3vOA2sEPdXtlUv68KWyHNFZnT/LDRXu/E4nZ5yxjciP30pADr/GQ97W1w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-8.1.0.tgz", + "integrity": "sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==", "inBundle": true, "dependencies": { "@npmcli/node-gyp": "^3.0.0", @@ -14973,7 +14973,7 @@ "@npmcli/package-json": "^5.1.0", "@npmcli/query": "^3.1.0", "@npmcli/redact": "^1.1.0", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "bin-links": "^4.0.1", "cacache": "^18.0.0", "common-ancestor-path": "^1.0.1", @@ -15084,7 +15084,7 @@ "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "ci-info": "^4.0.0", "npm-package-arg": "^11.0.2", "pacote": "^18.0.1", @@ -15163,7 +15163,7 @@ "license": "ISC", "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "npm-package-arg": "^11.0.2", "pacote": "^18.0.1" }, @@ -15241,7 +15241,7 @@ "license": "ISC", "dependencies": { "@npmcli/git": "^5.0.6", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "json-parse-even-better-errors": "^3.0.0", "proc-log": "^4.2.0", "semver": "^7.3.7" diff --git a/package.json b/package.json index 76debeb79dca0..570fad3703d37 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.1", "@npmcli/redact": "^1.1.0", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "@sigstore/tuf": "^2.3.2", "abbrev": "^2.0.0", "archy": "~1.0.0", diff --git a/workspaces/arborist/package.json b/workspaces/arborist/package.json index 4b089fd967b3a..26625d046e1e7 100644 --- a/workspaces/arborist/package.json +++ b/workspaces/arborist/package.json @@ -13,7 +13,7 @@ "@npmcli/package-json": "^5.1.0", "@npmcli/query": "^3.1.0", "@npmcli/redact": "^1.1.0", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "bin-links": "^4.0.1", "cacache": "^18.0.0", "common-ancestor-path": "^1.0.1", diff --git a/workspaces/libnpmexec/package.json b/workspaces/libnpmexec/package.json index 89cd0a35bdbbd..48e1938a9f828 100644 --- a/workspaces/libnpmexec/package.json +++ b/workspaces/libnpmexec/package.json @@ -60,7 +60,7 @@ }, "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "ci-info": "^4.0.0", "npm-package-arg": "^11.0.2", "pacote": "^18.0.1", diff --git a/workspaces/libnpmpack/package.json b/workspaces/libnpmpack/package.json index d25029101ef39..aa947bc814635 100644 --- a/workspaces/libnpmpack/package.json +++ b/workspaces/libnpmpack/package.json @@ -37,7 +37,7 @@ "homepage": "https://npmjs.com/package/libnpmpack", "dependencies": { "@npmcli/arborist": "^7.2.1", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "npm-package-arg": "^11.0.2", "pacote": "^18.0.1" }, diff --git a/workspaces/libnpmversion/package.json b/workspaces/libnpmversion/package.json index 5a504acb237ad..b7e0a152da9bd 100644 --- a/workspaces/libnpmversion/package.json +++ b/workspaces/libnpmversion/package.json @@ -38,7 +38,7 @@ }, "dependencies": { "@npmcli/git": "^5.0.6", - "@npmcli/run-script": "^8.0.0", + "@npmcli/run-script": "^8.1.0", "json-parse-even-better-errors": "^3.0.0", "proc-log": "^4.2.0", "semver": "^7.3.7" From 104fcb53282653a1c5610a6590afecc207920a6b Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 29 Apr 2024 16:10:33 -0700 Subject: [PATCH 40/42] fix: remove doctor log for each file permission check (#7438) The previous change was made as part of the removal of the old progress bar for doctor. Log messages for each individual file scanned were moved from showing up in the progress message only to `log.silly`. There can be a very large amount of files scanned, and there is no reason to log each one individually. --- lib/commands/doctor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/commands/doctor.js b/lib/commands/doctor.js index 339dcf15f70f2..e46c97a94bc90 100644 --- a/lib/commands/doctor.js +++ b/lib/commands/doctor.js @@ -223,7 +223,6 @@ class Doctor extends BaseCommand { const gid = process.getgid() const files = new Set([root]) for (const f of files) { - log.silly('doctor', 'checkFilesPermission', f.slice(root.length + 1)) const st = await lstat(f).catch(er => { // if it can't be missing, or if it can and the error wasn't that it was missing if (!missingOk || er.code !== 'ENOENT') { From 7e349f45363bb8dbe1cc803f8b48befc01aae7fd Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 29 Apr 2024 16:33:59 -0700 Subject: [PATCH 41/42] feat: add spinner (#7432) Closes #7425 This is a little hard to test because everything should continue to work without progress, as evidenced by the lack of churn in the tests and snapshots here. The only existing tests that changed are the addition of newlines after prompts which is new behavior as part of this PR. I resorted to manually running some commands to get an idea of how the various states worked together: **`node . exec -- npm@4`** This should show progress at the start and then hide it as it prompts the user to install `npm@4`. `Ctrl+C` should exit from the prompt and the error should display on the next line (this is a current bug). **`node . audit signatures --loglevel=http`** This should show a lot of http log messages while always keeping the spinner on the last line of output. The spinner also should not jump between frames regardless of how quickly the log messages show up. **`node . pack`** This should immediately show the banners and output from `prepack` and not show the spinner until the actual packing is happening. **`node . login`** The spinner should never while the prompt is being displayed. **`node . view npm`** The spinner should appear while data is being fetched and then disappear for the rest of the command as output is being displayed. The end output on completion should not have any spinner frames rendered on new lines in the output. The old progress bar achieved this by calling `npmlog.disableProgress()` but now it is able to hide the spinner appropriately even while outputting individual lines to stdout. --- DEPENDENCIES.md | 2 - lib/commands/init.js | 8 +- lib/utils/display.js | 304 ++++++++++++------ lib/utils/open-url-prompt.js | 10 +- lib/utils/read-user-info.js | 6 +- package-lock.json | 3 - package.json | 2 - .../test/lib/commands/init.js.test.cjs | 1 + test/fixtures/mock-logs.js | 2 + test/lib/commands/token.js | 10 +- test/lib/utils/display.js | 29 +- test/lib/utils/read-user-info.js | 54 ++-- workspaces/libnpmexec/lib/index.js | 26 +- workspaces/libnpmexec/test/prompt.js | 19 +- 14 files changed, 309 insertions(+), 167 deletions(-) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 730d8a35ca730..62bed0488e891 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -132,7 +132,6 @@ graph LR; npm-->pacote; npm-->parse-conflict-json; npm-->proc-log; - npm-->proggy; npm-->read; npm-->semver; npm-->ssri; @@ -527,7 +526,6 @@ graph LR; npm-->pacote; npm-->parse-conflict-json; npm-->proc-log; - npm-->proggy; npm-->qrcode-terminal; npm-->read; npm-->remark-gfm; diff --git a/lib/commands/init.js b/lib/commands/init.js index 1847e19a9560f..205352e86e6ed 100644 --- a/lib/commands/init.js +++ b/lib/commands/init.js @@ -6,7 +6,7 @@ const npa = require('npm-package-arg') const libexec = require('libnpmexec') const mapWorkspaces = require('@npmcli/map-workspaces') const PackageJson = require('@npmcli/package-json') -const { log, output } = require('proc-log') +const { log, output, input } = require('proc-log') const updateWorkspaces = require('../utils/update-workspaces.js') const BaseCommand = require('../base-cmd.js') @@ -148,8 +148,6 @@ class Init extends BaseCommand { } async template (path = process.cwd()) { - log.pause() - const initFile = this.npm.config.get('init-module') if (!this.npm.config.get('yes') && !this.npm.config.get('force')) { output.standard([ @@ -167,7 +165,7 @@ class Init extends BaseCommand { } try { - const data = await initJson(path, initFile, this.npm.config) + const data = await input.read(() => initJson(path, initFile, this.npm.config)) log.silly('package data', data) return data } catch (er) { @@ -176,8 +174,6 @@ class Init extends BaseCommand { } else { throw er } - } finally { - log.resume() } } diff --git a/lib/utils/display.js b/lib/utils/display.js index 299edc797aaf3..4939bc4169bda 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -1,5 +1,4 @@ -const proggy = require('proggy') -const { log, output, META } = require('proc-log') +const { log, output, input, META } = require('proc-log') const { explain } = require('./explain-eresolve.js') const { formatWithOptions } = require('./format') @@ -137,18 +136,17 @@ class Display { // Handlers are set immediately so they can buffer all events process.on('log', this.#logHandler) process.on('output', this.#outputHandler) + process.on('input', this.#inputHandler) + this.#progress = new Progress({ stream: stderr }) } off () { process.off('log', this.#logHandler) this.#logState.buffer.length = 0 - process.off('output', this.#outputHandler) this.#outputState.buffer.length = 0 - - if (this.#progress) { - this.#progress.stop() - } + process.off('input', this.#inputHandler) + this.#progress.off() } get chalk () { @@ -170,7 +168,6 @@ class Display { timing, unicode, }) { - this.#command = command // get createSupportsColor from chalk directly if this lands // https://github.com/chalk/chalk/pull/600 const [{ Chalk }, { createSupportsColor }] = await Promise.all([ @@ -181,17 +178,14 @@ class Display { // what it knows about the environment to get color support since we already // determined in our definitions that we want to show colors. const level = Math.max(createSupportsColor(null).level, 1) - this.#noColorChalk = new Chalk({ level: 0 }) - this.#stdoutColor = stdoutColor this.#stdoutChalk = stdoutColor ? new Chalk({ level }) : this.#noColorChalk - this.#stderrColor = stderrColor this.#stderrChalk = stderrColor ? new Chalk({ level }) : this.#noColorChalk - this.#logColors = COLOR_PALETTE({ chalk: this.#stderrChalk }) + this.#command = command this.#levelIndex = LEVEL_OPTIONS[loglevel].index this.#timing = timing this.#json = json @@ -201,18 +195,19 @@ class Display { // Emit resume event on the logs which will flush output log.resume() output.flush() - this.#startProgress({ progress, unicode }) + this.#progress.load({ + unicode, + enabled: !!progress && !this.#silent, + }) } // STREAM WRITES // Write formatted and (non-)colorized output to streams - #stdoutWrite (options, ...args) { - this.#stdout.write(formatWithOptions({ colors: this.#stdoutColor, ...options }, ...args)) - } - - #stderrWrite (options, ...args) { - this.#stderr.write(formatWithOptions({ colors: this.#stderrColor, ...options }, ...args)) + #write (stream, options, ...args) { + const colors = stream === this.#stdout ? this.#stdoutColor : this.#stderrColor + const value = formatWithOptions({ colors, ...options }, ...args) + this.#progress.write(() => stream.write(value)) } // HANDLERS @@ -220,85 +215,112 @@ class Display { // Arrow function assigned to a private class field so it can be passed // directly as a listener and still reference "this" #logHandler = withMeta((level, meta, ...args) => { - if (level === log.KEYS.resume) { - this.#logState.buffering = false - this.#logState.buffer.forEach((item) => this.#tryWriteLog(...item)) - this.#logState.buffer.length = 0 - return - } - - if (level === log.KEYS.pause) { - this.#logState.buffering = true - return - } - - if (this.#logState.buffering) { - this.#logState.buffer.push([level, meta, ...args]) - return + switch (level) { + case log.KEYS.resume: + this.#logState.buffering = false + this.#logState.buffer.forEach((item) => this.#tryWriteLog(...item)) + this.#logState.buffer.length = 0 + break + + case log.KEYS.pause: + this.#logState.buffering = true + break + + default: + if (this.#logState.buffering) { + this.#logState.buffer.push([level, meta, ...args]) + } else { + this.#tryWriteLog(level, meta, ...args) + } + break } - - this.#tryWriteLog(level, meta, ...args) }) // Arrow function assigned to a private class field so it can be passed // directly as a listener and still reference "this" #outputHandler = withMeta((level, meta, ...args) => { - if (level === output.KEYS.flush) { - this.#outputState.buffering = false - - if (meta.jsonError && this.#json) { - const json = {} - for (const item of this.#outputState.buffer) { - // index 2 skips the level and meta - Object.assign(json, tryJsonParse(item[2])) + switch (level) { + case output.KEYS.flush: + this.#outputState.buffering = false + if (meta.jsonError && this.#json) { + const json = {} + for (const item of this.#outputState.buffer) { + // index 2 skips the level and meta + Object.assign(json, tryJsonParse(item[2])) + } + this.#writeOutput( + output.KEYS.standard, + meta, + JSON.stringify({ ...json, error: meta.jsonError }, null, 2) + ) + } else { + this.#outputState.buffer.forEach((item) => this.#writeOutput(...item)) } - this.#writeOutput( - output.KEYS.standard, - meta, - JSON.stringify({ ...json, error: meta.jsonError }, null, 2) - ) - } else { - this.#outputState.buffer.forEach((item) => this.#writeOutput(...item)) - } - - this.#outputState.buffer.length = 0 - return - } - - if (level === output.KEYS.buffer) { - this.#outputState.buffer.push([output.KEYS.standard, meta, ...args]) - return - } - - if (this.#outputState.buffering) { - this.#outputState.buffer.push([level, meta, ...args]) - return + this.#outputState.buffer.length = 0 + break + + case output.KEYS.buffer: + this.#outputState.buffer.push([output.KEYS.standard, meta, ...args]) + break + + default: + if (this.#outputState.buffering) { + this.#outputState.buffer.push([level, meta, ...args]) + } else { + // HACK: if it looks like the banner and we are in a state where we hide the + // banner then dont write any output. This hack can be replaced with proc-log.META + const isBanner = args.length === 1 && + typeof args[0] === 'string' && + args[0].startsWith('\n> ') && + args[0].endsWith('\n') + const hideBanner = this.#silent || ['exec', 'explore'].includes(this.#command) + if (!(isBanner && hideBanner)) { + this.#writeOutput(level, meta, ...args) + } + } + break } + }) - // HACK: if it looks like the banner and we are in a state where we hide the - // banner then dont write any output. This hack can be replaced with proc-log.META - const isBanner = args.length === 1 && - typeof args[0] === 'string' && - args[0].startsWith('\n> ') && - args[0].endsWith('\n') - const hideBanner = this.#silent || ['exec', 'explore'].includes(this.#command) - if (isBanner && hideBanner) { - return + #inputHandler = withMeta((level, meta, ...args) => { + switch (level) { + case input.KEYS.start: + log.pause() + this.#outputState.buffering = true + this.#progress.off() + break + + case input.KEYS.end: + log.resume() + output.flush() + this.#progress.resume() + break + + case input.KEYS.read: { + // The convention when calling input.read is to pass in a single fn that returns + // the promise to await. resolve and reject are provided by proc-log + const [res, rej, p] = args + return input.start(() => p() + .then(res) + .catch(rej) + // Any call to procLog.input.read will render a prompt to the user, so we always + // add a single newline of output to stdout to move the cursor to the next line + .finally(() => output.standard(''))) + } } - - this.#writeOutput(level, meta, ...args) }) // OUTPUT #writeOutput (level, meta, ...args) { - if (level === output.KEYS.standard) { - this.#stdoutWrite({}, ...args) - return - } - - if (level === output.KEYS.error) { - this.#stderrWrite({}, ...args) + switch (level) { + case output.KEYS.standard: + this.#write(this.#stdout, {}, ...args) + break + + case output.KEYS.error: + this.#write(this.#stderr, {}, ...args) + break } } @@ -344,22 +366,118 @@ class Display { this.#logColors[level](level), title ? this.#logColors.title(title) : null, ] - this.#stderrWrite({ prefix }, ...args) - } else if (this.#progress) { - // TODO: make this display a single log line of filtered messages + this.#write(this.#stderr, { prefix }, ...args) + } + } +} + +class Progress { + // Taken from https://github.com/sindresorhus/cli-spinners + // MIT License + // Copyright (c) Sindre Sorhus (https://sindresorhus.com) + static dots = { duration: 80, frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] } + static lines = { duration: 130, frames: ['-', '\\', '|', '/'] } + + #stream + #spinner + #enabled = false + + #frameIndex = 0 + #lastUpdate = 0 + #interval + #timeout + + // We are rendering is enabled option is set and we are not waiting for the render timeout + get #rendering () { + return this.#enabled && !this.#timeout + } + + // We are spinning if enabled option is set and the render interval has been set + get #spinning () { + return this.#enabled && this.#interval + } + + constructor ({ stream }) { + this.#stream = stream + } + + load ({ enabled, unicode }) { + this.#enabled = enabled + this.#spinner = unicode ? Progress.dots : Progress.lines + // Dont render the spinner for short durations + this.#render(200) + } + + off () { + if (!this.#enabled) { + return + } + clearTimeout(this.#timeout) + this.#timeout = null + clearInterval(this.#interval) + this.#interval = null + this.#frameIndex = 0 + this.#lastUpdate = 0 + this.#clearSpinner() + } + + resume () { + this.#render() + } + + // If we are currenting rendering the spinner we clear it + // before writing our line and then re-render the spinner after. + // If not then all we need to do is write the line + write (write) { + if (this.#spinning) { + this.#clearSpinner() + } + write() + if (this.#spinning) { + this.#render() } } - // PROGRESS + #render (ms) { + if (ms) { + this.#timeout = setTimeout(() => { + this.#timeout = null + this.#renderSpinner() + }, ms) + // Make sure this timeout does not keep the process open + this.#timeout.unref() + } else { + this.#renderSpinner() + } + } - #startProgress ({ progress, unicode }) { - if (!progress || this.#silent) { + #renderSpinner () { + if (!this.#rendering) { return } - this.#progress = proggy.createClient({ normalize: true }) - // TODO: implement proggy trackers in arborist/doctor - // TODO: listen to progress events here and build progress UI - // TODO: see deprecated gauge package for what unicode chars were used + // We always attempt to render immediately but we only request to move to the next + // frame if it has been longer than our spinner frame duration since our last update + this.#renderFrame(Date.now() - this.#lastUpdate >= this.#spinner.duration) + clearInterval(this.#interval) + this.#interval = setInterval(() => this.#renderFrame(true), this.#spinner.duration) + } + + #renderFrame (next) { + if (next) { + this.#lastUpdate = Date.now() + this.#frameIndex++ + if (this.#frameIndex >= this.#spinner.frames.length) { + this.#frameIndex = 0 + } + } + this.#clearSpinner() + this.#stream.write(this.#spinner.frames[this.#frameIndex]) + } + + #clearSpinner () { + // Move to the start of the line and clear the rest of the line + this.#stream.cursorTo(0) + this.#stream.clearLine(1) } } diff --git a/lib/utils/open-url-prompt.js b/lib/utils/open-url-prompt.js index 261cf370da6bd..6f4d453a959d5 100644 --- a/lib/utils/open-url-prompt.js +++ b/lib/utils/open-url-prompt.js @@ -1,5 +1,5 @@ const readline = require('readline') -const { output } = require('proc-log') +const { input, output } = require('proc-log') const open = require('./open-url.js') function print (npm, title, url) { @@ -34,7 +34,7 @@ const promptOpen = async (npm, url, title, prompt, emitter) => { output: process.stdout, }) - const tryOpen = await new Promise(resolve => { + const tryOpen = await input.read(() => new Promise(resolve => { rl.on('SIGINT', () => { rl.close() resolve('SIGINT') @@ -47,14 +47,10 @@ const promptOpen = async (npm, url, title, prompt, emitter) => { if (emitter && emitter.addListener) { emitter.addListener('abort', () => { rl.close() - - // clear the prompt line - output.standard('') - resolve(false) }) } - }) + })) if (tryOpen === 'SIGINT') { throw new Error('canceled') diff --git a/lib/utils/read-user-info.js b/lib/utils/read-user-info.js index b2cd7374c17c3..4e8def4bdf1de 100644 --- a/lib/utils/read-user-info.js +++ b/lib/utils/read-user-info.js @@ -1,6 +1,6 @@ -const { read } = require('read') +const { read: _read } = require('read') const userValidate = require('npm-user-validate') -const { log } = require('proc-log') +const { log, input } = require('proc-log') exports.otp = readOTP exports.password = readPassword @@ -16,6 +16,8 @@ const passwordPrompt = 'npm password: ' const usernamePrompt = 'npm username: ' const emailPrompt = 'email (this IS public): ' +const read = (...args) => input.read(() => _read(...args)) + function readOTP (msg = otpPrompt, otp, isRetry) { if (isRetry && otp && /^[\d ]+$|^[A-Fa-f0-9]{64,64}$/.test(otp)) { return otp.replace(/\s+/g, '') diff --git a/package-lock.json b/package-lock.json index fe21cfb258713..547afaa35bd48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,6 @@ "pacote", "parse-conflict-json", "proc-log", - "proggy", "qrcode-terminal", "read", "semver", @@ -142,7 +141,6 @@ "pacote": "^18.0.2", "parse-conflict-json": "^3.0.1", "proc-log": "^4.2.0", - "proggy": "^2.0.0", "qrcode-terminal": "^0.12.0", "read": "^3.0.1", "semver": "^7.6.0", @@ -9879,7 +9877,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/proggy/-/proggy-2.0.0.tgz", "integrity": "sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==", - "inBundle": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } diff --git a/package.json b/package.json index 570fad3703d37..4a52b246687f3 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,6 @@ "pacote": "^18.0.2", "parse-conflict-json": "^3.0.1", "proc-log": "^4.2.0", - "proggy": "^2.0.0", "qrcode-terminal": "^0.12.0", "read": "^3.0.1", "semver": "^7.6.0", @@ -177,7 +176,6 @@ "pacote", "parse-conflict-json", "proc-log", - "proggy", "qrcode-terminal", "read", "semver", diff --git a/tap-snapshots/test/lib/commands/init.js.test.cjs b/tap-snapshots/test/lib/commands/init.js.test.cjs index 821193a55e1a9..eae04d77d2e82 100644 --- a/tap-snapshots/test/lib/commands/init.js.test.cjs +++ b/tap-snapshots/test/lib/commands/init.js.test.cjs @@ -20,5 +20,6 @@ Press ^C at any time to quit. exports[`test/lib/commands/init.js TAP workspaces no args -- yes > should print helper info 1`] = ` + added 1 package in {TIME} ` diff --git a/test/fixtures/mock-logs.js b/test/fixtures/mock-logs.js index 346944d7405b0..ce4c189219467 100644 --- a/test/fixtures/mock-logs.js +++ b/test/fixtures/mock-logs.js @@ -41,6 +41,8 @@ module.exports = () => { const streams = { stderr: { + cursorTo: () => {}, + clearLine: () => {}, write: (str) => { str = trimTrailingNewline(str) diff --git a/test/lib/commands/token.js b/test/lib/commands/token.js index 1290a5ee9cb17..f60a938b5b34b 100644 --- a/test/lib/commands/token.js +++ b/test/lib/commands/token.js @@ -265,6 +265,7 @@ t.test('token create', async t => { registry.createToken({ password, cidr }) await npm.exec('token', ['create']) t.strictSame(outputs, [ + '', 'Created publish token n3wt0k3n', 'with IP whitelist: 10.0.0.0/8,192.168.1.0/24', ]) @@ -291,6 +292,7 @@ t.test('token create read only', async t => { registry.createToken({ readonly: true, password }) await npm.exec('token', ['create']) t.strictSame(outputs, [ + '', 'Created read only token n3wt0k3n', ]) }) @@ -347,10 +349,10 @@ t.test('token create parseable output', async t => { }, { replace: true }) registry.createToken({ password, cidr }) await npm.exec('token', ['create']) - t.equal(outputs[0], 'token\tn3wt0k3n') - t.ok(outputs[1].startsWith('created\t')) - t.equal(outputs[2], 'readonly\tfalse') - t.equal(outputs[3], 'cidr_whitelist\t10.0.0.0/8,192.168.1.0/24') + t.equal(outputs[1], 'token\tn3wt0k3n') + t.ok(outputs[2].startsWith('created\t')) + t.equal(outputs[3], 'readonly\tfalse') + t.equal(outputs[4], 'cidr_whitelist\t10.0.0.0/8,192.168.1.0/24') }) t.test('token create ipv6 cidr', async t => { diff --git a/test/lib/utils/display.js b/test/lib/utils/display.js index b05690ebd8179..33f9360e5728c 100644 --- a/test/lib/utils/display.js +++ b/test/lib/utils/display.js @@ -1,11 +1,12 @@ const t = require('tap') +const timers = require('node:timers/promises') const tmock = require('../../fixtures/tmock') const mockLogs = require('../../fixtures/mock-logs') const mockGlobals = require('@npmcli/mock-globals') const { inspect } = require('util') const mockDisplay = async (t, { mocks, load } = {}) => { - const { log, output } = require('proc-log') + const procLog = require('proc-log') const logs = mockLogs() @@ -25,9 +26,8 @@ const mockDisplay = async (t, { mocks, load } = {}) => { t.teardown(() => display.off()) return { + ...procLog, display, - output, - log, displayLoad, ...logs.logs, } @@ -72,16 +72,31 @@ t.test('can buffer output when paused', async t => { }) t.test('can do progress', async (t) => { - const { log, logs } = await mockDisplay(t, { + const { log, logs, outputs, outputErrors, output, input } = await mockDisplay(t, { load: { progress: true, - loglevel: 'error', }, }) - log.silly('', 'this would go to progress') + // wait for initial timer interval to load + await timers.setTimeout(200) + + log.error('', 'before input') + output.standard('before input') + + const end = input.start() + log.error('', 'during input') + output.standard('during input') + end() + + // wait long enough for all spinner frames to render + await timers.setTimeout(800) + log.error('', 'after input') + output.standard('after input') - t.strictSame(logs, [], 'no logs were shown normally') + t.strictSame([...new Set(outputErrors)].sort(), ['-', '/', '\\', '|']) + t.strictSame(logs, ['error before input', 'error during input', 'error after input']) + t.strictSame(outputs, ['before input', 'during input', 'after input']) }) t.test('handles log throwing', async (t) => { diff --git a/test/lib/utils/read-user-info.js b/test/lib/utils/read-user-info.js index 854277783bb6b..35628f7f2faac 100644 --- a/test/lib/utils/read-user-info.js +++ b/test/lib/utils/read-user-info.js @@ -1,39 +1,45 @@ const t = require('tap') +const procLog = require('proc-log') const tmock = require('../../fixtures/tmock') let readOpts = null let readResult = null -const read = { read: async (opts) => { - readOpts = opts - return readResult -} } - -const npmUserValidate = { - username: (username) => { - if (username === 'invalid') { - return new Error('invalid username') - } - - return null - }, - email: (email) => { - if (email.startsWith('invalid')) { - return new Error('invalid email') - } - - return null - }, -} - let logMsg = null + const readUserInfo = tmock(t, '{LIB}/utils/read-user-info.js', { - read, + read: { + read: async (opts) => { + readOpts = opts + return readResult + }, + }, 'proc-log': { + ...procLog, log: { + ...procLog.log, warn: (msg) => logMsg = msg, }, + input: { + ...procLog.input, + read: (fn) => fn(), + }, + }, + 'npm-user-validate': { + username: (username) => { + if (username === 'invalid') { + return new Error('invalid username') + } + + return null + }, + email: (email) => { + if (email.startsWith('invalid')) { + return new Error('invalid email') + } + + return null + }, }, - 'npm-user-validate': npmUserValidate, }) t.beforeEach(() => { diff --git a/workspaces/libnpmexec/lib/index.js b/workspaces/libnpmexec/lib/index.js index 944f34b01c237..28cba79a7f227 100644 --- a/workspaces/libnpmexec/lib/index.js +++ b/workspaces/libnpmexec/lib/index.js @@ -4,18 +4,16 @@ const { mkdir } = require('fs/promises') const Arborist = require('@npmcli/arborist') const ciInfo = require('ci-info') const crypto = require('crypto') -const { log } = require('proc-log') +const { log, input } = require('proc-log') const npa = require('npm-package-arg') const pacote = require('pacote') const { read } = require('read') const semver = require('semver') - const { fileExists, localFileExists } = require('./file-exists.js') const getBinFromManifest = require('./get-bin-from-manifest.js') const noTTY = require('./no-tty.js') const runScript = require('./run-script.js') const isWindows = require('./is-windows.js') - const { dirname, resolve } = require('path') const binPaths = [] @@ -242,26 +240,24 @@ const exec = async (opts) => { if (add.length) { if (!yes) { - const missingPackages = add.map(a => `${a.replace(/@$/, '')}`) + const addList = add.map(a => `${a.replace(/@$/, '')}`) + // set -n to always say no if (yes === false) { // Error message lists missing package(s) when process is canceled /* eslint-disable-next-line max-len */ - throw new Error(`npx canceled due to missing packages and no YES option: ${JSON.stringify(missingPackages)}`) + throw new Error(`npx canceled due to missing packages and no YES option: ${JSON.stringify(addList)}`) } if (noTTY() || ciInfo.isCI) { - log.warn('exec', `The following package${ - add.length === 1 ? ' was' : 's were' - } not found and will be installed: ${ - add.map((pkg) => pkg.replace(/@$/, '')).join(', ') - }`) + /* eslint-disable-next-line max-len */ + log.warn('exec', `The following package${add.length === 1 ? ' was' : 's were'} not found and will be installed: ${addList.join(', ')}`) } else { - const addList = missingPackages.join('\n') + '\n' - const prompt = `Need to install the following packages:\n${ - addList - }Ok to proceed? ` - const confirm = await read({ prompt, default: 'y' }) + const confirm = await input.read(() => read({ + /* eslint-disable-next-line max-len */ + prompt: `Need to install the following packages:\n${addList.join('\n')}\nOk to proceed? `, + default: 'y', + })) if (confirm.trim().toLowerCase().charAt(0) !== 'y') { throw new Error('canceled') } diff --git a/workspaces/libnpmexec/test/prompt.js b/workspaces/libnpmexec/test/prompt.js index 5edcff9a3d9cb..8c8c520d497b6 100644 --- a/workspaces/libnpmexec/test/prompt.js +++ b/workspaces/libnpmexec/test/prompt.js @@ -1,4 +1,4 @@ -const { log } = require('proc-log') +const procLog = require('proc-log') const { resolve } = require('path') const t = require('tap') const fs = require('fs/promises') @@ -15,6 +15,13 @@ t.test('prompt, accepts', async t => { 'ci-info': { isCI: false }, '../../lib/no-tty.js': () => false, read: { read: async () => 'y' }, + 'proc-log': { + ...procLog, + input: { + ...procLog.input, + read: (fn) => fn(), + }, + }, }, }) @@ -39,6 +46,13 @@ t.test('prompt, refuses', async t => { mocks: { 'ci-info': { isCI: false }, read: { read: async () => 'n' }, + 'proc-log': { + ...procLog, + input: { + ...procLog.input, + read: (fn) => fn(), + }, + }, '../../lib/no-tty.js': () => false, }, }) @@ -146,8 +160,9 @@ t.test('no prompt if CI, multiple packages', async t => { mocks: { 'ci-info': { isCI: true }, 'proc-log': { + ...procLog, log: { - ...log, + ...procLog.log, warn (title, msg) { t.equal(title, 'exec', 'should warn exec title') // this message is nondeterministic as it queries manifests so we just From bcc781abf10b46aa5b04da996fc4602524be9b0e Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Mon, 29 Apr 2024 16:42:35 -0700 Subject: [PATCH 42/42] fix: move run-script banners to stderr when in json mode (#7439) Fixes #7354 --- docs/bin/build.js | 2 +- lib/utils/display.js | 24 ++++++++++++------- smoke-tests/test/pack-json-output.js | 12 ++++++++++ .../test/lib/commands/pack.js.test.cjs | 13 +++++++++- test/lib/commands/pack.js | 6 ++++- 5 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 smoke-tests/test/pack-json-output.js diff --git a/docs/bin/build.js b/docs/bin/build.js index b94a85cf6f9bc..c25fd76ed7e7f 100644 --- a/docs/bin/build.js +++ b/docs/bin/build.js @@ -16,7 +16,7 @@ const run = require('../lib/build.js') const { paths } = require('../lib/index') run(paths) - .then((res) => console.log(`Wrote ${res.length} files`)) + .then((res) => console.error(`Wrote ${res.length} files`)) .catch((err) => { process.exitCode = 1 console.error(err) diff --git a/lib/utils/display.js b/lib/utils/display.js index 4939bc4169bda..29a1f7951d506 100644 --- a/lib/utils/display.js +++ b/lib/utils/display.js @@ -267,16 +267,22 @@ class Display { if (this.#outputState.buffering) { this.#outputState.buffer.push([level, meta, ...args]) } else { - // HACK: if it looks like the banner and we are in a state where we hide the - // banner then dont write any output. This hack can be replaced with proc-log.META - const isBanner = args.length === 1 && - typeof args[0] === 'string' && - args[0].startsWith('\n> ') && - args[0].endsWith('\n') - const hideBanner = this.#silent || ['exec', 'explore'].includes(this.#command) - if (!(isBanner && hideBanner)) { - this.#writeOutput(level, meta, ...args) + // HACK: Check if the argument looks like a run-script banner. This can be + // replaced with proc-log.META in @npmcli/run-script + if (typeof args[0] === 'string' && args[0].startsWith('\n> ') && args[0].endsWith('\n')) { + if (this.#silent || ['exec', 'explore'].includes(this.#command)) { + // Silent mode and some specific commands always hide run script banners + break + } else if (this.#json) { + // In json mode, change output to stderr since we dont want to break json + // parsing on stdout if the user is piping to jq or something. + // XXX: in a future (breaking?) change it might make sense for run-script to + // always output these banners with proc-log.output.error if we think they + // align closer with "logging" instead of "output" + level = output.KEYS.error + } } + this.#writeOutput(level, meta, ...args) } break } diff --git a/smoke-tests/test/pack-json-output.js b/smoke-tests/test/pack-json-output.js new file mode 100644 index 0000000000000..419da58324213 --- /dev/null +++ b/smoke-tests/test/pack-json-output.js @@ -0,0 +1,12 @@ + +const t = require('tap') +const setup = require('./fixtures/setup.js') + +t.test('pack --json returns only json on stdout', async t => { + const { npmLocal } = await setup(t) + + const { stderr, stdout } = await npmLocal('pack', '--json') + + t.match(stderr, /> npm@.* prepack\n/, 'stderr has banner') + t.ok(JSON.parse(stdout), 'stdout can be parsed as json') +}) diff --git a/tap-snapshots/test/lib/commands/pack.js.test.cjs b/tap-snapshots/test/lib/commands/pack.js.test.cjs index e251e63d4c279..9ec24b3816261 100644 --- a/tap-snapshots/test/lib/commands/pack.js.test.cjs +++ b/tap-snapshots/test/lib/commands/pack.js.test.cjs @@ -109,13 +109,24 @@ Array [ "name": "@myscope/test-package", "shasum": "{sha}", "size": "{size}", - "unpackedSize": 50, + "unpackedSize": 88, "version": "1.0.0", }, ], ] ` +exports[`test/lib/commands/pack.js TAP should log scoped package output as valid json > stderr has banners 1`] = ` +Array [ + String( + + > @myscope/test-package@1.0.0 prepack + > echo prepack! + + ), +] +` + exports[`test/lib/commands/pack.js TAP should pack current directory with no arguments > logs pack contents 1`] = ` Array [ "package: test-package@1.0.0", diff --git a/test/lib/commands/pack.js b/test/lib/commands/pack.js index 067e84a0980e0..3ea67c78d996a 100644 --- a/test/lib/commands/pack.js +++ b/test/lib/commands/pack.js @@ -72,11 +72,14 @@ t.test('should log output as valid json', async t => { }) t.test('should log scoped package output as valid json', async t => { - const { npm, outputs, logs } = await loadMockNpm(t, { + const { npm, outputs, outputErrors, logs } = await loadMockNpm(t, { prefixDir: { 'package.json': JSON.stringify({ name: '@myscope/test-package', version: '1.0.0', + scripts: { + prepack: 'echo prepack!', + }, }), }, config: { json: true }, @@ -84,6 +87,7 @@ t.test('should log scoped package output as valid json', async t => { await npm.exec('pack', []) const filename = 'myscope-test-package-1.0.0.tgz' t.matchSnapshot(outputs.map(JSON.parse), 'outputs as json') + t.matchSnapshot(outputErrors, 'stderr has banners') t.matchSnapshot(logs.notice, 'logs pack contents') t.ok(fs.statSync(path.resolve(npm.prefix, filename))) })