From f7792c66b417b76f2d9a1f114e3779e8eaed6c4e Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 6 Mar 2014 22:32:23 +0000 Subject: [PATCH] Add cmd-line help and reduce node error output by default Added nopt package dependency - npm update required! Added -v cmdline option to show node module load errors, which are otherwise hidden by default with only a summary shown --- package.json | 19 +++++++------ red.js | 77 +++++++++++++++++++++++++++++++++++++-------------- red/nodes.js | 13 ++++++--- red/server.js | 31 +++++++++++++-------- 4 files changed, 95 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index 7b56abb4b..4002ec21c 100644 --- a/package.json +++ b/package.json @@ -22,21 +22,22 @@ ], "dependencies": { "express": "3.x", - "when": "~2.6.0", - "mqtt": "~0.3.3", - "ws": "~0.4.31", + "when": "2.8.0", + "nopt": "2.2.0", + "mqtt": "~0.3.7", + "ws": "0.4.31", "fs-extra": "~0.8.1", - "clone": "~0.1.11", - "mustache": "~0.7.2", - "cron":"1.x", - "raw-body":"~1.1.2", + "clone": "0.1.11", + "mustache": "~0.8.1", + "cron":"~1.0.3", + "raw-body":"1.1.2", "twitter-ng":"~0.6.2", - "oauth":"~0.9.10", + "oauth":"~0.9.11", "xml2js":"~0.2.8", "sentiment":"~0.2.1", "irc":"~0.3.6", "follow-redirects":"~0.0.3", - "cors":"~2.1.1", + "cors":"~2.2.0", "mkdirp":"~0.3.5" }, "devDependencies": { diff --git a/red.js b/red.js index dcb030046..85d7134bd 100644 --- a/red.js +++ b/red.js @@ -18,6 +18,8 @@ var https = require('https'); var util = require("util"); var express = require("express"); var crypto = require("crypto"); +var nopt = require("nopt"); +var path = require("path"); var RED = require("./red/red.js"); var server; @@ -26,21 +28,53 @@ var app = express(); var settingsFile = "./settings"; var flowFile; -for (var argp = 2;argp < process.argv.length;argp+=1) { - var v = process.argv[argp]; - if (v == "--settings" || v == "-s") { - if (argp+1 == process.argv.length) { - console.log("Missing argument to --settings"); - return; - } - argp++; - settingsFile = process.argv[argp]; - } else { - flowFile = v; - } +var knownOpts = { + "settings":[path], + "v": Boolean, + "help": Boolean +}; +var shortHands = { + "s":["--settings"], + "?":["--help"] +}; +nopt.invalidHandler = function(k,v,t) { + // TODO: console.log(k,v,t); } -var settings = require(settingsFile); +var parsedArgs = nopt(knownOpts,shortHands,process.argv,2) + +if (parsedArgs.help) { + console.log("Usage: node red.js [-v] [-?] [--settings settings.js] [flows.json]"); + console.log(""); + console.log("Options:"); + console.log(" -s, --settings FILE use specified settings file"); + console.log(" -v enable verbose output"); + console.log(" -?, --help show usage"); + console.log(""); + console.log("Documentation can be found at http://nodered.org"); + process.exit(); +} +if (parsedArgs.argv.remain.length > 0) { + flowFile = parsedArgs.argv.remain[0]; +} + +if (parsedArgs.settings) { + settingsFile = parsedArgs.settings; +} +try { + var settings = require(settingsFile); +} catch(err) { + if (err.code == 'MODULE_NOT_FOUND') { + console.log("Unable to load settings file "+settingsFile); + } else { + console.log(err); + } + process.exit(); +} + +if (parsedArgs.v) { + settings.verbose = true; +} if (settings.https) { server = https.createServer(settings.https,function(req,res){app(req,res);}); @@ -102,16 +136,17 @@ if (settings.httpStatic) { app.use("/",express.static(settings.httpStatic)); } -RED.start(); - -var listenPath = 'http'+(settings.https?'s':'')+'://'+ - (settings.uiHost == '0.0.0.0'?'127.0.0.1':settings.uiHost)+ - ':'+settings.uiPort+settings.httpAdminRoot; - -server.listen(settings.uiPort,settings.uiHost,function() { - util.log('[red] Server now running at '+listenPath); +RED.start().then(function() { + var listenPath = 'http'+(settings.https?'s':'')+'://'+ + (settings.uiHost == '0.0.0.0'?'127.0.0.1':settings.uiHost)+ + ':'+settings.uiPort+settings.httpAdminRoot; + + server.listen(settings.uiPort,settings.uiHost,function() { + util.log('[red] Server now running at '+listenPath); + }); }); + process.on('uncaughtException',function(err) { if (err.errno === "EADDRINUSE") { util.log('[red] Unable to listen on '+listenPath); diff --git a/red/nodes.js b/red/nodes.js index a9508dcc2..cc9e3bf7d 100644 --- a/red/nodes.js +++ b/red/nodes.js @@ -273,6 +273,7 @@ module.exports.load = function(settings) { } function loadNodes(dir) { + var errors = []; fs.readdirSync(dir).sort().filter(function(fn){ var stats = fs.statSync(path.join(dir,fn)); if (stats.isFile()) { @@ -280,26 +281,30 @@ module.exports.load = function(settings) { try { require(path.join(dir,fn)); } catch(err) { - util.log("["+fn+"] "+err); + errors.push({fn:fn, err:err}); + //util.log("["+fn+"] "+err); //console.log(err.stack); } } } else if (stats.isDirectory()) { // Ignore /.dirs/, /lib/ /node_modules/ if (!/^(\..*|lib|icons|node_modules)$/.test(fn)) { - loadNodes(path.join(dir,fn)); + errors = errors.concat(loadNodes(path.join(dir,fn))); } else if (fn === "icons") { events.emit("node-icon-dir",path.join(dir,fn)); } } }); + return errors; } - loadNodes(__dirname+"/../nodes"); + var errors = loadNodes(__dirname+"/../nodes"); scanForNodes(__dirname+"/../nodes"); if (settings.nodesDir) { - loadNodes(settings.nodesDir); + errors = errors.concat(loadNodes(settings.nodesDir)); scanForNodes(settings.nodesDir); } + //console.log(errors); + return errors; //events.emit("nodes-loaded"); } diff --git a/red/server.js b/red/server.js index ec1509a71..3f2d246be 100644 --- a/red/server.js +++ b/red/server.js @@ -16,6 +16,8 @@ var express = require('express'); var util = require('util'); +var when = require('when'); + var createUI = require("./ui"); var redNodes = require("./nodes"); @@ -71,20 +73,25 @@ function createServer(_server,_settings) { } function start() { + var defer = when.defer(); + storage.init(settings).then(function() { console.log("\nWelcome to Node-RED\n===================\n"); util.log("[red] Loading palette nodes"); - util.log("------------------------------------------"); - redNodes.load(settings); - util.log(""); - util.log('You may ignore any errors above here if they are for'); - util.log('nodes you are not using. The nodes indicated will not'); - util.log('be available in the main palette until any missing'); - util.log('modules are installed, typically by running:'); - util.log(' npm install {the module name}'); - util.log('or any other errors are resolved'); - util.log("------------------------------------------"); - + var nodeErrors = redNodes.load(settings); + if (nodeErrors.length > 0) { + util.log("------------------------------------------"); + if (settings.verbose) { + for (var i=0;i 0) { redNodes.setConfig(flows); @@ -93,6 +100,8 @@ function start() { util.log("[red] Error loading flows : "+err); }); }); + + return defer.promise; } function stop() {