mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add JSONata expr tester and improved feedback
This commit is contained in:
parent
b030e935ce
commit
dbf0486acb
@ -124,6 +124,7 @@ module.exports = function(grunt) {
|
||||
"editor/js/ui/utils.js",
|
||||
"editor/js/ui/common/editableList.js",
|
||||
"editor/js/ui/common/menu.js",
|
||||
"editor/js/ui/common/panels.js",
|
||||
"editor/js/ui/common/popover.js",
|
||||
"editor/js/ui/common/searchBox.js",
|
||||
"editor/js/ui/common/tabs.js",
|
||||
|
83
editor/js/ui/common/panels.js
Normal file
83
editor/js/ui/common/panels.js
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* 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.
|
||||
**/
|
||||
|
||||
|
||||
RED.panels = (function() {
|
||||
|
||||
function createPanel(options) {
|
||||
var container = options.container || $("#"+options.id);
|
||||
var children = container.children();
|
||||
if (children.length !== 2) {
|
||||
throw new Error("Container must have exactly two children");
|
||||
}
|
||||
|
||||
container.addClass("red-ui-panels");
|
||||
var separator = $('<div class="red-ui-panels-separator"></div>').insertAfter(children[0]);
|
||||
var startPosition;
|
||||
var panelHeights = [];
|
||||
var modifiedHeights = false;
|
||||
var panelRatio;
|
||||
|
||||
separator.draggable({
|
||||
axis: "y",
|
||||
containment: container,
|
||||
scroll: false,
|
||||
start:function(event,ui) {
|
||||
var height = container.height();
|
||||
startPosition = ui.position.top;
|
||||
panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
console.log("START",height,panelHeights,panelHeights[0]+panelHeights[1],height-(panelHeights[0]+panelHeights[1]));
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
var height = container.height();
|
||||
var delta = ui.position.top-startPosition;
|
||||
var newHeights = [panelHeights[0]+delta,panelHeights[1]-delta];
|
||||
$(children[0]).height(newHeights[0]);
|
||||
$(children[1]).height(newHeights[1]);
|
||||
if (options.resize) {
|
||||
options.resize(newHeights[0],newHeights[1]);
|
||||
}
|
||||
ui.position.top -= delta;
|
||||
panelRatio = newHeights[0]/height;
|
||||
},
|
||||
stop:function(event,ui) {
|
||||
modifiedHeights = true;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
resize: function(height) {
|
||||
var panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
container.height(height);
|
||||
if (modifiedHeights) {
|
||||
var topPanelHeight = panelRatio*height;
|
||||
var bottomPanelHeight = height - topPanelHeight - 48;
|
||||
panelHeights = [topPanelHeight,bottomPanelHeight];
|
||||
$(children[0]).height(panelHeights[0]);
|
||||
$(children[1]).height(panelHeights[1]);
|
||||
console.log("SET",height,panelHeights,panelHeights[0]+panelHeights[1],height-(panelHeights[0]+panelHeights[1]));
|
||||
}
|
||||
if (options.resize) {
|
||||
options.resize(panelHeights[0],panelHeights[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createPanel
|
||||
}
|
||||
})();
|
@ -1598,6 +1598,9 @@ RED.editor = (function() {
|
||||
editStack.push({type:type});
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var testDataEditor;
|
||||
var testResultEditor
|
||||
var panels;
|
||||
|
||||
var trayOptions = {
|
||||
title: getEditStackTitle(),
|
||||
@ -1621,20 +1624,18 @@ RED.editor = (function() {
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
editTrayWidthCache[type] = dimensions.width;
|
||||
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
if (dimensions) {
|
||||
editTrayWidthCache[type] = dimensions.width;
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
var height = $("#dialog-form").height();
|
||||
if (panels) {
|
||||
panels.resize(height);
|
||||
}
|
||||
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
trayBody.addClass("node-input-expression-editor")
|
||||
var dialogForm = buildEditForm(tray.find('.editor-tray-body'),'dialog-form','_expression','editor');
|
||||
var funcSelect = $("#node-input-expression-func");
|
||||
Object.keys(jsonata.functions).forEach(function(f) {
|
||||
@ -1749,6 +1750,118 @@ RED.editor = (function() {
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
|
||||
var tabs = RED.tabs.create({
|
||||
element: $("#node-input-expression-tabs"),
|
||||
onchange:function(tab) {
|
||||
$(".node-input-expression-tab-content").hide();
|
||||
tab.content.show();
|
||||
trayOptions.resize();
|
||||
}
|
||||
})
|
||||
|
||||
tabs.addTab({
|
||||
id: 'expression-help',
|
||||
label: 'Function reference',
|
||||
content: $("#node-input-expression-tab-help")
|
||||
});
|
||||
tabs.addTab({
|
||||
id: 'expression-tests',
|
||||
label: 'Test',
|
||||
content: $("#node-input-expression-tab-test")
|
||||
});
|
||||
testDataEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-data',
|
||||
value: '{\n "payload": "hello world"\n}',
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false
|
||||
});
|
||||
var changeTimer;
|
||||
$(".node-input-expression-legacy").click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("expressionEditor.compatModeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
})
|
||||
var testExpression = function() {
|
||||
var value = testDataEditor.getValue();
|
||||
var parsedData;
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var legacyMode = false;
|
||||
try {
|
||||
expr = jsonata(currentExpression);
|
||||
expr.assign('flow',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign('global',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue("Invalid jsonata expression:\n "+err.message);
|
||||
return;
|
||||
}
|
||||
$(".node-input-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
parsedData = JSON.parse(value);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue("Invalid example message:\n "+err.toString())
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var result = expr.evaluate(legacyMode?{msg:parsedData}:parsedData);
|
||||
if (usesContext) {
|
||||
testResultEditor.setValue("Cannot test a function that uses context values");
|
||||
return;
|
||||
}
|
||||
var formattedResult = JSON.stringify(result,null,4);
|
||||
testResultEditor.setValue(formattedResult || "No match");
|
||||
} catch(err) {
|
||||
testResultEditor.setValue("Error evaluating expression:\n "+err.message);
|
||||
}
|
||||
}
|
||||
|
||||
testDataEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
});
|
||||
expressionEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
});
|
||||
|
||||
testResultEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-result',
|
||||
value: "",
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false,
|
||||
readOnly: true
|
||||
});
|
||||
panels = RED.panels.create({
|
||||
id:"node-input-expression-panels",
|
||||
resize: function(p1Height,p2Height) {
|
||||
var p1 = $("#node-input-expression-panel-expr");
|
||||
p1Height -= $(p1.children()[0]).outerHeight(true);
|
||||
var editorRow = $(p1.children()[1]);
|
||||
p1Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-expression").css("height",(p1Height-5)+"px");
|
||||
expressionEditor.resize();
|
||||
|
||||
var p2 = $("#node-input-expression-panel-info > .form-row > div:first-child");
|
||||
p2Height -= p2.outerHeight(true) + 20;
|
||||
$(".node-input-expression-tab-content").height(p2Height);
|
||||
$("#node-input-expression-test-data").css("height",(p2Height-5)+"px");
|
||||
testDataEditor.resize();
|
||||
$("#node-input-expression-test-result").css("height",(p2Height-5)+"px");
|
||||
testResultEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
testExpression();
|
||||
},
|
||||
close: function() {
|
||||
editStack.pop();
|
||||
@ -1855,6 +1968,7 @@ RED.editor = (function() {
|
||||
validateNode: validateNode,
|
||||
updateNodeProperties: updateNodeProperties, // TODO: only exposed for edit-undo
|
||||
|
||||
|
||||
createEditor: function(options) {
|
||||
var editor = ace.edit(options.id);
|
||||
editor.setTheme("ace/theme/tomorrow");
|
||||
@ -1875,6 +1989,12 @@ RED.editor = (function() {
|
||||
enableSnippets:true
|
||||
});
|
||||
}
|
||||
if (options.readOnly) {
|
||||
editor.setOption('readOnly',options.readOnly);
|
||||
}
|
||||
if (options.hasOwnProperty('lineNumbers')) {
|
||||
editor.renderer.setOption('showGutter',options.lineNumbers);
|
||||
}
|
||||
editor.$blockScrolling = Infinity;
|
||||
if (options.value) {
|
||||
session.setValue(options.value,-1);
|
||||
|
@ -350,7 +350,8 @@ RED.sidebar.info = (function() {
|
||||
// tips.stop();
|
||||
sections.show();
|
||||
nodeSection.container.hide();
|
||||
$(infoSection.content).html(html);
|
||||
var wrapped = $('<div class="node-help"></div>').html(html);
|
||||
$(infoSection.content).empty().append(wrapped);
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,8 +48,10 @@
|
||||
.editor-tray-body {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
form {
|
||||
padding: 0.1px; // prevent margin collapsing
|
||||
.dialog-form,#dialog-form, #dialog-config-form {
|
||||
margin: 20px;
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
}
|
||||
.editor-tray-content {
|
||||
@ -154,7 +156,7 @@
|
||||
|
||||
|
||||
.dialog-form,#dialog-form, #dialog-config-form {
|
||||
height: calc(100% - 20px);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.input-error {
|
||||
@ -245,3 +247,48 @@
|
||||
font-size: 12px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.node-input-expression-editor #dialog-form {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
.red-ui-panel {
|
||||
&:first-child {
|
||||
padding: 20px 20px 0;
|
||||
}
|
||||
&:last-child {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-input-expression-tab-content {
|
||||
position: relative;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
#node-input-expression-help {
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
left:0;
|
||||
right: 0;
|
||||
bottom:0;
|
||||
padding: 0 20px;
|
||||
overflow: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#node-input-expression-panel-info {
|
||||
& > .form-row {
|
||||
margin: 0;
|
||||
& > div:first-child {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-input-expression-legacy {
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
border: 1px solid white;
|
||||
padding: 0 5px;
|
||||
border-radius: 2px;
|
||||
&:hover {
|
||||
border-color: $primary-border-color;
|
||||
}
|
||||
}
|
||||
|
23
editor/sass/panels.scss
Normal file
23
editor/sass/panels.scss
Normal file
@ -0,0 +1,23 @@
|
||||
.red-ui-panels {
|
||||
position: relative;
|
||||
|
||||
& > div {
|
||||
// border: 1px solid red;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.red-ui-panels-separator {
|
||||
border-top: 1px solid $secondary-border-color;
|
||||
border-bottom: 1px solid $secondary-border-color;
|
||||
height: 7px;
|
||||
box-sizing: border-box;
|
||||
cursor: ns-resize;
|
||||
background: $background-color url(images/grip.png) no-repeat 50% 50%;
|
||||
}
|
||||
|
||||
|
||||
.red-ui-panel {
|
||||
overflow: auto;
|
||||
height: calc(50% - 4px);
|
||||
}
|
@ -37,6 +37,7 @@
|
||||
@import "library";
|
||||
@import "search";
|
||||
|
||||
@import "panels";
|
||||
@import "tabs";
|
||||
@import "tab-config";
|
||||
@import "tab-info";
|
||||
|
@ -166,22 +166,41 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="_expression">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<button id="node-input-expression-reformat" class="editor-button editor-button-small">format</button>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-expression"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-expression-func" data-i18n="expressionEditor.functions"></label>
|
||||
<select id="node-input-expression-func"></select>
|
||||
<button id="node-input-expression-func-insert" class="editor-button" data-i18n="expressionEditor.insert"></button>
|
||||
<div style="min-height: 200px;" id="node-input-expression-help"></div>
|
||||
<div id="node-input-expression-panels">
|
||||
<div id="node-input-expression-panel-expr" class="red-ui-panel">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<span class="node-input-expression-legacy"><i class="fa fa-exclamation-circle"></i> <span data-i18n="expressionEditor.compatMode"></span></span>
|
||||
<button id="node-input-expression-reformat" class="editor-button editor-button-small"><span data-i18n="expressionEditor.format"></span></button>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div class="node-text-editor" id="node-input-expression"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="node-input-expression-panel-info" class="red-ui-panel">
|
||||
<div class="form-row">
|
||||
<ul id="node-input-expression-tabs"></ul>
|
||||
<div id="node-input-expression-tab-help" class="node-input-expression-tab-content hide">
|
||||
<div>
|
||||
<select id="node-input-expression-func"></select>
|
||||
<button id="node-input-expression-func-insert" class="editor-button" data-i18n="expressionEditor.insert"></button>
|
||||
</div>
|
||||
<div id="node-input-expression-help"></div>
|
||||
</div>
|
||||
<div id="node-input-expression-tab-test" class="node-input-expression-tab-content hide">
|
||||
<div>
|
||||
<span style="display: inline-block; width: calc(50% - 5px);" data-i18n="expressionEditor.data"></span>
|
||||
<span style="display: inline-block; width: calc(50% - 5px);" data-i18n="expressionEditor.result"></span>
|
||||
</div>
|
||||
<div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-data"></div>
|
||||
<div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-result"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/x-red" data-template-name="_json">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<button id="node-input-expression-reformat" class="editor-button editor-button-small">format</button>
|
||||
<button id="node-input-expression-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>
|
||||
|
5
editor/vendor/jsonata/formatter.js
vendored
5
editor/vendor/jsonata/formatter.js
vendored
@ -111,11 +111,10 @@
|
||||
'$average':{ args:['value'] },
|
||||
'$boolean':{ args:['value'] },
|
||||
'$contains':{ args:['str','pattern']},
|
||||
'$context': {args:['string']},
|
||||
'$count':{ args:['array'] },
|
||||
'$exists':{ args:['value'] },
|
||||
'$flow': {args:['string']},
|
||||
'$global': {args:['string']},
|
||||
'$flowContext': {args:['string']},
|
||||
'$globalContext': {args:['string']},
|
||||
'$join':{ args:['array','separator'] },
|
||||
'$keys':{ args:['object'] },
|
||||
'$length':{ args:['string'] },
|
||||
|
@ -519,7 +519,7 @@
|
||||
"else":"otherwise"
|
||||
},
|
||||
"errors": {
|
||||
"invalid-expr": "Invalid expression: __error__"
|
||||
"invalid-expr": "Invalid JSONata expression: __error__"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
@ -544,7 +544,8 @@
|
||||
},
|
||||
"errors": {
|
||||
"invalid-from": "Invalid 'from' property: __error__",
|
||||
"invalid-json": "Invalid 'to' JSON property"
|
||||
"invalid-json": "Invalid 'to' JSON property",
|
||||
"invalid-expr": "Invalid JSONata expression: __error__"
|
||||
}
|
||||
},
|
||||
"range": {
|
||||
|
@ -104,7 +104,7 @@ module.exports = function(RED) {
|
||||
try {
|
||||
var prop;
|
||||
if (node.propertyType === 'jsonata') {
|
||||
prop = node.property.evaluate({msg:msg});
|
||||
prop = RED.util.evaluateJSONataExpression(node.property,msg);
|
||||
} else {
|
||||
prop = RED.util.evaluateNodeProperty(node.property,node.propertyType,node,msg);
|
||||
}
|
||||
@ -117,7 +117,7 @@ module.exports = function(RED) {
|
||||
v1 = node.previousValue;
|
||||
} else if (rule.vt === 'jsonata') {
|
||||
try {
|
||||
v1 = rule.v.evaluate({msg:msg});
|
||||
v1 = RED.util.evaluateJSONataExpression(rule.v,msg);
|
||||
} catch(err) {
|
||||
node.error(RED._("switch.errors.invalid-expr",{error:err.message}));
|
||||
return;
|
||||
@ -134,7 +134,7 @@ module.exports = function(RED) {
|
||||
v2 = node.previousValue;
|
||||
} else if (rule.v2t === 'jsonata') {
|
||||
try {
|
||||
v2 = rule.v2.evaluate({msg:msg});
|
||||
v2 = RED.util.evaluateJSONataExpression(rule.v2,msg);
|
||||
} catch(err) {
|
||||
node.error(RED._("switch.errors.invalid-expr",{error:err.message}));
|
||||
return;
|
||||
|
@ -19,6 +19,7 @@ module.exports = function(RED) {
|
||||
|
||||
function ChangeNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
var node = this;
|
||||
|
||||
this.rules = n.rules;
|
||||
var rule;
|
||||
@ -90,7 +91,7 @@ module.exports = function(RED) {
|
||||
rule.to = RED.util.prepareJSONataExpression(rule.to,this);
|
||||
} catch(e) {
|
||||
valid = false;
|
||||
this.error(RED._("change.errors.invalid-from",{error:e.message}));
|
||||
this.error(RED._("change.errors.invalid-expr",{error:e.message}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,7 +116,12 @@ module.exports = function(RED) {
|
||||
} else if (rule.tot === 'date') {
|
||||
value = Date.now();
|
||||
} else if (rule.tot === 'jsonata') {
|
||||
value = rule.to.evaluate({msg:msg});
|
||||
try{
|
||||
value = RED.util.evaluateJSONataExpression(rule.to,msg);
|
||||
} catch(err) {
|
||||
node.error(RED._("change.errors.invalid-expr",{error:err.message}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (rule.t === 'change') {
|
||||
if (rule.fromt === 'msg' || rule.fromt === 'flow' || rule.fromt === 'global') {
|
||||
@ -219,7 +225,6 @@ module.exports = function(RED) {
|
||||
return msg;
|
||||
}
|
||||
if (valid) {
|
||||
var node = this;
|
||||
this.on('input', function(msg) {
|
||||
for (var i=0; i<this.rules.length; i++) {
|
||||
if (this.rules[i].t === "move") {
|
||||
|
@ -398,9 +398,15 @@
|
||||
"expressionEditor": {
|
||||
"functions": "Functions",
|
||||
"insert": "Insert",
|
||||
"title": "JSONata Expression editor"
|
||||
"title": "JSONata Expression editor",
|
||||
"data": "Example message",
|
||||
"result": "Result",
|
||||
"format": "format expression",
|
||||
"compatMode": "Compatibility mode enabled",
|
||||
"compatModeDesc": "<h3>JSONata compatibility mode</h3><p> The current expression appears to still reference <code>msg</code> so will be evaluated in compatibility mode. Please update the expression to not use <code>msg</code> as this mode will be removed in the future.</p><p> When JSONata support was first added to Node-RED, it required the expression to reference the <code>msg</code> object. For example <code>msg.payload</code> would be used to access the payload.</p><p> That is no longer necessary as the expression will be evaluated against the message directly. To access the payload, the expression should be just <code>payload</code>.</p>"
|
||||
},
|
||||
"jsonEditor": {
|
||||
"title": "JSON editor"
|
||||
"title": "JSON editor",
|
||||
"format": "format JSON"
|
||||
}
|
||||
}
|
||||
|
@ -110,16 +110,11 @@
|
||||
"args": "object",
|
||||
"desc": "Splits an object containing key/value pairs into an array of objects, each of which has a single key/value pair from the input object. If the parameter is an array of objects, then the resultant array contains an object for every key/value pair in every object in the supplied array."
|
||||
},
|
||||
|
||||
"$context": {
|
||||
"args": "string",
|
||||
"desc": "Retrieves a node context property."
|
||||
},
|
||||
"$flow": {
|
||||
"$flowContext": {
|
||||
"args": "string",
|
||||
"desc": "Retrieves a flow context property."
|
||||
},
|
||||
"$global": {
|
||||
"$globalContext": {
|
||||
"args": "string",
|
||||
"desc": "Retrieves a global context property."
|
||||
}
|
||||
|
@ -323,25 +323,33 @@ function evaluateNodeProperty(value, type, node, msg) {
|
||||
} else if (type === 'bool') {
|
||||
return /^true$/i.test(value);
|
||||
} else if (type === 'jsonata') {
|
||||
return prepareJSONataExpression(value,node).evaluate({msg:msg});
|
||||
var expr = prepareJSONataExpression(value,node);
|
||||
return evaluateJSONataExpression(expr,msg);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function prepareJSONataExpression(value,node) {
|
||||
var expr = jsonata(value);
|
||||
expr.assign('context',function(val) {
|
||||
return node.context().get(val);
|
||||
});
|
||||
expr.assign('flow',function(val) {
|
||||
expr.assign('flowContext',function(val) {
|
||||
return node.context().flow.get(val);
|
||||
});
|
||||
expr.assign('global',function(val) {
|
||||
expr.assign('globalContext',function(val) {
|
||||
return node.context().global(val);
|
||||
});
|
||||
expr._legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(value);
|
||||
return expr;
|
||||
}
|
||||
|
||||
function evaluateJSONataExpression(expr,msg) {
|
||||
var context = msg;
|
||||
if (expr._legacyMode) {
|
||||
context = {msg:msg};
|
||||
}
|
||||
return expr.evaluate(context);
|
||||
}
|
||||
|
||||
|
||||
function normaliseNodeTypeName(name) {
|
||||
var result = name.replace(/[^a-zA-Z0-9]/g, " ");
|
||||
result = result.trim();
|
||||
@ -366,5 +374,6 @@ module.exports = {
|
||||
evaluateNodeProperty: evaluateNodeProperty,
|
||||
normalisePropertyExpression: normalisePropertyExpression,
|
||||
normaliseNodeTypeName: normaliseNodeTypeName,
|
||||
prepareJSONataExpression: prepareJSONataExpression
|
||||
prepareJSONataExpression: prepareJSONataExpression,
|
||||
evaluateJSONataExpression: evaluateJSONataExpression
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user