Move node registry to its own top level dir

This commit is contained in:
Nick O'Leary 2018-04-26 12:32:05 +01:00
parent 5866d414ce
commit 11d87205d7
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
63 changed files with 674 additions and 584 deletions

View File

@ -17,6 +17,7 @@
var registry = require("./registry"); var registry = require("./registry");
var loader = require("./loader"); var loader = require("./loader");
var installer = require("./installer"); var installer = require("./installer");
var library = require("./library");
var settings; var settings;
@ -24,7 +25,8 @@ function init(runtime) {
settings = runtime.settings; settings = runtime.settings;
installer.init(runtime); installer.init(runtime);
loader.init(runtime); loader.init(runtime);
registry.init(settings,loader); registry.init(settings,loader,runtime.events);
library.init();
} }
function load() { function load() {
@ -79,5 +81,11 @@ module.exports = {
cleanModuleList: registry.cleanModuleList, cleanModuleList: registry.cleanModuleList,
paletteEditorEnabled: installer.paletteEditorEnabled paletteEditorEnabled: installer.paletteEditorEnabled,
getNodeExampleFlows: library.getExampleFlows,
getNodeExampleFlowPath: library.getExampleFlowPath,
deprecated: require("./deprecated")
}; };

View File

@ -19,9 +19,10 @@ var path = require("path");
var fs = require("fs"); var fs = require("fs");
var registry = require("./registry"); var registry = require("./registry");
var library = require("./library");
var log; var log;
var events = require("../../events"); var events;
var child_process = require('child_process'); var child_process = require('child_process');
var npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'; var npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
@ -32,6 +33,7 @@ var moduleRe = /^(@[^/]+?[/])?[^/]+?$/;
var slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/; var slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/;
function init(runtime) { function init(runtime) {
events = runtime.events;
settings = runtime.settings; settings = runtime.settings;
log = runtime.log; log = runtime.log;
} }
@ -210,8 +212,7 @@ function uninstallModule(module) {
} else { } else {
log.info(log._("server.install.uninstalled",{name:module})); log.info(log._("server.install.uninstalled",{name:module}));
reportRemovedModules(list); reportRemovedModules(list);
// TODO: tidy up internal event names library.removeExamplesDir(module);
events.emit("node-module-uninstalled",module)
resolve(list); resolve(list);
} }
} }

View File

