mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Remove promises from Change node
This commit is contained in:
		| @@ -98,7 +98,7 @@ module.exports = function(RED) { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         function getToValue(msg,rule) { | ||||
|         function getToValue(msg,rule,done) { | ||||
|             var value = rule.to; | ||||
|             if (rule.tot === 'json') { | ||||
|                 value = JSON.parse(rule.to); | ||||
| @@ -107,222 +107,236 @@ module.exports = function(RED) { | ||||
|             } | ||||
|             if (rule.tot === "msg") { | ||||
|                 value = RED.util.getMessageProperty(msg,rule.to); | ||||
|             } else if ((rule.tot === 'flow') || | ||||
|                        (rule.tot === 'global')) { | ||||
|                 return new Promise((resolve,reject) => { | ||||
|                     RED.util.evaluateNodeProperty(rule.to, rule.tot, node, msg, (err,value) => { | ||||
|                         if (err) { | ||||
|                             resolve(undefined); | ||||
|                         } else { | ||||
|                             resolve(value); | ||||
|                         } | ||||
|                     }); | ||||
|             } else if ((rule.tot === 'flow') || (rule.tot === 'global')) { | ||||
|                 RED.util.evaluateNodeProperty(rule.to, rule.tot, node, msg, (err,value) => { | ||||
|                     if (err) { | ||||
|                         done(undefined,undefined); | ||||
|                     } else { | ||||
|                         done(undefined,value); | ||||
|                     } | ||||
|                 }); | ||||
|                 return | ||||
|             } else if (rule.tot === 'date') { | ||||
|                 value = Date.now(); | ||||
|             } else if (rule.tot === 'jsonata') { | ||||
|                 return new Promise((resolve,reject) => { | ||||
|                     RED.util.evaluateJSONataExpression(rule.to,msg, (err, value) => { | ||||
|                         if (err) { | ||||
|                             reject(RED._("change.errors.invalid-expr",{error:err.message})) | ||||
|                         } else { | ||||
|                             resolve(value); | ||||
|                         } | ||||
|                     }); | ||||
|                 RED.util.evaluateJSONataExpression(rule.to,msg, (err, value) => { | ||||
|                     if (err) { | ||||
|                         done(RED._("change.errors.invalid-expr",{error:err.message})) | ||||
|                     } else { | ||||
|                         done(undefined, value); | ||||
|                     } | ||||
|                 }); | ||||
|                 return; | ||||
|             } | ||||
|             return Promise.resolve(value); | ||||
|             done(undefined,value); | ||||
|         } | ||||
|         function getFromValue(msg,rule) { | ||||
|  | ||||
|         function getFromValueType(fromValue, done) { | ||||
|             var fromType; | ||||
|             var fromRE; | ||||
|             if (typeof fromValue === 'number' || fromValue instanceof Number) { | ||||
|                 fromType = 'num'; | ||||
|             } else if (typeof fromValue === 'boolean') { | ||||
|                 fromType = 'bool' | ||||
|             } else if (fromValue instanceof RegExp) { | ||||
|                 fromType = 're'; | ||||
|                 fromRE = fromValue; | ||||
|             } else if (typeof fromValue === 'string') { | ||||
|                 fromType = 'str'; | ||||
|                 fromRE = fromValue.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); | ||||
|                 try { | ||||
|                     fromRE = new RegExp(fromRE, "g"); | ||||
|                 } catch (e) { | ||||
|                     done(new Error(RED._("change.errors.invalid-from",{error:e.message}))); | ||||
|                 } | ||||
|             } else { | ||||
|                 done(new Error(RED._("change.errors.invalid-from",{error:"unsupported type: "+(typeof fromValue)}))); | ||||
|             } | ||||
|             done(undefined,{ | ||||
|                 fromType, | ||||
|                 fromValue, | ||||
|                 fromRE | ||||
|             }); | ||||
|         } | ||||
|         function getFromValue(msg,rule, done) { | ||||
|             var fromValue; | ||||
|             var fromType; | ||||
|             var fromRE; | ||||
|             if (rule.t === 'change') { | ||||
|                 if (rule.fromt === 'msg' || rule.fromt === 'flow' || rule.fromt === 'global') { | ||||
|                     return new Promise((resolve,reject) => { | ||||
|                         if (rule.fromt === "msg") { | ||||
|                             resolve(RED.util.getMessageProperty(msg,rule.from)); | ||||
|                         } else if (rule.fromt === 'flow' || rule.fromt === 'global') { | ||||
|                             var contextKey = RED.util.parseContextStore(rule.from); | ||||
|                             node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => { | ||||
|                                 if (err) { | ||||
|                                     reject(err); | ||||
|                                 } else { | ||||
|                                     resolve(fromValue); | ||||
|                                 } | ||||
|                             }); | ||||
|                         } | ||||
|                     }).then(fromValue => { | ||||
|                         if (typeof fromValue === 'number' || fromValue instanceof Number) { | ||||
|                             fromType = 'num'; | ||||
|                         } else if (typeof fromValue === 'boolean') { | ||||
|                             fromType = 'bool' | ||||
|                         } else if (fromValue instanceof RegExp) { | ||||
|                             fromType = 're'; | ||||
|                             fromRE = fromValue; | ||||
|                         } else if (typeof fromValue === 'string') { | ||||
|                             fromType = 'str'; | ||||
|                             fromRE = fromValue.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); | ||||
|                             try { | ||||
|                                 fromRE = new RegExp(fromRE, "g"); | ||||
|                             } catch (e) { | ||||
|                                 throw new Error(RED._("change.errors.invalid-from",{error:e.message})); | ||||
|                     if (rule.fromt === "msg") { | ||||
|                         return getFromValueType(RED.util.getMessageProperty(msg,rule.from),done); | ||||
|                     } else if (rule.fromt === 'flow' || rule.fromt === 'global') { | ||||
|                         var contextKey = RED.util.parseContextStore(rule.from); | ||||
|                         node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => { | ||||
|                             if (err) { | ||||
|                                 done(err) | ||||
|                             } else { | ||||
|                                 getFromValueType(fromValue,done); | ||||
|                             } | ||||
|                         } else { | ||||
|                             throw new Error(RED._("change.errors.invalid-from",{error:"unsupported type: "+(typeof fromValue)})); | ||||
|                         } | ||||
|                         return { | ||||
|                             fromType, | ||||
|                             fromValue, | ||||
|                             fromRE | ||||
|                         } | ||||
|                     }); | ||||
|                         }); | ||||
|                         return; | ||||
|                     } | ||||
|                 } else { | ||||
|                     fromType = rule.fromt; | ||||
|                     fromValue = rule.from; | ||||
|                     fromRE = rule.fromRE; | ||||
|                 } | ||||
|             } | ||||
|             return Promise.resolve({ | ||||
|             done(undefined, { | ||||
|                 fromType, | ||||
|                 fromValue, | ||||
|                 fromRE | ||||
|             }); | ||||
|         } | ||||
|         function applyRule(msg,rule) { | ||||
|                 var property = rule.p; | ||||
|                 var current; | ||||
|                 var fromValue; | ||||
|                 var fromType; | ||||
|                 var fromRE; | ||||
|                 try { | ||||
|                 return getToValue(msg,rule).then(value => { | ||||
|                     return getFromValue(msg,rule).then(fromParts => { | ||||
|                         fromValue = fromParts.fromValue; | ||||
|                         fromType = fromParts.fromType; | ||||
|                         fromRE = fromParts.fromRE; | ||||
|                         if (rule.pt === 'msg') { | ||||
|                             try { | ||||
|                                 if (rule.t === 'delete') { | ||||
|                                     RED.util.setMessageProperty(msg,property,undefined); | ||||
|                                 } else if (rule.t === 'set') { | ||||
|                                     RED.util.setMessageProperty(msg,property,value); | ||||
|                                 } else if (rule.t === 'change') { | ||||
|                                     current = RED.util.getMessageProperty(msg,property); | ||||
|                                     if (typeof current === 'string') { | ||||
|                                         if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) { | ||||
|                                             // str representation of exact from number/boolean | ||||
|                                             // only replace if they match exactly | ||||
|         function applyRule(msg,rule,done) { | ||||
|             var property = rule.p; | ||||
|             var current; | ||||
|             var fromValue; | ||||
|             var fromType; | ||||
|             var fromRE; | ||||
|  | ||||
|             try { | ||||
|                 getToValue(msg,rule,(err,value) => { | ||||
|                     if (err) { | ||||
|                         node.error(err, msg); | ||||
|                         return done(undefined,null); | ||||
|                     } else { | ||||
|                         getFromValue(msg,rule,(err,fromParts) => { | ||||
|                             if (err) { | ||||
|                                 node.error(err, msg); | ||||
|                                 return done(undefined,null); | ||||
|                             } else { | ||||
|                                 fromValue = fromParts.fromValue; | ||||
|                                 fromType = fromParts.fromType; | ||||
|                                 fromRE = fromParts.fromRE; | ||||
|                                 if (rule.pt === 'msg') { | ||||
|                                     try { | ||||
|                                         if (rule.t === 'delete') { | ||||
|                                             RED.util.setMessageProperty(msg,property,undefined); | ||||
|                                         } else if (rule.t === 'set') { | ||||
|                                             RED.util.setMessageProperty(msg,property,value); | ||||
|                                         } else { | ||||
|                                             current = current.replace(fromRE,value); | ||||
|                                             RED.util.setMessageProperty(msg,property,current); | ||||
|                                         } else if (rule.t === 'change') { | ||||
|                                             current = RED.util.getMessageProperty(msg,property); | ||||
|                                             if (typeof current === 'string') { | ||||
|                                                 if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) { | ||||
|                                                     // str representation of exact from number/boolean | ||||
|                                                     // only replace if they match exactly | ||||
|                                                     RED.util.setMessageProperty(msg,property,value); | ||||
|                                                 } else { | ||||
|                                                     current = current.replace(fromRE,value); | ||||
|                                                     RED.util.setMessageProperty(msg,property,current); | ||||
|                                                 } | ||||
|                                             } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') { | ||||
|                                                 if (current == Number(fromValue)) { | ||||
|                                                     RED.util.setMessageProperty(msg,property,value); | ||||
|                                                 } | ||||
|                                             } else if (typeof current === 'boolean' && fromType === 'bool') { | ||||
|                                                 if (current.toString() === fromValue) { | ||||
|                                                     RED.util.setMessageProperty(msg,property,value); | ||||
|                                                 } | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') { | ||||
|                                         if (current == Number(fromValue)) { | ||||
|                                             RED.util.setMessageProperty(msg,property,value); | ||||
|                                         } | ||||
|                                     } else if (typeof current === 'boolean' && fromType === 'bool') { | ||||
|                                         if (current.toString() === fromValue) { | ||||
|                                             RED.util.setMessageProperty(msg,property,value); | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                             } catch(err) {} | ||||
|                             return msg; | ||||
|                         } else if (rule.pt === 'flow' || rule.pt === 'global') { | ||||
|                             var contextKey = RED.util.parseContextStore(property); | ||||
|                             return new Promise((resolve,reject) => { | ||||
|                                 var target = node.context()[rule.pt]; | ||||
|                                 var callback = err => { | ||||
|                                     if (err) { | ||||
|                                         reject(err); | ||||
|                                     } else { | ||||
|                                         resolve(msg); | ||||
|                                     } | ||||
|                                 } | ||||
|                                 if (rule.t === 'delete') { | ||||
|                                     target.set(contextKey.key,undefined,contextKey.store,callback); | ||||
|                                 } else if (rule.t === 'set') { | ||||
|                                     target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                 } else if (rule.t === 'change') { | ||||
|                                     target.get(contextKey.key,contextKey.store,(err,current) => { | ||||
|                                     } catch(err) {} | ||||
|                                     return done(undefined,msg); | ||||
|                                 } else if (rule.pt === 'flow' || rule.pt === 'global') { | ||||
|                                     var contextKey = RED.util.parseContextStore(property); | ||||
|                                     var target = node.context()[rule.pt]; | ||||
|                                     var callback = err => { | ||||
|                                         if (err) { | ||||
|                                             reject(err); | ||||
|                                             return; | ||||
|                                             node.error(err, msg); | ||||
|                                             return done(undefined,null); | ||||
|                                         } else { | ||||
|                                             done(undefined,msg); | ||||
|                                         } | ||||
|                                         if (typeof current === 'string') { | ||||
|                                             if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) { | ||||
|                                                 // str representation of exact from number/boolean | ||||
|                                                 // only replace if they match exactly | ||||
|                                                 target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                             } else { | ||||
|                                                 current = current.replace(fromRE,value); | ||||
|                                                 target.set(contextKey.key,current,contextKey.store,callback); | ||||
|                                     } | ||||
|                                     if (rule.t === 'delete') { | ||||
|                                         target.set(contextKey.key,undefined,contextKey.store,callback); | ||||
|                                     } else if (rule.t === 'set') { | ||||
|                                         target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                     } else if (rule.t === 'change') { | ||||
|                                         target.get(contextKey.key,contextKey.store,(err,current) => { | ||||
|                                             if (err) { | ||||
|                                                 node.error(err, msg); | ||||
|                                                 return done(undefined,null); | ||||
|                                             } | ||||
|                                         } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') { | ||||
|                                             if (current == Number(fromValue)) { | ||||
|                                                 target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                             if (typeof current === 'string') { | ||||
|                                                 if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) { | ||||
|                                                     // str representation of exact from number/boolean | ||||
|                                                     // only replace if they match exactly | ||||
|                                                     target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                                 } else { | ||||
|                                                     current = current.replace(fromRE,value); | ||||
|                                                     target.set(contextKey.key,current,contextKey.store,callback); | ||||
|                                                 } | ||||
|                                             } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') { | ||||
|                                                 if (current == Number(fromValue)) { | ||||
|                                                     target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                                 } | ||||
|                                             } else if (typeof current === 'boolean' && fromType === 'bool') { | ||||
|                                                 if (current.toString() === fromValue) { | ||||
|                                                     target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                                 } | ||||
|                                             } | ||||
|                                         } else if (typeof current === 'boolean' && fromType === 'bool') { | ||||
|                                             if (current.toString() === fromValue) { | ||||
|                                                 target.set(contextKey.key,value,contextKey.store,callback); | ||||
|                                             } | ||||
|                                         } | ||||
|                                     }); | ||||
|                                         }); | ||||
|                                     } | ||||
|                                 } | ||||
|                             }); | ||||
|                         } | ||||
|                     }); | ||||
|                 }).catch(err => { | ||||
|                     node.error(err, msg); | ||||
|                     return null; | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                 }); | ||||
|             } catch(err) { | ||||
|                 return Promise.resolve(msg); | ||||
|                 // This is an okay error | ||||
|                 done(undefined,msg); | ||||
|             } | ||||
|         } | ||||
|         function applyRules(msg, currentRule) { | ||||
|         function completeApplyingRules(msg,currentRule,done) { | ||||
|             if (!msg) { | ||||
|                 return done(); | ||||
|             } else if (currentRule === node.rules.length - 1) { | ||||
|                 return done(undefined, msg); | ||||
|             } else { | ||||
|                 applyRules(msg, currentRule+1,done); | ||||
|             } | ||||
|         } | ||||
|         function applyRules(msg, currentRule, done) { | ||||
|             if (currentRule >= node.rules.length) { | ||||
|                 return Promise.resolve(msg); | ||||
|                 return done(undefined,msg); | ||||
|             } | ||||
|             var r = node.rules[currentRule]; | ||||
|             var rulePromise; | ||||
|             if (r.t === "move") { | ||||
|                 if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) { | ||||
|                     rulePromise = applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt}).then( | ||||
|                         msg => applyRule(msg,{t:"delete", p:r.p, pt:r.pt}) | ||||
|                     ); | ||||
|                 } | ||||
|                 else { // 2 step move if we are moving from a child | ||||
|                     rulePromise = applyRule(msg,{t:"set", p:"_temp_move", pt:r.tot, to:r.p, tot:r.pt}).then( | ||||
|                         msg => applyRule(msg,{t:"delete", p:r.p, pt:r.pt}) | ||||
|                     ).then( | ||||
|                         msg => applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:"_temp_move", tot:r.pt}) | ||||
|                     ).then( | ||||
|                         msg => applyRule(msg,{t:"delete", p:"_temp_move", pt:r.pt}) | ||||
|                     ) | ||||
|                     applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => { | ||||
|                         applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => { | ||||
|                             completeApplyingRules(msg,currentRule,done); | ||||
|                         }) | ||||
|                     }); | ||||
|                 } else { // 2 step move if we are moving from a child | ||||
|                     applyRule(msg,{t:"set", p:"_temp_move", pt:r.tot, to:r.p, tot:r.pt},(err,msg)=> { | ||||
|                         applyRule(msg,{t:"delete", p:r.p, pt:r.pt},(err,msg)=> { | ||||
|                             applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:"_temp_move", tot:r.pt},(err,msg)=> { | ||||
|                                 applyRule(msg,{t:"delete", p:"_temp_move", pt:r.pt},(err,msg)=> { | ||||
|                                     completeApplyingRules(msg,currentRule,done); | ||||
|                                 }); | ||||
|                             }); | ||||
|                         }); | ||||
|                     }); | ||||
|                 } | ||||
|             } else { | ||||
|                 rulePromise = applyRule(msg,r); | ||||
|                 applyRule(msg,r,(err,msg)=> { completeApplyingRules(msg,currentRule,done); }); | ||||
|             } | ||||
|             return rulePromise.then( | ||||
|                 msg => { | ||||
|                     if (!msg) { | ||||
|                         return | ||||
|                     } else if (currentRule === node.rules.length - 1) { | ||||
|                         return msg; | ||||
|                     } else { | ||||
|                         return applyRules(msg, currentRule+1); | ||||
|                     } | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         if (valid) { | ||||
|             this.on('input', function(msg) { | ||||
|                 applyRules(msg, 0) | ||||
|                     .then( msg => { if (msg) { node.send(msg) }} ) | ||||
|                     .catch( err => node.error(err, msg)) | ||||
|                 applyRules(msg, 0, (err,msg) => { | ||||
|                     if (err) { | ||||
|                         node.error(err,msg); | ||||
|                     } else if (msg) { | ||||
|                         node.send(msg); | ||||
|                     } | ||||
|                 }) | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user