Skip to content

Commit

Permalink
fix(scoped): avoiding crash when dealing with scoped dependencies, fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
bahmutov committed Dec 3, 2015
1 parent 0ab68ab commit 3a46ac7
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 90 deletions.
94 changes: 73 additions & 21 deletions src/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,37 @@ function cleanVersions(nameVersionPairs) {
return cleaned;
}

function formNpmErrorMessage(name, info) {
var reason = info.reason || info.error || JSON.stringify(info);
var str = 'ERROR in npm info for ' + name + ' reason ' + reason;
return str;
}

function cleanVersionFor(name, version) {
return cleanVersion(version, name);
}

function extractVersions(info) {
if (info.time) {
return Object.keys(info.time);
}
if (info.versions) {
return Object.keys(info.versions);
}
}

function is404(response) {
return response && response.statusCode === 404;
}

function isNotFound(str) {
var moduleNotFound = (/not found/).test(str);
var cannotConnect = (/ENOTFOUND/).test(str);
var errorInNpm = (/ERROR in npm/).test(str);
var couldNotFetch = (/could not fetch/i).test(str);
return moduleNotFound || cannotConnect || errorInNpm || couldNotFetch;
}

// fetching versions inspired by
// https://github.com/jprichardson/npm-latest
// returns a promise
Expand All @@ -113,10 +144,22 @@ function fetchVersions(nameVersion) {
check.verify.string(name, 'missing name string');
check.verify.string(version, 'missing version string');

var cleanVersionForName = _.partial(cleanVersionFor, name);
function isLaterVersion(ver) {
var later = semver.gt(ver, version);
return later;
}

// console.log('fetching versions for', name, 'current version', version);
var MAX_WAIT_TIMEOUT = 5000;
var deferred = q.defer();

function rejectOnTimeout() {
var msg = 'timed out waiting for NPM for package ' + name;
console.error(msg);
deferred.reject(msg);
}

registryUrl().then(function (npmUrl) {
check.verify.webUrl(npmUrl, 'need npm registry url, got ' + npmUrl);

Expand All @@ -126,11 +169,7 @@ function fetchVersions(nameVersion) {
// TODO how to detect if the registry is not responding?

request.get(url, onNPMversions);
var timer = setTimeout(function () {
var msg = 'timed out waiting for NPM for package ' + name;
console.error(msg);
deferred.reject(msg);
}, MAX_WAIT_TIMEOUT);
var timer = setTimeout(rejectOnTimeout, MAX_WAIT_TIMEOUT);

function onNPMversions(err, response, body) {
clearTimeout(timer);
Expand All @@ -141,31 +180,41 @@ function fetchVersions(nameVersion) {
return;
}

if (is404(response)) {
deferred.resolve({
name: name,
versions: []
});
return;
}

try {
var info = JSON.parse(body);
if (info.error) {
var str = 'ERROR in npm info for ' + name + ' reason ' + info.reason;
var str = formNpmErrorMessage(name, info);
console.error(str);

if (isNotFound(info.error)) {
deferred.resolve({
name: name,
versions: []
});
return;
}

deferred.reject(str);
return;
}
var versions;
if (info.time) {
versions = Object.keys(info.time);
} else if (info.versions) {
versions = Object.keys(info.versions);
}
var versions = extractVersions(info);

if (!Array.isArray(versions)) {
throw new Error('Could not get versions for ' + name + ' from ' + info);
throw new Error('Could not get versions for ' + name +
' from ' + JSON.stringify(info) +
' response ' + JSON.stringify(response, null, 2));
}

var validVersions = versions.filter(function (version) {
return cleanVersion(version, name);
});
var newerVersions = validVersions.filter(function (ver) {
var later = semver.gt(ver, version);
return later;
});
var validVersions = versions.filter(cleanVersionForName);
var newerVersions = validVersions.filter(isLaterVersion);

deferred.resolve({
name: name,
Expand Down Expand Up @@ -201,8 +250,11 @@ function nextVersions(options, nameVersionPairs, checkLatestOnly) {
.timeout(MAX_CHECK_TIMEOUT, 'timed out waiting for NPM');

fetchAllPromise.then(function (results) {
check.verify.array(results, 'expected list of results');
var available = results.filter(function (nameNewVersions) {
return nameNewVersions.versions.length;
return nameNewVersions &&
check.array(nameNewVersions.versions) &&
nameNewVersions.versions.length;
});
if (checkLatestOnly) {
available = available.map(function (nameVersions) {
Expand Down
10 changes: 3 additions & 7 deletions src/test/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,10 @@ gt.async('fetch non existent module', 2, function () {
});
gt.func(promise.then, 'return object has then method');
promise.then(function (results) {
gt.ok(false, 'should not get success, results ' + JSON.stringify(results, null, 2));
console.log('has results', results);
gt.ok(typeof results === 'object', 'has results');
}).catch(function (error) {
var moduleNotFound = (/not found/).test(error);
var cannotConnect = (/ENOTFOUND/).test(error);
var errorInNpm = (/ERROR in npm/).test(error);
var couldNot = (/could not fetch/i).test(error);
gt.ok(moduleNotFound || cannotConnect || errorInNpm || couldNot,
'error message gives a good reason,', error);
gt.ok(false, 'should not get success, results ' + JSON.stringify(results, null, 2));
}).finally(gt.start);
}, timeout);

Expand Down
98 changes: 36 additions & 62 deletions test/test-next-updater/node_modules/check-types/package.json

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

0 comments on commit 3a46ac7

Please sign in to comment.