1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add jsonata support to Change/Switch nodes

This commit is contained in:
Nick O'Leary 2016-11-10 23:58:34 +00:00
parent 89a05c580f
commit bf90509526
12 changed files with 2884 additions and 8 deletions

View File

@ -160,7 +160,8 @@ module.exports = function(grunt) {
build: { build: {
files: { files: {
'public/red/red.min.js': 'public/red/red.js', 'public/red/red.min.js': 'public/red/red.js',
'public/red/main.min.js': 'public/red/main.js' 'public/red/main.min.js': 'public/red/main.js',
'public/vendor/jsonata/jsonata.min.js': 'editor/vendor/jsonata/jsonata.js'
} }
} }
}, },

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

View File

@ -94,7 +94,8 @@
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.png",options:["true","false"]}, bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.png",options:["true","false"]},
json: {value:"json",label:"JSON",icon:"red/images/typedInput/json.png", validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}}}, json: {value:"json",label:"JSON",icon:"red/images/typedInput/json.png", validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}}},
re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.png"}, re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.png"},
date: {value:"date",label:"timestamp",hasValue:false} date: {value:"date",label:"timestamp",hasValue:false},
jsonata: {value:"jsonata",label:"expression",icon:"red/images/typedInput/expr.png", validate: function(v) { try{jsonata(v);return true;}catch(e){return false;}}},
}; };
var nlsd = false; var nlsd = false;

View File

@ -160,6 +160,7 @@
</script> </script>
<script src="vendor/vendor.js"></script> <script src="vendor/vendor.js"></script>
<script src="vendor/jsonata/jsonata.min.js"></script>
<script src="vendor/ace/ace.js"></script> <script src="vendor/ace/ace.js"></script>
<script src="vendor/ace/ext-language_tools.js"></script> <script src="vendor/ace/ext-language_tools.js"></script>
<script src="{{ asset.red }}"></script> <script src="{{ asset.red }}"></script>

