mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
WIP: add flow api
This commit is contained in:
parent
d5f2255a68
commit
fd2e47ed73
32
red/api/flow.js
Normal file
32
red/api/flow.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2014, 2015 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 log;
|
||||||
|
var redNodes;
|
||||||
|
var settings;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function(runtime) {
|
||||||
|
settings = runtime.settings;
|
||||||
|
redNodes = runtime.nodes;
|
||||||
|
log = runtime.log;
|
||||||
|
},
|
||||||
|
get: function(req,res) {
|
||||||
|
var id = req.params.id;
|
||||||
|
log.audit({event: "flow.get"},req);
|
||||||
|
res.json(redNodes.getFlow(id));
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ var when = require('when');
|
|||||||
var ui = require("./ui");
|
var ui = require("./ui");
|
||||||
var nodes = require("./nodes");
|
var nodes = require("./nodes");
|
||||||
var flows = require("./flows");
|
var flows = require("./flows");
|
||||||
|
var flow = require("./flow");
|
||||||
var library = require("./library");
|
var library = require("./library");
|
||||||
var info = require("./info");
|
var info = require("./info");
|
||||||
var theme = require("./theme");
|
var theme = require("./theme");
|
||||||
@ -64,6 +65,7 @@ function init(_server,runtime) {
|
|||||||
auth.init(runtime);
|
auth.init(runtime);
|
||||||
credentials.init(runtime);
|
credentials.init(runtime);
|
||||||
flows.init(runtime);
|
flows.init(runtime);
|
||||||
|
flow.init(runtime);
|
||||||
info.init(runtime);
|
info.init(runtime);
|
||||||
library.init(adminApp,runtime);
|
library.init(adminApp,runtime);
|
||||||
locales.init(runtime);
|
locales.init(runtime);
|
||||||
@ -103,6 +105,8 @@ function init(_server,runtime) {
|
|||||||
adminApp.get("/flows",needsPermission("flows.read"),flows.get);
|
adminApp.get("/flows",needsPermission("flows.read"),flows.get);
|
||||||
adminApp.post("/flows",needsPermission("flows.write"),flows.post);
|
adminApp.post("/flows",needsPermission("flows.write"),flows.post);
|
||||||
|
|
||||||
|
adminApp.get("/flow/:id",needsPermission("flows.read"),flow.get);
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll);
|
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll);
|
||||||
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post);
|
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post);
|
||||||
|
@ -352,6 +352,81 @@ function checkTypeInUse(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addFlow(flow) {
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
id:'',
|
||||||
|
label:'',
|
||||||
|
nodes:[]
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// flow.id should not exist - it will be assigned by the runtime
|
||||||
|
// all flow.{subflows|configs|nodes}.z will be set to flow.id
|
||||||
|
// all nodes will have new ids assigned if there is a clash
|
||||||
|
// check all known types - fail if otherwise?
|
||||||
|
//
|
||||||
|
// resolves with generated flow id
|
||||||
|
|
||||||
|
return when.promise(function(resolve,reject) {
|
||||||
|
var i,id,node;
|
||||||
|
|
||||||
|
flow.id = redUtil.generateId();
|
||||||
|
|
||||||
|
for (i=0;i<flow.nodes.length;i++) {
|
||||||
|
node = flow.nodes[i];
|
||||||
|
if (activeFlowConfig.allNodes[node.id]) {
|
||||||
|
// TODO nls
|
||||||
|
return reject(new Error('duplicate id'));
|
||||||
|
}
|
||||||
|
node.z = flow.id;
|
||||||
|
}
|
||||||
|
var tabNode = {
|
||||||
|
type:'tab',
|
||||||
|
label:flow.label,
|
||||||
|
id:flow.id
|
||||||
|
}
|
||||||
|
var nodes = [tabNode].concat(flow.nodes);
|
||||||
|
var parsedConfig = flowUtil.parseConfig(clone(nodes));
|
||||||
|
// TODO: handle unknown type
|
||||||
|
for (id in parsedConfig.flows[flow.id]) {
|
||||||
|
if (parsedConfig.flows[flow.id].hasOwnProperty(id)) {
|
||||||
|
activeFlowConfig.allNodes[id] = parsedConfig.flows[flow.id][id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activeFlowConfig.flows[flow.id] = parsedConfig.flows[flow.id];
|
||||||
|
|
||||||
|
activeConfig = activeConfig.concat(nodes);
|
||||||
|
// TODO: extract creds
|
||||||
|
// TODO: save config
|
||||||
|
|
||||||
|
start("flows",{added:flow.nodes.map(function(n) { return n.id})}).then(function() {
|
||||||
|
// console.log(activeFlowConfig);
|
||||||
|
resolve(flow.id);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlow(id) {
|
||||||
|
var flow = activeFlowConfig.flows[id];
|
||||||
|
if (!flow) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var result = {
|
||||||
|
id: id,
|
||||||
|
label: flow.label,
|
||||||
|
nodes: []
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i=0;i<activeConfig.length;i++) {
|
||||||
|
if (activeConfig[i].z === id && activeConfig[i].type != 'tab') {
|
||||||
|
result.nodes.push(activeConfig[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: init,
|
init: init,
|
||||||
|
|
||||||
@ -388,11 +463,19 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
stopFlows: stop,
|
stopFlows: stop,
|
||||||
|
|
||||||
started: function() { return started },
|
get started() { return started },
|
||||||
|
|
||||||
handleError: handleError,
|
handleError: handleError,
|
||||||
handleStatus: handleStatus,
|
handleStatus: handleStatus,
|
||||||
|
|
||||||
checkTypeInUse: checkTypeInUse
|
checkTypeInUse: checkTypeInUse,
|
||||||
|
|
||||||
|
|
||||||
|
addFlow: addFlow,
|
||||||
|
getFlow: getFlow,
|
||||||
|
updateFlow:null,
|
||||||
|
removeFlow:null,
|
||||||
|
disableFlow:null,
|
||||||
|
enableFlow:null
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -120,11 +120,19 @@ module.exports = {
|
|||||||
cleanModuleList: registry.cleanModuleList,
|
cleanModuleList: registry.cleanModuleList,
|
||||||
|
|
||||||
// Flow handling
|
// Flow handling
|
||||||
loadFlows: flows.load,
|
loadFlows: flows.load,
|
||||||
startFlows: flows.startFlows,
|
startFlows: flows.startFlows,
|
||||||
stopFlows: flows.stopFlows,
|
stopFlows: flows.stopFlows,
|
||||||
setFlows: flows.setFlows,
|
setFlows: flows.setFlows,
|
||||||
getFlows: flows.getFlows,
|
getFlows: flows.getFlows,
|
||||||
|
|
||||||
|
addFlow: flows.addFlow,
|
||||||
|
getFlow: flows.getFlow,
|
||||||
|
updateFlow: flows.updateFlow,
|
||||||
|
removeFlow: flows.removeFlow,
|
||||||
|
disableFlow: flows.disableFlow,
|
||||||
|
enableFlow: flows.enableFlow,
|
||||||
|
|
||||||
|
|
||||||
// Credentials
|
// Credentials
|
||||||
addCredentials: credentials.add,
|
addCredentials: credentials.add,
|
||||||
|
@ -497,4 +497,74 @@ describe('flows/index', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#addFlow', function() {
|
||||||
|
it("rejects duplicate node id",function(done) {
|
||||||
|
var originalConfig = [
|
||||||
|
{id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
|
||||||
|
{id:"t1",type:"tab"}
|
||||||
|
];
|
||||||
|
storage.getFlows = function() {
|
||||||
|
return when.resolve(originalConfig);
|
||||||
|
}
|
||||||
|
flows.init({},storage);
|
||||||
|
flows.load().then(function() {
|
||||||
|
flows.addFlow({
|
||||||
|
label:'new flow',
|
||||||
|
nodes:[
|
||||||
|
{id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]}
|
||||||
|
]
|
||||||
|
}).then(function() {
|
||||||
|
done(new Error('failed to reject duplicate node id'));
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("addFlow",function(done) {
|
||||||
|
var originalConfig = [
|
||||||
|
{id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
|
||||||
|
{id:"t1",type:"tab"}
|
||||||
|
];
|
||||||
|
storage.getFlows = function() {
|
||||||
|
return when.resolve(originalConfig);
|
||||||
|
}
|
||||||
|
flows.init({},storage);
|
||||||
|
flows.load().then(function() {
|
||||||
|
return flows.startFlows();
|
||||||
|
}).then(function() {
|
||||||
|
flows.addFlow({
|
||||||
|
label:'new flow',
|
||||||
|
nodes:[
|
||||||
|
{id:"t2-1",x:10,y:10,z:"t1",type:"test",wires:[]},
|
||||||
|
{id:"t2-2",x:10,y:10,z:"t1",type:"test",wires:[]},
|
||||||
|
{id:"t2-3",z:"t1",type:"test"}
|
||||||
|
]
|
||||||
|
}).then(function(id) {
|
||||||
|
flows.getFlows().should.have.lengthOf(6);
|
||||||
|
var createdFlows = Object.keys(flowCreate.flows);
|
||||||
|
createdFlows.should.have.lengthOf(3);
|
||||||
|
createdFlows[2].should.eql(id);
|
||||||
|
done();
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
})
|
||||||
|
describe('#updateFlow', function() {
|
||||||
|
it.skip("updateFlow");
|
||||||
|
})
|
||||||
|
describe('#removeFlow', function() {
|
||||||
|
it.skip("removeFlow");
|
||||||
|
})
|
||||||
|
describe('#disableFlow', function() {
|
||||||
|
it.skip("disableFlow");
|
||||||
|
})
|
||||||
|
describe('#enableFlow', function() {
|
||||||
|
it.skip("enableFlow");
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user