mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #498 from anna2130/nr-cli-enhancements
nr-cli enhancements - server side api
This commit is contained in:
commit
14b84f0c7b
@ -19,7 +19,6 @@ var util = require('util');
|
|||||||
|
|
||||||
var ui = require("./ui");
|
var ui = require("./ui");
|
||||||
var nodes = require("./nodes");
|
var nodes = require("./nodes");
|
||||||
var plugins = require("./plugins");
|
|
||||||
var flows = require("./flows");
|
var flows = require("./flows");
|
||||||
var library = require("./library");
|
var library = require("./library");
|
||||||
|
|
||||||
@ -52,20 +51,18 @@ function init(adminApp) {
|
|||||||
adminApp.get("/nodes",nodes.getAll);
|
adminApp.get("/nodes",nodes.getAll);
|
||||||
adminApp.post("/nodes",nodes.post);
|
adminApp.post("/nodes",nodes.post);
|
||||||
|
|
||||||
adminApp.get("/nodes/:id",nodes.get);
|
adminApp.get("/nodes/:mod",nodes.getModule);
|
||||||
adminApp.put("/nodes/:id",nodes.put);
|
adminApp.put("/nodes/:mod",nodes.putModule);
|
||||||
adminApp.delete("/nodes/:id",nodes.delete);
|
adminApp.delete("/nodes/:mod",nodes.delete);
|
||||||
|
|
||||||
// Plugins
|
adminApp.get("/nodes/:mod/:set",nodes.getSet);
|
||||||
adminApp.get("/plugins",plugins.getAll);
|
adminApp.put("/nodes/:mod/:set",nodes.putSet);
|
||||||
adminApp.get("/plugins/:id",plugins.get);
|
|
||||||
|
|
||||||
// Library
|
// Library
|
||||||
adminApp.post(new RegExp("/library/flows\/(.*)"),library.post);
|
adminApp.post(new RegExp("/library/flows\/(.*)"),library.post);
|
||||||
adminApp.get("/library/flows",library.getAll);
|
adminApp.get("/library/flows",library.getAll);
|
||||||
adminApp.get(new RegExp("/library/flows\/(.*)"),library.get);
|
adminApp.get(new RegExp("/library/flows\/(.*)"),library.get);
|
||||||
|
|
||||||
|
|
||||||
// Error Handler
|
// Error Handler
|
||||||
adminApp.use(errorHandler);
|
adminApp.use(errorHandler);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ module.exports = {
|
|||||||
res.send(redNodes.getNodeConfigs());
|
res.send(redNodes.getNodeConfigs());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
post: function(req,res) {
|
post: function(req,res) {
|
||||||
if (!settings.available()) {
|
if (!settings.available()) {
|
||||||
res.send(400,new Error("Settings unavailable").toString());
|
res.send(400,new Error("Settings unavailable").toString());
|
||||||
@ -55,7 +56,7 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
promise.then(function(info) {
|
promise.then(function(info) {
|
||||||
res.json(info);
|
res.json(redNodes.getModuleInfo(node.module));
|
||||||
}).otherwise(function(err) {
|
}).otherwise(function(err) {
|
||||||
if (err.code === 404) {
|
if (err.code === 404) {
|
||||||
res.send(404);
|
res.send(404);
|
||||||
@ -70,25 +71,19 @@ module.exports = {
|
|||||||
res.send(400,new Error("Settings unavailable").toString());
|
res.send(400,new Error("Settings unavailable").toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var id = req.params.id;
|
var mod = req.params.mod;
|
||||||
var removedNodes = [];
|
|
||||||
try {
|
try {
|
||||||
var node = redNodes.getNodeInfo(id);
|
|
||||||
var promise = null;
|
var promise = null;
|
||||||
if (!node) {
|
var module = redNodes.getNodeModuleInfo(mod);
|
||||||
var module = redNodes.getNodeModuleInfo(id);
|
|
||||||
if (!module) {
|
if (!module) {
|
||||||
res.send(404);
|
res.send(404);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
promise = server.uninstallModule(id);
|
promise = server.uninstallModule(mod);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
promise = when.resolve([redNodes.removeNode(id)]).then(server.reportRemovedModules);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.then(function(removedNodes) {
|
promise.then(function() {
|
||||||
res.json(removedNodes);
|
res.send(204);
|
||||||
}).otherwise(function(err) {
|
}).otherwise(function(err) {
|
||||||
res.send(400,err.toString());
|
res.send(400,err.toString());
|
||||||
});
|
});
|
||||||
@ -97,10 +92,10 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get: function(req,res) {
|
getSet: function(req,res) {
|
||||||
var id = req.params.id;
|
var id = req.params.mod + "/" + req.params.set;
|
||||||
var result = null;
|
var result = null;
|
||||||
if (req.get("accept") == "application/json") {
|
if (req.get("accept") === "application/json") {
|
||||||
result = redNodes.getNodeInfo(id);
|
result = redNodes.getNodeInfo(id);
|
||||||
} else {
|
} else {
|
||||||
result = redNodes.getNodeConfig(id);
|
result = redNodes.getNodeConfig(id);
|
||||||
@ -112,7 +107,17 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
put: function(req,res) {
|
getModule: function(req,res) {
|
||||||
|
var module = req.params.mod;
|
||||||
|
var result = redNodes.getModuleInfo(module);
|
||||||
|
if (result) {
|
||||||
|
res.send(result);
|
||||||
|
} else {
|
||||||
|
res.send(404);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
putSet: function(req,res) {
|
||||||
if (!settings.available()) {
|
if (!settings.available()) {
|
||||||
res.send(400,new Error("Settings unavailable").toString());
|
res.send(400,new Error("Settings unavailable").toString());
|
||||||
return;
|
return;
|
||||||
@ -123,9 +128,9 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var info;
|
var id = req.params.mod+"/"+req.params.set;
|
||||||
var id = req.params.id;
|
|
||||||
var node = redNodes.getNodeInfo(id);
|
var node = redNodes.getNodeInfo(id);
|
||||||
|
var info;
|
||||||
if (!node) {
|
if (!node) {
|
||||||
res.send(404);
|
res.send(404);
|
||||||
} else if (!node.err && node.enabled === body.enabled) {
|
} else if (!node.err && node.enabled === body.enabled) {
|
||||||
@ -151,5 +156,50 @@ module.exports = {
|
|||||||
} catch(err) {
|
} catch(err) {
|
||||||
res.send(400,err.toString());
|
res.send(400,err.toString());
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
putModule: function(req,res) {
|
||||||
|
if (!settings.available()) {
|
||||||
|
res.send(400,new Error("Settings unavailable").toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var body = req.body;
|
||||||
|
if (!body.hasOwnProperty("enabled")) {
|
||||||
|
res.send(400,"Invalid request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var mod = req.params.mod;
|
||||||
|
var module = redNodes.getModuleInfo(mod);
|
||||||
|
if (!module) {
|
||||||
|
res.send(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var nodes = module.nodes;
|
||||||
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
|
var node = nodes[i];
|
||||||
|
var info;
|
||||||
|
if (node.err || node.enabled !== body.enabled) {
|
||||||
|
if (body.enabled) {
|
||||||
|
info = redNodes.enableNode(node.id);
|
||||||
|
} else {
|
||||||
|
info = redNodes.disableNode(node.id);
|
||||||
|
}
|
||||||
|
if (info.enabled === body.enabled && !info.err) {
|
||||||
|
comms.publish("node/"+(body.enabled?"enabled":"disabled"),info,false);
|
||||||
|
util.log("[red] "+(body.enabled?"Enabled":"Disabled")+" node types:");
|
||||||
|
for (var j = 0; j < info.types.length; j++) {
|
||||||
|
util.log("[red] - " + info.types[j]);
|
||||||
|
}
|
||||||
|
} else if (body.enabled && info.err) {
|
||||||
|
util.log("[red] Failed to enable node:");
|
||||||
|
util.log("[red] - "+info.name+" : "+info.err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
res.json(redNodes.getModuleInfo(mod));
|
||||||
|
} catch(err) {
|
||||||
|
res.send(400,err.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
var redNodes = require("../nodes");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAll: function(req,res) {
|
|
||||||
res.json(redNodes.getPluginList());
|
|
||||||
},
|
|
||||||
get: function(req,res) {
|
|
||||||
var id = req.params.id;
|
|
||||||
var result = redNodes.getPluginInfo(id);
|
|
||||||
if (result) {
|
|
||||||
res.send(result);
|
|
||||||
} else {
|
|
||||||
res.send(404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,53 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
var path = require("path");
|
|
||||||
var fs = require("fs");
|
|
||||||
|
|
||||||
var userHome = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
|
|
||||||
|
|
||||||
var configDir = path.join(userHome,".nodered");
|
|
||||||
var configFile = path.join(configDir,"config.json");
|
|
||||||
|
|
||||||
var config;
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
if (config == null) {
|
|
||||||
try {
|
|
||||||
config = JSON.parse(fs.readFileSync(configFile));
|
|
||||||
} catch(err) {
|
|
||||||
config = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function save() {
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(configDir);
|
|
||||||
} catch(err) {
|
|
||||||
if (err.code != "EEXIST") {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fs.writeFileSync(configFile,JSON.stringify(config,null,4));
|
|
||||||
}
|
|
||||||
module.exports = {
|
|
||||||
unload: function() {
|
|
||||||
config = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
module.exports.__defineGetter__('target',function() { load(); return config.target|| "http://localhost:1880" });
|
|
||||||
module.exports.__defineSetter__('target',function(v) { load(); config.target = v; save();});
|
|
@ -1,51 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
var when = require("when");
|
|
||||||
var request = require("request");
|
|
||||||
var config = require("./config");
|
|
||||||
|
|
||||||
module.exports = function(path, options) {
|
|
||||||
var basePath = config.target;
|
|
||||||
return when.promise(function(resolve,reject) {
|
|
||||||
options.headers = options.headers||{};
|
|
||||||
options.headers['Accept'] = 'application/json';
|
|
||||||
if (options.method == 'PUT' || options.method == "POST") {
|
|
||||||
options.headers['content-type'] = 'application/json';
|
|
||||||
}
|
|
||||||
options.url = basePath+path;
|
|
||||||
|
|
||||||
// Pull out the request function so we can stub it in the tests
|
|
||||||
var requestFunc = request.get;
|
|
||||||
|
|
||||||
if (options.method == 'PUT') {
|
|
||||||
requestFunc = request.put;
|
|
||||||
} else if (options.method == 'POST') {
|
|
||||||
requestFunc = request.post;
|
|
||||||
} else if (options.method == 'DELETE') {
|
|
||||||
requestFunc = request.del;
|
|
||||||
}
|
|
||||||
requestFunc(options, function(error,response,body) {
|
|
||||||
if (!error && response.statusCode == 200) {
|
|
||||||
resolve(JSON.parse(body));
|
|
||||||
} else if (error) {
|
|
||||||
reject(error.toString());
|
|
||||||
} else {
|
|
||||||
reject(response.statusCode+": "+body)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,151 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
;(function() {
|
|
||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
var util = require("util");
|
|
||||||
var request = require("request");
|
|
||||||
var colors = require('colors');
|
|
||||||
var apiRequest = require("./lib/request");
|
|
||||||
var config = require("./lib/config");
|
|
||||||
|
|
||||||
var commands = {
|
|
||||||
"target": function() {
|
|
||||||
var target = process.argv[3];
|
|
||||||
if (target) {
|
|
||||||
if (!/^https?:\/\/.+/.test(target)) {
|
|
||||||
console.warn("Invalid target url");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (target.slice(-1) == "/") {
|
|
||||||
target = target.slice(0,target.length-1);
|
|
||||||
}
|
|
||||||
var oldTarget = config.target;
|
|
||||||
config.target = target;
|
|
||||||
} else {
|
|
||||||
console.log("Target: ".yellow+config.target);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
"nodes": function() {
|
|
||||||
apiRequest('/nodes',{}).then(logNodeList).otherwise(logFailure);
|
|
||||||
},
|
|
||||||
"node": function() {
|
|
||||||
apiRequest('/nodes/'+process.argv[3],{}).then(logNodeList).otherwise(logFailure);
|
|
||||||
},
|
|
||||||
"enable-node": function() {
|
|
||||||
apiRequest('/nodes/'+process.argv[3],{
|
|
||||||
method: "PUT",
|
|
||||||
body: JSON.stringify({enabled:true})
|
|
||||||
}).then(logNodeList).otherwise(logFailure);
|
|
||||||
},
|
|
||||||
"disable-node": function() {
|
|
||||||
apiRequest('/nodes/'+process.argv[3],{
|
|
||||||
method: "PUT",
|
|
||||||
body: JSON.stringify({enabled:false})
|
|
||||||
}).then(logNodeList).otherwise(logFailure);
|
|
||||||
},
|
|
||||||
"install": function() {
|
|
||||||
apiRequest('/nodes',{
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({module:process.argv[3]})
|
|
||||||
}).then(logNodeList).otherwise(logFailure);
|
|
||||||
},
|
|
||||||
"remove": function() {
|
|
||||||
apiRequest('/nodes/'+process.argv[3],{
|
|
||||||
method: "DELETE"
|
|
||||||
}).then(logNodeList).otherwise(logFailure);
|
|
||||||
},
|
|
||||||
"search": function() {
|
|
||||||
var options = {
|
|
||||||
method: "GET",
|
|
||||||
url: 'https://registry.npmjs.org/-/_view/byKeyword?startkey=["node-red"]&endkey=["node-red",{}]&group_level=3' ,
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
}
|
|
||||||
};
|
|
||||||
request(options, function (error, response, body) {
|
|
||||||
if (!error && response.statusCode == 200) {
|
|
||||||
var info = (JSON.parse(body)).rows;
|
|
||||||
var filter = null;
|
|
||||||
if (process.argv[3]) {
|
|
||||||
filter = new RegExp(process.argv[3]);
|
|
||||||
}
|
|
||||||
for (var i=0;i<info.length;i++) {
|
|
||||||
var n = info[i];
|
|
||||||
if (!filter || filter.test(n.key[1]) || filter.test(n.key[2])) {
|
|
||||||
console.log(n.key[1] + (" - "+ n.key[2]).grey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (error) {
|
|
||||||
console.log(error.toString().red);
|
|
||||||
} else {
|
|
||||||
console.log((response.statusCode+": "+body).red);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function logNodeList(nodes) {
|
|
||||||
if (!util.isArray(nodes)) {
|
|
||||||
nodes = [nodes];
|
|
||||||
}
|
|
||||||
for (var i=0;i<nodes.length;i++) {
|
|
||||||
var n = nodes[i];
|
|
||||||
console.log(formatNodeInfo(n))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function logFailure(msg) {
|
|
||||||
console.log(msg.red);
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatBoolean(v,c) {
|
|
||||||
if (v) {
|
|
||||||
return ("["+c+"]");
|
|
||||||
} else {
|
|
||||||
return ("[ ]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatNodeInfo(n) {
|
|
||||||
var inError = n.hasOwnProperty("err");
|
|
||||||
|
|
||||||
var str = formatBoolean(n.enabled,"X")+formatBoolean(n.loaded,"L")+" ";
|
|
||||||
str += n.id;
|
|
||||||
if (n.enabled && n.loaded) {
|
|
||||||
str = str.green;
|
|
||||||
} else if (n.enabled && n.err) {
|
|
||||||
str = str.red;
|
|
||||||
} else {
|
|
||||||
str = str.yellow;
|
|
||||||
}
|
|
||||||
if (n.module) {
|
|
||||||
str += " ["+n.module+"]";
|
|
||||||
}
|
|
||||||
str += " "+n.types.join(", ");
|
|
||||||
if (n.err) {
|
|
||||||
str+=" "+n.err.red;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commands[process.argv[2]]) {
|
|
||||||
commands[process.argv[2]].call();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})();
|
|
@ -55,7 +55,7 @@ function checkTypeInUse(id) {
|
|||||||
var nodeInfo = registry.getNodeInfo(id);
|
var nodeInfo = registry.getNodeInfo(id);
|
||||||
if (!nodeInfo) {
|
if (!nodeInfo) {
|
||||||
throw new Error("Unrecognised id: "+id);
|
throw new Error("Unrecognised id: "+id);
|
||||||
}
|
} else {
|
||||||
var inUse = {};
|
var inUse = {};
|
||||||
flows.each(function(n) {
|
flows.each(function(n) {
|
||||||
inUse[n.type] = (inUse[n.type]||0)+1;
|
inUse[n.type] = (inUse[n.type]||0)+1;
|
||||||
@ -71,6 +71,7 @@ function checkTypeInUse(id) {
|
|||||||
throw new Error("Type in use: "+msg);
|
throw new Error("Type in use: "+msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function removeNode(id) {
|
function removeNode(id) {
|
||||||
checkTypeInUse(id);
|
checkTypeInUse(id);
|
||||||
@ -79,12 +80,15 @@ function removeNode(id) {
|
|||||||
|
|
||||||
function removeModule(module) {
|
function removeModule(module) {
|
||||||
var info = registry.getNodeModuleInfo(module);
|
var info = registry.getNodeModuleInfo(module);
|
||||||
for (var i=0;i<info.nodes.length;i++) {
|
if (!info) {
|
||||||
checkTypeInUse(info.nodes[i]);
|
throw new Error("Unrecognised module: "+module);
|
||||||
|
} else {
|
||||||
|
for (var i=0;i<info.length;i++) {
|
||||||
|
checkTypeInUse(module+"/"+info[i]);
|
||||||
}
|
}
|
||||||
return registry.removeModule(module);
|
return registry.removeModule(module);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function disableNode(id) {
|
function disableNode(id) {
|
||||||
checkTypeInUse(id);
|
checkTypeInUse(id);
|
||||||
@ -112,15 +116,20 @@ module.exports = {
|
|||||||
// Node type registry
|
// Node type registry
|
||||||
registerType: registerType,
|
registerType: registerType,
|
||||||
getType: registry.get,
|
getType: registry.get,
|
||||||
|
|
||||||
getNodeInfo: registry.getNodeInfo,
|
getNodeInfo: registry.getNodeInfo,
|
||||||
getNodeModuleInfo: registry.getNodeModuleInfo,
|
|
||||||
getPluginInfo: registry.getPluginInfo,
|
|
||||||
getNodeList: registry.getNodeList,
|
getNodeList: registry.getNodeList,
|
||||||
getPluginList: registry.getPluginList,
|
|
||||||
|
getNodeModuleInfo: registry.getNodeModuleInfo,
|
||||||
|
|
||||||
|
getModuleInfo: registry.getModuleInfo,
|
||||||
|
getModuleList: registry.getModuleList,
|
||||||
|
|
||||||
getNodeConfigs: registry.getNodeConfigs,
|
getNodeConfigs: registry.getNodeConfigs,
|
||||||
getNodeConfig: registry.getNodeConfig,
|
getNodeConfig: registry.getNodeConfig,
|
||||||
|
|
||||||
clearRegistry: registry.clear,
|
clearRegistry: registry.clear,
|
||||||
cleanNodeList: registry.cleanNodeList,
|
cleanModuleList: registry.cleanModuleList,
|
||||||
|
|
||||||
// Flow handling
|
// Flow handling
|
||||||
loadFlows: flows.load,
|
loadFlows: flows.load,
|
||||||
|
@ -46,31 +46,48 @@ function filterNodeInfo(n) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getModule(id) {
|
||||||
|
return id.split("/")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNode(id) {
|
||||||
|
return id.split("/")[1];
|
||||||
|
}
|
||||||
|
|
||||||
var registry = (function() {
|
var registry = (function() {
|
||||||
var nodeConfigCache = null;
|
var nodeConfigCache = null;
|
||||||
var nodeConfigs = {};
|
var moduleConfigs = {};
|
||||||
var nodeList = [];
|
var nodeList = [];
|
||||||
var nodeConstructors = {};
|
var nodeConstructors = {};
|
||||||
var nodeTypeToId = {};
|
var nodeTypeToId = {};
|
||||||
var nodeModules = {};
|
var moduleNodes = {};
|
||||||
|
|
||||||
function saveNodeList() {
|
function saveNodeList() {
|
||||||
var nodeList = {};
|
var moduleList = {};
|
||||||
|
|
||||||
for (var i in nodeConfigs) {
|
for (var module in moduleConfigs) {
|
||||||
if (nodeConfigs.hasOwnProperty(i)) {
|
if (moduleConfigs.hasOwnProperty(module)) {
|
||||||
var nodeConfig = nodeConfigs[i];
|
if (!moduleList[module]) {
|
||||||
var n = filterNodeInfo(nodeConfig);
|
moduleList[module] = {};
|
||||||
n.file = nodeConfig.file;
|
moduleList[module].name = module;
|
||||||
|
moduleList[module].nodes = {};
|
||||||
|
}
|
||||||
|
var nodes = moduleConfigs[module].nodes;
|
||||||
|
for(var node in nodes) {
|
||||||
|
if (nodes.hasOwnProperty(node)) {
|
||||||
|
var config = nodes[node];
|
||||||
|
var n = filterNodeInfo(config);
|
||||||
delete n.loaded;
|
delete n.loaded;
|
||||||
delete n.err;
|
delete n.err;
|
||||||
delete n.file;
|
delete n.file;
|
||||||
delete n.id;
|
delete n.id;
|
||||||
nodeList[i] = n;
|
moduleList[module].nodes[node] = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (settings.available()) {
|
if (settings.available()) {
|
||||||
return settings.set("nodes",nodeList);
|
return settings.set("modules",moduleList);
|
||||||
} else {
|
} else {
|
||||||
return when.reject("Settings unavailable");
|
return when.reject("Settings unavailable");
|
||||||
}
|
}
|
||||||
@ -79,45 +96,47 @@ var registry = (function() {
|
|||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
if (settings.available()) {
|
if (settings.available()) {
|
||||||
nodeConfigs = settings.get("nodes")||{};
|
moduleConfigs = settings.get("modules")||{};
|
||||||
// Restore the node id property to individual entries
|
|
||||||
for (var id in nodeConfigs) {
|
|
||||||
if (nodeConfigs.hasOwnProperty(id)) {
|
|
||||||
nodeConfigs[id].id = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
nodeConfigs = {};
|
moduleConfigs = {};
|
||||||
}
|
}
|
||||||
nodeModules = {};
|
moduleNodes = {};
|
||||||
nodeTypeToId = {};
|
nodeTypeToId = {};
|
||||||
nodeConstructors = {};
|
nodeConstructors = {};
|
||||||
nodeList = [];
|
nodeList = [];
|
||||||
nodeConfigCache = null;
|
nodeConfigCache = null;
|
||||||
},
|
},
|
||||||
|
addNodeSet: function(id,set,version) {
|
||||||
addNodeSet: function(id,set) {
|
|
||||||
if (!set.err) {
|
if (!set.err) {
|
||||||
set.types.forEach(function(t) {
|
set.types.forEach(function(t) {
|
||||||
nodeTypeToId[t] = id;
|
nodeTypeToId[t] = id;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set.module) {
|
moduleNodes[set.module] = moduleNodes[set.module]||[];
|
||||||
nodeModules[set.module] = nodeModules[set.module]||{nodes:[]};
|
moduleNodes[set.module].push(set.name);
|
||||||
nodeModules[set.module].nodes.push(id);
|
|
||||||
|
if (!moduleConfigs[set.module]) {
|
||||||
|
moduleConfigs[set.module] = {
|
||||||
|
name: set.module,
|
||||||
|
nodes: {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeConfigs[id] = set;
|
if (version) {
|
||||||
|
moduleConfigs[set.module].version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
moduleConfigs[set.module].nodes[set.name] = set;
|
||||||
nodeList.push(id);
|
nodeList.push(id);
|
||||||
nodeConfigCache = null;
|
nodeConfigCache = null;
|
||||||
},
|
},
|
||||||
removeNode: function(id) {
|
removeNode: function(id) {
|
||||||
var config = nodeConfigs[id];
|
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new Error("Unrecognised id: "+id);
|
throw new Error("Unrecognised id: "+id);
|
||||||
}
|
}
|
||||||
delete nodeConfigs[id];
|
delete moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||||
var i = nodeList.indexOf(id);
|
var i = nodeList.indexOf(id);
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
nodeList.splice(i,1);
|
nodeList.splice(i,1);
|
||||||
@ -135,62 +154,81 @@ var registry = (function() {
|
|||||||
if (!settings.available()) {
|
if (!settings.available()) {
|
||||||
throw new Error("Settings unavailable");
|
throw new Error("Settings unavailable");
|
||||||
}
|
}
|
||||||
var nodes = nodeModules[module];
|
var nodes = moduleNodes[module];
|
||||||
if (!nodes) {
|
if (!nodes) {
|
||||||
throw new Error("Unrecognised module: "+module);
|
throw new Error("Unrecognised module: "+module);
|
||||||
}
|
}
|
||||||
var infoList = [];
|
var infoList = [];
|
||||||
for (var i=0;i<nodes.nodes.length;i++) {
|
for (var i=0;i<nodes.length;i++) {
|
||||||
infoList.push(registry.removeNode(nodes.nodes[i]));
|
infoList.push(registry.removeNode(module+"/"+nodes[i]));
|
||||||
}
|
}
|
||||||
delete nodeModules[module];
|
delete moduleNodes[module];
|
||||||
saveNodeList();
|
saveNodeList();
|
||||||
return infoList;
|
return infoList;
|
||||||
},
|
},
|
||||||
getNodeInfo: function(typeOrId) {
|
getNodeInfo: function(typeOrId) {
|
||||||
|
var id = typeOrId;
|
||||||
if (nodeTypeToId[typeOrId]) {
|
if (nodeTypeToId[typeOrId]) {
|
||||||
return filterNodeInfo(nodeConfigs[nodeTypeToId[typeOrId]]);
|
id = nodeTypeToId[typeOrId];
|
||||||
} else if (nodeConfigs[typeOrId]) {
|
}
|
||||||
return filterNodeInfo(nodeConfigs[typeOrId]);
|
if (id) {
|
||||||
|
var module = moduleConfigs[getModule(id)];
|
||||||
|
if (module) {
|
||||||
|
var config = module.nodes[getNode(id)];
|
||||||
|
if (config) {
|
||||||
|
return filterNodeInfo(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
getNodeList: function() {
|
getNodeList: function() {
|
||||||
var list = [];
|
var list = [];
|
||||||
for (var id in nodeConfigs) {
|
for (var module in moduleConfigs) {
|
||||||
if (nodeConfigs.hasOwnProperty(id)) {
|
if (moduleConfigs.hasOwnProperty(module)) {
|
||||||
list.push(filterNodeInfo(nodeConfigs[id]));
|
var nodes = moduleConfigs[module].nodes;
|
||||||
|
for (var node in nodes) {
|
||||||
|
if (nodes.hasOwnProperty(node)) {
|
||||||
|
list.push(filterNodeInfo(nodes[node]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
},
|
},
|
||||||
getPluginList: function() {
|
getModuleList: function() {
|
||||||
var list = [];
|
var list = [];
|
||||||
for (var plugin in nodeModules) {
|
for (var module in moduleNodes) {
|
||||||
if (nodeModules.hasOwnProperty(plugin)) {
|
if (moduleNodes.hasOwnProperty(module)) {
|
||||||
var nodes = nodeModules[plugin].nodes;
|
var nodes = moduleNodes[module];
|
||||||
var m = {
|
var m = {
|
||||||
name: plugin,
|
name: module,
|
||||||
|
version: moduleConfigs[module].version,
|
||||||
nodes: []
|
nodes: []
|
||||||
};
|
};
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
m.nodes.push(filterNodeInfo(nodeConfigs[nodes[i]]));
|
m.nodes.push(filterNodeInfo(moduleConfigs[module].nodes[nodes[i]]));
|
||||||
}
|
}
|
||||||
list.push(m);
|
list.push(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
},
|
},
|
||||||
getPluginInfo: function(plugin) {
|
getModuleInfo: function(module) {
|
||||||
var nodes = nodeModules[plugin].nodes;
|
if (moduleNodes[module]) {
|
||||||
|
var nodes = moduleNodes[module];
|
||||||
var m = {
|
var m = {
|
||||||
name: plugin,
|
name: module,
|
||||||
|
version: moduleConfigs[module].version,
|
||||||
nodes: []
|
nodes: []
|
||||||
};
|
};
|
||||||
for (var i = 0; i < nodes.length; ++i) {
|
for (var i = 0; i < nodes.length; ++i) {
|
||||||
m.nodes.push(filterNodeInfo(nodeConfigs[nodes[i]]));
|
m.nodes.push(filterNodeInfo(moduleConfigs[module].nodes[nodes[i]]));
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
registerNodeConstructor: function(type,constructor) {
|
registerNodeConstructor: function(type,constructor) {
|
||||||
if (nodeConstructors[type]) {
|
if (nodeConstructors[type]) {
|
||||||
@ -214,7 +252,8 @@ var registry = (function() {
|
|||||||
var result = "";
|
var result = "";
|
||||||
var script = "";
|
var script = "";
|
||||||
for (var i=0;i<nodeList.length;i++) {
|
for (var i=0;i<nodeList.length;i++) {
|
||||||
var config = nodeConfigs[nodeList[i]];
|
var id = nodeList[i];
|
||||||
|
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||||
if (config.enabled && !config.err) {
|
if (config.enabled && !config.err) {
|
||||||
result += config.config;
|
result += config.config;
|
||||||
script += config.script;
|
script += config.script;
|
||||||
@ -231,7 +270,7 @@ var registry = (function() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getNodeConfig: function(id) {
|
getNodeConfig: function(id) {
|
||||||
var config = nodeConfigs[id];
|
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||||
if (config) {
|
if (config) {
|
||||||
var result = config.config;
|
var result = config.config;
|
||||||
if (config.script) {
|
if (config.script) {
|
||||||
@ -244,7 +283,15 @@ var registry = (function() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getNodeConstructor: function(type) {
|
getNodeConstructor: function(type) {
|
||||||
var config = nodeConfigs[nodeTypeToId[type]];
|
var id = nodeTypeToId[type];
|
||||||
|
|
||||||
|
var config;
|
||||||
|
if (typeof id === "undefined") {
|
||||||
|
config = undefined;
|
||||||
|
} else {
|
||||||
|
config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||||
|
}
|
||||||
|
|
||||||
if (!config || (config.enabled && !config.err)) {
|
if (!config || (config.enabled && !config.err)) {
|
||||||
return nodeConstructors[type];
|
return nodeConstructors[type];
|
||||||
}
|
}
|
||||||
@ -253,7 +300,7 @@ var registry = (function() {
|
|||||||
|
|
||||||
clear: function() {
|
clear: function() {
|
||||||
nodeConfigCache = null;
|
nodeConfigCache = null;
|
||||||
nodeConfigs = {};
|
moduleConfigs = {};
|
||||||
nodeList = [];
|
nodeList = [];
|
||||||
nodeConstructors = {};
|
nodeConstructors = {};
|
||||||
nodeTypeToId = {};
|
nodeTypeToId = {};
|
||||||
@ -263,21 +310,23 @@ var registry = (function() {
|
|||||||
return nodeTypeToId[type];
|
return nodeTypeToId[type];
|
||||||
},
|
},
|
||||||
|
|
||||||
getModuleInfo: function(type) {
|
getNodeModuleInfo: function(module) {
|
||||||
return nodeModules[type];
|
return moduleNodes[module];
|
||||||
},
|
},
|
||||||
|
|
||||||
enableNodeSet: function(id) {
|
enableNodeSet: function(typeOrId) {
|
||||||
if (!settings.available()) {
|
if (!settings.available()) {
|
||||||
throw new Error("Settings unavailable");
|
throw new Error("Settings unavailable");
|
||||||
}
|
}
|
||||||
var config;
|
|
||||||
if (nodeTypeToId[id]) {
|
var id = typeOrId;
|
||||||
config = nodeConfigs[nodeTypeToId[id]];
|
if (nodeTypeToId[typeOrId]) {
|
||||||
} else {
|
id = nodeTypeToId[typeOrId];
|
||||||
config = nodeConfigs[id];
|
|
||||||
}
|
}
|
||||||
if (config) {
|
|
||||||
|
var config;
|
||||||
|
try {
|
||||||
|
config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||||
delete config.err;
|
delete config.err;
|
||||||
config.enabled = true;
|
config.enabled = true;
|
||||||
if (!config.loaded) {
|
if (!config.loaded) {
|
||||||
@ -286,28 +335,28 @@ var registry = (function() {
|
|||||||
}
|
}
|
||||||
nodeConfigCache = null;
|
nodeConfigCache = null;
|
||||||
saveNodeList();
|
saveNodeList();
|
||||||
} else {
|
} catch (err) {
|
||||||
throw new Error("Unrecognised id: "+id);
|
throw new Error("Unrecognised id: "+typeOrId);
|
||||||
}
|
}
|
||||||
return filterNodeInfo(config);
|
return filterNodeInfo(config);
|
||||||
},
|
},
|
||||||
|
|
||||||
disableNodeSet: function(id) {
|
disableNodeSet: function(typeOrId) {
|
||||||
if (!settings.available()) {
|
if (!settings.available()) {
|
||||||
throw new Error("Settings unavailable");
|
throw new Error("Settings unavailable");
|
||||||
}
|
}
|
||||||
var config;
|
var id = typeOrId;
|
||||||
if (nodeTypeToId[id]) {
|
if (nodeTypeToId[typeOrId]) {
|
||||||
config = nodeConfigs[nodeTypeToId[id]];
|
id = nodeTypeToId[typeOrId];
|
||||||
} else {
|
|
||||||
config = nodeConfigs[id];
|
|
||||||
}
|
}
|
||||||
if (config) {
|
var config;
|
||||||
|
try {
|
||||||
|
config = moduleConfigs[getModule(id)].nodes[getNode(id)];
|
||||||
// TODO: persist setting
|
// TODO: persist setting
|
||||||
config.enabled = false;
|
config.enabled = false;
|
||||||
nodeConfigCache = null;
|
nodeConfigCache = null;
|
||||||
saveNodeList();
|
saveNodeList();
|
||||||
} else {
|
} catch (err) {
|
||||||
throw new Error("Unrecognised id: "+id);
|
throw new Error("Unrecognised id: "+id);
|
||||||
}
|
}
|
||||||
return filterNodeInfo(config);
|
return filterNodeInfo(config);
|
||||||
@ -315,16 +364,21 @@ var registry = (function() {
|
|||||||
|
|
||||||
saveNodeList: saveNodeList,
|
saveNodeList: saveNodeList,
|
||||||
|
|
||||||
cleanNodeList: function() {
|
cleanModuleList: function() {
|
||||||
var removed = false;
|
var removed = false;
|
||||||
for (var id in nodeConfigs) {
|
for (var mod in moduleConfigs) {
|
||||||
if (nodeConfigs.hasOwnProperty(id)) {
|
if (moduleConfigs.hasOwnProperty(mod)) {
|
||||||
if (nodeConfigs[id].module && !nodeModules[nodeConfigs[id].module]) {
|
if (moduleConfigs[mod] && !moduleNodes[mod]) {
|
||||||
registry.removeNode(id);
|
var nodes = moduleConfigs[mod].nodes;
|
||||||
|
for (var node in nodes) {
|
||||||
|
if (nodes.hasOwnProperty(node)) {
|
||||||
|
registry.removeNode(mod+"/"+node);
|
||||||
removed = true;
|
removed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (removed) {
|
if (removed) {
|
||||||
saveNodeList();
|
saveNodeList();
|
||||||
}
|
}
|
||||||
@ -401,7 +455,7 @@ function scanTreeForNodesModules(moduleName) {
|
|||||||
var files = fs.readdirSync(pm);
|
var files = fs.readdirSync(pm);
|
||||||
for (var i=0;i<files.length;i++) {
|
for (var i=0;i<files.length;i++) {
|
||||||
var fn = files[i];
|
var fn = files[i];
|
||||||
if (!registry.getModuleInfo(fn)) {
|
if (!registry.getNodeModuleInfo(fn)) {
|
||||||
if (!moduleName || fn == moduleName) {
|
if (!moduleName || fn == moduleName) {
|
||||||
var pkgfn = path.join(pm,fn,"package.json");
|
var pkgfn = path.join(pm,fn,"package.json");
|
||||||
try {
|
try {
|
||||||
@ -435,7 +489,7 @@ function scanTreeForNodesModules(moduleName) {
|
|||||||
* @param moduleDir the root directory of the package
|
* @param moduleDir the root directory of the package
|
||||||
* @param pkg the module's package.json object
|
* @param pkg the module's package.json object
|
||||||
*/
|
*/
|
||||||
function loadNodesFromModule(moduleDir,pkg) {
|
function loadNodesFromModule(moduleDir,pkg,version) {
|
||||||
var nodes = pkg['node-red'].nodes||{};
|
var nodes = pkg['node-red'].nodes||{};
|
||||||
var results = [];
|
var results = [];
|
||||||
var iconDirs = [];
|
var iconDirs = [];
|
||||||
@ -443,7 +497,7 @@ function loadNodesFromModule(moduleDir,pkg) {
|
|||||||
if (nodes.hasOwnProperty(n)) {
|
if (nodes.hasOwnProperty(n)) {
|
||||||
var file = path.join(moduleDir,nodes[n]);
|
var file = path.join(moduleDir,nodes[n]);
|
||||||
try {
|
try {
|
||||||
results.push(loadNodeConfig(file,pkg.name,n));
|
results.push(loadNodeConfig(file,pkg.name,n,version));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
}
|
}
|
||||||
var iconDir = path.join(moduleDir,path.dirname(nodes[n]),"icons");
|
var iconDir = path.join(moduleDir,path.dirname(nodes[n]),"icons");
|
||||||
@ -474,20 +528,8 @@ function loadNodesFromModule(moduleDir,pkg) {
|
|||||||
* types: an array of node type names in this file
|
* types: an array of node type names in this file
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
function loadNodeConfig(file,module,name) {
|
function loadNodeConfig(file,module,name,version) {
|
||||||
var id = crypto.createHash('sha1').update(file).digest("hex");
|
var id = module + "/" + name;
|
||||||
if (module && name) {
|
|
||||||
var newid = crypto.createHash('sha1').update(module+":"+name).digest("hex");
|
|
||||||
var existingInfo = registry.getNodeInfo(id);
|
|
||||||
if (existingInfo) {
|
|
||||||
// For a brief period, id for modules were calculated incorrectly.
|
|
||||||
// To prevent false-duplicates, this removes the old id entry
|
|
||||||
registry.removeNode(id);
|
|
||||||
registry.saveNodeList();
|
|
||||||
}
|
|
||||||
id = newid;
|
|
||||||
|
|
||||||
}
|
|
||||||
var info = registry.getNodeInfo(id);
|
var info = registry.getNodeInfo(id);
|
||||||
|
|
||||||
var isEnabled = true;
|
var isEnabled = true;
|
||||||
@ -501,18 +543,14 @@ function loadNodeConfig(file,module,name) {
|
|||||||
|
|
||||||
var node = {
|
var node = {
|
||||||
id: id,
|
id: id,
|
||||||
|
module: module,
|
||||||
|
name: name,
|
||||||
file: file,
|
file: file,
|
||||||
template: file.replace(/\.js$/,".html"),
|
template: file.replace(/\.js$/,".html"),
|
||||||
enabled: isEnabled,
|
enabled: isEnabled,
|
||||||
loaded:false
|
loaded:false
|
||||||
};
|
};
|
||||||
|
|
||||||
if (module) {
|
|
||||||
node.name = module+":"+name;
|
|
||||||
node.module = module;
|
|
||||||
} else {
|
|
||||||
node.name = path.basename(file);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
var content = fs.readFileSync(node.template,'utf8');
|
var content = fs.readFileSync(node.template,'utf8');
|
||||||
|
|
||||||
@ -544,7 +582,7 @@ function loadNodeConfig(file,module,name) {
|
|||||||
node.err = err.toString();
|
node.err = err.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registry.addNodeSet(id,node);
|
registry.addNodeSet(id,node,version);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,7 +614,7 @@ function load(defaultNodesDir,disableNodePathScan) {
|
|||||||
var nodes = [];
|
var nodes = [];
|
||||||
nodeFiles.forEach(function(file) {
|
nodeFiles.forEach(function(file) {
|
||||||
try {
|
try {
|
||||||
nodes.push(loadNodeConfig(file));
|
nodes.push(loadNodeConfig(file,"node-red",path.basename(file).replace(/^\d+-/,"").replace(/\.js$/,"")));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
@ -682,19 +720,19 @@ function addNode(file) {
|
|||||||
}
|
}
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
try {
|
try {
|
||||||
nodes.push(loadNodeConfig(file));
|
nodes.push(loadNodeConfig(file,"node-red",path.basename(file).replace(/^\d+-/,"").replace(/\.js$/,"")));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
return when.reject(err);
|
return when.reject(err);
|
||||||
}
|
}
|
||||||
return loadNodeList(nodes);
|
return loadNodeList(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addModule(module) {
|
function addModule(module,version) {
|
||||||
if (!settings.available()) {
|
if (!settings.available()) {
|
||||||
throw new Error("Settings unavailable");
|
throw new Error("Settings unavailable");
|
||||||
}
|
}
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
if (registry.getModuleInfo(module)) {
|
if (registry.getNodeModuleInfo(module)) {
|
||||||
return when.reject(new Error("Module already loaded"));
|
return when.reject(new Error("Module already loaded"));
|
||||||
}
|
}
|
||||||
var moduleFiles = scanTreeForNodesModules(module);
|
var moduleFiles = scanTreeForNodesModules(module);
|
||||||
@ -704,7 +742,7 @@ function addModule(module) {
|
|||||||
return when.reject(err);
|
return when.reject(err);
|
||||||
}
|
}
|
||||||
moduleFiles.forEach(function(moduleFile) {
|
moduleFiles.forEach(function(moduleFile) {
|
||||||
nodes = nodes.concat(loadNodesFromModule(moduleFile.dir,moduleFile.package));
|
nodes = nodes.concat(loadNodesFromModule(moduleFile.dir,moduleFile.package,version));
|
||||||
});
|
});
|
||||||
return loadNodeList(nodes);
|
return loadNodeList(nodes);
|
||||||
}
|
}
|
||||||
@ -714,14 +752,19 @@ module.exports = {
|
|||||||
load:load,
|
load:load,
|
||||||
clear: registry.clear,
|
clear: registry.clear,
|
||||||
registerType: registry.registerNodeConstructor,
|
registerType: registry.registerNodeConstructor,
|
||||||
|
|
||||||
get: registry.getNodeConstructor,
|
get: registry.getNodeConstructor,
|
||||||
getNodeInfo: registry.getNodeInfo,
|
getNodeInfo: registry.getNodeInfo,
|
||||||
getNodeModuleInfo: registry.getModuleInfo,
|
|
||||||
getPluginInfo: registry.getPluginInfo,
|
|
||||||
getNodeList: registry.getNodeList,
|
getNodeList: registry.getNodeList,
|
||||||
getPluginList: registry.getPluginList,
|
|
||||||
|
getNodeModuleInfo: registry.getNodeModuleInfo,
|
||||||
|
|
||||||
|
getModuleInfo: registry.getModuleInfo,
|
||||||
|
getModuleList: registry.getModuleList,
|
||||||
|
|
||||||
getNodeConfigs: registry.getAllNodeConfigs,
|
getNodeConfigs: registry.getAllNodeConfigs,
|
||||||
getNodeConfig: registry.getNodeConfig,
|
getNodeConfig: registry.getNodeConfig,
|
||||||
|
|
||||||
addNode: addNode,
|
addNode: addNode,
|
||||||
removeNode: registry.removeNode,
|
removeNode: registry.removeNode,
|
||||||
enableNode: registry.enableNodeSet,
|
enableNode: registry.enableNodeSet,
|
||||||
@ -729,5 +772,5 @@ module.exports = {
|
|||||||
|
|
||||||
addModule: addModule,
|
addModule: addModule,
|
||||||
removeModule: registry.removeModule,
|
removeModule: registry.removeModule,
|
||||||
cleanNodeList: registry.cleanNodeList
|
cleanModuleList: registry.cleanModuleList
|
||||||
};
|
};
|
||||||
|
@ -91,7 +91,7 @@ function start() {
|
|||||||
}
|
}
|
||||||
if (!settings.autoInstallModules) {
|
if (!settings.autoInstallModules) {
|
||||||
util.log("[red] Removing modules from config");
|
util.log("[red] Removing modules from config");
|
||||||
redNodes.cleanNodeList();
|
redNodes.cleanModuleList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer.resolve();
|
defer.resolve();
|
||||||
@ -162,8 +162,11 @@ function installModule(module) {
|
|||||||
reject(new Error("Install failed"));
|
reject(new Error("Install failed"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
util.log("[red] Installed module: "+module);
|
var grandchild = child_process.exec('npm view '+module+' version', function(err, stdin, stdout) {
|
||||||
resolve(redNodes.addModule(module).then(reportAddedModules));
|
var version = stdin.replace(/\s/g, "");
|
||||||
|
util.log("[red] Installed module: "+module+":"+version);
|
||||||
|
resolve(redNodes.addModule(module,version).then(reportAddedModules));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -36,8 +36,10 @@ describe("nodes api", function() {
|
|||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.get("/nodes",nodes.getAll);
|
app.get("/nodes",nodes.getAll);
|
||||||
app.post("/nodes",nodes.post);
|
app.post("/nodes",nodes.post);
|
||||||
app.get("/nodes/:id",nodes.get);
|
app.get("/nodes/:mod",nodes.getModule);
|
||||||
app.put("/nodes/:id",nodes.put);
|
app.get("/nodes/:mod/:set",nodes.getSet);
|
||||||
|
app.put("/nodes/:mod",nodes.putModule);
|
||||||
|
app.put("/nodes/:mod/:set",nodes.putSet);
|
||||||
app.delete("/nodes/:id",nodes.delete);
|
app.delete("/nodes/:id",nodes.delete);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -78,12 +80,45 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns an individual node info', function(done) {
|
it('returns node module info', function(done) {
|
||||||
var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) {
|
var getNodeInfo = sinon.stub(redNodes,'getModuleInfo', function(id) {
|
||||||
return {"123":{id:"123"}}[id];
|
return {"node-red":{name:"node-red"}}[id];
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/nodes/123')
|
.get('/nodes/node-red')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
getNodeInfo.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property("name","node-red");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 404 for unknown module', function(done) {
|
||||||
|
var getNodeInfo = sinon.stub(redNodes,'getModuleInfo', function(id) {
|
||||||
|
return {"node-red":{name:"node-red"}}[id];
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get('/nodes/node-blue')
|
||||||
|
.expect(404)
|
||||||
|
.end(function(err,res) {
|
||||||
|
getNodeInfo.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns individual node info', function(done) {
|
||||||
|
var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) {
|
||||||
|
return {"node-red/123":{id:"node-red/123"}}[id];
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get('/nodes/node-red/123')
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
@ -91,17 +126,17 @@ describe("nodes api", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
res.body.should.have.property("id","123");
|
res.body.should.have.property("id","node-red/123");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns an individual node configs', function(done) {
|
it('returns individual node configs', function(done) {
|
||||||
var getNodeConfig = sinon.stub(redNodes,'getNodeConfig', function(id) {
|
var getNodeConfig = sinon.stub(redNodes,'getNodeConfig', function(id) {
|
||||||
return {"123":"<script></script>"}[id];
|
return {"node-red/123":"<script></script>"}[id];
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/nodes/123')
|
.get('/nodes/node-red/123')
|
||||||
.set('Accept', 'text/html')
|
.set('Accept', 'text/html')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.expect("<script></script>")
|
.expect("<script></script>")
|
||||||
@ -116,10 +151,10 @@ describe("nodes api", function() {
|
|||||||
|
|
||||||
it('returns 404 for unknown node', function(done) {
|
it('returns 404 for unknown node', function(done) {
|
||||||
var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) {
|
var getNodeInfo = sinon.stub(redNodes,'getNodeInfo', function(id) {
|
||||||
return {"123":{id:"123"}}[id];
|
return {"node-red/123":{id:"node-red/123"}}[id];
|
||||||
});
|
});
|
||||||
request(app)
|
request(app)
|
||||||
.get('/nodes/456')
|
.get('/nodes/node-red/456')
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.expect(404)
|
.expect(404)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
@ -168,13 +203,21 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('by module', function() {
|
describe('by module', function() {
|
||||||
it('installs the module and returns node info', function(done) {
|
it('installs the module and returns module info', function(done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
var getNodeModuleInfo = sinon.stub(redNodes,'getNodeModuleInfo',function(id) {
|
var getNodeModuleInfo = sinon.stub(redNodes,'getNodeModuleInfo',function(id) {
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(module) {
|
||||||
|
if (module === "foo") {
|
||||||
|
return {
|
||||||
|
name:"foo",
|
||||||
|
nodes:[{id:123}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
var installModule = sinon.stub(server,'installModule', function() {
|
var installModule = sinon.stub(server,'installModule', function() {
|
||||||
return when.resolve({id:"123"});
|
return when.resolve({id:"123"});
|
||||||
});
|
});
|
||||||
@ -186,11 +229,14 @@ describe("nodes api", function() {
|
|||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
settingsAvailable.restore();
|
settingsAvailable.restore();
|
||||||
getNodeModuleInfo.restore();
|
getNodeModuleInfo.restore();
|
||||||
|
getModuleInfo.restore();
|
||||||
installModule.restore();
|
installModule.restore();
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
res.body.should.have.property("id","123");
|
res.body.should.have.property("name","foo");
|
||||||
|
res.body.should.have.property("nodes");
|
||||||
|
res.body.nodes[0].should.have.property("id","123");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -294,7 +340,7 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('by module', function() {
|
describe('by module', function() {
|
||||||
it('uninstalls the module and returns node info', function(done) {
|
it('uninstalls the module', function(done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -310,7 +356,7 @@ describe("nodes api", function() {
|
|||||||
|
|
||||||
request(app)
|
request(app)
|
||||||
.del('/nodes/foo')
|
.del('/nodes/foo')
|
||||||
.expect(200)
|
.expect(204)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
settingsAvailable.restore();
|
settingsAvailable.restore();
|
||||||
getNodeInfo.restore();
|
getNodeInfo.restore();
|
||||||
@ -319,7 +365,6 @@ describe("nodes api", function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
res.body.should.have.property("id","123");
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -399,7 +444,27 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns 400 for invalid payload', function(done) {
|
it('returns 400 for invalid node payload', function(done) {
|
||||||
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-red/foo')
|
||||||
|
.send({})
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err,res) {
|
||||||
|
settingsAvailable.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.text.should.equal("Invalid request");
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 400 for invalid module payload', function(done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -418,6 +483,7 @@ describe("nodes api", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns 404 for unknown node', function(done) {
|
it('returns 404 for unknown node', function(done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
return true;
|
return true;
|
||||||
@ -427,7 +493,7 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/nodes/foo')
|
.put('/nodes/node-red/foo')
|
||||||
.send({enabled:false})
|
.send({enabled:false})
|
||||||
.expect(404)
|
.expect(404)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
@ -440,6 +506,28 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns 404 for unknown module', function(done) {
|
||||||
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) {
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-blue')
|
||||||
|
.send({enabled:false})
|
||||||
|
.expect(404)
|
||||||
|
.end(function(err,res) {
|
||||||
|
settingsAvailable.restore();
|
||||||
|
getModuleInfo.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('enables disabled node', function(done) {
|
it('enables disabled node', function(done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
return true;
|
return true;
|
||||||
@ -452,7 +540,7 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/nodes/foo')
|
.put('/nodes/node-red/foo')
|
||||||
.send({enabled:true})
|
.send({enabled:true})
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
@ -468,6 +556,7 @@ describe("nodes api", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('disables enabled node', function(done) {
|
it('disables enabled node', function(done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
return true;
|
return true;
|
||||||
@ -480,7 +569,7 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/nodes/foo')
|
.put('/nodes/node-red/foo')
|
||||||
.send({enabled:false})
|
.send({enabled:false})
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
@ -496,6 +585,7 @@ describe("nodes api", function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('no-ops if already in the right state', function() {
|
describe('no-ops if already in the right state', function() {
|
||||||
function run(state,done) {
|
function run(state,done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
@ -513,7 +603,7 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/nodes/foo')
|
.put('/nodes/node-red/foo')
|
||||||
.send({enabled:state})
|
.send({enabled:state})
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
@ -541,6 +631,7 @@ describe("nodes api", function() {
|
|||||||
run(false,done);
|
run(false,done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('does not no-op if err on node', function() {
|
describe('does not no-op if err on node', function() {
|
||||||
function run(state,done) {
|
function run(state,done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
@ -558,7 +649,7 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/nodes/foo')
|
.put('/nodes/node-red/foo')
|
||||||
.send({enabled:state})
|
.send({enabled:state})
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
@ -586,6 +677,186 @@ describe("nodes api", function() {
|
|||||||
run(false,done);
|
run(false,done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('enables disabled module', function(done) {
|
||||||
|
var n1 = {id:"123",enabled:false,types:['a']};
|
||||||
|
var n2 = {id:"456",enabled:false,types:['b']};
|
||||||
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(name) {
|
||||||
|
return {name:"node-red", nodes:[n1, n2]};
|
||||||
|
});
|
||||||
|
|
||||||
|
var enableNode = sinon.stub(redNodes,'enableNode');
|
||||||
|
enableNode.onFirstCall().returns((function() {
|
||||||
|
n1.enabled = true;
|
||||||
|
return n1;
|
||||||
|
})());
|
||||||
|
enableNode.onSecondCall().returns((function() {
|
||||||
|
n2.enabled = true;
|
||||||
|
return n2;
|
||||||
|
})());
|
||||||
|
enableNode.returns(null);
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-red')
|
||||||
|
.send({enabled:true})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
settingsAvailable.restore();
|
||||||
|
getModuleInfo.restore();
|
||||||
|
enableNode.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property("name","node-red");
|
||||||
|
res.body.should.have.property("nodes");
|
||||||
|
res.body.nodes[0].should.have.property("enabled",true);
|
||||||
|
res.body.nodes[1].should.have.property("enabled",true);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables enabled module', function(done) {
|
||||||
|
var n1 = {id:"123",enabled:true,types:['a']};
|
||||||
|
var n2 = {id:"456",enabled:true,types:['b']};
|
||||||
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(name) {
|
||||||
|
return {name:"node-red", nodes:[n1, n2]};
|
||||||
|
});
|
||||||
|
|
||||||
|
var disableNode = sinon.stub(redNodes,'disableNode');
|
||||||
|
disableNode.onFirstCall().returns((function() {
|
||||||
|
n1.enabled = false;
|
||||||
|
return n1;
|
||||||
|
})());
|
||||||
|
disableNode.onSecondCall().returns((function() {
|
||||||
|
n2.enabled = false;
|
||||||
|
return n2;
|
||||||
|
})());
|
||||||
|
disableNode.returns(null);
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-red')
|
||||||
|
.send({enabled:false})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
settingsAvailable.restore();
|
||||||
|
getModuleInfo.restore();
|
||||||
|
disableNode.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
res.body.should.have.property("name","node-red");
|
||||||
|
res.body.should.have.property("nodes");
|
||||||
|
res.body.nodes[0].should.have.property("enabled",false);
|
||||||
|
res.body.nodes[1].should.have.property("enabled",false);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('no-ops if a node in module already in the right state', function() {
|
||||||
|
function run(state,done) {
|
||||||
|
var node = {id:"123",enabled:state,types:['a']};
|
||||||
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) {
|
||||||
|
return {name:"node-red", nodes:[node]};
|
||||||
|
});
|
||||||
|
var enableNode = sinon.stub(redNodes,'enableNode',function(id) {
|
||||||
|
node.enabled = true;
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
var disableNode = sinon.stub(redNodes,'disableNode',function(id) {
|
||||||
|
node.enabled = false;
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-red')
|
||||||
|
.send({enabled:state})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
settingsAvailable.restore();
|
||||||
|
getModuleInfo.restore();
|
||||||
|
var enableNodeCalled = enableNode.called;
|
||||||
|
var disableNodeCalled = disableNode.called;
|
||||||
|
enableNode.restore();
|
||||||
|
disableNode.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
enableNodeCalled.should.be.false;
|
||||||
|
disableNodeCalled.should.be.false;
|
||||||
|
res.body.should.have.property("name","node-red");
|
||||||
|
res.body.should.have.property("nodes");
|
||||||
|
res.body.nodes[0].should.have.property("enabled",state);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
it('already enabled', function(done) {
|
||||||
|
run(true,done);
|
||||||
|
});
|
||||||
|
it('already disabled', function(done) {
|
||||||
|
run(false,done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('does not no-op if err on a node in module', function() {
|
||||||
|
function run(state,done) {
|
||||||
|
var node = {id:"123",enabled:state,types:['a'],err:"foo"};
|
||||||
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(id) {
|
||||||
|
return {name:"node-red", nodes:[node]};
|
||||||
|
});
|
||||||
|
var enableNode = sinon.stub(redNodes,'enableNode',function(id) {
|
||||||
|
node.enabled = true;
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
var disableNode = sinon.stub(redNodes,'disableNode',function(id) {
|
||||||
|
node.enabled = false;
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
|
||||||
|
request(app)
|
||||||
|
.put('/nodes/node-red')
|
||||||
|
.send({enabled:state})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
settingsAvailable.restore();
|
||||||
|
getModuleInfo.restore();
|
||||||
|
var enableNodeCalled = enableNode.called;
|
||||||
|
var disableNodeCalled = disableNode.called;
|
||||||
|
enableNode.restore();
|
||||||
|
disableNode.restore();
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
enableNodeCalled.should.be.equal(state);
|
||||||
|
disableNodeCalled.should.be.equal(!state);
|
||||||
|
res.body.should.have.property("name","node-red");
|
||||||
|
res.body.should.have.property("nodes");
|
||||||
|
res.body.nodes[0].should.have.property("enabled",state);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
it('already enabled', function(done) {
|
||||||
|
run(true,done);
|
||||||
|
});
|
||||||
|
it('already disabled', function(done) {
|
||||||
|
run(false,done);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
var should = require("should");
|
|
||||||
var request = require('supertest');
|
|
||||||
var express = require('express');
|
|
||||||
var sinon = require('sinon');
|
|
||||||
var when = require('when');
|
|
||||||
|
|
||||||
var app = express();
|
|
||||||
var redNodes = require("../../../red/nodes");
|
|
||||||
var server = require("../../../red/server");
|
|
||||||
var settings = require("../../../red/settings");
|
|
||||||
|
|
||||||
var plugins = require("../../../red/api/plugins");
|
|
||||||
|
|
||||||
describe("plugins api", function() {
|
|
||||||
|
|
||||||
var app;
|
|
||||||
|
|
||||||
before(function() {
|
|
||||||
app = express();
|
|
||||||
app.use(express.json());
|
|
||||||
app.get("/plugins",plugins.getAll);
|
|
||||||
app.get("/plugins/:id",plugins.get);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('get plugins', function() {
|
|
||||||
it('returns plugins list', function(done) {
|
|
||||||
var getPluginList = sinon.stub(redNodes,'getPluginList', function() {
|
|
||||||
return [1,2,3];
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.get('/plugins')
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
getPluginList.restore();
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
res.body.should.be.an.Array.and.have.lengthOf(3);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns an individual plugin info', function(done) {
|
|
||||||
var getPluginInfo = sinon.stub(redNodes,'getPluginInfo', function(id) {
|
|
||||||
return {"name":"123", "nodes":[1,2,3]};
|
|
||||||
});
|
|
||||||
request(app)
|
|
||||||
.get('/plugins/123')
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
getPluginInfo.restore();
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
res.body.should.have.property("name","123");
|
|
||||||
res.body.should.have.property("nodes",[1,2,3]);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,53 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
var should = require("should");
|
|
||||||
var sinon = require("sinon");
|
|
||||||
var fs = require("fs");
|
|
||||||
|
|
||||||
var config = require("../../../../red/cli/lib/config");
|
|
||||||
|
|
||||||
describe("cli config", function() {
|
|
||||||
afterEach(function() {
|
|
||||||
config.unload();
|
|
||||||
});
|
|
||||||
it('loads preferences when target referenced', sinon.test(function() {
|
|
||||||
this.stub(fs,"readFileSync",function() {
|
|
||||||
return '{"target":"http://example.com:1880"}'
|
|
||||||
});
|
|
||||||
config.target.should.eql("http://example.com:1880");
|
|
||||||
}));
|
|
||||||
it('provide default value for target', sinon.test(function() {
|
|
||||||
this.stub(fs,"readFileSync",function() {
|
|
||||||
return '{}'
|
|
||||||
});
|
|
||||||
config.target.should.eql("http://localhost:1880");
|
|
||||||
}));
|
|
||||||
it('saves preferences when target set', sinon.test(function() {
|
|
||||||
this.stub(fs,"readFileSync",function() {
|
|
||||||
return '{"target":"http://another.example.com:1880"}'
|
|
||||||
});
|
|
||||||
this.stub(fs,"writeFileSync",function() {});
|
|
||||||
|
|
||||||
config.target.should.eql("http://another.example.com:1880");
|
|
||||||
config.target = "http://final.example.com:1880";
|
|
||||||
|
|
||||||
fs.readFileSync.calledOnce.should.be.true;
|
|
||||||
fs.writeFileSync.calledOnce.should.be.true;
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
@ -1,46 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
var should = require("should");
|
|
||||||
var sinon = require("sinon");
|
|
||||||
var fs = require("fs");
|
|
||||||
var request = require("request");
|
|
||||||
|
|
||||||
var apiRequest = require("../../../../red/cli/lib/request");
|
|
||||||
var config = require("../../../../red/cli/lib/config");
|
|
||||||
|
|
||||||
describe("cli request", function() {
|
|
||||||
var sandbox = sinon.sandbox.create();
|
|
||||||
before(function() {
|
|
||||||
sandbox.stub(fs,"readFileSync",function() {
|
|
||||||
return '{"target":"http://example.com:1880"}'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
after(function() {
|
|
||||||
sandbox.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns the json response to a get', sinon.test(function(done) {
|
|
||||||
this.stub(request, 'get').yields(null, {statusCode:200}, JSON.stringify({a: "b"}));
|
|
||||||
|
|
||||||
apiRequest("/foo",{}).then(function(res) {
|
|
||||||
res.should.eql({a:"b"});
|
|
||||||
done();
|
|
||||||
}).otherwise(function(err) {
|
|
||||||
done(err);
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2014 IBM Corp.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
@ -135,7 +135,7 @@ describe("red/nodes/index", function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('allows nodes to be added/remove/enabled/disabled from the registry', function() {
|
describe('allows nodes to be added/removed/enabled/disabled from the registry', function() {
|
||||||
var registry = require("../../../red/nodes/registry");
|
var registry = require("../../../red/nodes/registry");
|
||||||
var randomNodeInfo = {id:"5678",types:["random"]};
|
var randomNodeInfo = {id:"5678",types:["random"]};
|
||||||
|
|
||||||
@ -248,8 +248,73 @@ describe("red/nodes/index", function() {
|
|||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('allows modules to be removed from the registry', function() {
|
||||||
|
var registry = require("../../../red/nodes/registry");
|
||||||
|
var randomNodeInfo = {id:"5678",types:["random"]};
|
||||||
|
var randomModuleInfo = {
|
||||||
|
name:"random",
|
||||||
|
nodes: [randomNodeInfo]
|
||||||
|
};
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
sinon.stub(registry,"getNodeInfo",function(id) {
|
||||||
|
if (id == "node-red/foo") {
|
||||||
|
return {id:"1234",types:["test"]};
|
||||||
|
} else if (id == "doesnotexist") {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return randomNodeInfo;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(registry,"getNodeModuleInfo",function(module) {
|
||||||
|
if (module == "node-red") {
|
||||||
|
return ["foo"];
|
||||||
|
} else if (module == "doesnotexist") {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return randomModuleInfo.nodes;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(registry,"removeModule",function(id) {
|
||||||
|
return randomModuleInfo;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
registry.getNodeInfo.restore();
|
||||||
|
registry.getNodeModuleInfo.restore();
|
||||||
|
registry.removeModule.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(': prevents removing a module that is in use',function(done) {
|
||||||
|
index.init(settings, storage);
|
||||||
|
index.registerType('test', TestNode);
|
||||||
|
index.loadFlows().then(function() {
|
||||||
|
/*jshint immed: false */
|
||||||
|
(function() {
|
||||||
|
index.removeModule("node-red");
|
||||||
|
}).should.throw();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(': prevents removing a module that is unknown',function(done) {
|
||||||
|
index.init(settings, storage);
|
||||||
|
index.registerType('test', TestNode);
|
||||||
|
index.loadFlows().then(function() {
|
||||||
|
/*jshint immed: false */
|
||||||
|
(function() {
|
||||||
|
index.removeModule("doesnotexist");
|
||||||
|
}).should.throw();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -33,10 +33,10 @@ describe('NodeRegistry', function() {
|
|||||||
var resourcesDir = __dirname+ path.sep + "resources" + path.sep;
|
var resourcesDir = __dirname+ path.sep + "resources" + path.sep;
|
||||||
|
|
||||||
function stubSettings(s,available) {
|
function stubSettings(s,available) {
|
||||||
s.available = function() {return available;}
|
s.available = function() {return available;};
|
||||||
s.set = function(s,v) { return when.resolve()},
|
s.set = function(s,v) { return when.resolve();};
|
||||||
s.get = function(s) { return null;}
|
s.get = function(s) { return null;};
|
||||||
return s
|
return s;
|
||||||
}
|
}
|
||||||
var settings = stubSettings({},false);
|
var settings = stubSettings({},false);
|
||||||
var settingsWithStorage = stubSettings({},true);
|
var settingsWithStorage = stubSettings({},true);
|
||||||
@ -56,8 +56,9 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
|
typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode1");
|
||||||
list[0].should.have.property("name","TestNode1.js");
|
list[0].should.have.property("name","TestNode1");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-1"]);
|
list[0].should.have.property("types",["test-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
@ -78,8 +79,9 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load(resourcesDir + "TestNode2",true).then(function() {
|
typeRegistry.load(resourcesDir + "TestNode2",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode2");
|
||||||
list[0].should.have.property("name","TestNode2.js");
|
list[0].should.have.property("name","TestNode2");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-2"]);
|
list[0].should.have.property("types",["test-node-2"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
@ -98,8 +100,9 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load(resourcesDir + "TestNode3",true).then(function() {
|
typeRegistry.load(resourcesDir + "TestNode3",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode3");
|
||||||
list[0].should.have.property("name","TestNode3.js");
|
list[0].should.have.property("name","TestNode3");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-3"]);
|
list[0].should.have.property("types",["test-node-3"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.have.property("err","fail");
|
list[0].should.have.property("err","fail");
|
||||||
@ -119,8 +122,9 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load(resourcesDir + "MultipleNodes1",true).then(function() {
|
typeRegistry.load(resourcesDir + "MultipleNodes1",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/MultipleNodes1");
|
||||||
list[0].should.have.property("name","MultipleNodes1.js");
|
list[0].should.have.property("name","MultipleNodes1");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-multiple-1a","test-node-multiple-1b"]);
|
list[0].should.have.property("types",["test-node-multiple-1a","test-node-multiple-1b"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
@ -142,8 +146,9 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
|
typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/NestedNode");
|
||||||
list[0].should.have.property("name","NestedNode.js");
|
list[0].should.have.property("name","NestedNode");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["nested-node-1"]);
|
list[0].should.have.property("types",["nested-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
@ -159,7 +164,9 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
|
typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("name","NestedNode.js");
|
list[0].should.have.property("id","node-red/NestedNode");
|
||||||
|
list[0].should.have.property("name","NestedNode");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["nested-node-1"]);
|
list[0].should.have.property("types",["nested-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
@ -189,26 +196,13 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load("wontexist",true).then(function() {
|
typeRegistry.load("wontexist",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
|
|
||||||
list.should.be.an.Array.and.have.lengthOf(2);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode1");
|
||||||
list[0].should.have.property("name","TestNode1.js");
|
list[0].should.have.property("name","TestNode1");
|
||||||
list[0].should.have.property("types",["test-node-1"]);
|
list[0].should.have.property("types",["test-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
|
|
||||||
list[1].should.have.property("id");
|
|
||||||
list[1].id.should.not.equal(list[0].id);
|
|
||||||
|
|
||||||
list[1].should.have.property("name","TestNode1.js");
|
|
||||||
list[1].should.have.property("types",["test-node-1"]);
|
|
||||||
list[1].should.have.property("enabled",true);
|
|
||||||
list[1].should.have.property("err");
|
|
||||||
/already registered/.test(list[1].err).should.be.true;
|
|
||||||
|
|
||||||
var nodeConstructor = typeRegistry.get("test-node-1");
|
|
||||||
// Verify the duplicate node hasn't replaced the original one
|
|
||||||
nodeConstructor.name.should.be.equal("TestNode");
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
done(e);
|
done(e);
|
||||||
@ -297,24 +291,28 @@ describe('NodeRegistry', function() {
|
|||||||
available: function() { return true; },
|
available: function() { return true; },
|
||||||
set: function(s,v) { return when.resolve(); },
|
set: function(s,v) { return when.resolve(); },
|
||||||
get: function(s) { return null; }
|
get: function(s) { return null; }
|
||||||
}
|
};
|
||||||
var settingsSave = sinon.spy(settings,"set");
|
var settingsSave = sinon.spy(settings,"set");
|
||||||
typeRegistry.init(settings);
|
typeRegistry.init(settings);
|
||||||
typeRegistry.load("wontexist",true).then(function() {
|
typeRegistry.load("wontexist",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var nodeList = typeRegistry.getNodeList();
|
||||||
list.should.be.Array.and.have.length(3);
|
var moduleList = typeRegistry.getModuleList();
|
||||||
|
nodeList.should.be.Array.and.have.length(3);
|
||||||
|
moduleList.should.be.Array.and.have.length(1);
|
||||||
|
|
||||||
settingsSave.callCount.should.equal(1);
|
settingsSave.callCount.should.equal(1);
|
||||||
settingsSave.firstCall.args[0].should.be.equal("nodes");
|
settingsSave.firstCall.args[0].should.be.equal("modules");
|
||||||
var savedList = settingsSave.firstCall.args[1];
|
var savedList = settingsSave.firstCall.args[1];
|
||||||
|
|
||||||
savedList[list[0].id].name == list[0].name;
|
savedList[moduleList[0].name].name.should.equal(moduleList[0].name);
|
||||||
savedList[list[1].id].name == list[1].name;
|
|
||||||
savedList[list[2].id].name == list[2].name;
|
|
||||||
|
|
||||||
savedList[list[0].id].should.not.have.property("err");
|
savedList[moduleList[0].name].nodes[moduleList[0].nodes[0].name].name.should.equal(moduleList[0].nodes[0].name);
|
||||||
savedList[list[1].id].should.not.have.property("err");
|
savedList[moduleList[0].name].nodes[moduleList[0].nodes[1].name].name.should.equal(moduleList[0].nodes[1].name);
|
||||||
savedList[list[2].id].should.not.have.property("err");
|
savedList[moduleList[0].name].nodes[moduleList[0].nodes[2].name].name.should.equal(moduleList[0].nodes[2].name);
|
||||||
|
|
||||||
|
savedList[moduleList[0].name].nodes[moduleList[0].nodes[0].name].should.not.have.property("err");
|
||||||
|
savedList[moduleList[0].name].nodes[moduleList[0].nodes[1].name].should.not.have.property("err");
|
||||||
|
savedList[moduleList[0].name].nodes[moduleList[0].nodes[2].name].should.not.have.property("err");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
@ -336,10 +334,12 @@ describe('NodeRegistry', function() {
|
|||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.be.empty;
|
list.should.be.an.Array.and.be.empty;
|
||||||
|
|
||||||
|
// TODO: Needs module and name params for loadNodeConfig
|
||||||
typeRegistry.addNode(resourcesDir + "TestNode1/TestNode1.js").then(function(node) {
|
typeRegistry.addNode(resourcesDir + "TestNode1/TestNode1.js").then(function(node) {
|
||||||
list = typeRegistry.getNodeList();
|
list = typeRegistry.getNodeList();
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode1");
|
||||||
list[0].should.have.property("name","TestNode1.js");
|
list[0].should.have.property("name","TestNode1");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-1"]);
|
list[0].should.have.property("types",["test-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
@ -386,8 +386,9 @@ describe('NodeRegistry', function() {
|
|||||||
var id = list[0].id;
|
var id = list[0].id;
|
||||||
var type = list[0].types[0];
|
var type = list[0].types[0];
|
||||||
|
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode1");
|
||||||
list[0].should.have.property("name","TestNode1.js");
|
list[0].should.have.property("name","TestNode1");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-1"]);
|
list[0].should.have.property("types",["test-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
@ -405,7 +406,7 @@ describe('NodeRegistry', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns plugins list', function(done) {
|
it('returns modules list', function(done) {
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
@ -438,7 +439,7 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load("wontexist",true).then(function(){
|
typeRegistry.load("wontexist",true).then(function(){
|
||||||
|
|
||||||
typeRegistry.addModule("TestNodeModule").then(function() {
|
typeRegistry.addModule("TestNodeModule").then(function() {
|
||||||
var list = typeRegistry.getPluginList();
|
var list = typeRegistry.getModuleList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("name", "TestNodeModule");
|
list[0].should.have.property("name", "TestNodeModule");
|
||||||
list[0].should.have.property("nodes");
|
list[0].should.have.property("nodes");
|
||||||
@ -457,7 +458,7 @@ describe('NodeRegistry', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns plugin info', function(done) {
|
it('returns module info', function(done) {
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
@ -490,11 +491,11 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load("wontexist",true).then(function(){
|
typeRegistry.load("wontexist",true).then(function(){
|
||||||
|
|
||||||
typeRegistry.addModule("TestNodeModule").then(function(nodes) {
|
typeRegistry.addModule("TestNodeModule").then(function(nodes) {
|
||||||
var list = typeRegistry.getPluginList();
|
var list = typeRegistry.getModuleList();
|
||||||
|
|
||||||
var plugin = typeRegistry.getPluginInfo(list[0].name);
|
var module = typeRegistry.getModuleInfo(list[0].name);
|
||||||
plugin.should.have.property("name", list[0].name);
|
module.should.have.property("name", list[0].name);
|
||||||
plugin.should.have.property("nodes", nodes);
|
module.should.have.property("nodes", nodes);
|
||||||
done();
|
done();
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
done(e);
|
done(e);
|
||||||
@ -532,8 +533,9 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
|
typeRegistry.load(resourcesDir + "TestNode1",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode1");
|
||||||
list[0].should.have.property("name","TestNode1.js");
|
list[0].should.have.property("name","TestNode1");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-1"]);
|
list[0].should.have.property("types",["test-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.have.property("loaded",true);
|
list[0].should.have.property("loaded",true);
|
||||||
@ -552,7 +554,6 @@ describe('NodeRegistry', function() {
|
|||||||
var nodeConstructor = typeRegistry.get("test-node-1");
|
var nodeConstructor = typeRegistry.get("test-node-1");
|
||||||
(typeof nodeConstructor).should.be.equal("undefined");
|
(typeof nodeConstructor).should.be.equal("undefined");
|
||||||
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
done(e);
|
done(e);
|
||||||
@ -612,14 +613,16 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.load("wontexist",false).then(function(){
|
typeRegistry.load("wontexist",false).then(function(){
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(2);
|
list.should.be.an.Array.and.have.lengthOf(2);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","TestNodeModule/TestNodeMod1");
|
||||||
list[0].should.have.property("name","TestNodeModule:TestNodeMod1");
|
list[0].should.have.property("name","TestNodeMod1");
|
||||||
|
list[0].should.have.property("module","TestNodeModule");
|
||||||
list[0].should.have.property("types",["test-node-mod-1"]);
|
list[0].should.have.property("types",["test-node-mod-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
|
|
||||||
list[1].should.have.property("id");
|
list[1].should.have.property("id","TestNodeModule/TestNodeMod2");
|
||||||
list[1].should.have.property("name","TestNodeModule:TestNodeMod2");
|
list[1].should.have.property("name","TestNodeMod2");
|
||||||
|
list[1].should.have.property("module","TestNodeModule");
|
||||||
list[1].should.have.property("types",["test-node-mod-2"]);
|
list[1].should.have.property("types",["test-node-mod-2"]);
|
||||||
list[1].should.have.property("enabled",true);
|
list[1].should.have.property("enabled",true);
|
||||||
list[1].should.have.property("err");
|
list[1].should.have.property("err");
|
||||||
@ -681,14 +684,16 @@ describe('NodeRegistry', function() {
|
|||||||
typeRegistry.addModule("TestNodeModule").then(function(node) {
|
typeRegistry.addModule("TestNodeModule").then(function(node) {
|
||||||
list = typeRegistry.getNodeList();
|
list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(2);
|
list.should.be.an.Array.and.have.lengthOf(2);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","TestNodeModule/TestNodeMod1");
|
||||||
list[0].should.have.property("name","TestNodeModule:TestNodeMod1");
|
list[0].should.have.property("name","TestNodeMod1");
|
||||||
|
list[0].should.have.property("module","TestNodeModule");
|
||||||
list[0].should.have.property("types",["test-node-mod-1"]);
|
list[0].should.have.property("types",["test-node-mod-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
list[0].should.not.have.property("err");
|
list[0].should.not.have.property("err");
|
||||||
|
|
||||||
list[1].should.have.property("id");
|
list[1].should.have.property("id","TestNodeModule/TestNodeMod2");
|
||||||
list[1].should.have.property("name","TestNodeModule:TestNodeMod2");
|
list[1].should.have.property("name","TestNodeMod2");
|
||||||
|
list[1].should.have.property("module","TestNodeModule");
|
||||||
list[1].should.have.property("types",["test-node-mod-2"]);
|
list[1].should.have.property("types",["test-node-mod-2"]);
|
||||||
list[1].should.have.property("enabled",true);
|
list[1].should.have.property("enabled",true);
|
||||||
list[1].should.have.property("err");
|
list[1].should.have.property("err");
|
||||||
@ -708,6 +713,60 @@ describe('NodeRegistry', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('adds module with version number', function(done) {
|
||||||
|
var fs = require("fs");
|
||||||
|
var path = require("path");
|
||||||
|
|
||||||
|
var pathJoin = (function() {
|
||||||
|
var _join = path.join;
|
||||||
|
return sinon.stub(path,"join",function() {
|
||||||
|
if (arguments.length == 3 && arguments[2] == "package.json") {
|
||||||
|
return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]);
|
||||||
|
}
|
||||||
|
if (arguments.length == 2 && arguments[1] == "TestNodeModule") {
|
||||||
|
return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]);
|
||||||
|
}
|
||||||
|
return _join.apply(this,arguments);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
var readdirSync = (function() {
|
||||||
|
var originalReaddirSync = fs.readdirSync;
|
||||||
|
var callCount = 0;
|
||||||
|
return sinon.stub(fs,"readdirSync",function(dir) {
|
||||||
|
var result = [];
|
||||||
|
if (callCount == 1) {
|
||||||
|
result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules");
|
||||||
|
}
|
||||||
|
callCount++;
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
typeRegistry.init(settingsWithStorage);
|
||||||
|
typeRegistry.load("wontexist",true).then(function(){
|
||||||
|
typeRegistry.addModule("TestNodeModule","0.0.1").then(function(node) {
|
||||||
|
var module = typeRegistry.getModuleInfo("TestNodeModule");
|
||||||
|
|
||||||
|
module.should.have.property("name","TestNodeModule");
|
||||||
|
module.should.have.property("version","0.0.1");
|
||||||
|
|
||||||
|
var modules = typeRegistry.getModuleList();
|
||||||
|
|
||||||
|
modules[0].should.have.property("name","TestNodeModule");
|
||||||
|
modules[0].should.have.property("version","0.0.1");
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).catch(function(e) {
|
||||||
|
done(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
}).catch(function(e) {
|
||||||
|
done(e);
|
||||||
|
}).finally(function() {
|
||||||
|
readdirSync.restore();
|
||||||
|
pathJoin.restore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('rejects adding duplicate node modules', function(done) {
|
it('rejects adding duplicate node modules', function(done) {
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
@ -847,13 +906,14 @@ describe('NodeRegistry', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('allows nodes to be enabled and disabled by hex-id', function(done) {
|
it('allows nodes to be enabled and disabled by id', function(done) {
|
||||||
typeRegistry.init(settingsWithStorage);
|
typeRegistry.init(settingsWithStorage);
|
||||||
typeRegistry.load(resourcesDir+path.sep+"TestNode1",true).then(function() {
|
typeRegistry.load(resourcesDir+path.sep+"TestNode1",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode1");
|
||||||
list[0].should.have.property("name","TestNode1.js");
|
list[0].should.have.property("name","TestNode1");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
|
|
||||||
var nodeConfig = typeRegistry.getNodeConfigs();
|
var nodeConfig = typeRegistry.getNodeConfigs();
|
||||||
@ -892,8 +952,9 @@ describe('NodeRegistry', function() {
|
|||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
|
|
||||||
list.should.be.an.Array.and.have.lengthOf(1);
|
list.should.be.an.Array.and.have.lengthOf(1);
|
||||||
list[0].should.have.property("id");
|
list[0].should.have.property("id","node-red/TestNode1");
|
||||||
list[0].should.have.property("name","TestNode1.js");
|
list[0].should.have.property("name","TestNode1");
|
||||||
|
list[0].should.have.property("module","node-red");
|
||||||
list[0].should.have.property("types",["test-node-1"]);
|
list[0].should.have.property("types",["test-node-1"]);
|
||||||
list[0].should.have.property("enabled",true);
|
list[0].should.have.property("enabled",true);
|
||||||
|
|
||||||
@ -930,7 +991,7 @@ describe('NodeRegistry', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('fails to enable/disable non-existent nodes', function(done) {
|
it('fails to enable/disable non-existent nodes', function(done) {
|
||||||
typeRegistry.init(settings);
|
typeRegistry.init(settingsWithStorage);
|
||||||
typeRegistry.load("wontexist",true).then(function() {
|
typeRegistry.load("wontexist",true).then(function() {
|
||||||
var list = typeRegistry.getNodeList();
|
var list = typeRegistry.getNodeList();
|
||||||
list.should.be.an.Array.and.be.empty;
|
list.should.be.an.Array.and.be.empty;
|
||||||
|
Loading…
Reference in New Issue
Block a user