diff --git a/editor/images/typedInput/env.png b/editor/images/typedInput/env.png new file mode 100644 index 000000000..0ea51da00 Binary files /dev/null and b/editor/images/typedInput/env.png differ diff --git a/editor/js/ui/common/typedInput.js b/editor/js/ui/common/typedInput.js index 3b5a0d62c..f5227fd68 100644 --- a/editor/js/ui/common/typedInput.js +++ b/editor/js/ui/common/typedInput.js @@ -76,6 +76,11 @@ } }) } + }, + env: { + value: "env", + label: "env variable", + icon: "red/images/typedInput/env.png" } }; var nlsd = false; diff --git a/nodes/core/core/20-inject.html b/nodes/core/core/20-inject.html index 4090fdbbd..6f8ebcf69 100644 --- a/nodes/core/core/20-inject.html +++ b/nodes/core/core/20-inject.html @@ -263,7 +263,7 @@ If you want every 20 minutes from now - use the "interval" option.

$("#node-input-payload").typedInput({ default: 'str', typeField: $("#node-input-payloadType"), - types:['flow','global','str','num','bool','json','bin','date'] + types:['flow','global','str','num','bool','json','bin','date','env'] }); $("#inject-time-type-select").change(function() { diff --git a/nodes/core/logic/10-switch.html b/nodes/core/logic/10-switch.html index ffa5a48e5..f4ffc7dea 100644 --- a/nodes/core/logic/10-switch.html +++ b/nodes/core/logic/10-switch.html @@ -230,12 +230,12 @@ selectField.append($("").val(operators[d].v).text(/^switch/.test(operators[d].t)?node._(operators[d].t):operators[d].t)); } } - var valueField = $('',{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 numValueField = $('',{class:"node-input-rule-num-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['flow','global','num','jsonata']}); + var valueField = $('',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'str',types:['msg','flow','global','str','num','jsonata','env',previousValueType]}); + var numValueField = $('',{class:"node-input-rule-num-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['flow','global','num','jsonata','env']}); var expValueField = $('',{class:"node-input-rule-exp-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'jsonata',types:['jsonata']}); - var btwnValueField = $('',{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 btwnValueField = $('',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata','env',previousValueType]}); var btwnAndLabel = $('',{class:"node-input-rule-btwn-label"}).text(" "+andLabel+" ").appendTo(row3); - var btwnValue2Field = $('',{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 btwnValue2Field = $('',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata','env',previousValueType]}); var typeValueField = $('',{class:"node-input-rule-type-value",type:"text",style:"margin-left: 5px;"}).appendTo(row) .typedInput({default:'string',types:[ {value:"string",label:"string",hasValue:false}, diff --git a/nodes/core/logic/15-change.html b/nodes/core/logic/15-change.html index 999c0ed71..83bdecf9e 100644 --- a/nodes/core/logic/15-change.html +++ b/nodes/core/logic/15-change.html @@ -146,7 +146,7 @@ .appendTo(row2); var propertyValue = $('',{class:"node-input-rule-property-value",type:"text"}) .appendTo(row2) - .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata']}); + .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env']}); var row3_1 = $('
').appendTo(row3); $('
',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"}) @@ -154,7 +154,7 @@ .appendTo(row3_1); var fromValue = $('',{class:"node-input-rule-property-search-value",type:"text"}) .appendTo(row3_1) - .typedInput({default:'str',types:['msg','flow','global','str','re','num','bool']}); + .typedInput({default:'str',types:['msg','flow','global','str','re','num','bool','env']}); var row3_2 = $('
',{style:"margin-top:8px;"}).appendTo(row3); $('
',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"}) @@ -162,7 +162,7 @@ .appendTo(row3_2); var toValue = $('',{class:"node-input-rule-property-replace-value",type:"text"}) .appendTo(row3_2) - .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin']}); + .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','env']}); $('
',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"}) .text(to) diff --git a/nodes/core/logic/15-change.js b/nodes/core/logic/15-change.js index ae50394ed..c7c05118e 100644 --- a/nodes/core/logic/15-change.js +++ b/nodes/core/logic/15-change.js @@ -93,6 +93,8 @@ module.exports = function(RED) { valid = false; this.error(RED._("change.errors.invalid-expr",{error:e.message})); } + } else if (rule.tot === 'env') { + rule.to = RED.util.evaluateNodeProperty(rule.to,'env'); } } diff --git a/red/runtime/util.js b/red/runtime/util.js index 88c06a029..1480a841a 100644 --- a/red/runtime/util.js +++ b/red/runtime/util.js @@ -303,6 +303,23 @@ function setMessageProperty(msg,prop,value,createMissing) { } } +function evaluteEnvProperty(value) { + if (/^\${[^}]+}$/.test(value)) { + // ${ENV_VAR} + value = value.substring(2,value.length-1); + value = process.env.hasOwnProperty(value)?process.env[value]:"" + } else if (!/\${\S+}/.test(value)) { + // ENV_VAR + value = process.env.hasOwnProperty(value)?process.env[value]:"" + } else { + // FOO${ENV_VAR}BAR + value = value.replace(/\${([^}]+)}/g, function(match, v) { + return process.env.hasOwnProperty(v)?process.env[v]:"" + }); + } + return value; +} + function evaluateNodeProperty(value, type, node, msg) { if (type === 'str') { return ""+value; @@ -328,6 +345,8 @@ function evaluateNodeProperty(value, type, node, msg) { } else if (type === 'jsonata') { var expr = prepareJSONataExpression(value,node); return evaluateJSONataExpression(expr,msg); + } else if (type === 'env') { + return evaluteEnvProperty(value); } return value; } diff --git a/test/nodes/core/logic/15-change_spec.js b/test/nodes/core/logic/15-change_spec.js index f5ca0f3d2..e444b2663 100644 --- a/test/nodes/core/logic/15-change_spec.js +++ b/test/nodes/core/logic/15-change_spec.js @@ -390,7 +390,7 @@ describe('change Node', function() { changeNode1.receive({payload:""}); }); }); - + it('sets the value of the message property to the current timestamp', function(done) { var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"set","p":"ts","pt":"msg","to":"","tot":"date"}],"name":"changeNode","wires":[["helperNode1"]]}, {id:"helperNode1", type:"helper", wires:[]}]; @@ -409,6 +409,33 @@ describe('change Node', function() { }); }); + describe('env var', function() { + before(function() { + process.env.NR_TEST_A = 'foo'; + }) + after(function() { + delete process.env.NR_TEST_A; + }) + it('sets the value using env property', function(done) { + var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","pt":"msg","to":"NR_TEST_A","tot":"env"}],"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("foo"); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({payload:"123",topic:"ABC"}); + }); + }); + }); + + it('changes the value using jsonata', function(done) { var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$length(payload)","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]]}, {id:"helperNode1", type:"helper", wires:[]}]; @@ -872,6 +899,33 @@ describe('change Node', function() { changeNode1.receive({payload:""}); }); }); + + describe('env var', function() { + before(function() { + process.env.NR_TEST_A = 'foo'; + }) + after(function() { + delete process.env.NR_TEST_A; + }) + it('changes the value using env property', function(done) { + var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"NR_TEST_A","fromt":"msg","tot":"env"}],"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("abcfooabc"); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({payload:"abcABCabc",topic:"ABC"}); + }); + }); + }); + }); describe("#delete", function() { diff --git a/test/red/runtime/util_spec.js b/test/red/runtime/util_spec.js index f542228a2..1b7438efd 100644 --- a/test/red/runtime/util_spec.js +++ b/test/red/runtime/util_spec.js @@ -307,6 +307,38 @@ describe("red/util", function() { },{}); result.should.eql("123"); }); + describe('environment variable', function() { + before(function() { + process.env.NR_TEST_A = "foo"; + process.env.NR_TEST_B = "${NR_TEST_A}"; + }) + after(function() { + delete process.env.NR_TEST_A; + delete process.env.NR_TEST_B; + }) + + it('returns an environment variable - NR_TEST_A', function() { + var result = util.evaluateNodeProperty('NR_TEST_A','env'); + result.should.eql('foo'); + }); + it('returns an environment variable - ${NR_TEST_A}', function() { + var result = util.evaluateNodeProperty('${NR_TEST_A}','env'); + result.should.eql('foo'); + }); + it('returns an environment variable - ${NR_TEST_A', function() { + var result = util.evaluateNodeProperty('${NR_TEST_A','env'); + result.should.eql(''); + }); + it('returns an environment variable - foo${NR_TEST_A}bar', function() { + var result = util.evaluateNodeProperty('123${NR_TEST_A}456','env'); + result.should.eql('123foo456'); + }); + it('returns an environment variable - foo${NR_TEST_B}bar', function() { + var result = util.evaluateNodeProperty('123${NR_TEST_B}456','env'); + result.should.eql('123${NR_TEST_A}456'); + }); + + }); }); describe('normalisePropertyExpression', function() {