Restore node order in palette following async changes

The move to async loading of node files led to them appearing
out of order in the palette.
This commit is contained in:
Nick O'Leary 2015-04-08 20:17:24 +01:00
parent 8ee90777ee
commit e1dd8cf2ab
6 changed files with 127 additions and 44 deletions

View File

@ -127,7 +127,6 @@ module.exports = {
getNodeList: registry.getNodeList, getNodeList: registry.getNodeList,
getModuleInfo: registry.getModuleInfo, getModuleInfo: registry.getModuleInfo,
getModuleList: registry.getModuleList,
getNodeConfigs: registry.getNodeConfigs, getNodeConfigs: registry.getNodeConfigs,
getNodeConfig: registry.getNodeConfig, getNodeConfig: registry.getNodeConfig,

View File

@ -31,6 +31,11 @@ function init(_settings) {
} }
function load(defaultNodesDir,disableNodePathScan) { function load(defaultNodesDir,disableNodePathScan) {
// To skip node scan, the following line will use the stored node list.
// We should expose that as an option at some point, although the
// performance gains are minimal.
//return loadNodeFiles(registry.getModuleList());
var nodeFiles = localfilesystem.getNodeFiles(defaultNodesDir,disableNodePathScan); var nodeFiles = localfilesystem.getNodeFiles(defaultNodesDir,disableNodePathScan);
return loadNodeFiles(nodeFiles); return loadNodeFiles(nodeFiles);
} }
@ -41,9 +46,31 @@ function loadNodeFiles(nodeFiles) {
/* istanbul ignore else */ /* istanbul ignore else */
if (nodeFiles.hasOwnProperty(module)) { if (nodeFiles.hasOwnProperty(module)) {
if (!registry.getModuleInfo(module)) { if (!registry.getModuleInfo(module)) {
var first = true;
for (var node in nodeFiles[module].nodes) { for (var node in nodeFiles[module].nodes) {
/* istanbul ignore else */ /* istanbul ignore else */
if (nodeFiles[module].nodes.hasOwnProperty(node)) { if (nodeFiles[module].nodes.hasOwnProperty(node)) {
if (module != "node-red" && first) {
// Check the module directory exists
first = false;
var fn = nodeFiles[module].nodes[node].file;
var parts = fn.split("/");
var i = parts.length-1;
for (;i>=0;i--) {
if (parts[i] == "node_modules") {
break;
}
}
var moduleFn = parts.slice(0,i+2).join("/");
try {
var stat = fs.statSync(moduleFn);
} catch(err) {
// Module not found, don't attempt to load its nodes
break;
}
}
try { try {
promises.push(loadNodeConfig(nodeFiles[module].nodes[node])) promises.push(loadNodeConfig(nodeFiles[module].nodes[node]))
} catch(err) { } catch(err) {
@ -55,7 +82,10 @@ function loadNodeFiles(nodeFiles) {
} }
} }
return when.settle(promises).then(function(results) { return when.settle(promises).then(function(results) {
var nodes = results.map(function(r) { return r.value; }); var nodes = results.map(function(r) {
registry.addNodeSet(r.value.id,r.value,r.value.version);
return r.value;
});
return loadNodeSetList(nodes); return loadNodeSetList(nodes);
}); });
} }
@ -84,15 +114,23 @@ function loadNodeConfig(fileInfo) {
file: file, file: file,
template: file.replace(/\.js$/,".html"), template: file.replace(/\.js$/,".html"),
enabled: isEnabled, enabled: isEnabled,
loaded:false loaded:false,
version: version
}; };
if (fileInfo.hasOwnProperty("types")) {
node.types = fileInfo.types;
}
fs.readFile(node.template,'utf8', function(err,content) { fs.readFile(node.template,'utf8', function(err,content) {
if (err) { if (err) {
node.types = []; node.types = [];
if (err.code === 'ENOENT') { if (err.code === 'ENOENT') {
if (!node.types) {
node.types = [];
}
node.err = "Error: "+file+" does not exist"; node.err = "Error: "+file+" does not exist";
} else { } else {
node.types = [];
node.err = err.toString(); node.err = err.toString();
} }
} else { } else {
@ -116,7 +154,6 @@ function loadNodeConfig(fileInfo) {
} }
} }
} }
registry.addNodeSet(id,node,version);
resolve(node); resolve(node);
}); });
}); });

View File

