next-update
Version:
Tests if module's dependencies can be updated to latest version
135 lines (119 loc) • 4.67 kB
JavaScript
var request = require('request');
var check = require('check-types');
var semver = require('semver');
var q = require('q');
var localVersion = require('./local-module-version');
var NPM_URL = 'http://registry.npmjs.org/';
function cleanVersions(nameVersionPairs) {
check.verifyArray(nameVersionPairs, 'expected array');
var cleaned = nameVersionPairs.map(function (nameVersion) {
var name = nameVersion[0];
var version = nameVersion[1];
check.verifyString(name, 'could not get module name from ' + nameVersion);
check.verifyString(version, 'could not get module version from ' + nameVersion);
version = version.replace('~', '');
var twoDigitVersion = /^\d+\.\d+$/;
if (twoDigitVersion.test(version)) {
version += '.0';
}
if (version === 'latest' || version === '*') {
console.log('Module', name, 'uses version', version);
console.log('It is recommented to list a specific version number');
version = localVersion(name);
if (!version) {
version = '0.0.1';
}
console.log('module', name, 'local version', version);
}
version = semver.clean(version);
console.assert(version, 'could not clean version ' + nameVersion[1]);
nameVersion[1] = version;
return nameVersion;
});
return cleaned;
}
// fetching versions inspired by
// https://github.com/jprichardson/npm-latest
// returns a promise
function fetchVersions(nameVersion) {
check.verifyArray(nameVersion, 'expected name / version array');
var name = nameVersion[0];
var version = nameVersion[1];
check.verifyString(name, 'missing name string');
check.verifyString(version, 'missing version string');
console.log('fetching versions for', name, 'current version', version);
var url = NPM_URL + name;
var deferred = q.defer();
request(url, function (err, response, body) {
if (err) {
console.error('ERROR when fetching info for package', name);
deferred.reject(err.message);
return;
}
try {
var info = JSON.parse(body);
if (info.error) {
var str = 'ERROR in npm info for ' + name + ' reason ' + info.reason;
console.error(str);
deferred.reject(str);
return;
}
var versions;
if (info.time) {
versions = Object.keys(info.time);
} else if (info.versions) {
versions = Object.keys(info.versions);
}
if (!Array.isArray(versions)) {
throw new Error('Could not get versions for ' + name + ' from ' + info);
}
var newerVersions = versions.filter(function (ver) {
var later = semver.gt(ver, version);
return later;
});
deferred.resolve({
name: name,
versions: newerVersions
});
return;
} catch (err) {
console.error(err);
deferred.reject('Could not fetch versions for ' + name);
return;
}
});
return deferred.promise;
}
// returns a promise with available new versions
function nextVersions(nameVersionPairs, checkLatestOnly) {
check.verifyArray(nameVersionPairs, 'expected array');
checkLatestOnly = !!checkLatestOnly;
nameVersionPairs = cleanVersions(nameVersionPairs);
var deferred = q.defer();
var fetchPromises = nameVersionPairs.map(fetchVersions);
var fetchAllPromise = q.all(fetchPromises);
fetchAllPromise.then(function (results) {
var available = results.filter(function (nameNewVersions) {
return nameNewVersions.versions.length;
});
if (checkLatestOnly) {
available = available.map(function (nameVersions) {
if (nameVersions.versions.length > 1) {
nameVersions.versions = nameVersions.versions.slice(-1);
}
return nameVersions;
});
console.log('only checking latest versions');
console.dir(available);
}
deferred.resolve(available);
}, function (error) {
deferred.reject(error);
});
return deferred.promise;
}
module.exports = {
cleanVersions: cleanVersions,
fetchVersions: fetchVersions,
nextVersions: nextVersions
};