diff --git a/lib/package-managers/npm.js b/lib/package-managers/npm.js index e18e3b9f..e7c583fa 100644 --- a/lib/package-managers/npm.js +++ b/lib/package-managers/npm.js @@ -2,8 +2,8 @@ const _ = require('lodash'); const cint = require('cint'); const semver = require('semver'); -const versionUtil = require('../version-util.js'); -const spawn = require('spawn-please'); +const versionUtil = require('../version-util.js'); +const spawn = require('spawn-please'); const pacote = require('pacote'); const TIME_FIELDS = ['modified', 'created']; @@ -45,6 +45,7 @@ function parseJson(result, data) { } /** + * Returns the value of one of the properties retrieved by npm view. * @param {string} packageName Name of the package * @param {string} field Field such as "versions" or "dist-tags.latest" are parsed from the pacote result (https://www.npmjs.com/package/pacote#packument) * @param {string} currentVersion @@ -52,12 +53,11 @@ function parseJson(result, data) { */ function viewOne(packageName, field, currentVersion) { return viewMany(packageName, [field], currentVersion) - .then(result => { - return result && result[field]; - }); + .then(result => result && result[field]); } /** + * Returns an object of specified values retrieved by npm view. * @param {string} packageName Name of the package * @param {string[]} fields Array of fields like versions, time, version * @param {string} currentVersion @@ -70,20 +70,16 @@ function viewMany(packageName, fields, currentVersion) { npmConfig['full-metadata'] = _.includes(fields, 'time'); - return pacote.packument(packageName, npmConfig).then(result => { - const resultObject = {}; - _.each(fields, (field) => { - if (field.startsWith('dist-tags.')) { - const [tagName, version] = field.split('.'); - if (result[tagName]) { - resultObject[field] = result.versions[result[tagName][version]]; - } - } else { - resultObject[field] = result[field]; + return pacote.packument(packageName, npmConfig).then(result => + fields.reduce((accum, field) => Object.assign( + accum, + { + [field]: field.startsWith('dist-tags.') ? + result.versions[_.get(result, field)] : + result[field] } - }); - return resultObject; - }); + ), {}) + ); } /** @@ -92,9 +88,7 @@ function viewMany(packageName, fields, currentVersion) { * @returns {Array} An array of versions with the release versions filtered out */ function filterOutPrereleaseVersions(versions, pre) { - return _.filter(versions, (version) => { - return pre || _.negate(isPre)(version); - }); + return _.filter(versions, version => pre || !isPre(version)); } /** @@ -118,7 +112,7 @@ function doesSatisfyEnginesNode(versions, enginesNode) { if (!minVersion) { return _.keys(versions); } - return _.keys(versions).filter((version) => { + return _.keys(versions).filter(version => { let versionEnginesNode = _.get(versions[version], 'engines.node'); return versionEnginesNode && semver.satisfies(minVersion, versionEnginesNode); }); @@ -203,13 +197,10 @@ module.exports = { latest(packageName, currentVersion, options) { return viewOne(packageName, 'dist-tags.latest', currentVersion) .then(latest => { - // if latest exists and latest not satisfies min version of engines.node, set null to it - if (latest && !doesSatisfyEnginesNode({[latest.version]: latest}, options.enginesNode).length) { - latest = null; - } // if latest exists and latest is not a prerelease version, return it // if latest exists and latest is a prerelease version and --pre is specified, return it - if (latest && (!isPre(latest.version) || options.pre)) { + // if latest exists and latest not satisfies min version of engines.node + if (latest && (!isPre(latest.version) || options.pre) && doesSatisfyEnginesNode({[latest.version]: latest}, options.enginesNode).length) { return latest.version; // if latest is a prerelease version and --pre is not specified, find the next // version that is not a prerelease @@ -231,19 +222,16 @@ module.exports = { */ newest(packageName, currentVersion, options) { return viewMany(packageName, ['time', 'versions'], currentVersion) - .then((result) => { + .then(result => { const versions = doesSatisfyEnginesNode(result.versions, options.enginesNode); - _.keys(result.time).forEach((key) => { - if (!_.includes(TIME_FIELDS, key) && !_.includes(versions, key)) { - delete result.time[key]; - } - }); - return _.keys(result.time); + return Object.keys(result.time).reduce((accum, key) => + accum.concat(_.includes(TIME_FIELDS, key) || _.includes(versions, key) ? key : []), [] + ); }) .then(_.partialRight(_.pullAll, TIME_FIELDS)) - .then(versions => { - return _.last(filterOutPrereleaseVersions(versions, options.pre)); - }); + .then(versions => + _.last(filterOutPrereleaseVersions(versions, options.pre)) + ); }, /** @@ -254,10 +242,12 @@ module.exports = { */ greatest(packageName, currentVersion, options) { return viewOne(packageName, 'versions', currentVersion) - .then(versions => { - versions = doesSatisfyEnginesNode(versions, options.enginesNode); - return _.last(filterOutPrereleaseVersions(versions, options.pre)); - }); + .then(versions => + _.last(filterOutPrereleaseVersions( + doesSatisfyEnginesNode(versions, options.enginesNode), + options.pre + )) + ); }, /** @@ -268,11 +258,16 @@ module.exports = { */ greatestMajor(packageName, currentVersion, options) { return viewOne(packageName, 'versions', currentVersion) - .then(versions => { - versions = doesSatisfyEnginesNode(versions, options.enginesNode); - versions = filterOutPrereleaseVersions(versions, options.pre); - return versionUtil.findGreatestByLevel(versions, currentVersion, 'major'); - }); + .then(versions => + versionUtil.findGreatestByLevel( + filterOutPrereleaseVersions( + doesSatisfyEnginesNode(versions, options.enginesNode), + options.pre + ), + currentVersion, + 'major' + ) + ); }, /** @@ -283,11 +278,16 @@ module.exports = { */ greatestMinor(packageName, currentVersion, options) { return viewOne(packageName, 'versions', currentVersion) - .then(versions => { - versions = doesSatisfyEnginesNode(versions, options.enginesNode); - versions = filterOutPrereleaseVersions(versions, options.pre); - return versionUtil.findGreatestByLevel(versions, currentVersion, 'minor'); - }); + .then(versions => + versionUtil.findGreatestByLevel( + filterOutPrereleaseVersions( + doesSatisfyEnginesNode(versions, options.enginesNode), + options.pre + ), + currentVersion, + 'minor' + ) + ); }, defaultPrefix