@ -158,7 +158,6 @@ function addNodeSet(id,set,version) {
nodeTypeToId[t] = id; nodeTypeToId[t] = id;
}); });
} }
moduleNodes[set.module] = moduleNodes[set.module]||[]; moduleNodes[set.module] = moduleNodes[set.module]||[];
moduleNodes[set.module].push(set.name); moduleNodes[set.module].push(set.name);
@ -262,14 +261,16 @@ function getNodeList(filter) {
} }
function getModuleList() { function getModuleList() {
var list = []; //var list = [];
for (var module in moduleNodes) { //for (var module in moduleNodes) {
/* istanbul ignore else */ // /* istanbul ignore else */
if (moduleNodes.hasOwnProperty(module)) { // if (moduleNodes.hasOwnProperty(module)) {
list.push(registry.getModuleInfo(module)); // list.push(registry.getModuleInfo(module));
} // }
} //}
return list; //return list;
return moduleConfigs;
} }
function getModuleInfo(module) { function getModuleInfo(module) {
@ -437,16 +438,18 @@ function cleanModuleList() {
} }
} }
} }
} else if (moduleConfigs[mod] && !moduleNodes[mod]) { } else {
// For node modules, look for missing ones if (moduleConfigs[mod] && !moduleNodes[mod]) {
for (node in nodes) { // For node modules, look for missing ones
/* istanbul ignore else */ for (node in nodes) {
if (nodes.hasOwnProperty(node)) { /* istanbul ignore else */
removeNode(mod+"/"+node); if (nodes.hasOwnProperty(node)) {
removed = true; removeNode(mod+"/"+node);
removed = true;
}
} }
delete moduleConfigs[mod];
} }
delete moduleConfigs[mod];
} }
} }
} }

View File

@ -63,7 +63,7 @@ function start() {
log.info("Node.js version: "+process.version); log.info("Node.js version: "+process.version);
log.info("Loading palette nodes"); log.info("Loading palette nodes");
redNodes.init(settings,storage,app); redNodes.init(settings,storage,app);
redNodes.load().then(function() { return redNodes.load().then(function() {
var i; var i;
var nodeErrors = redNodes.getNodeList(function(n) { return n.err!=null;}); var nodeErrors = redNodes.getNodeList(function(n) { return n.err!=null;});
@ -106,10 +106,10 @@ function start() {
} }
log.info("Settings file : "+settings.settingsFile); log.info("Settings file : "+settings.settingsFile);
redNodes.loadFlows(); redNodes.loadFlows();
comms.start();
}).otherwise(function(err) { }).otherwise(function(err) {
console.log(err); console.log(err);
}); });
comms.start();
}); });
} }

View File

