mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Add add/update/delete flow apis
This commit is contained in:
		| @@ -26,7 +26,64 @@ module.exports = { | |||||||
|     }, |     }, | ||||||
|     get: function(req,res) { |     get: function(req,res) { | ||||||
|         var id = req.params.id; |         var id = req.params.id; | ||||||
|         log.audit({event: "flow.get"},req); |         var flow = redNodes.getFlow(id); | ||||||
|         res.json(redNodes.getFlow(id)); |         if (flow) { | ||||||
|  |             log.audit({event: "flow.get",id:id},req); | ||||||
|  |             res.json(flow); | ||||||
|  |         } else { | ||||||
|  |             log.audit({event: "flow.get",id:id,error:"not_found"},req); | ||||||
|  |             res.status(404).end(); | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     post: function(req,res) { | ||||||
|  |         var flow = req.body; | ||||||
|  |         redNodes.addFlow(flow).then(function(id) { | ||||||
|  |             log.audit({event: "flow.add",id:id},req); | ||||||
|  |             res.json({id:id}); | ||||||
|  |         }).otherwise(function(err) { | ||||||
|  |             log.audit({event: "flow.add",error:err.code||"unexpected_error",message:err.toString()},req); | ||||||
|  |             res.status(400).json({error:err.code||"unexpected_error", message:err.toString()}); | ||||||
|  |         }) | ||||||
|  |  | ||||||
|  |     }, | ||||||
|  |     put: function(req,res) { | ||||||
|  |         var id = req.params.id; | ||||||
|  |         var flow = req.body; | ||||||
|  |         try { | ||||||
|  |             redNodes.updateFlow(id,flow).then(function() { | ||||||
|  |                 log.audit({event: "flow.update",id:id},req); | ||||||
|  |                 res.json({id:id}); | ||||||
|  |             }).otherwise(function(err) { | ||||||
|  |                 console.log(err.stack); | ||||||
|  |                 log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()},req); | ||||||
|  |                 res.status(400).json({error:err.code||"unexpected_error", message:err.toString()}); | ||||||
|  |             }) | ||||||
|  |         } catch(err) { | ||||||
|  |             if (err.code === 404) { | ||||||
|  |                 log.audit({event: "flow.update",id:id,error:"not_found"},req); | ||||||
|  |                 res.status(404).end(); | ||||||
|  |             } else { | ||||||
|  |                 console.log(err.stack); | ||||||
|  |                 log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()},req); | ||||||
|  |                 res.status(400).json({error:err.code||"unexpected_error", message:err.toString()}); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     delete: function(req,res) { | ||||||
|  |         var id = req.params.id; | ||||||
|  |         try { | ||||||
|  |             redNodes.removeFlow(id).then(function() { | ||||||
|  |                 log.audit({event: "flow.remove",id:id},req); | ||||||
|  |                 res.status(204).end(); | ||||||
|  |             }) | ||||||
|  |         } catch(err) { | ||||||
|  |             if (err.code === 404) { | ||||||
|  |                 log.audit({event: "flow.remove",id:id,error:"not_found"},req); | ||||||
|  |                 res.status(404).end(); | ||||||
|  |             } else { | ||||||
|  |                 log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()},req); | ||||||
|  |                 res.status(400).json({error:err.code||"unexpected_error", message:err.toString()}); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -106,6 +106,9 @@ function init(_server,runtime) { | |||||||
|         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); |         adminApp.get("/flow/:id",needsPermission("flows.read"),flow.get); | ||||||
|  |         adminApp.post("/flow",needsPermission("flows.write"),flow.post); | ||||||
|  |         adminApp.delete("/flow/:id",needsPermission("flows.write"),flow.delete); | ||||||
|  |         adminApp.put("/flow/:id",needsPermission("flows.write"),flow.put); | ||||||
|  |  | ||||||
|         // Nodes |         // Nodes | ||||||
|         adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll); |         adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll); | ||||||
|   | |||||||
| @@ -121,6 +121,7 @@ module.exports = { | |||||||
|         var nodeType = node.type; |         var nodeType = node.type; | ||||||
|         var newCreds = node.credentials; |         var newCreds = node.credentials; | ||||||
|         if (newCreds) { |         if (newCreds) { | ||||||
|  |             delete node.credentials; | ||||||
|             var savedCredentials = credentialCache[nodeID] || {}; |             var savedCredentials = credentialCache[nodeID] || {}; | ||||||
|             var dashedType = nodeType.replace(/\s+/g, '-'); |             var dashedType = nodeType.replace(/\s+/g, '-'); | ||||||
|             var definition = credentialsDef[dashedType]; |             var definition = credentialsDef[dashedType]; | ||||||
| @@ -145,7 +146,6 @@ module.exports = { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             credentialCache[nodeID] = savedCredentials; |             credentialCache[nodeID] = savedCredentials; | ||||||
|             delete node.credentials; |  | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ function Flow(global,flow) { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (diff) { |         if (diff && diff.rewired) { | ||||||
|             for (var j=0;j<diff.rewired.length;j++) { |             for (var j=0;j<diff.rewired.length;j++) { | ||||||
|                 var rewireNode = activeNodes[diff.rewired[j]]; |                 var rewireNode = activeNodes[diff.rewired[j]]; | ||||||
|                 if (rewireNode) { |                 if (rewireNode) { | ||||||
| @@ -262,7 +262,6 @@ function mapEnvVarProperties(obj,prop) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function createNode(type,config) { | function createNode(type,config) { | ||||||
|     // console.log("CREATE",type,config.id); |  | ||||||
|     var nn = null; |     var nn = null; | ||||||
|     var nt = typeRegistry.get(type); |     var nt = typeRegistry.get(type); | ||||||
|     if (nt) { |     if (nt) { | ||||||
|   | |||||||
| @@ -200,6 +200,7 @@ function handleStatus(node,statusMessage) { | |||||||
|  |  | ||||||
|  |  | ||||||
| function start(type,diff) { | function start(type,diff) { | ||||||
|  |     //dumpActiveNodes(); | ||||||
|     type = type||"full"; |     type = type||"full"; | ||||||
|     started = true; |     started = true; | ||||||
|     var i; |     var i; | ||||||
| @@ -231,14 +232,18 @@ function start(type,diff) { | |||||||
|     } |     } | ||||||
|     var id; |     var id; | ||||||
|     if (!diff) { |     if (!diff) { | ||||||
|         activeFlows['_GLOBAL_'] = Flow.create(activeFlowConfig); |         if (!activeFlows['global']) { | ||||||
|  |             activeFlows['global'] = Flow.create(activeFlowConfig); | ||||||
|  |         } | ||||||
|         for (id in activeFlowConfig.flows) { |         for (id in activeFlowConfig.flows) { | ||||||
|             if (activeFlowConfig.flows.hasOwnProperty(id)) { |             if (activeFlowConfig.flows.hasOwnProperty(id)) { | ||||||
|                 activeFlows[id] = Flow.create(activeFlowConfig,activeFlowConfig.flows[id]); |                 if (!activeFlows[id]) { | ||||||
|  |                     activeFlows[id] = Flow.create(activeFlowConfig,activeFlowConfig.flows[id]); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         activeFlows['_GLOBAL_'].update(activeFlowConfig,activeFlowConfig); |         activeFlows['global'].update(activeFlowConfig,activeFlowConfig); | ||||||
|         for (id in activeFlowConfig.flows) { |         for (id in activeFlowConfig.flows) { | ||||||
|             if (activeFlowConfig.flows.hasOwnProperty(id)) { |             if (activeFlowConfig.flows.hasOwnProperty(id)) { | ||||||
|                 if (activeFlows[id]) { |                 if (activeFlows[id]) { | ||||||
| @@ -352,7 +357,34 @@ function checkTypeInUse(id) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function updateMissingTypes() { | ||||||
|  |     var subflowInstanceRE = /^subflow:(.+)$/; | ||||||
|  |     activeFlowConfig.missingTypes = []; | ||||||
|  |  | ||||||
|  |     for (var id in activeFlowConfig.allNodes) { | ||||||
|  |         if (activeFlowConfig.allNodes.hasOwnProperty(id)) { | ||||||
|  |             var node = activeFlowConfig.allNodes[id]; | ||||||
|  |             if (node.type !== 'tab' && node.type !== 'subflow') { | ||||||
|  |                 var subflowDetails = subflowInstanceRE.exec(node.type); | ||||||
|  |                 if ( (subflowDetails && !activeFlowConfig.subflows[subflowDetails[1]]) || (!subflowDetails && !typeRegistry.get(node.type)) ) { | ||||||
|  |                     if (activeFlowConfig.missingTypes.indexOf(node.type) === -1) { | ||||||
|  |                         activeFlowConfig.missingTypes.push(node.type); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // function dumpActiveNodes() { | ||||||
|  | //     console.log("--------") | ||||||
|  | //     for (var i in activeFlowConfig.allNodes) { | ||||||
|  | //         console.log(i,activeFlowConfig.allNodes[i].type,activeFlowConfig.allNodes[i].z) | ||||||
|  | //     } | ||||||
|  | //     console.log("--------") | ||||||
|  | // } | ||||||
| function addFlow(flow) { | function addFlow(flow) { | ||||||
|  |     //dumpActiveNodes(); | ||||||
|     /* |     /* | ||||||
|     { |     { | ||||||
|         id:'', |         id:'', | ||||||
| @@ -364,69 +396,214 @@ function addFlow(flow) { | |||||||
|  |  | ||||||
|     // flow.id should not exist - it will be assigned by the runtime |     // 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 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? |     // check all known types - fail if otherwise? | ||||||
|     // |     // | ||||||
|     // resolves with generated flow id |     // resolves with generated flow id | ||||||
|  |  | ||||||
|     return when.promise(function(resolve,reject) { |     var i,id,node; | ||||||
|         var i,id,node; |  | ||||||
|  |  | ||||||
|         flow.id = redUtil.generateId(); |     flow.id = redUtil.generateId(); | ||||||
|  |  | ||||||
|         for (i=0;i<flow.nodes.length;i++) { |     for (i=0;i<flow.nodes.length;i++) { | ||||||
|             node = flow.nodes[i]; |         node = flow.nodes[i]; | ||||||
|  |         if (activeFlowConfig.allNodes[node.id]) { | ||||||
|  |             // TODO nls | ||||||
|  |             return when.reject(new Error('duplicate id')); | ||||||
|  |         } | ||||||
|  |         node.z = flow.id; | ||||||
|  |     } | ||||||
|  |     if (flow.configs) { | ||||||
|  |         for (i=0;i<flow.configs.length;i++) { | ||||||
|  |             node = flow.configs[i]; | ||||||
|             if (activeFlowConfig.allNodes[node.id]) { |             if (activeFlowConfig.allNodes[node.id]) { | ||||||
|                 // TODO nls |                 // TODO nls | ||||||
|                 return reject(new Error('duplicate id')); |                 return when.reject(new Error('duplicate id')); | ||||||
|             } |             } | ||||||
|             node.z = flow.id; |             node.z = flow.id; | ||||||
|         } |         } | ||||||
|         var tabNode = { |     } | ||||||
|             type:'tab', |     var tabNode = { | ||||||
|             label:flow.label, |         type:'tab', | ||||||
|             id:flow.id |         label:flow.label, | ||||||
|  |         id:flow.id | ||||||
|  |     } | ||||||
|  |     var nodes = [tabNode].concat(flow.nodes||[]).concat(flow.configs||[]); | ||||||
|  |     var credentialSavePromise; | ||||||
|  |     var credentialsChanged = false; | ||||||
|  |     nodes.forEach(function(node) { | ||||||
|  |         if (node.credentials) { | ||||||
|  |             credentials.extract(node); | ||||||
|  |             credentialsChanged = true; | ||||||
|         } |         } | ||||||
|         var nodes = [tabNode].concat(flow.nodes); |     }); | ||||||
|         var parsedConfig = flowUtil.parseConfig(clone(nodes)); |     if (credentialsChanged) { | ||||||
|         // TODO: handle unknown type |         credentialSavePromise = credentials.save(); | ||||||
|         for (id in parsedConfig.flows[flow.id]) { |     } else { | ||||||
|             if (parsedConfig.flows[flow.id].hasOwnProperty(id)) { |         credentialSavePromise = when.resolve(); | ||||||
|                 activeFlowConfig.allNodes[id] = parsedConfig.flows[flow.id][id]; |     } | ||||||
|  |  | ||||||
|  |     var parsedConfig = flowUtil.parseConfig(clone(nodes)); | ||||||
|  |     parsedConfig.missingTypes.forEach(function(type) { | ||||||
|  |         if (activeFlowConfig.missingTypes.indexOf(type) == -1) { | ||||||
|  |             activeFlowConfig.missingTypes.push(type); | ||||||
|  |         } | ||||||
|  |     }) | ||||||
|  |     activeFlowConfig.allNodes[tabNode.id] = tabNode; | ||||||
|  |     for (id in parsedConfig.flows[flow.id].nodes) { | ||||||
|  |         if (parsedConfig.flows[flow.id].nodes.hasOwnProperty(id)) { | ||||||
|  |             activeFlowConfig.allNodes[id] = parsedConfig.flows[flow.id].nodes[id]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (parsedConfig.flows[flow.id].configs) { | ||||||
|  |         for (id in parsedConfig.flows[flow.id].configs) { | ||||||
|  |             if (parsedConfig.flows[flow.id].configs.hasOwnProperty(id)) { | ||||||
|  |                 activeFlowConfig.allNodes[id] = parsedConfig.flows[flow.id].configs[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() { |     activeFlowConfig.flows[flow.id] = parsedConfig.flows[flow.id]; | ||||||
|             // console.log(activeFlowConfig); |  | ||||||
|             resolve(flow.id); |     activeConfig = activeConfig.concat(nodes); | ||||||
|  |     // TODO: extract creds | ||||||
|  |     return credentialSavePromise.then(function() { | ||||||
|  |         return storage.saveFlows(activeConfig).then(function() { | ||||||
|  |             return start("flows",{added:flow.nodes.map(function(n) { return n.id})}).then(function() { | ||||||
|  |                 //dumpActiveNodes(); | ||||||
|  |                 // console.log(activeFlowConfig); | ||||||
|  |                 return flow.id; | ||||||
|  |             }) | ||||||
|         }) |         }) | ||||||
|     }) |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
| function getFlow(id) { | function getFlow(id) { | ||||||
|     var flow = activeFlowConfig.flows[id]; |     var flow; | ||||||
|  |     if (id === 'global') { | ||||||
|  |         flow = activeFlowConfig; | ||||||
|  |     } else { | ||||||
|  |         flow = activeFlowConfig.flows[id]; | ||||||
|  |     } | ||||||
|     if (!flow) { |     if (!flow) { | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|     var result = { |     var result = { | ||||||
|         id: id, |         id: id | ||||||
|         label: flow.label, |  | ||||||
|         nodes: [] |  | ||||||
|     }; |     }; | ||||||
|  |     if (flow.label) { | ||||||
|     for (var i=0;i<activeConfig.length;i++) { |         result.label = flow.label; | ||||||
|         if (activeConfig[i].z === id && activeConfig[i].type != 'tab') { |     } | ||||||
|             result.nodes.push(activeConfig[i]); |     if (flow.nodes) { | ||||||
|  |         var nodeIds = Object.keys(flow.nodes); | ||||||
|  |         if (nodeIds.length > 0) { | ||||||
|  |             result.nodes = nodeIds.map(function(nodeId) { | ||||||
|  |                 return clone(flow.nodes[nodeId]); | ||||||
|  |             }) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     if (flow.configs) { | ||||||
|  |         var configIds = Object.keys(flow.configs); | ||||||
|  |         result.configs = configIds.map(function(configId) { | ||||||
|  |             return clone(flow.configs[configId]); | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |     if (flow.subflows) { | ||||||
|  |         var subflowIds = Object.keys(flow.subflows); | ||||||
|  |         result.subflows = subflowIds.map(function(subflowId) { | ||||||
|  |             var subflow = clone(flow.subflows[subflowId]); | ||||||
|  |             var nodeIds = Object.keys(subflow.nodes); | ||||||
|  |             subflow.nodes = nodeIds.map(function(id) { | ||||||
|  |                 return subflow.nodes[id]; | ||||||
|  |             }); | ||||||
|  |             if (subflow.configs) { | ||||||
|  |                 var configIds = Object.keys(subflow.configs); | ||||||
|  |                 subflow.configs = configIds.map(function(id) { | ||||||
|  |                     return subflow.configs[id]; | ||||||
|  |                 }) | ||||||
|  |             } | ||||||
|  |             delete subflow.instances; | ||||||
|  |             return subflow; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  | function updateFlow(id,newFlow) { | ||||||
|  |     if (id === 'global') { | ||||||
|  |         // TODO: handle global update | ||||||
|  |         throw new Error('not allowed to update global'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     var flow = activeFlowConfig.flows[id]; | ||||||
|  |     if (!flow) { | ||||||
|  |         var e = new Error(); | ||||||
|  |         e.code = 404; | ||||||
|  |         throw e; | ||||||
|  |     } | ||||||
|  |     var newConfig = clone(activeConfig); | ||||||
|  |     newConfig = newConfig.filter(function(node) { | ||||||
|  |         return node.z !== id && node.id !== id; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     var tabNode = { | ||||||
|  |         type:'tab', | ||||||
|  |         label:newFlow.label, | ||||||
|  |         id:id | ||||||
|  |     } | ||||||
|  |     var nodes = [tabNode].concat(newFlow.nodes||[]).concat(newFlow.configs||[]); | ||||||
|  |     nodes.forEach(function(n) { | ||||||
|  |         n.z = id; | ||||||
|  |     }); | ||||||
|  |     newConfig = newConfig.concat(nodes); | ||||||
|  |  | ||||||
|  |     return setConfig(newConfig,'flows'); | ||||||
|  |  | ||||||
|  |     // filter activeConfig to remove nodes | ||||||
|  |  | ||||||
|  | } | ||||||
|  | function removeFlow(id) { | ||||||
|  |     if (id === 'global') { | ||||||
|  |         // TODO: nls + error code | ||||||
|  |         throw new Error('not allowed to remove global'); | ||||||
|  |     } | ||||||
|  |     var flow = activeFlowConfig.flows[id]; | ||||||
|  |     if (!flow) { | ||||||
|  |         var e = new Error(); | ||||||
|  |         e.code = 404; | ||||||
|  |         throw e; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     var diff = { | ||||||
|  |         removed: [id].concat(Object.keys(flow.nodes)).concat(Object.keys(flow.configs)), | ||||||
|  |         linked:[], | ||||||
|  |         changed:[] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     delete activeFlowConfig.flows[id]; | ||||||
|  |  | ||||||
|  |     diff.removed.forEach(function(id) { | ||||||
|  |         delete activeFlowConfig.allNodes[id]; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     activeConfig = activeConfig.filter(function(node) { | ||||||
|  |         return node.z !== id && node.id !== id; | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     var missingTypeCount = activeFlowConfig.missingTypes.length; | ||||||
|  |     updateMissingTypes(); | ||||||
|  |  | ||||||
|  |     return credentials.clean(activeConfig).then(function() { | ||||||
|  |         storage.saveFlows(activeConfig).then(function() { | ||||||
|  |             stop("flows",diff).then(function() { | ||||||
|  |                 if (missingTypeCount > 0 && activeFlowConfig.missingTypes.length === 0) { | ||||||
|  |                     return start(); | ||||||
|  |                 } | ||||||
|  |                 //dumpActiveNodes(); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  | } | ||||||
| module.exports = { | module.exports = { | ||||||
|     init: init, |     init: init, | ||||||
|  |  | ||||||
| @@ -470,11 +647,10 @@ module.exports = { | |||||||
|  |  | ||||||
|     checkTypeInUse: checkTypeInUse, |     checkTypeInUse: checkTypeInUse, | ||||||
|  |  | ||||||
|  |  | ||||||
|     addFlow: addFlow, |     addFlow: addFlow, | ||||||
|     getFlow: getFlow, |     getFlow: getFlow, | ||||||
|     updateFlow:null, |     updateFlow: updateFlow, | ||||||
|     removeFlow:null, |     removeFlow: removeFlow, | ||||||
|     disableFlow:null, |     disableFlow:null, | ||||||
|     enableFlow:null |     enableFlow:null | ||||||
|  |  | ||||||
|   | |||||||
| @@ -76,29 +76,28 @@ module.exports = { | |||||||
|                     if (flow.missingTypes.indexOf(n.type) === -1) { |                     if (flow.missingTypes.indexOf(n.type) === -1) { | ||||||
|                         flow.missingTypes.push(n.type); |                         flow.missingTypes.push(n.type); | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } | ||||||
|                     var container = null; |                 var container = null; | ||||||
|                     if (flow.flows[n.z]) { |                 if (flow.flows[n.z]) { | ||||||
|                         container = flow.flows[n.z]; |                     container = flow.flows[n.z]; | ||||||
|                     } else if (flow.subflows[n.z]) { |                 } else if (flow.subflows[n.z]) { | ||||||
|                         container = flow.subflows[n.z]; |                     container = flow.subflows[n.z]; | ||||||
|  |                 } | ||||||
|  |                 if (n.hasOwnProperty('x') && n.hasOwnProperty('y')) { | ||||||
|  |                     if (subflowDetails) { | ||||||
|  |                         var subflowType = subflowDetails[1] | ||||||
|  |                         n.subflow = subflowType; | ||||||
|  |                         flow.subflows[subflowType].instances.push(n) | ||||||
|                     } |                     } | ||||||
|                     if (n.hasOwnProperty('x') && n.hasOwnProperty('y')) { |                     if (container) { | ||||||
|                         if (subflowDetails) { |                         container.nodes[n.id] = n; | ||||||
|                             var subflowType = subflowDetails[1] |                     } | ||||||
|                             n.subflow = subflowType; |                 } else { | ||||||
|                             flow.subflows[subflowType].instances.push(n) |                     if (container) { | ||||||
|                         } |                         container.configs[n.id] = n; | ||||||
|                         if (container) { |  | ||||||
|                             container.nodes[n.id] = n; |  | ||||||
|                         } |  | ||||||
|                     } else { |                     } else { | ||||||
|                         if (container) { |                         flow.configs[n.id] = n; | ||||||
|                             container.configs[n.id] = n; |                         flow.configs[n.id]._users = []; | ||||||
|                         } else { |  | ||||||
|                             flow.configs[n.id] = n; |  | ||||||
|                             flow.configs[n.id]._users = []; |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -531,6 +531,9 @@ describe('flows/index', function() { | |||||||
|             storage.getFlows = function() { |             storage.getFlows = function() { | ||||||
|                 return when.resolve(originalConfig); |                 return when.resolve(originalConfig); | ||||||
|             } |             } | ||||||
|  |             storage.setFlows = function() { | ||||||
|  |                 return when.resolve(); | ||||||
|  |             } | ||||||
|             flows.init({},storage); |             flows.init({},storage); | ||||||
|             flows.load().then(function() { |             flows.load().then(function() { | ||||||
|                 return flows.startFlows(); |                 return flows.startFlows(); | ||||||
| @@ -539,7 +542,8 @@ describe('flows/index', function() { | |||||||
|                     label:'new flow', |                     label:'new flow', | ||||||
|                     nodes:[ |                     nodes:[ | ||||||
|                         {id:"t2-1",x:10,y:10,z:"t1",type:"test",wires:[]}, |                         {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-2",x:10,y:10,z:"t1",type:"test",wires:[]} | ||||||
|  |                         , | ||||||
|                         {id:"t2-3",z:"t1",type:"test"} |                         {id:"t2-3",z:"t1",type:"test"} | ||||||
|                     ] |                     ] | ||||||
|                 }).then(function(id) { |                 }).then(function(id) { | ||||||
|   | |||||||
| @@ -137,8 +137,7 @@ describe('flows/util', function() { | |||||||
|             ]; |             ]; | ||||||
|             var parsedConfig = flowUtil.parseConfig(originalConfig); |             var parsedConfig = flowUtil.parseConfig(originalConfig); | ||||||
|             parsedConfig.missingTypes.should.eql(['missing']); |             parsedConfig.missingTypes.should.eql(['missing']); | ||||||
|             var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]},"t1-2":{"id":"t1-2","x":10,"y":10,"z":"t1","type":"missing","wires":[]}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]}}}},"missingTypes":["missing"]}; |             var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]},"t1-2":{"id":"t1-2","x":10,"y":10,"z":"t1","type":"missing","wires":[]}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]},'t1-2': { id: 't1-2', x: 10, y: 10, z: 't1', type: 'missing', wires: [] }}}},"missingTypes":["missing"]}; | ||||||
|  |  | ||||||
|             redUtil.compareObjects(parsedConfig,expectedConfig).should.be.true; |             redUtil.compareObjects(parsedConfig,expectedConfig).should.be.true; | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user