2805
editor/vendor/jsonata/jsonata.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -502,6 +502,9 @@
"null":"is null", "null":"is null",
"nnull":"is not null", "nnull":"is not null",
"else":"otherwise" "else":"otherwise"
},
"errors": {
"invalid-expr": "Invalid expression: __error__"
} }
}, },
"change": { "change": {

View File

@ -64,7 +64,7 @@
var node = this; var node = this;
var previousValueType = {value:"prev",label:this._("inject.previous"),hasValue:false}; var previousValueType = {value:"prev",label:this._("inject.previous"),hasValue:false};
$("#node-input-property").typedInput({default:this.propertyType||'msg',types:['msg','flow','global']}); $("#node-input-property").typedInput({default:this.propertyType||'msg',types:['msg','flow','global','jsonata']});
var operators = [ var operators = [
{v:"eq",t:"=="}, {v:"eq",t:"=="},
{v:"neq",t:"!="}, {v:"neq",t:"!="},
@ -129,10 +129,10 @@
for (var d in operators) { for (var d in operators) {
selectField.append($("<option></option>").val(operators[d].v).text(operators[d].t)); selectField.append($("<option></option>").val(operators[d].v).text(operators[d].t));
} }
var valueField = $('<input/>',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'str',types:['msg','flow','global','str','num',previousValueType]}); var valueField = $('<input/>',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'str',types:['msg','flow','global','str','num','jsonata',previousValueType]});
var btwnValueField = $('<input/>',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['msg','flow','global','str','num',previousValueType]}); var btwnValueField = $('<input/>',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata',previousValueType]});
var btwnAndLabel = $('<span/>',{class:"node-input-rule-btwn-label"}).text(" "+andLabel+" ").appendTo(row3); var btwnAndLabel = $('<span/>',{class:"node-input-rule-btwn-label"}).text(" "+andLabel+" ").appendTo(row3);
var btwnValue2Field = $('<input/>',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).typedInput({default:'num',types:['msg','flow','global','str','num',previousValueType]}); var btwnValue2Field = $('<input/>',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata',previousValueType]});
var finalspan = $('<span/>',{style:"float: right;margin-top: 6px;"}).appendTo(row); var finalspan = $('<span/>',{style:"float: right;margin-top: 6px;"}).appendTo(row);
finalspan.append(' &#8594; <span class="node-input-rule-index">'+(i+1)+'</span> '); finalspan.append(' &#8594; <span class="node-input-rule-index">'+(i+1)+'</span> ');
var caseSensitive = $('<input/>',{id:"node-input-rule-case-"+i,class:"node-input-rule-case",type:"checkbox",style:"width:auto;vertical-align:top"}).appendTo(row2); var caseSensitive = $('<input/>',{id:"node-input-rule-case-"+i,class:"node-input-rule-case",type:"checkbox",style:"width:auto;vertical-align:top"}).appendTo(row2);

View File

@ -16,6 +16,9 @@
module.exports = function(RED) { module.exports = function(RED) {
"use strict"; "use strict";
var jsonata = require('jsonata');
var operators = { var operators = {
'eq': function(a, b) { return a == b; }, 'eq': function(a, b) { return a == b; },
'neq': function(a, b) { return a != b; }, 'neq': function(a, b) { return a != b; },
@ -38,9 +41,20 @@ module.exports = function(RED) {
this.rules = n.rules || []; this.rules = n.rules || [];
this.property = n.property; this.property = n.property;
this.propertyType = n.propertyType || "msg"; this.propertyType = n.propertyType || "msg";
if (this.propertyType === 'jsonata') {
try {
this.property = jsonata(this.property);
} catch(err) {
this.error(RED._("switch.errors.invalid-expr",{error:err.message}));
return;
}
}
this.checkall = n.checkall || "true"; this.checkall = n.checkall || "true";
this.previousValue = null; this.previousValue = null;
var node = this; var node = this;
var valid = true;
for (var i=0; i<this.rules.length; i+=1) { for (var i=0; i<this.rules.length; i+=1) {
var rule = this.rules[i]; var rule = this.rules[i];
if (!rule.vt) { if (!rule.vt) {
@ -54,6 +68,13 @@ module.exports = function(RED) {
if (!isNaN(Number(rule.v))) { if (!isNaN(Number(rule.v))) {
rule.v = Number(rule.v); rule.v = Number(rule.v);
} }
} else if (rule.vt === "jsonata") {
try {
rule.v = jsonata(rule.v);
} catch(err) {
this.error(RED._("switch.errors.invalid-expr",{error:err.message}));
valid = false;
}
} }
if (typeof rule.v2 !== 'undefined') { if (typeof rule.v2 !== 'undefined') {
if (!rule.v2t) { if (!rule.v2t) {
@ -65,14 +86,30 @@ module.exports = function(RED) {
} }
if (rule.v2t === 'num') { if (rule.v2t === 'num') {
rule.v2 = Number(rule.v2); rule.v2 = Number(rule.v2);
} else if (rule.v2t === 'jsonata') {
try {
rule.v2 = jsonata(rule.v2);
} catch(err) {
this.error(RED._("switch.errors.invalid-expr",{error:err.message}));
valid = false;
}
} }
} }
} }
if (!valid) {
return;
}
this.on('input', function (msg) { this.on('input', function (msg) {
var onward = []; var onward = [];
try { try {
var prop = RED.util.evaluateNodeProperty(node.property,node.propertyType,node,msg); var prop;
if (node.propertyType === 'jsonata') {
prop = node.property.evaluate({msg:msg});
} else {
prop = RED.util.evaluateNodeProperty(node.property,node.propertyType,node,msg);
}
var elseflag = true; var elseflag = true;
for (var i=0; i<node.rules.length; i+=1) { for (var i=0; i<node.rules.length; i+=1) {
var rule = node.rules[i]; var rule = node.rules[i];
@ -80,12 +117,26 @@ module.exports = function(RED) {
var v1,v2; var v1,v2;
if (rule.vt === 'prev') { if (rule.vt === 'prev') {
v1 = node.previousValue; v1 = node.previousValue;
} else if (rule.vt === 'jsonata') {
try {
v1 = rule.v.evaluate({msg:msg});
} catch(err) {
node.error(RED._("switch.errors.invalid-expr",{error:err.message}));
return;
}
} else { } else {
v1 = RED.util.evaluateNodeProperty(rule.v,rule.vt,node,msg); v1 = RED.util.evaluateNodeProperty(rule.v,rule.vt,node,msg);
} }
v2 = rule.v2; v2 = rule.v2;
if (rule.v2t === 'prev') { if (rule.v2t === 'prev') {
v2 = node.previousValue; v2 = node.previousValue;
} else if (rule.v2t === 'jsonata') {
try {
v2 = rule.v2.evaluate({msg:msg});
} catch(err) {
node.error(RED._("switch.errors.invalid-expr",{error:err.message}));
return;
}
} else if (typeof v2 !== 'undefined') { } else if (typeof v2 !== 'undefined') {
v2 = RED.util.evaluateNodeProperty(rule.v2,rule.v2t,node,msg); v2 = RED.util.evaluateNodeProperty(rule.v2,rule.v2t,node,msg);
} }

View File

@ -150,7 +150,7 @@
.appendTo(row2); .appendTo(row2);
var propertyValue = $('<input/>',{class:"node-input-rule-property-value",type:"text"}) var propertyValue = $('<input/>',{class:"node-input-rule-property-value",type:"text"})
.appendTo(row2) .appendTo(row2)
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','date']}); .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','date','jsonata']});
var row3_1 = $('<div/>').appendTo(row3); var row3_1 = $('<div/>').appendTo(row3);
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"}) $('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})

View File

@ -16,6 +16,7 @@
module.exports = function(RED) { module.exports = function(RED) {
"use strict"; "use strict";
var jsonata = require("jsonata");
function ChangeNode(n) { function ChangeNode(n) {
RED.nodes.createNode(this, n); RED.nodes.createNode(this, n);
@ -85,6 +86,13 @@ module.exports = function(RED) {
} }
} else if (rule.tot === 'bool') { } else if (rule.tot === 'bool') {
rule.to = /^true$/i.test(rule.to); rule.to = /^true$/i.test(rule.to);
} else if (rule.tot === 'jsonata') {
try {
rule.to = jsonata(rule.to);
} catch(e) {
valid = false;
this.error(RED._("change.errors.invalid-from",{error:e.message}));
}
} }
} }
@ -107,6 +115,8 @@ module.exports = function(RED) {
value = node.context().global.get(rule.to); value = node.context().global.get(rule.to);
} else if (rule.tot === 'date') { } else if (rule.tot === 'date') {
value = Date.now(); value = Date.now();
} else if (rule.tot === 'jsonata') {
value = rule.to.evaluate({msg:msg});
} }
if (rule.t === 'change') { if (rule.t === 'change') {
if (rule.fromt === 'msg' || rule.fromt === 'flow' || rule.fromt === 'global') { if (rule.fromt === 'msg' || rule.fromt === 'flow' || rule.fromt === 'global') {

View File

@ -40,6 +40,7 @@
"fs.notify":"0.0.4", "fs.notify":"0.0.4",
"i18next":"1.10.6", "i18next":"1.10.6",
"is-utf8":"0.2.1", "is-utf8":"0.2.1",
"jsonata":"1.0.7",
"media-typer": "0.3.0", "media-typer": "0.3.0",
"mqtt": "1.14.1", "mqtt": "1.14.1",
"mustache": "2.2.1", "mustache": "2.2.1",

View File

@ -15,6 +15,7 @@
**/ **/
var clone = require("clone"); var clone = require("clone");
var jsonata = require("jsonata");
function generateId() { function generateId() {
return (1+Math.random()*4294967295).toString(16); return (1+Math.random()*4294967295).toString(16);
@ -310,6 +311,8 @@ function evaluateNodeProperty(value, type, node, msg) {
return node.context().global.get(value); return node.context().global.get(value);
} else if (type === 'bool') { } else if (type === 'bool') {
return /^true$/i.test(value); return /^true$/i.test(value);
} else if (type === 'jsonata') {
return jsonata(value).evaluate({msg:msg});
} }
return value; return value;
} }