@ -307,22 +307,34 @@ describe('red/nodes/registry/index', function() {
typeRegistry.load("wontexist",true).then(function() { typeRegistry.load("wontexist",true).then(function() {
var nodeList = typeRegistry.getNodeList(); var nodeList = typeRegistry.getNodeList();
var moduleList = typeRegistry.getModuleList(); var moduleList = typeRegistry.getModuleList();
Object.keys(moduleList).should.have.length(1);
moduleList.should.have.a.property("node-red");
Object.keys(moduleList["node-red"].nodes).should.have.length(3);
nodeList.should.be.Array.and.have.length(3); nodeList.should.be.Array.and.have.length(3);
moduleList.should.be.Array.and.have.length(1);
settingsSave.callCount.should.equal(1); settingsSave.callCount.should.equal(1);
settingsSave.firstCall.args[0].should.be.equal("nodes"); settingsSave.firstCall.args[0].should.be.equal("nodes");
var savedList = settingsSave.firstCall.args[1]; var savedList = settingsSave.firstCall.args[1];
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("id","node-red/TestNode1");
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("name","TestNode1");
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("module","node-red");
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("file");
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("enabled",true);
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("types");
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("config");
moduleList['node-red'].nodes['TestNode1'].should.have.a.property("template");
savedList[moduleList[0].name].name.should.equal(moduleList[0].name); savedList['node-red'].nodes['TestNode1'].should.not.have.a.property("id");
savedList['node-red'].nodes['TestNode1'].should.have.a.property("name",moduleList['node-red'].nodes['TestNode1'].name);
savedList[moduleList[0].name].nodes[moduleList[0].nodes[0].name].name.should.equal(moduleList[0].nodes[0].name); savedList['node-red'].nodes['TestNode1'].should.have.a.property("module",moduleList['node-red'].nodes['TestNode1'].module);
savedList[moduleList[0].name].nodes[moduleList[0].nodes[1].name].name.should.equal(moduleList[0].nodes[1].name); savedList['node-red'].nodes['TestNode1'].should.have.a.property("file",moduleList['node-red'].nodes['TestNode1'].file);
savedList[moduleList[0].name].nodes[moduleList[0].nodes[2].name].name.should.equal(moduleList[0].nodes[2].name); savedList['node-red'].nodes['TestNode1'].should.have.a.property("enabled",moduleList['node-red'].nodes['TestNode1'].enabled);
savedList['node-red'].nodes['TestNode1'].should.have.a.property("types",moduleList['node-red'].nodes['TestNode1'].types);
savedList[moduleList[0].name].nodes[moduleList[0].nodes[0].name].should.not.have.property("err"); savedList['node-red'].nodes['TestNode1'].should.not.have.a.property("config");
savedList[moduleList[0].name].nodes[moduleList[0].nodes[1].name].should.not.have.property("err"); savedList['node-red'].nodes['TestNode1'].should.not.have.a.property("template");
savedList[moduleList[0].name].nodes[moduleList[0].nodes[2].name].should.not.have.property("err");
done(); done();
}).catch(function(e) { }).catch(function(e) {
@ -415,10 +427,12 @@ describe('red/nodes/registry/index', function() {
typeRegistry.addModule("TestNodeModule").then(function() { typeRegistry.addModule("TestNodeModule").then(function() {
var list = typeRegistry.getModuleList(); var list = typeRegistry.getModuleList();
list.should.be.an.Array.and.have.lengthOf(1); Object.keys(list).should.have.length(1);
list[0].should.have.property("name", "TestNodeModule"); list.should.have.a.property("TestNodeModule");
list[0].should.have.property("nodes"); Object.keys(list["TestNodeModule"].nodes).should.have.length(2);
list[0].nodes.should.be.an.Array.and.have.lengthOf(2);
list["TestNodeModule"].nodes["TestNodeMod1"].should.have.property("name", "TestNodeMod1");
list["TestNodeModule"].nodes["TestNodeMod2"].should.have.property("name", "TestNodeMod2");
done(); done();
}).catch(function(e) { }).catch(function(e) {
@ -656,8 +670,8 @@ describe('red/nodes/registry/index', function() {
var modules = typeRegistry.getModuleList(); var modules = typeRegistry.getModuleList();
modules[0].should.have.property("name","TestNodeModule"); modules.should.have.property("TestNodeModule");
modules[0].should.have.property("version","0.0.1"); modules["TestNodeModule"].should.have.property("version","0.0.1");
done(); done();
}).catch(function(e) { }).catch(function(e) {

View File

@ -117,12 +117,26 @@ describe("red/nodes/registry/registry",function() {
typeRegistry.init(settings); typeRegistry.init(settings);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.have.lengthOf(0); typeRegistry.getModuleList().should.eql({});
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1"); typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
typeRegistry.getNodeList().should.have.lengthOf(1); typeRegistry.getNodeList().should.have.lengthOf(1);
typeRegistry.getModuleList().should.have.lengthOf(1); var moduleList = typeRegistry.getModuleList();
moduleList.should.have.a.property("test-module");
moduleList["test-module"].should.have.a.property("name","test-module");
moduleList["test-module"].should.have.a.property("version","0.0.1");
moduleList["test-module"].should.have.a.property("nodes");
moduleList["test-module"].nodes.should.have.a.property("test-name");
moduleList["test-module"].nodes["test-name"].should.eql({
id: 'test-module/test-name',
module: 'test-module',
name: 'test-name',
enabled: true,
loaded: false,
types: [ 'test-a', 'test-b' ]
});
}); });
@ -130,20 +144,36 @@ describe("red/nodes/registry/registry",function() {
typeRegistry.init(settings); typeRegistry.init(settings);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.have.lengthOf(0); typeRegistry.getModuleList().should.eql({});
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1"); typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
typeRegistry.getNodeList().should.have.lengthOf(1);
var moduleList = typeRegistry.getModuleList();
Object.keys(moduleList).should.have.a.lengthOf(1);
moduleList.should.have.a.property("test-module");
moduleList["test-module"].should.have.a.property("name","test-module");
moduleList["test-module"].should.have.a.property("version","0.0.1");
moduleList["test-module"].should.have.a.property("nodes");
Object.keys(moduleList["test-module"].nodes).should.have.a.lengthOf(1);
moduleList["test-module"].nodes.should.have.a.property("test-name");
typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2); typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2);
typeRegistry.getNodeList().should.have.lengthOf(2); typeRegistry.getNodeList().should.have.lengthOf(2);
typeRegistry.getModuleList().should.have.lengthOf(1); moduleList = typeRegistry.getModuleList();
Object.keys(moduleList).should.have.a.lengthOf(1);
Object.keys(moduleList["test-module"].nodes).should.have.a.lengthOf(2);
moduleList["test-module"].nodes.should.have.a.property("test-name");
moduleList["test-module"].nodes.should.have.a.property("test-name-2");
}); });
it('doesnt add node set types if node set has an error', function() { it('doesnt add node set types if node set has an error', function() {
typeRegistry.init(settings); typeRegistry.init(settings);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.have.lengthOf(0); typeRegistry.getModuleList().should.eql({});
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1"); typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");