@ -59,11 +59,11 @@ function getFlowsFromPath(path) {
}) })
} }
function addNodeExamplesDir(module) { function addNodeExamplesDir(module,path) {
exampleRoots[module.name] = module.path; exampleRoots[module] = path;
getFlowsFromPath(module.path).then(function(result) { return getFlowsFromPath(path).then(function(result) {
exampleFlows = exampleFlows||{d:{}}; exampleFlows = exampleFlows||{d:{}};
exampleFlows.d[module.name] = result; exampleFlows.d[module] = result;
}); });
} }
function removeNodeExamplesDir(module) { function removeNodeExamplesDir(module) {
@ -77,17 +77,9 @@ function removeNodeExamplesDir(module) {
} }
function init(_runtime) { function init() {
runtime = _runtime;
exampleRoots = {}; exampleRoots = {};
exampleFlows = null; exampleFlows = null;
runtime.events.removeListener("node-examples-dir",addNodeExamplesDir);
runtime.events.on("node-examples-dir",addNodeExamplesDir);
runtime.events.removeListener("node-module-uninstalled",removeNodeExamplesDir);
runtime.events.on("node-module-uninstalled",removeNodeExamplesDir);
} }
function getExampleFlows() { function getExampleFlows() {
@ -103,6 +95,8 @@ function getExampleFlowPath(module,path) {
module.exports = { module.exports = {
init: init, init: init,
addExamplesDir: addNodeExamplesDir,
removeExamplesDir: removeNodeExamplesDir,
getExampleFlows: getExampleFlows, getExampleFlows: getExampleFlows,
getExampleFlowPath: getExampleFlowPath getExampleFlowPath: getExampleFlowPath
} }

View File

@ -22,6 +22,8 @@ var semver = require("semver");
var localfilesystem = require("./localfilesystem"); var localfilesystem = require("./localfilesystem");
var registry = require("./registry"); var registry = require("./registry");
var i18n = require("../util").i18n; // TODO: separate module
var settings; var settings;
var runtime; var runtime;
@ -110,7 +112,7 @@ function createNodeApi(node) {
if (args[0].indexOf(":") === -1) { if (args[0].indexOf(":") === -1) {
args[0] = node.namespace+":"+args[0]; args[0] = node.namespace+":"+args[0];
} }
return runtime.i18n._.apply(null,args); return i18n._.apply(null,args);
} }
return red; return red;
} }
@ -118,6 +120,7 @@ function createNodeApi(node) {
function loadNodeFiles(nodeFiles) { function loadNodeFiles(nodeFiles) {
var promises = []; var promises = [];
var nodes = [];
for (var module in nodeFiles) { for (var module in nodeFiles) {
/* istanbul ignore else */ /* istanbul ignore else */
if (nodeFiles.hasOwnProperty(module)) { if (nodeFiles.hasOwnProperty(module)) {
@ -125,6 +128,7 @@ function loadNodeFiles(nodeFiles) {
!semver.satisfies(runtime.version().replace(/(\-[1-9A-Za-z-][0-9A-Za-z-\.]*)?(\+[0-9A-Za-z-\.]+)?$/,""), nodeFiles[module].redVersion)) { !semver.satisfies(runtime.version().replace(/(\-[1-9A-Za-z-][0-9A-Za-z-\.]*)?(\+[0-9A-Za-z-\.]+)?$/,""), nodeFiles[module].redVersion)) {
//TODO: log it //TODO: log it
runtime.log.warn("["+module+"] "+runtime.log._("server.node-version-mismatch",{version:nodeFiles[module].redVersion})); runtime.log.warn("["+module+"] "+runtime.log._("server.node-version-mismatch",{version:nodeFiles[module].redVersion}));
nodeFiles[module].err = "version_mismatch";
continue; continue;
} }
if (module == "node-red" || !registry.getModuleInfo(module)) { if (module == "node-red" || !registry.getModuleInfo(module)) {
@ -154,7 +158,14 @@ function loadNodeFiles(nodeFiles) {
} }
try { try {
promises.push(loadNodeConfig(nodeFiles[module].nodes[node])) promises.push(loadNodeConfig(nodeFiles[module].nodes[node]).then((function() {
var m = module;
var n = node;
return function(nodeSet) {
nodeFiles[m].nodes[n] = nodeSet;
nodes.push(nodeSet);
}
})()));
} catch(err) { } catch(err) {
// //
} }
@ -164,10 +175,13 @@ function loadNodeFiles(nodeFiles) {
} }
} }
return when.settle(promises).then(function(results) { return when.settle(promises).then(function(results) {
var nodes = results.map(function(r) { for (var module in nodeFiles) {
registry.addNodeSet(r.value.id,r.value,r.value.version); if (nodeFiles.hasOwnProperty(module)) {
return r.value; if (!nodeFiles[module].err) {
}); registry.addModule(nodeFiles[module]);
}
}
}
return loadNodeSetList(nodes); return loadNodeSetList(nodes);
}); });
} }
@ -239,7 +253,7 @@ function loadNodeConfig(fileInfo) {
index = regExp.lastIndex; index = regExp.lastIndex;
var help = content.substring(regExp.lastIndex-match[1].length,regExp.lastIndex); var help = content.substring(regExp.lastIndex-match[1].length,regExp.lastIndex);
var lang = runtime.i18n.defaultLang; var lang = i18n.defaultLang;
if ((match = langRegExp.exec(help)) !== null) { if ((match = langRegExp.exec(help)) !== null) {
lang = match[1]; lang = match[1];
} }
@ -270,7 +284,7 @@ function loadNodeConfig(fileInfo) {
fs.stat(path.join(path.dirname(file),"locales"),function(err,stat) { fs.stat(path.join(path.dirname(file),"locales"),function(err,stat) {
if (!err) { if (!err) {
node.namespace = node.id; node.namespace = node.id;
runtime.i18n.registerMessageCatalog(node.id, i18n.registerMessageCatalog(node.id,
path.join(path.dirname(file),"locales"), path.join(path.dirname(file),"locales"),
path.basename(file,".js")+".json") path.basename(file,".js")+".json")
.then(function() { .then(function() {
@ -414,10 +428,10 @@ function getNodeHelp(node,lang) {
} }
if (help) { if (help) {
node.help[lang] = help; node.help[lang] = help;
} else if (lang === runtime.i18n.defaultLang) { } else if (lang === i18n.defaultLang) {
return null; return null;
} else { } else {
node.help[lang] = getNodeHelp(node, runtime.i18n.defaultLang); node.help[lang] = getNodeHelp(node, i18n.defaultLang);
} }
} }
return node.help[lang]; return node.help[lang];

View File

@ -19,7 +19,8 @@ var path = require("path");
var events; var events;
var log; var log;
var i18n;
var i18n = require("../util").i18n; // TODO: separate module
var settings; var settings;
var disableNodePathScan = false; var disableNodePathScan = false;
@ -29,7 +30,6 @@ function init(runtime) {
settings = runtime.settings; settings = runtime.settings;
events = runtime.events; events = runtime.events;
log = runtime.log; log = runtime.log;
i18n = runtime.i18n;
} }
function isIncluded(name) { function isIncluded(name) {
@ -84,6 +84,7 @@ function getLocalNodeFiles(dir) {
var result = []; var result = [];
var files = []; var files = [];
var icons = [];
try { try {
files = fs.readdirSync(dir); files = fs.readdirSync(dir);
} catch(err) { } catch(err) {
@ -102,14 +103,16 @@ function getLocalNodeFiles(dir) {
} else if (stats.isDirectory()) { } else if (stats.isDirectory()) {
// Ignore /.dirs/, /lib/ /node_modules/ // Ignore /.dirs/, /lib/ /node_modules/
if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) { if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) {
result = result.concat(getLocalNodeFiles(path.join(dir,fn))); var subDirResults = getLocalNodeFiles(path.join(dir,fn));
result = result.concat(subDirResults.files);
icons = icons.concat(subDirResults.icons);
} else if (fn === "icons") { } else if (fn === "icons") {
var iconList = scanIconDir(path.join(dir,fn)); var iconList = scanIconDir(path.join(dir,fn));
events.emit("node-icon-dir",{name:'node-red',path:path.join(dir,fn),icons:iconList}); icons.push({path:path.join(dir,fn),icons:iconList});
} }
} }
}); });
return result; return {files: result, icons: icons}
} }
function scanDirForNodesModules(dir,moduleName) { function scanDirForNodesModules(dir,moduleName) {
@ -197,7 +200,7 @@ function getModuleNodeFiles(module) {
var nodes = pkg['node-red'].nodes||{}; var nodes = pkg['node-red'].nodes||{};
var results = []; var results = [];
var iconDirs = []; var iconDirs = [];
var iconList = [];
for (var n in nodes) { for (var n in nodes) {
/* istanbul ignore else */ /* istanbul ignore else */
if (nodes.hasOwnProperty(n)) { if (nodes.hasOwnProperty(n)) {
@ -212,47 +215,55 @@ function getModuleNodeFiles(module) {
if (iconDirs.indexOf(iconDir) == -1) { if (iconDirs.indexOf(iconDir) == -1) {
try { try {
fs.statSync(iconDir); fs.statSync(iconDir);
var iconList = scanIconDir(iconDir); var icons = scanIconDir(iconDir);
events.emit("node-icon-dir",{name:pkg.name,path:iconDir,icons:iconList}); iconList.push({path:iconDir,icons:icons});
iconDirs.push(iconDir); iconDirs.push(iconDir);
} catch(err) { } catch(err) {
} }
} }
} }
} }
var result = {files:results,icons:iconList};
var examplesDir = path.join(moduleDir,"examples"); var examplesDir = path.join(moduleDir,"examples");
try { try {
fs.statSync(examplesDir) fs.statSync(examplesDir)
events.emit("node-examples-dir",{name:pkg.name,path:examplesDir}); result.examples = {path:examplesDir};
// events.emit("node-examples-dir",{name:pkg.name,path:examplesDir});
} catch(err) { } catch(err) {
} }
return results; return result;
} }
function getNodeFiles(disableNodePathScan) { function getNodeFiles(disableNodePathScan) {
var dir; var dir;
// Find all of the nodes to load // Find all of the nodes to load
var nodeFiles = []; var nodeFiles = [];
var results;
var dir = path.resolve(__dirname + '/../../../../public/icons'); var dir = path.resolve(__dirname + '/../../public/icons');
var iconList = scanIconDir(dir); var iconList = [{path:dir,icons:scanIconDir(dir)}];
events.emit("node-icon-dir",{name:'node-red',path:dir,icons:iconList});
if (settings.coreNodesDir) { if (settings.coreNodesDir) {
nodeFiles = getLocalNodeFiles(path.resolve(settings.coreNodesDir)); results = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
var defaultLocalesPath = path.join(settings.coreNodesDir,"core","locales"); var defaultLocalesPath = path.join(settings.coreNodesDir,"core","locales");
i18n.registerMessageCatalog("node-red",defaultLocalesPath,"messages.json"); i18n.registerMessageCatalog("node-red",defaultLocalesPath,"messages.json");
} }
if (settings.userDir) { if (settings.userDir) {
dir = path.join(settings.userDir,"lib","icons"); dir = path.join(settings.userDir,"lib","icons");
iconList = scanIconDir(dir); var icons = scanIconDir(dir);
if (iconList.length > 0) { if (icons.length > 0) {
events.emit("node-icon-dir",{name:'Library',path:dir,icons:iconList}); iconList.push({path:dir,icons:icons});
} }
dir = path.join(settings.userDir,"nodes"); dir = path.join(settings.userDir,"nodes");
nodeFiles = nodeFiles.concat(getLocalNodeFiles(dir)); results = getLocalNodeFiles(path.resolve(dir));
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
} }
if (settings.nodesDir) { if (settings.nodesDir) {
dir = settings.nodesDir; dir = settings.nodesDir;
@ -260,7 +271,9 @@ function getNodeFiles(disableNodePathScan) {
dir = [dir]; dir = [dir];
} }
for (var i=0;i<dir.length;i++) { for (var i=0;i<dir.length;i++) {
nodeFiles = nodeFiles.concat(getLocalNodeFiles(dir[i])); results = getLocalNodeFiles(dir[i]);
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
} }
} }
@ -268,7 +281,8 @@ function getNodeFiles(disableNodePathScan) {
"node-red": { "node-red": {
name: "node-red", name: "node-red",
version: settings.version, version: settings.version,
nodes: {} nodes: {},
icons: iconList
} }
} }
nodeFiles.forEach(function(node) { nodeFiles.forEach(function(node) {
@ -283,19 +297,21 @@ function getNodeFiles(disableNodePathScan) {
name: moduleFile.package.name, name: moduleFile.package.name,
version: moduleFile.package.version, version: moduleFile.package.version,
local: moduleFile.local||false, local: moduleFile.local||false,
nodes: {} nodes: {},
icons: nodeModuleFiles.icons,
examples: nodeModuleFiles.examples
}; };
if (moduleFile.package['node-red'].version) { if (moduleFile.package['node-red'].version) {
nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version; nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version;
} }
nodeModuleFiles.forEach(function(node) { nodeModuleFiles.files.forEach(function(node) {
node.local = moduleFile.local||false; node.local = moduleFile.local||false;
nodeList[moduleFile.package.name].nodes[node.name] = node; nodeList[moduleFile.package.name].nodes[node.name] = node;
}); });
nodeFiles = nodeFiles.concat(nodeModuleFiles); nodeFiles = nodeFiles.concat(nodeModuleFiles.files);
}); });
} else { } else {
console.log("node path scan disabled"); // console.log("node path scan disabled");
} }
return nodeList; return nodeList;
} }
@ -315,12 +331,14 @@ function getModuleFiles(module) {
nodeList[moduleFile.package.name] = { nodeList[moduleFile.package.name] = {
name: moduleFile.package.name, name: moduleFile.package.name,
version: moduleFile.package.version, version: moduleFile.package.version,
nodes: {} nodes: {},
icons: nodeModuleFiles.icons,
examples: nodeModuleFiles.examples
}; };
if (moduleFile.package['node-red'].version) { if (moduleFile.package['node-red'].version) {
nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version; nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version;
} }
nodeModuleFiles.forEach(function(node) { nodeModuleFiles.files.forEach(function(node) {
nodeList[moduleFile.package.name].nodes[node.name] = node; nodeList[moduleFile.package.name].nodes[node.name] = node;
nodeList[moduleFile.package.name].nodes[node.name].local = moduleFile.local || false; nodeList[moduleFile.package.name].nodes[node.name].local = moduleFile.local || false;
}); });

View File

@ -15,16 +15,13 @@
**/ **/
//var UglifyJS = require("uglify-js"); //var UglifyJS = require("uglify-js");
var util = require("util");
var path = require("path"); var path = require("path");
var fs = require("fs"); var fs = require("fs");
var events = require("../../events"); var library = require("./library");
var events;
var settings; var settings;
var Node;
var loader; var loader;
var nodeConfigCache = null; var nodeConfigCache = null;
@ -34,18 +31,15 @@ var nodeConstructors = {};
var nodeTypeToId = {}; var nodeTypeToId = {};
var moduleNodes = {}; var moduleNodes = {};
function init(_settings,_loader) { function init(_settings,_loader, _events) {
settings = _settings; settings = _settings;
loader = _loader; loader = _loader;
events = _events;
moduleNodes = {}; moduleNodes = {};
nodeTypeToId = {}; nodeTypeToId = {};
nodeConstructors = {}; nodeConstructors = {};
nodeList = []; nodeList = [];
nodeConfigCache = null; nodeConfigCache = null;
Node = require("../Node");
events.removeListener("node-icon-dir",nodeIconDir);
events.on("node-icon-dir",nodeIconDir);
} }
function load() { function load() {
@ -180,46 +174,46 @@ function loadNodeConfigs() {
} }
} }
function addNodeSet(id,set,version) { function addModule(module) {
if (!set.err) { moduleNodes[module.name] = [];
set.types.forEach(function(t) { moduleConfigs[module.name] = module;
if (nodeTypeToId.hasOwnProperty(t)) { for (var setName in module.nodes) {
set.err = new Error("Type already registered"); if (module.nodes.hasOwnProperty(setName)) {
set.err.code = "type_already_registered"; var set = module.nodes[setName];
set.err.details = { moduleNodes[module.name].push(set.name);
type: t, nodeList.push(set.id);
moduleA: getNodeInfo(t).module, if (!set.err) {
moduleB: set.module set.types.forEach(function(t) {
} if (nodeTypeToId.hasOwnProperty(t)) {
set.err = new Error("Type already registered");
set.err.code = "type_already_registered";
set.err.details = {
type: t,
moduleA: getNodeInfo(t).module,
moduleB: set.module
}
}
});
if (!set.err) {
set.types.forEach(function(t) {
nodeTypeToId[t] = set.id;
});
}
} }
});
if (!set.err) {
set.types.forEach(function(t) {
nodeTypeToId[t] = id;
});
} }
} }
moduleNodes[set.module] = moduleNodes[set.module]||[]; if (module.icons) {
moduleNodes[set.module].push(set.name); icon_paths[module.name] = [];
module.icons.forEach(icon=>icon_paths[module.name].push(path.resolve(icon.path)) )
if (!moduleConfigs[set.module]) {
moduleConfigs[set.module] = {
name: set.module,
nodes: {}
};
} }
if (module.examples) {
if (version) { library.addExamplesDir(module.name,module.examples.path);
moduleConfigs[set.module].version = version;
} }
moduleConfigs[set.module].local = set.local;
moduleConfigs[set.module].nodes[set.name] = set;
nodeList.push(id);
nodeConfigCache = null; nodeConfigCache = null;
} }
function removeNode(id) { function removeNode(id) {
var config = moduleConfigs[getModule(id)].nodes[getNode(id)]; var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
if (!config) { if (!config) {
@ -370,27 +364,6 @@ function getCaller(){
return stack[0].getFileName(); return stack[0].getFileName();
} }
function inheritNode(constructor) {
if(Object.getPrototypeOf(constructor.prototype) === Object.prototype) {
util.inherits(constructor,Node);
} else {
var proto = constructor.prototype;
while(Object.getPrototypeOf(proto) !== Object.prototype) {
proto = Object.getPrototypeOf(proto);
}
//TODO: This is a partial implementation of util.inherits >= node v5.0.0
// which should be changed when support for node < v5.0.0 is dropped
// see: https://github.com/nodejs/node/pull/3455
proto.constructor.super_ = Node;
if(Object.setPrototypeOf) {
Object.setPrototypeOf(proto, Node.prototype);
} else {
// hack for node v0.10
proto.__proto__ = Node.prototype;
}
}
}
function registerNodeConstructor(nodeSet,type,constructor) { function registerNodeConstructor(nodeSet,type,constructor) {
if (nodeConstructors.hasOwnProperty(type)) { if (nodeConstructors.hasOwnProperty(type)) {
throw new Error(type+" already registered"); throw new Error(type+" already registered");
@ -398,9 +371,6 @@ function registerNodeConstructor(nodeSet,type,constructor) {
//TODO: Ensure type is known - but doing so will break some tests //TODO: Ensure type is known - but doing so will break some tests
// that don't have a way to register a node template ahead // that don't have a way to register a node template ahead
// of registering the constructor // of registering the constructor
if(!(constructor.prototype instanceof Node)) {
inheritNode(constructor);
}
var nodeSetInfo = getFullNodeInfo(nodeSet); var nodeSetInfo = getFullNodeInfo(nodeSet);
if (nodeSetInfo) { if (nodeSetInfo) {
@ -584,10 +554,10 @@ function setModulePendingUpdated(module,version) {
} }
var icon_paths = { var icon_paths = {
"node-red":[path.resolve(__dirname + '/../../../../public/icons')] "node-red":[path.resolve(__dirname + '/../../public/icons')]
}; };
var iconCache = {}; var iconCache = {};
var defaultIcon = path.resolve(__dirname + '/../../../../public/icons/arrow-in.png'); var defaultIcon = path.resolve(__dirname + '/../../public/icons/arrow-in.png');
function nodeIconDir(dir) { function nodeIconDir(dir) {
icon_paths[dir.name] = icon_paths[dir.name] || []; icon_paths[dir.name] = icon_paths[dir.name] || [];
@ -648,7 +618,8 @@ function getNodeIcons() {
for (var module in moduleConfigs) { for (var module in moduleConfigs) {
if (moduleConfigs.hasOwnProperty(module)) { if (moduleConfigs.hasOwnProperty(module)) {
if (moduleConfigs[module].icons) { if (moduleConfigs[module].icons) {
iconList[module] = moduleConfigs[module].icons; iconList[module] = [];
moduleConfigs[module].icons.forEach(icon=>{ iconList[module] = iconList[module].concat(icon.icons)})
} }
} }
} }
@ -664,7 +635,9 @@ var registry = module.exports = {
registerNodeConstructor: registerNodeConstructor, registerNodeConstructor: registerNodeConstructor,
getNodeConstructor: getNodeConstructor, getNodeConstructor: getNodeConstructor,
addNodeSet: addNodeSet,
addModule: addModule,
enableNodeSet: enableNodeSet, enableNodeSet: enableNodeSet,
disableNodeSet: disableNodeSet, disableNodeSet: disableNodeSet,

View File

@ -69,6 +69,7 @@ function getEntry(type,path) {
} catch(err) { } catch(err) {
return reject(err); return reject(err);
} }
return;
} }
} }
// IF we get here, we didn't find the file // IF we get here, we didn't find the file

View File

@ -16,10 +16,11 @@
var when = require("when"); var when = require("when");
var clone = require("clone"); var clone = require("clone");
var typeRegistry = require("../registry"); var typeRegistry = require("../../../runtime-registry");
var Log; var Log;
var redUtil = require("../../util"); var redUtil = require("../../util");
var flowUtil = require("./util"); var flowUtil = require("./util");
var Node;
var nodeCloseTimeout = 15000; var nodeCloseTimeout = 15000;
@ -292,6 +293,7 @@ function Flow(global,flow) {
function createNode(type,config) { function createNode(type,config) {
var nn = null; var nn = null;
try {
var nt = typeRegistry.get(type); var nt = typeRegistry.get(type);
if (nt) { if (nt) {
var conf = clone(config); var conf = clone(config);
@ -315,6 +317,9 @@ function createNode(type,config) {
} else { } else {
Log.error(Log._("nodes.flow.unknown-type", {type:type})); Log.error(Log._("nodes.flow.unknown-type", {type:type}));
} }
} catch(err) {
Log.error(err);
}
return nn; return nn;
} }
@ -498,6 +503,7 @@ module.exports = {
init: function(runtime) { init: function(runtime) {
nodeCloseTimeout = runtime.settings.nodeCloseTimeout || 15000; nodeCloseTimeout = runtime.settings.nodeCloseTimeout || 15000;
Log = runtime.log; Log = runtime.log;
Node = require("../Node");
}, },
create: function(global,conf) { create: function(global,conf) {
return new Flow(global,conf); return new Flow(global,conf);

View File

@ -19,7 +19,10 @@ var when = require("when");
var Flow = require('./Flow'); var Flow = require('./Flow');
var typeRegistry = require("../registry"); var typeRegistry = require("../../../runtime-registry");
var deprecated = typeRegistry.deprecated;
var context = require("../context") var context = require("../context")
var credentials = require("../credentials"); var credentials = require("../credentials");
@ -27,7 +30,6 @@ var flowUtil = require("./util");
var log; var log;
var events = require("../../events"); var events = require("../../events");
var redUtil = require("../../util"); var redUtil = require("../../util");
var deprecated = require("../registry/deprecated");
var storage = null; var storage = null;
var settings = null; var settings = null;

View File

@ -16,7 +16,7 @@
var clone = require("clone"); var clone = require("clone");
var redUtil = require("../../util"); var redUtil = require("../../util");
var subflowInstanceRE = /^subflow:(.+)$/; var subflowInstanceRE = /^subflow:(.+)$/;
var typeRegistry = require("../registry"); var typeRegistry = require("../../../runtime-registry");
function diffNodes(oldNode,newNode) { function diffNodes(oldNode,newNode) {
if (oldNode == null) { if (oldNode == null) {
@ -203,7 +203,7 @@ module.exports = {
var linkMap = {}; var linkMap = {};
var changedTabs = {}; var changedTabs = {};
// Look for tabs that have been removed // Look for tabs that have been removed
for (id in oldConfig.flows) { for (id in oldConfig.flows) {
if (oldConfig.flows.hasOwnProperty(id) && (!newConfig.flows.hasOwnProperty(id))) { if (oldConfig.flows.hasOwnProperty(id) && (!newConfig.flows.hasOwnProperty(id))) {

View File

@ -18,15 +18,16 @@ var when = require("when");
var path = require("path"); var path = require("path");
var fs = require("fs"); var fs = require("fs");
var clone = require("clone"); var clone = require("clone");
var util = require("util");
var registry = require("../../runtime-registry");
var registry = require("./registry");
var credentials = require("./credentials"); var credentials = require("./credentials");
var flows = require("./flows"); var flows = require("./flows");
var flowUtil = require("./flows/util") var flowUtil = require("./flows/util")
var context = require("./context"); var context = require("./context");
var Node = require("./Node"); var Node = require("./Node");
var log; var log;
var library = require("./library");
var events = require("../events"); var events = require("../events");
@ -61,6 +62,26 @@ function registerType(nodeSet,type,constructor,opts) {
} }
} }
} }
if(!(constructor.prototype instanceof Node)) {
if(Object.getPrototypeOf(constructor.prototype) === Object.prototype) {
util.inherits(constructor,Node);
} else {
var proto = constructor.prototype;
while(Object.getPrototypeOf(proto) !== Object.prototype) {
proto = Object.getPrototypeOf(proto);
}
//TODO: This is a partial implementation of util.inherits >= node v5.0.0
// which should be changed when support for node < v5.0.0 is dropped
// see: https://github.com/nodejs/node/pull/3455
proto.constructor.super_ = Node;
if(Object.setPrototypeOf) {
Object.setPrototypeOf(proto, Node.prototype);
} else {
// hack for node v0.10
proto.__proto__ = Node.prototype;
}
}
}
registry.registerType(nodeSet,type,constructor); registry.registerType(nodeSet,type,constructor);
} }
@ -99,7 +120,6 @@ function init(runtime) {
flows.init(runtime); flows.init(runtime);
registry.init(runtime); registry.init(runtime);
context.init(runtime.settings); context.init(runtime.settings);
library.init(runtime);
} }
function disableNode(id) { function disableNode(id) {
@ -188,8 +208,8 @@ module.exports = {
getNodeConfig: registry.getNodeConfig, getNodeConfig: registry.getNodeConfig,
getNodeIconPath: registry.getNodeIconPath, getNodeIconPath: registry.getNodeIconPath,
getNodeIcons: registry.getNodeIcons, getNodeIcons: registry.getNodeIcons,
getNodeExampleFlows: library.getExampleFlows, getNodeExampleFlows: registry.getNodeExampleFlows,
getNodeExampleFlowPath: library.getExampleFlowPath, getNodeExampleFlowPath: registry.getNodeExampleFlowPath,
clearRegistry: registry.clear, clearRegistry: registry.clear,
cleanModuleList: registry.cleanModuleList, cleanModuleList: registry.cleanModuleList,

View File

@ -83,7 +83,6 @@ module.exports = {
try { try {
fs.renameSync(path,backupPath); fs.renameSync(path,backupPath);
} catch(err) { } catch(err) {
console.log(err);
} }
} }
return when.promise(function(resolve,reject) { return when.promise(function(resolve,reject) {

View File

@ -16,7 +16,7 @@
var should = require("should"); var should = require("should");
var deprecated = require("../../../../../red/runtime/nodes/registry/deprecated.js"); var deprecated = require("../../../red/runtime-registry/deprecated.js");
describe('deprecated', function() { describe('deprecated', function() {
it('should return info on a node',function() { it('should return info on a node',function() {

View File

@ -20,16 +20,13 @@ var path = require("path");
var when = require("when"); var when = require("when");
var fs = require("fs"); var fs = require("fs");
var registry = require("../../../../../red/runtime/nodes/registry"); var registry = require("../../../red/runtime-registry");
var installer = require("../../../../../red/runtime/nodes/registry/installer"); var installer = require("../../../red/runtime-registry/installer");
var loader = require("../../../../../red/runtime/nodes/registry/loader"); var loader = require("../../../red/runtime-registry/loader");
var typeRegistry = require("../../../../../red/runtime/nodes/registry/registry"); var typeRegistry = require("../../../red/runtime-registry/registry");
describe('red/registry/index', function() {
describe('red/nodes/registry/index', function() {
var stubs = []; var stubs = [];
afterEach(function() { afterEach(function() {
while(stubs.length) { while(stubs.length) {

View File

@ -22,9 +22,9 @@ var fs = require('fs');
var EventEmitter = require('events'); var EventEmitter = require('events');
var child_process = require('child_process'); var child_process = require('child_process');
var installer = require("../../../../../red/runtime/nodes/registry/installer"); var installer = require("../../../red/runtime-registry/installer");
var registry = require("../../../../../red/runtime/nodes/registry/index"); var registry = require("../../../red/runtime-registry/index");
var typeRegistry = require("../../../../../red/runtime/nodes/registry/registry"); var typeRegistry = require("../../../red/runtime-registry/registry");
describe('nodes/registry/installer', function() { describe('nodes/registry/installer', function() {
@ -39,7 +39,7 @@ describe('nodes/registry/installer', function() {
} }
before(function() { before(function() {
installer.init({log:mockLog, settings:{}}); installer.init({log:mockLog, settings:{}, events: new EventEmitter()});
}); });
afterEach(function() { afterEach(function() {
if (child_process.spawn.restore) { if (child_process.spawn.restore) {
@ -166,7 +166,7 @@ describe('nodes/registry/installer', function() {
}); });
it("rejects when non-existant path is provided", function(done) { it("rejects when non-existant path is provided", function(done) {
this.timeout(10000); this.timeout(10000);
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule","node_modules","NonExistant")); var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","NonExistant"));
installer.installModule(resourcesDir).then(function() { installer.installModule(resourcesDir).then(function() {
done(new Error("Unexpected success")); done(new Error("Unexpected success"));
}).catch(function(err) { }).catch(function(err) {
@ -186,7 +186,7 @@ describe('nodes/registry/installer', function() {
var addModule = sinon.stub(registry,"addModule",function(md) { var addModule = sinon.stub(registry,"addModule",function(md) {
return when.resolve(nodeInfo); return when.resolve(nodeInfo);
}); });
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule","node_modules","TestNodeModule")); var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule"));
sinon.stub(child_process,"spawn",function(cmd,args,opt) { sinon.stub(child_process,"spawn",function(cmd,args,opt) {
var ee = new EventEmitter(); var ee = new EventEmitter();
ee.stdout = new EventEmitter(); ee.stdout = new EventEmitter();

View File

@ -14,56 +14,47 @@
* limitations under the License. * limitations under the License.
**/ **/
var EventEmitter = require('events').EventEmitter;
var events = new EventEmitter();
var should = require("should"); var should = require("should");
var fs = require("fs"); var fs = require("fs");
var path = require("path"); var path = require("path");
var library = require("../../../../red/runtime/nodes/library") var library = require("../../../red/runtime-registry/library");
describe("library api", function() { describe("library api", function() {
it('returns null list when no modules have been registered', function() { it('returns null list when no modules have been registered', function() {
library.init({events:events}); library.init();
should.not.exist(library.getExampleFlows()); should.not.exist(library.getExampleFlows());
}); });
it('returns null path when module is not known', function() { it('returns null path when module is not known', function() {
library.init({events:events}); library.init();
should.not.exist(library.getExampleFlowPath('foo','bar')); should.not.exist(library.getExampleFlowPath('foo','bar'));
}); });
it('returns a valid example path', function(done) { it('returns a valid example path', function(done) {
library.init({events:events}); library.init();
events.emit('node-examples-dir',{ library.addExamplesDir("test-module",path.resolve(__dirname+'/resources/examples')).then(function() {
name: "test-module",
path: path.resolve(__dirname+'/../../../resources/examples')
});
setTimeout(function() {
try { try {
var flows = library.getExampleFlows(); var flows = library.getExampleFlows();
flows.should.deepEqual({"d":{"test-module":{"f":["one"]}}}); flows.should.deepEqual({"d":{"test-module":{"f":["one"]}}});
var examplePath = library.getExampleFlowPath('test-module','one'); var examplePath = library.getExampleFlowPath('test-module','one');
examplePath.should.eql(path.resolve(__dirname+'/../../../resources/examples/one.json')) examplePath.should.eql(path.resolve(__dirname+'/resources/examples/one.json'))
events.emit('node-module-uninstalled', 'test-module'); library.removeExamplesDir('test-module');
setTimeout(function() { try {
try { should.not.exist(library.getExampleFlows());
should.not.exist(library.getExampleFlows()); should.not.exist(library.getExampleFlowPath('test-module','one'));
should.not.exist(library.getExampleFlowPath('test-module','one')); done();
done(); } catch(err) {
} catch(err) { done(err);
done(err); }
}
},20);
}catch(err) { }catch(err) {
done(err); done(err);
} }
},20); });
}) })
}); });

View File

@ -20,14 +20,14 @@ var sinon = require("sinon");
var path = require("path"); var path = require("path");
var fs = require("fs"); var fs = require("fs");
var loader = require("../../../../../red/runtime/nodes/registry/loader"); var loader = require("../../../red/runtime-registry/loader");
var localfilesystem = require("../../../../../red/runtime/nodes/registry/localfilesystem"); var localfilesystem = require("../../../red/runtime-registry/localfilesystem");
var registry = require("../../../../../red/runtime/nodes/registry/registry"); var registry = require("../../../red/runtime-registry/registry");
var nodes = require("../../../../../red/runtime/nodes/registry"); var nodes = require("../../../red/runtime-registry");
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local")); var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
describe("red/nodes/registry/loader",function() { describe("red/nodes/registry/loader",function() {
var stubs = []; var stubs = [];
@ -42,18 +42,12 @@ describe("red/nodes/registry/loader",function() {
stubs.pop().restore(); stubs.pop().restore();
} }
}) })
describe("#init",function() {
it("init",function() {
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){},log:{info:function(){},_:function(){}}}});
localfilesystem.init.called.should.be.true();
});
});
describe("#load",function() { describe("#load",function() {
it("load empty set without settings available", function(done) { it("load empty set without settings available", function(done) {
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};})); stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return {};})); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return {};}));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
loader.load("foo",true).then(function() { loader.load("foo",true).then(function() {
localfilesystem.getNodeFiles.called.should.be.true(); localfilesystem.getNodeFiles.called.should.be.true();
localfilesystem.getNodeFiles.lastCall.args[0].should.eql('foo'); localfilesystem.getNodeFiles.lastCall.args[0].should.eql('foo');
@ -65,7 +59,7 @@ describe("red/nodes/registry/loader",function() {
it("load empty set with settings available triggers registery save", function(done) { it("load empty set with settings available triggers registery save", function(done) {
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};})); stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return {};})); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return {};}));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load("foo",true).then(function() { loader.load("foo",true).then(function() {
registry.saveNodeList.called.should.be.true(); registry.saveNodeList.called.should.be.true();
done(); done();
@ -79,6 +73,7 @@ describe("red/nodes/registry/loader",function() {
var result = {}; var result = {};
result["node-red"] = { result["node-red"] = {
"name": "node-red", "name": "node-red",
"version": "1.2.3",
"nodes": { "nodes": {
"TestNode1": { "TestNode1": {
"file": path.join(resourcesDir,"TestNode1","TestNode1.js"), "file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
@ -91,27 +86,32 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded // This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; })); stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) { loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true(); registry.addModule.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode1"); var module = registry.addModule.lastCall.args[0];
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode1"); module.should.have.property("name","node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red"); module.should.have.property("version","1.2.3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true); module.should.have.property("nodes");
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true); module.nodes.should.have.property("TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined); module.nodes.TestNode1.should.have.property("id","node-red/TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('types'); module.nodes.TestNode1.should.have.property("module","node-red");
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1); module.nodes.TestNode1.should.have.property("name","TestNode1");
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-1'); module.nodes.TestNode1.should.have.property("file");
registry.addNodeSet.lastCall.args[1].should.have.a.property('config'); module.nodes.TestNode1.should.have.property("template");
registry.addNodeSet.lastCall.args[1].should.have.a.property('help'); module.nodes.TestNode1.should.have.property("enabled",true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red'); module.nodes.TestNode1.should.have.property("loaded",true);
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err'); module.nodes.TestNode1.should.have.property("types");
module.nodes.TestNode1.types.should.have.a.length(1);
module.nodes.TestNode1.types[0].should.eql('test-node-1');
module.nodes.TestNode1.should.have.property("config");
module.nodes.TestNode1.should.have.property("help");
module.nodes.TestNode1.should.have.property("namespace","node-red");
nodes.registerType.calledOnce.should.be.true(); nodes.registerType.calledOnce.should.be.true();
nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode1'); nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode1');
@ -128,6 +128,7 @@ describe("red/nodes/registry/loader",function() {
var result = {}; var result = {};
result["node-red"] = { result["node-red"] = {
"name": "node-red", "name": "node-red",
"version": "4.5.6",
"nodes": { "nodes": {
"MultipleNodes1": { "MultipleNodes1": {
"file": path.join(resourcesDir,"MultipleNodes1","MultipleNodes1.js"), "file": path.join(resourcesDir,"MultipleNodes1","MultipleNodes1.js"),
@ -140,27 +141,33 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded // This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; })); stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) { loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/MultipleNodes1"); registry.addModule.called.should.be.true();
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/MultipleNodes1"); var module = registry.addModule.lastCall.args[0];
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red"); module.should.have.property("name","node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true); module.should.have.property("version","4.5.6");
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true); module.should.have.property("nodes");
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined); module.nodes.should.have.property("MultipleNodes1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('types'); module.nodes.MultipleNodes1.should.have.property("id","node-red/MultipleNodes1");
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(2); module.nodes.MultipleNodes1.should.have.property("module","node-red");
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-multiple-1a'); module.nodes.MultipleNodes1.should.have.property("name","MultipleNodes1");
registry.addNodeSet.lastCall.args[1].types[1].should.eql('test-node-multiple-1b'); module.nodes.MultipleNodes1.should.have.property("file");
registry.addNodeSet.lastCall.args[1].should.have.a.property('config'); module.nodes.MultipleNodes1.should.have.property("template");
registry.addNodeSet.lastCall.args[1].should.have.a.property('help'); module.nodes.MultipleNodes1.should.have.property("enabled",true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red'); module.nodes.MultipleNodes1.should.have.property("loaded",true);
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err'); module.nodes.MultipleNodes1.should.have.property("types");
module.nodes.MultipleNodes1.types.should.have.a.length(2);
module.nodes.MultipleNodes1.types[0].should.eql('test-node-multiple-1a');
module.nodes.MultipleNodes1.types[1].should.eql('test-node-multiple-1b');
module.nodes.MultipleNodes1.should.have.property("config");
module.nodes.MultipleNodes1.should.have.property("help");
module.nodes.MultipleNodes1.should.have.property("namespace","node-red");
nodes.registerType.calledTwice.should.be.true(); nodes.registerType.calledTwice.should.be.true();
nodes.registerType.firstCall.args[0].should.eql('node-red/MultipleNodes1'); nodes.registerType.firstCall.args[0].should.eql('node-red/MultipleNodes1');
@ -168,6 +175,7 @@ describe("red/nodes/registry/loader",function() {
nodes.registerType.secondCall.args[0].should.eql('node-red/MultipleNodes1'); nodes.registerType.secondCall.args[0].should.eql('node-red/MultipleNodes1');
nodes.registerType.secondCall.args[1].should.eql('test-node-multiple-1b'); nodes.registerType.secondCall.args[1].should.eql('test-node-multiple-1b');
done(); done();
}).catch(function(err) { }).catch(function(err) {
done(err); done(err);
@ -180,6 +188,7 @@ describe("red/nodes/registry/loader",function() {
var result = {}; var result = {};
result["node-red"] = { result["node-red"] = {
"name": "node-red", "name": "node-red",
"version":"2.4.6",
"nodes": { "nodes": {
"TestNode2": { "TestNode2": {
"file": path.join(resourcesDir,"TestNode2","TestNode2.js"), "file": path.join(resourcesDir,"TestNode2","TestNode2.js"),
@ -192,27 +201,34 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded // This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; })); stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) { loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode2"); registry.addModule.called.should.be.true();
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode2"); var module = registry.addModule.lastCall.args[0];
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red"); module.should.have.property("name","node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true); module.should.have.property("version","2.4.6");
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true); module.should.have.property("nodes");
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined); module.nodes.should.have.property("TestNode2");
registry.addNodeSet.lastCall.args[1].should.have.a.property('types'); module.nodes.TestNode2.should.have.property("id","node-red/TestNode2");
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1); module.nodes.TestNode2.should.have.property("module","node-red");
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-2'); module.nodes.TestNode2.should.have.property("name","TestNode2");
registry.addNodeSet.lastCall.args[1].should.have.a.property('config'); module.nodes.TestNode2.should.have.property("file");
registry.addNodeSet.lastCall.args[1].should.have.a.property('help'); module.nodes.TestNode2.should.have.property("template");
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red'); module.nodes.TestNode2.should.have.property("enabled",true);
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err'); module.nodes.TestNode2.should.have.property("loaded",true);
module.nodes.TestNode2.should.have.property("types");
module.nodes.TestNode2.types.should.have.a.length(1);
module.nodes.TestNode2.types[0].should.eql('test-node-2');
module.nodes.TestNode2.should.have.property("config");
module.nodes.TestNode2.should.have.property("help");
module.nodes.TestNode2.should.have.property("namespace","node-red");
module.nodes.TestNode2.should.not.have.property('err');
nodes.registerType.calledOnce.should.be.true(); nodes.registerType.calledOnce.should.be.true();
nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode2'); nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode2');
@ -230,6 +246,7 @@ describe("red/nodes/registry/loader",function() {
var result = {}; var result = {};
result["node-red"] = { result["node-red"] = {
"name": "node-red", "name": "node-red",
"version":"1.2.3",
"nodes": { "nodes": {
"TestNode3": { "TestNode3": {
"file": path.join(resourcesDir,"TestNode3","TestNode3.js"), "file": path.join(resourcesDir,"TestNode3","TestNode3.js"),
@ -242,29 +259,35 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded // This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; })); stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) { loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true(); registry.addModule.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode3"); var module = registry.addModule.lastCall.args[0];
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode3"); module.should.have.property("name","node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red"); module.should.have.property("version","1.2.3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true); module.should.have.property("nodes");
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false); module.nodes.should.have.property("TestNode3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined); module.nodes.TestNode3.should.have.property("id","node-red/TestNode3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('types'); module.nodes.TestNode3.should.have.property("module","node-red");
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1); module.nodes.TestNode3.should.have.property("name","TestNode3");
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-3'); module.nodes.TestNode3.should.have.property("file");
registry.addNodeSet.lastCall.args[1].should.have.a.property('config'); module.nodes.TestNode3.should.have.property("template");
registry.addNodeSet.lastCall.args[1].should.have.a.property('help'); module.nodes.TestNode3.should.have.property("enabled",true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red'); module.nodes.TestNode3.should.have.property("loaded",false);
registry.addNodeSet.lastCall.args[1].should.have.a.property('err','fail'); module.nodes.TestNode3.should.have.property("types");
module.nodes.TestNode3.types.should.have.a.length(1);
module.nodes.TestNode3.types[0].should.eql('test-node-3');
module.nodes.TestNode3.should.have.property("config");
module.nodes.TestNode3.should.have.property("help");
module.nodes.TestNode3.should.have.property("namespace","node-red");
module.nodes.TestNode3.should.have.property('err','fail');
nodes.registerType.calledOnce.should.be.false(); nodes.registerType.called.should.be.false();
done(); done();
}).catch(function(err) { }).catch(function(err) {
@ -277,6 +300,7 @@ describe("red/nodes/registry/loader",function() {
var result = {}; var result = {};
result["node-red"] = { result["node-red"] = {
"name": "node-red", "name": "node-red",
"version":"1.2.3",
"nodes": { "nodes": {
"DoesNotExist": { "DoesNotExist": {
"file": path.join(resourcesDir,"doesnotexist"), "file": path.join(resourcesDir,"doesnotexist"),
@ -289,28 +313,34 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded // This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; })); stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) { loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true(); registry.addModule.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/DoesNotExist"); var module = registry.addModule.lastCall.args[0];
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/DoesNotExist"); module.should.have.property("name","node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red"); module.should.have.property("version","1.2.3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true); module.should.have.property("nodes");
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false); module.nodes.should.have.property("DoesNotExist");
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined); module.nodes.DoesNotExist.should.have.property("id","node-red/DoesNotExist");
registry.addNodeSet.lastCall.args[1].should.have.a.property('types'); module.nodes.DoesNotExist.should.have.property("module","node-red");
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(0); module.nodes.DoesNotExist.should.have.property("name","DoesNotExist");
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('config'); module.nodes.DoesNotExist.should.have.property("file");
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('help'); module.nodes.DoesNotExist.should.have.property("template");
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('namespace','node-red'); module.nodes.DoesNotExist.should.have.property("enabled",true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('err'); module.nodes.DoesNotExist.should.have.property("loaded",false);
module.nodes.DoesNotExist.should.have.property("types");
module.nodes.DoesNotExist.types.should.have.a.length(0);
module.nodes.DoesNotExist.should.not.have.property("config");
module.nodes.DoesNotExist.should.not.have.property("help");
module.nodes.DoesNotExist.should.not.have.property("namespace","node-red");
module.nodes.DoesNotExist.should.have.property('err');
nodes.registerType.calledOnce.should.be.false(); nodes.registerType.called.should.be.false();
done(); done();
}).catch(function(err) { }).catch(function(err) {
@ -323,6 +353,7 @@ describe("red/nodes/registry/loader",function() {
var result = {}; var result = {};
result["node-red"] = { result["node-red"] = {
"name": "node-red", "name": "node-red",
"version": "1.2.3",
"nodes": { "nodes": {
"DuffNode": { "DuffNode": {
"file": path.join(resourcesDir,"DuffNode","DuffNode.js"), "file": path.join(resourcesDir,"DuffNode","DuffNode.js"),
@ -335,29 +366,36 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded // This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; })); stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) { loader.load().then(function(result) {
registry.addNodeSet.called.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("node-red/DuffNode");
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/DuffNode");
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false);
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(0);
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('config');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('help');
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('namespace','node-red');
registry.addNodeSet.lastCall.args[1].should.have.a.property('err');
registry.addNodeSet.lastCall.args[1].err.should.endWith("DuffNode.html does not exist");
nodes.registerType.calledOnce.should.be.false(); registry.addModule.called.should.be.true();
var module = registry.addModule.lastCall.args[0];
module.should.have.property("name","node-red");
module.should.have.property("version","1.2.3");
module.should.have.property("nodes");
module.nodes.should.have.property("DuffNode");
module.nodes.DuffNode.should.have.property("id","node-red/DuffNode");
module.nodes.DuffNode.should.have.property("module","node-red");
module.nodes.DuffNode.should.have.property("name","DuffNode");
module.nodes.DuffNode.should.have.property("file");
module.nodes.DuffNode.should.have.property("template");
module.nodes.DuffNode.should.have.property("enabled",true);
module.nodes.DuffNode.should.have.property("loaded",false);
module.nodes.DuffNode.should.have.property("types");
module.nodes.DuffNode.types.should.have.a.length(0);
module.nodes.DuffNode.should.not.have.property("config");
module.nodes.DuffNode.should.not.have.property("help");
module.nodes.DuffNode.should.not.have.property("namespace","node-red");
module.nodes.DuffNode.should.have.property('err');
module.nodes.DuffNode.err.should.endWith("DuffNode.html does not exist");
nodes.registerType.called.should.be.false();
done(); done();
}).catch(function(err) { }).catch(function(err) {
@ -368,7 +406,7 @@ describe("red/nodes/registry/loader",function() {
describe("#addModule",function() { describe("#addModule",function() {
it("throws error if settings unavailable", function() { it("throws error if settings unavailable", function() {
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
loader.addModule("test-module"); loader.addModule("test-module");
@ -377,7 +415,7 @@ describe("red/nodes/registry/loader",function() {
it("returns rejected error if module already loaded", function(done) { it("returns rejected error if module already loaded", function(done) {
stubs.push(sinon.stub(registry,"getModuleInfo",function(){return{}})); stubs.push(sinon.stub(registry,"getModuleInfo",function(){return{}}));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.addModule("test-module").catch(function(err) { loader.addModule("test-module").catch(function(err) {
err.code.should.eql("module_already_loaded"); err.code.should.eql("module_already_loaded");
@ -389,7 +427,7 @@ describe("red/nodes/registry/loader",function() {
stubs.push(sinon.stub(localfilesystem,"getModuleFiles",function() { stubs.push(sinon.stub(localfilesystem,"getModuleFiles",function() {
throw new Error("failure"); throw new Error("failure");
})); }));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.addModule("test-module").catch(function(err) { loader.addModule("test-module").catch(function(err) {
err.message.should.eql("failure"); err.message.should.eql("failure");
done(); done();
@ -419,25 +457,32 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}}); loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.addModule("TestNodeModule").then(function(result) { loader.addModule("TestNodeModule").then(function(result) {
result.should.eql("a node list"); result.should.eql("a node list");
registry.addNodeSet.calledOnce.should.be.true();
registry.addNodeSet.lastCall.args[0].should.eql("TestNodeModule/TestNode1"); registry.addModule.called.should.be.true();
registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"TestNodeModule/TestNode1"); var module = registry.addModule.lastCall.args[0];
registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"TestNodeModule"); module.should.have.property("name","TestNodeModule");
registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true); module.should.have.property("version","1.2.3");
registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true); module.should.have.property("nodes");
registry.addNodeSet.lastCall.args[1].should.have.a.property('version',"1.2.3"); module.nodes.should.have.property("TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('types'); module.nodes.TestNode1.should.have.property("id","TestNodeModule/TestNode1");
registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1); module.nodes.TestNode1.should.have.property("module","TestNodeModule");
registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-mod-1'); module.nodes.TestNode1.should.have.property("name","TestNode1");
registry.addNodeSet.lastCall.args[1].should.have.a.property('config'); module.nodes.TestNode1.should.have.property("file");
registry.addNodeSet.lastCall.args[1].should.have.a.property('help'); module.nodes.TestNode1.should.have.property("template");
registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','TestNodeModule'); module.nodes.TestNode1.should.have.property("enabled",true);
registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err'); module.nodes.TestNode1.should.have.property("loaded",true);
module.nodes.TestNode1.should.have.property("types");
module.nodes.TestNode1.types.should.have.a.length(1);
module.nodes.TestNode1.types[0].should.eql('test-node-mod-1');
module.nodes.TestNode1.should.have.property("config");
module.nodes.TestNode1.should.have.property("help");
module.nodes.TestNode1.should.have.property("namespace","TestNodeModule");
module.nodes.TestNode1.should.not.have.property('err');
nodes.registerType.calledOnce.should.be.true(); nodes.registerType.calledOnce.should.be.true();
done(); done();
@ -469,12 +514,12 @@ describe("red/nodes/registry/loader",function() {
})); }));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" })); stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
stubs.push(sinon.stub(registry,"addNodeSet", function(){ return })); stubs.push(sinon.stub(registry,"addModule", function(){ return }));
stubs.push(sinon.stub(nodes,"registerType")); stubs.push(sinon.stub(nodes,"registerType"));
loader.init({log:{"_":function(){},warn:function(){}},nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},version: function() { return "0.12.0"}, settings:{available:function(){return true;}}}); loader.init({log:{"_":function(){},warn:function(){}},nodes:nodes,version: function() { return "0.12.0"}, settings:{available:function(){return true;}}});
loader.addModule("TestNodeModule").then(function(result) { loader.addModule("TestNodeModule").then(function(result) {
result.should.eql("a node list"); result.should.eql("a node list");
registry.addNodeSet.called.should.be.false(); registry.addModule.called.should.be.false();
nodes.registerType.called.should.be.false(); nodes.registerType.called.should.be.false();
done(); done();
}).catch(function(err) { }).catch(function(err) {

View File

@ -19,13 +19,19 @@ var when = require("when");
var sinon = require("sinon"); var sinon = require("sinon");
var path = require("path"); var path = require("path");
var localfilesystem = require("../../../../../red/runtime/nodes/registry/localfilesystem"); var localfilesystem = require("../../../red/runtime-registry/localfilesystem");
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","local")); var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
var userDir = path.resolve(path.join(__dirname,"..","resources","userDir")); var userDir = path.resolve(path.join(__dirname,"resources","userDir"));
var moduleDir = path.resolve(path.join(__dirname,"..","resources","local","TestNodeModule")); var moduleDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule"));
var i18n = require("../../../red/util").i18n; // TODO: separate module
describe("red/nodes/registry/localfilesystem",function() { describe("red/nodes/registry/localfilesystem",function() {
beforeEach(function() {
stubs.push(sinon.stub(i18n,"registerMessageCatalog", function() { return Promise.resolve(); }));
})
var stubs = []; var stubs = [];
afterEach(function() { afterEach(function() {
while(stubs.length) { while(stubs.length) {
@ -46,7 +52,7 @@ describe("red/nodes/registry/localfilesystem",function() {
} }
describe("#getNodeFiles",function() { describe("#getNodeFiles",function() {
it("Finds all the node files in the resources tree",function(done) { it("Finds all the node files in the resources tree",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:resourcesDir}}); localfilesystem.init({settings:{coreNodesDir:resourcesDir}});
var nodeList = localfilesystem.getNodeFiles(true); var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
@ -54,10 +60,14 @@ describe("red/nodes/registry/localfilesystem",function() {
nm.should.have.a.property("nodes"); nm.should.have.a.property("nodes");
var nodes = nm.nodes; var nodes = nm.nodes;
checkNodes(nm.nodes,['TestNode1','MultipleNodes1','NestedNode','TestNode2','TestNode3','TestNode4'],['TestNodeModule']); checkNodes(nm.nodes,['TestNode1','MultipleNodes1','NestedNode','TestNode2','TestNode3','TestNode4'],['TestNodeModule']);
i18n.registerMessageCatalog.called.should.be.true();
i18n.registerMessageCatalog.lastCall.args[0].should.eql('node-red');
i18n.registerMessageCatalog.lastCall.args[1].should.eql(path.resolve(path.join(resourcesDir,"core","locales")));
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
done(); done();
}); });
it("Includes node files from settings",function(done) { it("Includes node files from settings",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesIncludes:['TestNode1.js'],coreNodesDir:resourcesDir}}); localfilesystem.init({settings:{nodesIncludes:['TestNode1.js'],coreNodesDir:resourcesDir}});
var nodeList = localfilesystem.getNodeFiles(true); var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
@ -67,7 +77,7 @@ describe("red/nodes/registry/localfilesystem",function() {
done(); done();
}); });
it("Excludes node files from settings",function(done) { it("Excludes node files from settings",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesExcludes:['TestNode1.js'],coreNodesDir:resourcesDir}}); localfilesystem.init({settings:{nodesExcludes:['TestNode1.js'],coreNodesDir:resourcesDir}});
var nodeList = localfilesystem.getNodeFiles(true); var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
@ -77,7 +87,7 @@ describe("red/nodes/registry/localfilesystem",function() {
done(); done();
}); });
it("Finds nodes in userDir/nodes",function(done) { it("Finds nodes in userDir/nodes",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{userDir:userDir,coreNodesDir:__dirname}}); localfilesystem.init({settings:{userDir:userDir}});
var nodeList = localfilesystem.getNodeFiles(true); var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
@ -88,7 +98,7 @@ describe("red/nodes/registry/localfilesystem",function() {
}); });
it("Finds nodes in settings.nodesDir (string)",function(done) { it("Finds nodes in settings.nodesDir (string)",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesDir:userDir,coreNodesDir:__dirname}}); localfilesystem.init({settings:{nodesDir:userDir}});
var nodeList = localfilesystem.getNodeFiles(true); var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
@ -97,19 +107,19 @@ describe("red/nodes/registry/localfilesystem",function() {
checkNodes(nm.nodes,['TestNode5'],['TestNode1']); checkNodes(nm.nodes,['TestNode5'],['TestNode1']);
done(); done();
}); });
it("Finds nodes in settings.nodesDir (string,relative path)",function(done) { it("Finds nodes in settings.nodesDir (string,relative path)",function(done) {
var relativeUserDir = path.join("test","red","runtime","nodes","resources","userDir"); var relativeUserDir = path.join("test","red","runtime-registry","resources","userDir");
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesDir:relativeUserDir,coreNodesDir:__dirname}}); localfilesystem.init({settings:{nodesDir:relativeUserDir}});
var nodeList = localfilesystem.getNodeFiles(true); var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
nm.should.have.a.property('name','node-red'); nm.should.have.a.property('name','node-red');
nm.should.have.a.property("nodes"); nm.should.have.a.property("nodes");
checkNodes(nm.nodes,['TestNode5'],['TestNode1']); checkNodes(nm.nodes,['TestNode5'],['TestNode1']);
done(); done();
}); });
it("Finds nodes in settings.nodesDir (array)",function(done) { it("Finds nodes in settings.nodesDir (array)",function(done) {
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{nodesDir:[userDir],coreNodesDir:__dirname}}); localfilesystem.init({settings:{nodesDir:[userDir]}});
var nodeList = localfilesystem.getNodeFiles(true); var nodeList = localfilesystem.getNodeFiles(true);
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
@ -128,7 +138,7 @@ describe("red/nodes/registry/localfilesystem",function() {
} }
return _join.apply(null,arguments); return _join.apply(null,arguments);
})); }));
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}}); localfilesystem.init({settings:{coreNodesDir:moduleDir}});
var nodeList = localfilesystem.getNodeFiles(); var nodeList = localfilesystem.getNodeFiles();
nodeList.should.have.a.property("node-red"); nodeList.should.have.a.property("node-red");
var nm = nodeList['node-red']; var nm = nodeList['node-red'];
@ -146,6 +156,13 @@ describe("red/nodes/registry/localfilesystem",function() {
nm.should.have.a.property("nodes"); nm.should.have.a.property("nodes");
checkNodes(nm.nodes,['VersionMismatchMod1','VersionMismatchMod2'],[],'VersionMismatchModule'); checkNodes(nm.nodes,['VersionMismatchMod1','VersionMismatchMod2'],[],'VersionMismatchModule');
i18n.registerMessageCatalog.called.should.be.true();
i18n.registerMessageCatalog.lastCall.args[0].should.eql('node-red');
i18n.registerMessageCatalog.lastCall.args[1].should.eql(path.resolve(path.join(moduleDir,"core","locales")));
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
done(); done();
}); });
it.skip("finds locales directory"); it.skip("finds locales directory");
@ -153,42 +170,58 @@ describe("red/nodes/registry/localfilesystem",function() {
it("scans icon files in the resources tree",function(done) { it("scans icon files in the resources tree",function(done) {
var count = 0; var count = 0;
localfilesystem.init({ localfilesystem.init({
i18n:{registerMessageCatalog:function(){}},
events:{emit:function(eventName,dir){ // events:{emit:function(eventName,dir){
if (count === 0) { // if (count === 0) {
eventName.should.equal("node-icon-dir"); // eventName.should.equal("node-icon-dir");
dir.name.should.equal("node-red"); // dir.name.should.equal("node-red");
dir.icons.should.be.an.Array(); // dir.icons.should.be.an.Array();
count = 1; // count = 1;
} else if (count === 1) { // } else if (count === 1) {
done(); // done();
} // }
}}, // }},
settings:{coreNodesDir:resourcesDir} settings:{coreNodesDir:resourcesDir}
}); });
localfilesystem.getNodeFiles(true); var list = localfilesystem.getNodeFiles(true);
list.should.have.property("node-red");
list["node-red"].should.have.property("icons");
list["node-red"].icons.should.have.length(2);
list["node-red"].icons[1].should.have.property("path",path.join(__dirname,"resources/local/NestedDirectoryNode/NestedNode/icons"))
list["node-red"].icons[1].should.have.property("icons");
list["node-red"].icons[1].icons.should.have.length(1);
list["node-red"].icons[1].icons[0].should.eql("arrow-in.png");
done();
}); });
it("scans icons dir in library",function(done) { it("scans icons dir in library",function(done) {
var count = 0; var count = 0;
localfilesystem.init({ localfilesystem.init({
i18n:{registerMessageCatalog:function(){}}, //
events:{emit:function(eventName,dir){ // events:{emit:function(eventName,dir){
eventName.should.equal("node-icon-dir"); // eventName.should.equal("node-icon-dir");
if (count === 0) { // if (count === 0) {
dir.name.should.equal("node-red"); // dir.name.should.equal("node-red");
dir.icons.should.be.an.Array(); // dir.icons.should.be.an.Array();
count = 1; // count = 1;
} else if (count === 1) { // } else if (count === 1) {
dir.name.should.equal("Library"); // dir.name.should.equal("Library");
dir.icons.should.be.an.Array(); // dir.icons.should.be.an.Array();
dir.icons.length.should.equal(1); // dir.icons.length.should.equal(1);
dir.icons[0].should.be.equal("test_icon.png"); // dir.icons[0].should.be.equal("test_icon.png");
done(); // done();
} // }
}}, // }},
settings:{userDir:userDir} settings:{userDir:userDir}
}); });
localfilesystem.getNodeFiles(true); var list = localfilesystem.getNodeFiles(true);
list.should.have.property("node-red");
list["node-red"].should.have.property("icons");
list["node-red"].icons.should.have.length(2);
list["node-red"].icons[1].should.have.property("path",path.join(__dirname,"resources/userDir/lib/icons"))
list["node-red"].icons[1].should.have.property("icons");
list["node-red"].icons[1].icons.should.have.length(1);
list["node-red"].icons[1].icons[0].should.eql("test_icon.png");
done();
}); });
}); });
describe("#getModuleFiles",function() { describe("#getModuleFiles",function() {
@ -202,7 +235,7 @@ describe("red/nodes/registry/localfilesystem",function() {
} }
return _join.apply(null,arguments); return _join.apply(null,arguments);
})); }));
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}}); localfilesystem.init({settings:{coreNodesDir:moduleDir}});
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule'); var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
nodeModule.should.have.a.property('TestNodeModule'); nodeModule.should.have.a.property('TestNodeModule');
nodeModule['TestNodeModule'].should.have.a.property('name','TestNodeModule'); nodeModule['TestNodeModule'].should.have.a.property('name','TestNodeModule');
@ -226,7 +259,7 @@ describe("red/nodes/registry/localfilesystem",function() {
} }
return _join.apply(null,arguments); return _join.apply(null,arguments);
})); }));
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}}); localfilesystem.init({settings:{coreNodesDir:moduleDir}});
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
localfilesystem.getModuleFiles('WontExistModule'); localfilesystem.getModuleFiles('WontExistModule');
@ -246,16 +279,24 @@ describe("red/nodes/registry/localfilesystem",function() {
return _join.apply(null,arguments); return _join.apply(null,arguments);
})); }));
localfilesystem.init({ localfilesystem.init({
i18n:{registerMessageCatalog:function(){}},
events:{emit:function(eventName,dir){ // events:{emit:function(eventName,dir){
eventName.should.equal("node-icon-dir"); // eventName.should.equal("node-icon-dir");
dir.name.should.equal("TestNodeModule"); // dir.name.should.equal("TestNodeModule");
dir.icons.should.be.an.Array(); // dir.icons.should.be.an.Array();
done(); // done();
}}, // }},
settings:{coreNodesDir:moduleDir} settings:{coreNodesDir:moduleDir}
}); });
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule'); var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
nodeModule.should.have.property("TestNodeModule");
nodeModule.TestNodeModule.should.have.property('icons');
nodeModule.TestNodeModule.icons.should.have.length(1);
nodeModule.TestNodeModule.icons[0].should.have.property("path");
nodeModule.TestNodeModule.icons[0].should.have.property("icons");
nodeModule.TestNodeModule.icons[0].icons[0].should.eql("arrow-in.png");
done();
}); });
}); });
}); });

View File

@ -19,13 +19,10 @@ var when = require("when");
var sinon = require("sinon"); var sinon = require("sinon");
var path = require("path"); var path = require("path");
var typeRegistry = require("../../../../../red/runtime/nodes/registry/registry"); var typeRegistry = require("../../../red/runtime-registry/registry");
var EventEmitter = require('events');
var Node = require("../../../../../red/runtime/nodes/Node"); var events = new EventEmitter();
var events = require("../../../../../red/runtime/events");
var inherits = require("util").inherits;
describe("red/nodes/registry/registry",function() { describe("red/nodes/registry/registry",function() {
@ -86,7 +83,7 @@ describe("red/nodes/registry/registry",function() {
describe('#init/load', function() { describe('#init/load', function() {
it('loads initial config', function(done) { it('loads initial config', function(done) {
typeRegistry.init(settingsWithStorageAndInitialConfig); typeRegistry.init(settingsWithStorageAndInitialConfig,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.load(); typeRegistry.load();
typeRegistry.getNodeList().should.have.lengthOf(1); typeRegistry.getNodeList().should.have.lengthOf(1);
@ -123,7 +120,7 @@ describe("red/nodes/registry/registry",function() {
}} }}
}; };
var expected = JSON.parse('{"node-red":{"name":"node-red","nodes":{"sentiment":{"name":"sentiment","types":["sentiment"],"enabled":true,"module":"node-red"},"inject":{"name":"inject","types":["inject"],"enabled":true,"module":"node-red"}}},"testModule":{"name":"testModule","nodes":{"a-module.js":{"name":"a-module.js","types":["example"],"enabled":true,"module":"testModule"}}}}'); var expected = JSON.parse('{"node-red":{"name":"node-red","nodes":{"sentiment":{"name":"sentiment","types":["sentiment"],"enabled":true,"module":"node-red"},"inject":{"name":"inject","types":["inject"],"enabled":true,"module":"node-red"}}},"testModule":{"name":"testModule","nodes":{"a-module.js":{"name":"a-module.js","types":["example"],"enabled":true,"module":"testModule"}}}}');
typeRegistry.init(legacySettings); typeRegistry.init(legacySettings,null,events);
typeRegistry.load(); typeRegistry.load();
legacySettings.set.calledOnce.should.be.true(); legacySettings.set.calledOnce.should.be.true();
legacySettings.set.args[0][1].should.eql(expected); legacySettings.set.args[0][1].should.eql(expected);
@ -132,10 +129,10 @@ describe("red/nodes/registry/registry",function() {
}); });
describe('#addNodeSet', function() { describe.skip('#addNodeSet', function() {
it('adds a node set for an unknown module', function() { it('adds a node set for an unknown module', function() {
typeRegistry.init(settings); typeRegistry.init(settings,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({}); typeRegistry.getModuleList().should.eql({});
@ -164,7 +161,7 @@ describe("red/nodes/registry/registry",function() {
it('adds a node set to an existing module', function() { it('adds a node set to an existing module', function() {
typeRegistry.init(settings); typeRegistry.init(settings,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({}); typeRegistry.getModuleList().should.eql({});
@ -193,7 +190,7 @@ describe("red/nodes/registry/registry",function() {
}); });
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,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({}); typeRegistry.getModuleList().should.eql({});
@ -209,7 +206,7 @@ describe("red/nodes/registry/registry",function() {
}); });
it('doesnt add node set if type already exists', function() { it('doesnt add node set if type already exists', function() {
typeRegistry.init(settings); typeRegistry.init(settings,null,events);
typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getNodeList().should.have.lengthOf(0);
typeRegistry.getModuleList().should.eql({}); typeRegistry.getModuleList().should.eql({});
@ -243,7 +240,7 @@ describe("red/nodes/registry/registry",function() {
describe("#enableNodeSet", function() { describe("#enableNodeSet", function() {
it('throws error if settings unavailable', function() { it('throws error if settings unavailable', function() {
typeRegistry.init(settings); typeRegistry.init(settings,null,events);
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
typeRegistry.enableNodeSet("test-module/test-name"); typeRegistry.enableNodeSet("test-module/test-name");
@ -251,7 +248,7 @@ describe("red/nodes/registry/registry",function() {
}); });
it('throws error if module unknown', function() { it('throws error if module unknown', function() {
typeRegistry.init(settingsWithStorageAndInitialConfig); typeRegistry.init(settingsWithStorageAndInitialConfig,null,events);
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
typeRegistry.enableNodeSet("test-module/unknown"); typeRegistry.enableNodeSet("test-module/unknown");
@ -262,7 +259,7 @@ describe("red/nodes/registry/registry",function() {
}); });
describe("#disableNodeSet", function() { describe("#disableNodeSet", function() {
it('throws error if settings unavailable', function() { it('throws error if settings unavailable', function() {
typeRegistry.init(settings); typeRegistry.init(settings,null,events);
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
typeRegistry.disableNodeSet("test-module/test-name"); typeRegistry.disableNodeSet("test-module/test-name");
@ -270,7 +267,7 @@ describe("red/nodes/registry/registry",function() {
}); });
it('throws error if module unknown', function() { it('throws error if module unknown', function() {
typeRegistry.init(settingsWithStorageAndInitialConfig); typeRegistry.init(settingsWithStorageAndInitialConfig,null,events);
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
typeRegistry.disableNodeSet("test-module/unknown"); typeRegistry.disableNodeSet("test-module/unknown");
@ -281,7 +278,7 @@ describe("red/nodes/registry/registry",function() {
describe('#getNodeConfig', function() { describe('#getNodeConfig', function() {
it('returns nothing for an unregistered type config', function(done) { it('returns nothing for an unregistered type config', function(done) {
typeRegistry.init(settings); typeRegistry.init(settings,null,events);
var config = typeRegistry.getNodeConfig("imaginary-shark"); var config = typeRegistry.getNodeConfig("imaginary-shark");
(config === null).should.be.true(); (config === null).should.be.true();
done(); done();
@ -290,26 +287,32 @@ describe("red/nodes/registry/registry",function() {
describe('#saveNodeList',function() { describe('#saveNodeList',function() {
it('rejects when settings unavailable',function(done) { it('rejects when settings unavailable',function(done) {
typeRegistry.init(stubSettings({},false,{})); typeRegistry.init(stubSettings({},false,{}),null,events);
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1"); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {"test-name":{module:"test-module",name:"test-name",types:[]}}});
typeRegistry.saveNodeList().catch(function(err) { typeRegistry.saveNodeList().catch(function(err) {
done(); done();
}); });
}); });
it('saves the list',function(done) { it('saves the list',function(done) {
var s = stubSettings({},true,{}); var s = stubSettings({},true,{});
typeRegistry.init(s); typeRegistry.init(s,null,events);
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2WithError, "0.0.1"); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":testNodeSet1,
"test-name-2":testNodeSet2WithError
}});
typeRegistry.saveNodeList().then(function() { typeRegistry.saveNodeList().then(function() {
s.set.called.should.be.true(); s.set.called.should.be.true();
s.set.lastCall.args[0].should.eql('nodes'); s.set.lastCall.args[0].should.eql('nodes');
var nodes = s.set.lastCall.args[1]; var nodes = s.set.lastCall.args[1];
nodes.should.have.property('test-module'); nodes.should.have.property('test-module');
for (var n in nodes['test-module'].nodes) { for (var n in nodes['test-module'].nodes) {
var nn = nodes['test-module'].nodes[n]; if (nodes['test-module'].nodes.hasOwnProperty(n)) {
nn.should.not.have.property('err'); var nn = nodes['test-module'].nodes[n];
nn.should.not.have.property('id'); nn.should.not.have.property('err');
nn.should.not.have.property('id');
}
} }
done(); done();
}).catch(function(err) { }).catch(function(err) {
@ -321,7 +324,7 @@ describe("red/nodes/registry/registry",function() {
describe('#removeModule',function() { describe('#removeModule',function() {
it('throws error for unknown module', function() { it('throws error for unknown module', function() {
var s = stubSettings({},true,{}); var s = stubSettings({},true,{});
typeRegistry.init(s); typeRegistry.init(s,null,events);
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
typeRegistry.removeModule("test-module/unknown"); typeRegistry.removeModule("test-module/unknown");
@ -329,7 +332,7 @@ describe("red/nodes/registry/registry",function() {
}); });
it('throws error for unavaiable settings', function() { it('throws error for unavaiable settings', function() {
var s = stubSettings({},false,{}); var s = stubSettings({},false,{});
typeRegistry.init(s); typeRegistry.init(s,null,events);
/*jshint immed: false */ /*jshint immed: false */
(function(){ (function(){
typeRegistry.removeModule("test-module/unknown"); typeRegistry.removeModule("test-module/unknown");
@ -337,8 +340,10 @@ describe("red/nodes/registry/registry",function() {
}); });
it('removes a known module', function() { it('removes a known module', function() {
var s = stubSettings({},true,{}); var s = stubSettings({},true,{});
typeRegistry.init(s); typeRegistry.init(s,null,events);
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1"); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":testNodeSet1
}});
var moduleList = typeRegistry.getModuleList(); var moduleList = typeRegistry.getModuleList();
moduleList.should.have.a.property("test-module"); moduleList.should.have.a.property("test-module");
typeRegistry.getNodeList().should.have.lengthOf(1); typeRegistry.getNodeList().should.have.lengthOf(1);
@ -354,45 +359,48 @@ describe("red/nodes/registry/registry",function() {
it('returns node config', function() { it('returns node config', function() {
typeRegistry.init(settings,{ typeRegistry.init(settings,{
getNodeHelp: function(config) { return "HE"+config.name+"LP" } getNodeHelp: function(config) { return "HE"+config.name+"LP" }
}); },events);
typeRegistry.addNodeSet("test-module/test-name",{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"]
}, "0.0.1");
typeRegistry.getNodeConfig("test-module/test-name").should.eql('configAHEtest-nameLP');
typeRegistry.getAllNodeConfigs().should.eql('configAHEtest-nameLP');
typeRegistry.addNodeSet("test-module/test-name-2",{ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
id: "test-module/test-name-2", "test-name":{
module: "test-module", id: "test-module/test-name",
name: "test-name-2", module: "test-module",
enabled: true, name: "test-name",
loaded: false, enabled: true,
config: "configB", loaded: false,
types: [ "test-c","test-d"] config: "configA",
}, "0.0.1"); types: [ "test-a","test-b"]
},
"test-name-2":{
id: "test-module/test-name-2",
module: "test-module",
name: "test-name-2",
enabled: true,
loaded: false,
config: "configB",
types: [ "test-c","test-d"]
}
}});
typeRegistry.getNodeConfig("test-module/test-name").should.eql('configAHEtest-nameLP');
typeRegistry.getNodeConfig("test-module/test-name-2").should.eql('configBHEtest-name-2LP'); typeRegistry.getNodeConfig("test-module/test-name-2").should.eql('configBHEtest-name-2LP');
typeRegistry.getAllNodeConfigs().should.eql('configAHEtest-nameLPconfigBHEtest-name-2LP'); typeRegistry.getAllNodeConfigs().should.eql('configAHEtest-nameLPconfigBHEtest-name-2LP');
}); });
}); });
describe('#getModuleInfo', function() { describe('#getModuleInfo', function() {
it('returns module info', function() { it('returns module info', function() {
typeRegistry.init(settings,{}); typeRegistry.init(settings,{},events);
typeRegistry.addNodeSet("test-module/test-name",{ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
id: "test-module/test-name", "test-name":{
module: "test-module", id: "test-module/test-name",
name: "test-name", module: "test-module",
enabled: true, name: "test-name",
loaded: false, enabled: true,
config: "configA", loaded: false,
types: [ "test-a","test-b"], config: "configA",
file: "abc" types: [ "test-a","test-b"],
}, "0.0.1"); file: "abc"
}
}});
var moduleInfo = typeRegistry.getModuleInfo("test-module"); var moduleInfo = typeRegistry.getModuleInfo("test-module");
moduleInfo.should.have.a.property('name','test-module'); moduleInfo.should.have.a.property('name','test-module');
moduleInfo.should.have.a.property('version','0.0.1'); moduleInfo.should.have.a.property('version','0.0.1');
@ -404,17 +412,19 @@ describe("red/nodes/registry/registry",function() {
}); });
describe('#getNodeInfo', function() { describe('#getNodeInfo', function() {
it('returns node info', function() { it('returns node info', function() {
typeRegistry.init(settings,{}); typeRegistry.init(settings,{},events);
typeRegistry.addNodeSet("test-module/test-name",{ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
id: "test-module/test-name", "test-name":{
module: "test-module", id: "test-module/test-name",
name: "test-name", module: "test-module",
enabled: true, name: "test-name",
loaded: false, enabled: true,
config: "configA", loaded: false,
types: [ "test-a","test-b"], config: "configA",
file: "abc" types: [ "test-a","test-b"],
}, "0.0.1"); file: "abc"
}
}});
var nodeSetInfo = typeRegistry.getNodeInfo("test-module/test-name"); var nodeSetInfo = typeRegistry.getNodeInfo("test-module/test-name");
nodeSetInfo.should.have.a.property('id',"test-module/test-name"); nodeSetInfo.should.have.a.property('id',"test-module/test-name");
nodeSetInfo.should.not.have.a.property('config'); nodeSetInfo.should.not.have.a.property('config');
@ -423,18 +433,20 @@ describe("red/nodes/registry/registry",function() {
}); });
describe('#getFullNodeInfo', function() { describe('#getFullNodeInfo', function() {
it('returns node info', function() { it('returns node info', function() {
typeRegistry.init(settings,{}); typeRegistry.init(settings,{},events);
typeRegistry.addNodeSet("test-module/test-name",{ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
id: "test-module/test-name", "test-name":{
module: "test-module", id: "test-module/test-name",
name: "test-name", module: "test-module",
enabled: true, name: "test-name",
loaded: false, enabled: true,
config: "configA", loaded: false,
types: [ "test-a","test-b"], config: "configA",
file: "abc" types: [ "test-a","test-b"],
file: "abc"
}, "0.0.1"); }
}});
var nodeSetInfo = typeRegistry.getFullNodeInfo("test-module/test-name"); var nodeSetInfo = typeRegistry.getFullNodeInfo("test-module/test-name");
nodeSetInfo.should.have.a.property('id',"test-module/test-name"); nodeSetInfo.should.have.a.property('id',"test-module/test-name");
nodeSetInfo.should.have.a.property('config'); nodeSetInfo.should.have.a.property('config');
@ -446,27 +458,29 @@ describe("red/nodes/registry/registry",function() {
}); });
describe('#getNodeList', function() { describe('#getNodeList', function() {
it("returns a filtered list", function() { it("returns a filtered list", function() {
typeRegistry.init(settings,{}); typeRegistry.init(settings,{},events);
typeRegistry.addNodeSet("test-module/test-name",{ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
id: "test-module/test-name", "test-name":{
module: "test-module", id: "test-module/test-name",
name: "test-name", module: "test-module",
enabled: true, name: "test-name",
loaded: false, enabled: true,
config: "configA", loaded: false,
types: [ "test-a","test-b"], config: "configA",
file: "abc" types: [ "test-a","test-b"],
}, "0.0.1"); file: "abc"
typeRegistry.addNodeSet("test-module/test-name-2",{ },
id: "test-module/test-name-2", "test-name-2":{
module: "test-module", id: "test-module/test-name-2",
name: "test-name-2", module: "test-module",
enabled: true, name: "test-name-2",
loaded: false, enabled: true,
config: "configB", loaded: false,
types: [ "test-c","test-d"], config: "configB",
file: "def" types: [ "test-c","test-d"],
}, "0.0.1"); file: "def"
}
}});
var filterCallCount = 0; var filterCallCount = 0;
var filteredList = typeRegistry.getNodeList(function(n) { filterCallCount++; return n.name === 'test-name-2';}); var filteredList = typeRegistry.getNodeList(function(n) { filterCallCount++; return n.name === 'test-name-2';});
filterCallCount.should.eql(2); filterCallCount.should.eql(2);
@ -478,8 +492,7 @@ describe("red/nodes/registry/registry",function() {
describe('#registerNodeConstructor', function() { describe('#registerNodeConstructor', function() {
var TestNodeConstructor; var TestNodeConstructor;
beforeEach(function() { beforeEach(function() {
TestNodeConstructor = function TestNodeConstructor() { TestNodeConstructor = function TestNodeConstructor() {};
};
sinon.stub(events,'emit'); sinon.stub(events,'emit');
}); });
afterEach(function() { afterEach(function() {
@ -502,44 +515,36 @@ describe("red/nodes/registry/registry",function() {
}).should.throw("node-type already registered"); }).should.throw("node-type already registered");
events.emit.calledOnce.should.be.true(); events.emit.calledOnce.should.be.true();
}); });
it('extends a constructor with the Node constructor', function() {
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
});
it('does not override a constructor\'s prototype', function() {
function Foo(){};
inherits(TestNodeConstructor,Foo);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
typeRegistry.registerNodeConstructor('node-set','node-type2',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
});
}); });
describe('#getNodeIconPath', function() { describe('#getNodeIconPath', function() {
it('returns the default icon when getting an unknown icon', function() { it('returns the default icon when getting an unknown icon', function() {
var defaultIcon = path.resolve(__dirname+'/../../../../../public/icons/arrow-in.png'); var defaultIcon = path.resolve(__dirname+'/../../../public/icons/arrow-in.png');
var iconPath = typeRegistry.getNodeIconPath('random-module','youwonthaveme.png'); var iconPath = typeRegistry.getNodeIconPath('random-module','youwonthaveme.png');
iconPath.should.eql(defaultIcon); iconPath.should.eql(defaultIcon);
}); });
it('returns a registered icon' , function() { it('returns a registered icon' , function() {
var testIcon = path.resolve(__dirname+'/../../../../resources/icons/test_icon.png'); var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
events.emit("node-icon-dir",{name:"test-module", path: path.resolve(__dirname+'/../../../../resources/icons'), icons:[]}); typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}
},icons: [{path:testIcon,icons:['test_icon.png']}]});
var iconPath = typeRegistry.getNodeIconPath('test-module','test_icon.png'); var iconPath = typeRegistry.getNodeIconPath('test-module','test_icon.png');
iconPath.should.eql(testIcon); iconPath.should.eql(testIcon+"/test_icon.png");
}); });
it('returns the debug icon when getting an unknown module', function() { it('returns the debug icon when getting an unknown module', function() {
var debugIcon = path.resolve(__dirname+'/../../../../../public/icons/debug.png'); var debugIcon = path.resolve(__dirname+'/../../../public/icons/debug.png');
var iconPath = typeRegistry.getNodeIconPath('unknown-module', 'debug.png'); var iconPath = typeRegistry.getNodeIconPath('unknown-module', 'debug.png');
iconPath.should.eql(debugIcon); iconPath.should.eql(debugIcon);
}); });
@ -552,16 +557,22 @@ describe("red/nodes/registry/registry",function() {
}); });
it('returns an icon list of registered node module', function() { it('returns an icon list of registered node module', function() {
typeRegistry.addNodeSet("test-module/test-name",testNodeSet1,"0.0.1"); var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
events.emit("node-icon-dir",{name:"test-module", path:"",icons:["test_icon1.png"]}); typeRegistry.init(settings,{},events);
typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
"test-name":{
id: "test-module/test-name",
module: "test-module",
name: "test-name",
enabled: true,
loaded: false,
config: "configA",
types: [ "test-a","test-b"],
file: "abc"
}
},icons: [{path:testIcon,icons:['test_icon.png']}]});
var iconList = typeRegistry.getNodeIcons(); var iconList = typeRegistry.getNodeIcons();
iconList.should.eql({"test-module":["test_icon1.png"]}); iconList.should.eql({"test-module":["test_icon.png"]});
});
it('returns an icon list of unregistered node module', function() {
events.emit("node-icon-dir",{name:"test-module", path:"", icons:["test_icon1.png", "test_icon2.png"]});
var iconList = typeRegistry.getNodeIcons();
iconList.should.eql({"test-module":["test_icon1.png","test_icon2.png"]});
}); });
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

View File

Before

Width:  |  Height:  |  Size: 163 B

After

Width:  |  Height:  |  Size: 163 B

View File

@ -24,7 +24,7 @@ var flowUtils = require("../../../../../red/runtime/nodes/flows/util");
var Flow = require("../../../../../red/runtime/nodes/flows/Flow"); var Flow = require("../../../../../red/runtime/nodes/flows/Flow");
var flows = require("../../../../../red/runtime/nodes/flows"); var flows = require("../../../../../red/runtime/nodes/flows");
var Node = require("../../../../../red/runtime/nodes/Node"); var Node = require("../../../../../red/runtime/nodes/Node");
var typeRegistry = require("../../../../../red/runtime/nodes/registry"); var typeRegistry = require("../../../../../red/runtime-registry");
describe('Flow', function() { describe('Flow', function() {

View File

@ -23,7 +23,7 @@ var RedNode = require("../../../../../red/runtime/nodes/Node");
var RED = require("../../../../../red/runtime/nodes"); var RED = require("../../../../../red/runtime/nodes");
var events = require("../../../../../red/runtime/events"); var events = require("../../../../../red/runtime/events");
var credentials = require("../../../../../red/runtime/nodes/credentials"); var credentials = require("../../../../../red/runtime/nodes/credentials");
var typeRegistry = require("../../../../../red/runtime/nodes/registry"); var typeRegistry = require("../../../../../red/runtime-registry");
var Flow = require("../../../../../red/runtime/nodes/flows/Flow"); var Flow = require("../../../../../red/runtime/nodes/flows/Flow");
describe('flows/index', function() { describe('flows/index', function() {

View File

@ -19,7 +19,7 @@ var sinon = require("sinon");
var when = require("when"); var when = require("when");
var clone = require("clone"); var clone = require("clone");
var flowUtil = require("../../../../../red/runtime/nodes/flows/util"); var flowUtil = require("../../../../../red/runtime/nodes/flows/util");
var typeRegistry = require("../../../../../red/runtime/nodes/registry"); var typeRegistry = require("../../../../../red/runtime-registry");
var redUtil = require("../../../../../red/runtime/util"); var redUtil = require("../../../../../red/runtime/util");
describe('flows/util', function() { describe('flows/util', function() {

View File

@ -19,9 +19,12 @@ var fs = require('fs-extra');
var path = require('path'); var path = require('path');
var when = require("when"); var when = require("when");
var sinon = require('sinon'); var sinon = require('sinon');
var inherits = require("util").inherits;
var index = require("../../../../red/runtime/nodes/index"); var index = require("../../../../red/runtime/nodes/index");
var flows = require("../../../../red/runtime/nodes/flows"); var flows = require("../../../../red/runtime/nodes/flows");
var registry = require("../../../../red/runtime/nodes/registry"); var registry = require("../../../../red/runtime-registry");
var Node = require("../../../../red/runtime/nodes/Node");
describe("red/nodes/index", function() { describe("red/nodes/index", function() {
before(function() { before(function() {
@ -122,7 +125,45 @@ describe("red/nodes/index", function() {
registry.registerType.firstCall.args[2].should.eql(TestNode); registry.registerType.firstCall.args[2].should.eql(TestNode);
}); });
}); });
describe("extends constructor with Node constructor", function() {
var TestNodeConstructor;
before(function() {
sinon.stub(registry,"registerType");
});
after(function() {
registry.registerType.restore();
});
beforeEach(function() {
TestNodeConstructor = function TestNodeConstructor() {};
var runtime = {
settings: settings,
storage: storage,
log: {debug:function() {}, warn:sinon.spy()},
events: new EventEmitter()
}
index.init(runtime);
})
it('extends a constructor with the Node constructor', function() {
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
index.registerType('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
});
it('does not override a constructor prototype', function() {
function Foo(){};
inherits(TestNodeConstructor,Foo);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
index.registerType('node-set','node-type',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
index.registerType('node-set','node-type2',TestNodeConstructor);
TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
});
});
describe("register credentials definition", function() { describe("register credentials definition", function() {
var http = require('http'); var http = require('http');
var express = require('express'); var express = require('express');
@ -294,7 +335,6 @@ describe("red/nodes/index", function() {
}); });
describe('allows modules to be removed from the registry', function() { describe('allows modules to be removed from the registry', function() {
var registry = require("../../../../red/runtime/nodes/registry");
var randomNodeInfo = {id:"5678",types:["random"]}; var randomNodeInfo = {id:"5678",types:["random"]};
var randomModuleInfo = { var randomModuleInfo = {
name:"random", name:"random",

View File

@ -1,3 +0,0 @@
This file exists just to ensure the 'icons' directory is in the repository.
TODO: a future test needs to ensure the right icon files are loaded - this
directory can be used for that

View File

@ -1 +0,0 @@
This file exists just to ensure the parent directory is in the repository.

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-1"></script>
<script type="text/x-red" data-help-name="test-node-mod-1"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-1',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,5 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
function TestNode(n) {}
RED.nodes.registerType("test-node-mod-1",TestNode);
}

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-2"></script>
<script type="text/x-red" data-help-name="test-node-mod-2"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-2',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,4 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
throw new Error("fail to load");
}

View File

@ -1,3 +0,0 @@
This file exists just to ensure the 'icons' directory is in the repository.
TODO: a future test needs to ensure the right icon files are loaded - this
directory can be used for that

View File

@ -1,11 +0,0 @@
{
"name" : "TestNodeModule",
"version" : "0.0.1",
"description" : "A test node module",
"node-red" : {
"nodes": {
"TestNodeMod1": "TestNodeModule.js",
"TestNodeMod2": "TestNodeModule2.js"
}
}
}

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-1"></script>
<script type="text/x-red" data-help-name="test-node-mod-1"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-1',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,5 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
function TestNode(n) {}
RED.nodes.registerType("test-node-mod-1",TestNode);
}

View File

@ -1,5 +0,0 @@
<script type="text/x-red" data-template-name="test-node-mod-2"></script>
<script type="text/x-red" data-help-name="test-node-mod-2"></script>
<script type="text/javascript">RED.nodes.registerType('test-node-mod-2',{});</script>
<style></style>
<p>this should be filtered out</p>

View File

@ -1,4 +0,0 @@
// A test node that exports a function
module.exports = function(RED) {
throw new Error("fail to load");
}

View File

@ -1,3 +0,0 @@
This file exists just to ensure the 'icons' directory is in the repository.
TODO: a future test needs to ensure the right icon files are loaded - this
directory can be used for that

View File

@ -1,12 +0,0 @@
{
"name" : "VersionMismatchModule",
"version" : "0.0.1",
"description" : "A test node module",
"node-red" : {
"version": "100.0.0",
"nodes": {
"VersionMismatchMod1": "TestNodeModule.js",
"VersionMismatchMod2": "TestNodeModule2.js"
}
}
}