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
63 changed files with 674 additions and 584 deletions

View File

@@ -17,6 +17,7 @@
var registry = require("./registry");
var loader = require("./loader");
var installer = require("./installer");
var library = require("./library");
var settings;
@@ -24,7 +25,8 @@ function init(runtime) {
settings = runtime.settings;
installer.init(runtime);
loader.init(runtime);
registry.init(settings,loader);
registry.init(settings,loader,runtime.events);
library.init();
}
function load() {
@@ -79,5 +81,11 @@ module.exports = {
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 registry = require("./registry");
var library = require("./library");
var log;
var events = require("../../events");
var events;
var child_process = require('child_process');
var npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
@@ -32,6 +33,7 @@ var moduleRe = /^(@[^/]+?[/])?[^/]+?$/;
var slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/;
function init(runtime) {
events = runtime.events;
settings = runtime.settings;
log = runtime.log;
}
@@ -210,8 +212,7 @@ function uninstallModule(module) {
} else {
log.info(log._("server.install.uninstalled",{name:module}));
reportRemovedModules(list);
// TODO: tidy up internal event names
events.emit("node-module-uninstalled",module)
library.removeExamplesDir(module);
resolve(list);
}
}

View File

@@ -59,11 +59,11 @@ function getFlowsFromPath(path) {
})
}
function addNodeExamplesDir(module) {
exampleRoots[module.name] = module.path;
getFlowsFromPath(module.path).then(function(result) {
function addNodeExamplesDir(module,path) {
exampleRoots[module] = path;
return getFlowsFromPath(path).then(function(result) {
exampleFlows = exampleFlows||{d:{}};
exampleFlows.d[module.name] = result;
exampleFlows.d[module] = result;
});
}
function removeNodeExamplesDir(module) {
@@ -77,17 +77,9 @@ function removeNodeExamplesDir(module) {
}
function init(_runtime) {
runtime = _runtime;
function init() {
exampleRoots = {};
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() {
@@ -103,6 +95,8 @@ function getExampleFlowPath(module,path) {
module.exports = {
init: init,
addExamplesDir: addNodeExamplesDir,
removeExamplesDir: removeNodeExamplesDir,
getExampleFlows: getExampleFlows,
getExampleFlowPath: getExampleFlowPath
}

View File

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

View File

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

View File

@@ -15,16 +15,13 @@
**/
//var UglifyJS = require("uglify-js");
var util = require("util");
var path = require("path");
var fs = require("fs");
var events = require("../../events");
var library = require("./library");
var events;
var settings;
var Node;
var loader;
var nodeConfigCache = null;
@@ -34,18 +31,15 @@ var nodeConstructors = {};
var nodeTypeToId = {};
var moduleNodes = {};
function init(_settings,_loader) {
function init(_settings,_loader, _events) {
settings = _settings;
loader = _loader;
events = _events;
moduleNodes = {};
nodeTypeToId = {};
nodeConstructors = {};
nodeList = [];
nodeConfigCache = null;
Node = require("../Node");
events.removeListener("node-icon-dir",nodeIconDir);
events.on("node-icon-dir",nodeIconDir);
}
function load() {
@@ -180,46 +174,46 @@ function loadNodeConfigs() {
}
}
function addNodeSet(id,set,version) {
if (!set.err) {
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
}
function addModule(module) {
moduleNodes[module.name] = [];
moduleConfigs[module.name] = module;
for (var setName in module.nodes) {
if (module.nodes.hasOwnProperty(setName)) {
var set = module.nodes[setName];
moduleNodes[module.name].push(set.name);
nodeList.push(set.id);
if (!set.err) {
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]||[];
moduleNodes[set.module].push(set.name);
if (!moduleConfigs[set.module]) {
moduleConfigs[set.module] = {
name: set.module,
nodes: {}
};
if (module.icons) {
icon_paths[module.name] = [];
module.icons.forEach(icon=>icon_paths[module.name].push(path.resolve(icon.path)) )
}
if (version) {
moduleConfigs[set.module].version = version;
if (module.examples) {
library.addExamplesDir(module.name,module.examples.path);
}
moduleConfigs[set.module].local = set.local;
moduleConfigs[set.module].nodes[set.name] = set;
nodeList.push(id);
nodeConfigCache = null;
}
function removeNode(id) {
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
if (!config) {
@@ -370,27 +364,6 @@ function getCaller(){
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) {
if (nodeConstructors.hasOwnProperty(type)) {
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
// that don't have a way to register a node template ahead
// of registering the constructor
if(!(constructor.prototype instanceof Node)) {
inheritNode(constructor);
}
var nodeSetInfo = getFullNodeInfo(nodeSet);
if (nodeSetInfo) {
@@ -584,10 +554,10 @@ function setModulePendingUpdated(module,version) {
}
var icon_paths = {
"node-red":[path.resolve(__dirname + '/../../../../public/icons')]
"node-red":[path.resolve(__dirname + '/../../public/icons')]
};
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) {
icon_paths[dir.name] = icon_paths[dir.name] || [];
@@ -648,7 +618,8 @@ function getNodeIcons() {
for (var module in moduleConfigs) {
if (moduleConfigs.hasOwnProperty(module)) {
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,
getNodeConstructor: getNodeConstructor,
addNodeSet: addNodeSet,
addModule: addModule,
enableNodeSet: enableNodeSet,
disableNodeSet: disableNodeSet,

View File

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

View File

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

View File

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

View File

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

View File

@@ -18,15 +18,16 @@ var when = require("when");
var path = require("path");
var fs = require("fs");
var clone = require("clone");
var util = require("util");
var registry = require("../../runtime-registry");
var registry = require("./registry");
var credentials = require("./credentials");
var flows = require("./flows");
var flowUtil = require("./flows/util")
var context = require("./context");
var Node = require("./Node");
var log;
var library = require("./library");
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);
}
@@ -99,7 +120,6 @@ function init(runtime) {
flows.init(runtime);
registry.init(runtime);
context.init(runtime.settings);
library.init(runtime);
}
function disableNode(id) {
@@ -188,8 +208,8 @@ module.exports = {
getNodeConfig: registry.getNodeConfig,
getNodeIconPath: registry.getNodeIconPath,
getNodeIcons: registry.getNodeIcons,
getNodeExampleFlows: library.getExampleFlows,
getNodeExampleFlowPath: library.getExampleFlowPath,
getNodeExampleFlows: registry.getNodeExampleFlows,
getNodeExampleFlowPath: registry.getNodeExampleFlowPath,
clearRegistry: registry.clear,
cleanModuleList: registry.cleanModuleList,

View File

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