From 52e80039d81f7e9a6f57459519d1a41fe219fc5f Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 2 Sep 2015 18:30:35 -0400 Subject: [PATCH] CLI fixes for installing and removing services. --- cli/main.js | 30 ++++++++----- lib/node.js | 5 --- lib/scaffold/add.js | 5 +++ lib/scaffold/remove.js | 68 ++++++++++++++--------------- lib/scaffold/start.js | 8 +++- package.json | 4 +- test/scaffold/remove.integration.js | 14 +++--- test/scaffold/start.unit.js | 9 ++-- 8 files changed, 77 insertions(+), 66 deletions(-) diff --git a/cli/main.js b/cli/main.js index 04506701..dc0b98a9 100644 --- a/cli/main.js +++ b/cli/main.js @@ -58,20 +58,23 @@ function main() { }); program - .command('add ') + .command('add ') .alias('install') - .description('Install a module for the current node') - .action(function(modules){ + .description('Install a service for the current node') + .action(function(services){ var configInfo = findConfig(process.cwd()); if (!configInfo) { throw new Error('Could not find configuration, see `bitcore-node create --help`'); } var opts = { path: configInfo.path, - modules: modules + services: services }; - add(opts, function() { - console.log('Successfully added module(s):', modules.join(', ')); + add(opts, function(err) { + if (err) { + throw err; + } + console.log('Successfully added services(s):', services.join(', ')); }); }).on('--help', function() { console.log(' Examples:'); @@ -82,20 +85,23 @@ function main() { }); program - .command('remove ') + .command('remove ') .alias('uninstall') - .description('Uninstall a module for the current node') - .action(function(modules){ + .description('Uninstall a service for the current node') + .action(function(services){ var configInfo = findConfig(process.cwd()); if (!configInfo) { throw new Error('Could not find configuration, see `bitcore-node create --help`'); } var opts = { path: configInfo.path, - modules: modules + services: services }; - remove(opts, function() { - console.log('Successfully removed module(s):', modules.join(', ')); + remove(opts, function(err) { + if (err) { + throw err; + } + console.log('Successfully removed services(s):', services.join(', ')); }); }).on('--help', function() { console.log(' Examples:'); diff --git a/lib/node.js b/lib/node.js index d697070b..16828a19 100644 --- a/lib/node.js +++ b/lib/node.js @@ -147,11 +147,6 @@ Node.prototype._instantiateService = function(service) { config.node = this; var mod = new service.module(config); - $.checkState( - mod instanceof BaseService, - 'Unexpected module instance type for service:' + service.name - ); - // include in loaded services this.services[service.name] = mod; diff --git a/lib/scaffold/add.js b/lib/scaffold/add.js index 0d503120..2022f811 100644 --- a/lib/scaffold/add.js +++ b/lib/scaffold/add.js @@ -94,6 +94,11 @@ function add(options, done) { if (err) { return next(err); } + + // TODO: get the name of the package from the updated package.json + // to be able to support other types of installation such as + // hosted git urls + // add service to bitcore-node.json addConfig(bitcoreConfigPath, service, next); }); diff --git a/lib/scaffold/remove.js b/lib/scaffold/remove.js index 4a513ee9..4fd84d77 100644 --- a/lib/scaffold/remove.js +++ b/lib/scaffold/remove.js @@ -10,12 +10,12 @@ var $ = bitcore.util.preconditions; var _ = bitcore.deps._; /** - * Will remove a module from bitcore-node.json + * Will remove a service from bitcore-node.json * @param {String} configFilePath - The absolute path to the configuration file - * @param {String} module - The name of the module + * @param {String} service - The name of the module * @param {Function} done */ -function removeConfig(configFilePath, module, done) { +function removeConfig(configFilePath, service, done) { $.checkArgument(path.isAbsolute(configFilePath), 'An absolute path is expected'); fs.readFile(configFilePath, function(err, data) { if (err) { @@ -23,17 +23,17 @@ function removeConfig(configFilePath, module, done) { } var config = JSON.parse(data); $.checkState( - Array.isArray(config.modules), - 'Configuration file is expected to have a modules array.' + Array.isArray(config.services), + 'Configuration file is expected to have a services array.' ); - // remove the module from the configuration - for (var i = 0; i < config.modules.length; i++) { - if (config.modules[i] === module) { - config.modules.splice(i, 1); + // remove the service from the configuration + for (var i = 0; i < config.services.length; i++) { + if (config.services[i] === service) { + config.services.splice(i, 1); } } - config.modules = _.unique(config.modules); - config.modules.sort(function(a, b) { + config.services = _.unique(config.services); + config.services.sort(function(a, b) { return a > b; }); fs.writeFile(configFilePath, JSON.stringify(config, null, 2), done); @@ -41,16 +41,16 @@ function removeConfig(configFilePath, module, done) { } /** - * Will uninstall a Node.js module and remove from package.json. + * Will uninstall a Node.js service and remove from package.json. * @param {String} configDir - The absolute configuration directory path - * @param {String} module - The name of the module + * @param {String} service - The name of the service * @param {Function} done */ -function uninstallModule(configDir, module, done) { +function uninstallService(configDir, service, done) { $.checkArgument(path.isAbsolute(configDir), 'An absolute path is expected'); - $.checkArgument(_.isString(module), 'A string is expected for the module argument'); + $.checkArgument(_.isString(service), 'A string is expected for the service argument'); - var child = spawn('npm', ['uninstall', module, '--save'], {cwd: configDir}); + var child = spawn('npm', ['uninstall', service, '--save'], {cwd: configDir}); child.stdout.on('data', function(data) { process.stdout.write(data); @@ -62,7 +62,7 @@ function uninstallModule(configDir, module, done) { child.on('close', function(code) { if (code !== 0) { - return done(new Error('There was an error uninstalling module: ' + module)); + return done(new Error('There was an error uninstalling service(s): ' + service)); } else { return done(); } @@ -70,26 +70,26 @@ function uninstallModule(configDir, module, done) { } /** - * Will remove a Node.js module if it is installed. + * Will remove a Node.js service if it is installed. * @param {String} configDir - The absolute configuration directory path - * @param {String} module - The name of the module + * @param {String} service - The name of the service * @param {Function} done */ -function removeModule(configDir, module, done) { +function removeService(configDir, service, done) { $.checkArgument(path.isAbsolute(configDir), 'An absolute path is expected'); - $.checkArgument(_.isString(module), 'A string is expected for the module argument'); + $.checkArgument(_.isString(service), 'A string is expected for the service argument'); - // check if the module is installed + // check if the service is installed npm.load(function(err) { if (err) { return done(err); } - npm.commands.ls([module], true /*silent*/, function(err, data, lite) { + npm.commands.ls([service], true /*silent*/, function(err, data, lite) { if (err) { return done(err); } if (lite.dependencies) { - uninstallModule(configDir, module, done); + uninstallService(configDir, service, done); } else { done(); } @@ -99,10 +99,10 @@ function removeModule(configDir, module, done) { } /** - * Will remove the Node.js module and from the bitcore-node configuration. + * Will remove the Node.js service and from the bitcore-node configuration. * @param {String} options.cwd - The current working directory * @param {String} options.dirname - The bitcore-node configuration directory - * @param {Array} options.modules - An array of strings of module names + * @param {Array} options.services - An array of strings of service names * @param {Function} done - A callback function called when finished */ function remove(options, done) { @@ -112,10 +112,10 @@ function remove(options, done) { _.isString(options.path) && path.isAbsolute(options.path), 'An absolute path is expected' ); - $.checkArgument(Array.isArray(options.modules)); + $.checkArgument(Array.isArray(options.services)); var configPath = options.path; - var modules = options.modules; + var services = options.services; var bitcoreConfigPath = path.resolve(configPath, 'bitcore-node.json'); var packagePath = path.resolve(configPath, 'package.json'); @@ -127,15 +127,15 @@ function remove(options, done) { } async.eachSeries( - modules, - function(module, next) { - // if the module is installed remove it - removeModule(configPath, module, function(err) { + services, + function(service, next) { + // if the service is installed remove it + removeService(configPath, service, function(err) { if (err) { return next(err); } - // remove module to bitcore-node.json - removeConfig(bitcoreConfigPath, module, next); + // remove service to bitcore-node.json + removeConfig(bitcoreConfigPath, service, next); }); }, done ); diff --git a/lib/scaffold/start.js b/lib/scaffold/start.js index 3f092d82..bae01a23 100644 --- a/lib/scaffold/start.js +++ b/lib/scaffold/start.js @@ -20,11 +20,15 @@ log.debug = function() {}; * } * ] * @param {Function} req - The require function to use + * @param {Array} cwd - The local path (for requiring services) * @param {Object} config * @param {Array} config.services - An array of strings of service names. * @returns {Array} */ -function setupServices(req, config) { +function setupServices(req, cwd, config) { + + module.paths.push(path.resolve(cwd, './node_modules')); + var services = []; if (config.services) { for (var i = 0; i < config.services.length; i++) { @@ -160,7 +164,7 @@ function registerExitHandlers(proc, node) { function start(options) { var fullConfig = _.clone(options.config); - fullConfig.services = setupServices(require, options.config); + fullConfig.services = setupServices(require, options.path, options.config); fullConfig.datadir = path.resolve(options.path, options.config.datadir); var node = new BitcoreNode(fullConfig); diff --git a/package.json b/package.json index ea9b08bc..56b07680 100644 --- a/package.json +++ b/package.json @@ -47,14 +47,14 @@ "async": "^1.3.0", "bindings": "^1.2.1", "bitcore": "^0.13.0", - "colors": "^1.1.2", "body-parser": "^1.13.3", + "colors": "^1.1.2", "commander": "^2.8.1", "errno": "^0.1.4", + "express": "^4.13.3", "leveldown": "^1.4.1", "levelup": "^1.2.1", "liftoff": "^2.1.0", - "express": "^4.13.3", "memdown": "^1.0.0", "mkdirp": "0.5.0", "nan": "1.3.0", diff --git a/test/scaffold/remove.integration.js b/test/scaffold/remove.integration.js index 4228e18c..1607ed64 100644 --- a/test/scaffold/remove.integration.js +++ b/test/scaffold/remove.integration.js @@ -15,7 +15,7 @@ describe('#remove', function() { var testDir = path.resolve(basePath, 'temporary-test-data'); var startConfig = { name: 'My Node', - modules: ['a', 'b', 'c'] + services: ['a', 'b', 'c'] }; var startPackage = {}; @@ -56,7 +56,7 @@ describe('#remove', function() { it('will give an error if expected files do not exist', function(done) { remove({ path: path.resolve(testDir, 's0'), - modules: ['b'] + services: ['b'] }, function(err) { should.exist(err); err.message.match(/^Invalid state/); @@ -64,7 +64,7 @@ describe('#remove', function() { }); }); - it('will update bitcore-node.json modules', function(done) { + it('will update bitcore-node.json services', function(done) { var spawn = sinon.stub().returns({ stdout: { on: sinon.stub() @@ -89,12 +89,12 @@ describe('#remove', function() { }); removetest({ path: path.resolve(testDir, 's0/s1/'), - modules: ['b'] + services: ['b'] }, function(err) { should.not.exist(err); var configPath = path.resolve(testDir, 's0/s1/bitcore-node.json'); var config = JSON.parse(fs.readFileSync(configPath)); - config.modules.should.deep.equal(['a', 'c']); + config.services.should.deep.equal(['a', 'c']); done(); }); }); @@ -125,10 +125,10 @@ describe('#remove', function() { removetest({ path: path.resolve(testDir, 's0/s1/'), - modules: ['b'] + services: ['b'] }, function(err) { should.exist(err); - err.message.should.equal('There was an error uninstalling module: b'); + err.message.should.equal('There was an error uninstalling service(s): b'); done(); }); }); diff --git a/test/scaffold/start.unit.js b/test/scaffold/start.unit.js index 14f9c5d7..2a592045 100644 --- a/test/scaffold/start.unit.js +++ b/test/scaffold/start.unit.js @@ -9,6 +9,7 @@ var start = require('../../lib/scaffold/start'); describe('#start', function() { describe('#setupServices', function() { + var cwd = process.cwd(); var setupServices = proxyquire('../../lib/scaffold/start', {}).setupServices; it('will require an internal module', function() { function InternalService() {} @@ -28,7 +29,7 @@ describe('#start', function() { } } }; - var services = setupServices(testRequire, config); + var services = setupServices(testRequire, cwd, config); services[0].name.should.equal('internal'); services[0].config.should.deep.equal({param: 'value'}); services[0].module.should.equal(InternalService); @@ -53,7 +54,7 @@ describe('#start', function() { var config = { services: ['local'] }; - var services = setupServices(testRequire, config); + var services = setupServices(testRequire, cwd, config); services[0].name.should.equal('local'); services[0].module.should.equal(LocalService); }); @@ -78,7 +79,7 @@ describe('#start', function() { var config = { services: ['local'] }; - var services = setupServices(testRequire, config); + var services = setupServices(testRequire, cwd, config); services[0].name.should.equal('local'); services[0].module.should.equal(LocalService); }); @@ -91,7 +92,7 @@ describe('#start', function() { services: ['bitcoind'] }; (function() { - setupServices(testRequire, config); + setupServices(testRequire, cwd, config); }).should.throw('Could not load service'); }); });