Skip to content

Commit

Permalink
Remove npm module usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
raineorshine committed May 29, 2017
1 parent 3c6e2df commit c0bd8b7
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 226 deletions.
52 changes: 23 additions & 29 deletions lib/npm-check-updates.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,15 @@ function analyzeGlobalPackages(options) {
print(options, 'Getting installed packages...', 'verbose');

return vm.getInstalledPackages({
cwd: options.cwd,
filter: options.filter,
global: options.global,
packageManager: options.packageManager,
prefix: options.prefix,
reject: options.reject
})
.then(function (globalPackages) {
print(options, 'globalPackages', 'silly');
print(options, globalPackages, 'silly');
print(options, '', 'silly');
print(options, 'Fetching ' + vm.getVersionTarget(options) + ' versions...', 'verbose');
Expand All @@ -157,6 +162,7 @@ function analyzeGlobalPackages(options) {
upgraded: upgraded,
latest: latest
});
print(options, '');
}
return upgraded;
});
Expand Down Expand Up @@ -291,6 +297,7 @@ function printUpgrades(options, args) {
function initOptions(options) {

return _.assign({}, options, {
filter: options.args.join(' ') || options.filter,
// convert silent option to loglevel silent
loglevel: options.silent ? 'silent' : options.loglevel,
minimal: options.minimal === undefined ? false : options.loglevel,
Expand Down Expand Up @@ -388,39 +395,26 @@ function run(opts) {
});
}

// get filter from arguments
options.filter = options.args.join(' ') || options.filter;

print(options, 'Initializing...', 'verbose');

return vm.initialize({
global: options.global,
packageManager: options.packageManager,
registry: options.registry
})
.then(function () {

options = initOptions(options);
options = initOptions(options);

if (options.timeout) {
var timeoutMs = _.isString(options.timeout) ? parseInt(options.timeout, 10) : options.timeout;
var timeout = setTimeout(function () {
programError(options, chalk.red('Exceeded global timeout of ' + timeoutMs + 'ms'));
}, timeoutMs);
}
if (options.timeout) {
var timeoutMs = _.isString(options.timeout) ? parseInt(options.timeout, 10) : options.timeout;
var timeout = setTimeout(function () {
programError(options, chalk.red('Exceeded global timeout of ' + timeoutMs + 'ms'));
}, timeoutMs);
}

var pendingAnalysis = options.global ?
analyzeGlobalPackages(options) :
findPackage(options).spread(_.partial(analyzeProjectDependencies, options));
var pendingAnalysis = options.global ?
analyzeGlobalPackages(options) :
findPackage(options).spread(_.partial(analyzeProjectDependencies, options));

if (timeout) {
pendingAnalysis = pendingAnalysis.then(function () {
clearTimeout(timeout);
});
}
if (timeout) {
pendingAnalysis = pendingAnalysis.then(function () {
clearTimeout(timeout);
});
}

return pendingAnalysis;
});
return pendingAnalysis;
}

module.exports = _.assign({
Expand Down
9 changes: 2 additions & 7 deletions lib/package-managers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@ To add support for another package manager, drop in a module with the following
{
init: (PACKAGE_MANAGER_SPECIFIC_ARGS) => Promise<null> fulfilled if successful
list: () => Promise<{
dependencies: {
NAME: {
name: NAME,
version: VERSION
}
}
list: (npmOptions) => Promise<{
NAME: VERSION
}>
latest: (String packageName) => Promise<String> version
newest: (String packageName) => Promise<String> version
Expand Down
9 changes: 3 additions & 6 deletions lib/package-managers/bower.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,9 @@ module.exports = {
return new Promise(function (resolve, reject) {
bower.commands.list()
.on('end', function (results) {
// massage results (move pkgMeta up a level) to match expected interface (see ./README.md)
resolve({
dependencies: cint.mapObject(results.dependencies, function (key, value) {
return cint.keyValue(key, value.pkgMeta);
})
});
resolve(cint.mapObject(results.dependencies, function (key, value) {
return cint.keyValue(key, value.pkgMeta.version);
}));
})
.on('error', reject);
});
Expand Down
161 changes: 74 additions & 87 deletions lib/package-managers/npm.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
var _ = require('lodash');
var cint = require('cint');
var Promise = require('bluebird');
var npm = Promise.promisifyAll(require('npm'));
var rawPromisify = require('../raw-promisify.js');
var versionUtil = require('../version-util.js');
var spawn = require('spawn-please');

var initialized = false;
/** Parse JSON and throw an informative error on failure.
* @param data { command, packageName }
*/
function parseJson(result, data) {
var json;
// use a try-catch instead of .catch to avoid re-catching upstream errors
try {
json = JSON.parse(result);
} catch (err) {
throw new Error('Expected JSON from "' + data.command + '". This could be due to npm instability' + (data.packageName ? ' or problems with the ' + data.packageName + ' package' : '') + '.\n\n' + result)
}
return json;
}

/**
* @param packageName Name of the package
* @param field Field such as "versions" or "dist-tags.latest" accepted by npm.commands.view (https://docs.npmjs.com/api/view)
* @param field Field such as "versions" or "dist-tags.latest" accepted by npm view (https://docs.npmjs.com/api/view)
* @Returns Promised result
*/
function view(packageName, field) {
if (!initialized) {
throw new Error('init must be called before using the version manager');
}

return npm.commands.viewAsync([packageName, field], true)
.catch(function (err) {
// normalize 404 errors
throw err.statusCode === 404 ? new Error(404) : err;
})
.then(function (response) {

// rare case where npm view returns an empty response
// https://github.com/tjunnone/npm-check-updates/issues/162
if (_.isEmpty(response)) {
throw new Error(404);
}

return _.values(response)[0][field];
function view(packageName, field, options) {
var args = ['view', packageName, field]
return spawnNpm(args, options)
.then(function(result) {
return parseJson(result, {
command: 'npm ' + args.join(' '),
packageName: packageName
})
});
}

Expand All @@ -46,85 +45,73 @@ function filterOutPrereleaseVersions(versions) {
}


module.exports = {
/** Spawn npm requires a different command on Windows. */
function spawnNpm(args, npmOptions, spawnOptions) {
npmOptions = npmOptions || {};
spawnOptions = spawnOptions || {};
var cmd = process.platform === 'win32'? 'npm.cmd' : 'npm';

// get the npm prefix (async)
return Promise.resolve(npmOptions.prefix || defaultPrefix(npmOptions)).then(function(prefix) {
var fullArgs = [].concat(
args,
npmOptions.global ? '--global' : [],
prefix ? '--prefix=' + prefix : [],
'--depth=0',
'--json'
);
return spawn(cmd, fullArgs, spawnOptions)
.catch(function (err) {
// Normalize 404 message for upstream handling.
throw new Error(err.match('Registry returned 404') ? 404 : err);
});
})
}

/**
* @param args.global
* @param args.registry
* @param args.prefix
*/
init: function (args) {

args = args || {};

// use pickBy to eliminate undefined values
return npm.loadAsync(_.pickBy({
silent: true,
global: args.global || undefined,
prefix: args.prefix || undefined
}, _.identity))
.then(function () {

// configure registry
if (args.registry) {
npm.config.set('registry', args.registry);
}

rawPromisify(npm.commands);

// FIX: for ncu -g doesn't work on homebrew or windows #146
// https://github.com/tjunnone/npm-check-updates/issues/146
if (args.global && npm.config.get('prefix').match('Cellar')) {
npm.config.set('prefix', '/usr/local');
}

// Workaround: set prefix on windows for global packages
/** Get platform-specific default prefix to pass on to npm.
* @param options.global
* @param options.prefix
*/
function defaultPrefix(options) {
return spawn('npm', ['config', 'get', 'prefix']).then(function(prefix) {
// FIX: for ncu -g doesn't work on homebrew or windows #146
// https://github.com/tjunnone/npm-check-updates/issues/146
return options.prefix || (options.global && prefix.match('Cellar') ? '/usr/local' :

// Workaround: get prefix on windows for global packages
// Only needed when using npm api directly
if (process.platform === 'win32' && npm.config.get('global') && !process.env.prefix) {
npm.config.set('prefix', process.env.AppData + '\\npm');
}
process.platform === 'win32' && options.global && !process.env.prefix ?
process.env.AppData + '\\npm' :
null)
})
}

return initialized = true;
});
},
module.exports = {

/**
* @args Arguments for npm ls
* @options.cwd (optional)
* @options.global (optional)
* @options.prefix (optional)
*/
list: function (args, options) {
list: function (options) {

options = options || {};

if (!initialized) {
throw new Error('init must be called before using the version manager');
}

// if packageFile is specified, spawn an npm process so that installed modules can be read from the same directotry as the package file (#201)
return options.cwd ?
spawn(process.platform === 'win32'? 'npm.cmd' : 'npm', ['ls', '--json', '-depth=0'], {cwd: options.cwd})
.then(JSON.parse)
// transform results into a similar format as the API
.then(function (results) {
return {
dependencies: cint.mapObject(results.dependencies, function (name, info) {
return cint.keyValue(name, {
name: name,
version: info.version
});
})
};
}) :
npm.commands.listAsync(args || [], true); // silent:true
return spawnNpm('ls', options, options.cwd ? {cwd: options.cwd, rejectOnError: false} : {rejectOnError: false})
.then(function(result) {
var json = parseJson(result, {
command: 'npm ls'
});
return cint.mapObject(json.dependencies, function (name, info) {
return cint.keyValue(name, info.version);
});
});
},

latest: function (packageName, currentVersion, pre) {
return view(packageName, 'dist-tags.latest')
.then(function (version) {
if (
versionUtil.getPrecision(version) !== 'release' ||
pre
) {
if (versionUtil.getPrecision(version) !== 'release' || pre) {
return version;
} else {
return view(packageName, 'versions')
Expand Down
Loading

0 comments on commit c0bd8b7

Please sign in to comment.