diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js index 5fb21157e..eaf122fd8 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js @@ -424,6 +424,17 @@ class Flow { */ getGroupEnvSetting(node, group, name) { if (group) { + if (name === "NR_GROUP_NAME") { + return [{ + val: group.name + }, null]; + } + if (name === "NR_GROUP_ID") { + return [{ + val: group.id + }, null]; + } + if (group.credentials === undefined) { group.credentials = credentials.get(group.id) || {}; } @@ -498,7 +509,13 @@ class Flow { * @return {[type]} [description] */ getSetting(key) { - const flow = this.flow; + const flow = this.flow; + if (key === "NR_FLOW_NAME") { + return flow.label; + } + if (key === "NR_FLOW_ID") { + return flow.id; + } if (flow.credentials === undefined) { flow.credentials = credentials.get(flow.id) || {}; } diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js index 3d2bc3afe..993beace4 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js @@ -371,6 +371,14 @@ class Subflow extends Flow { name = name.substring(8); } const node = this.subflowInstance; + if (node) { + if (name === "NR_NODE_NAME") { + return node.name; + } + if (name === "NR_NODE_ID") { + return node.id; + } + } if (node.g) { const group = this.getGroupNode(node.g); const [result, newName] = this.getGroupEnvSetting(node, group, name); diff --git a/packages/node_modules/@node-red/util/lib/util.js b/packages/node_modules/@node-red/util/lib/util.js index 93dcd83cd..e5ea0f3e5 100644 --- a/packages/node_modules/@node-red/util/lib/util.js +++ b/packages/node_modules/@node-red/util/lib/util.js @@ -522,6 +522,14 @@ function setObjectProperty(msg,prop,value,createMissing) { * @return {String} value of env var */ function getSetting(node, name, flow_) { + if (node) { + if (name === "NR_NODE_NAME") { + return node.name; + } + if (name === "NR_NODE_ID") { + return node.id; + } + } var flow = (flow_ ? flow_ : (node ? node._flow : null)); if (flow) { if (node && node.g) { diff --git a/test/nodes/core/common/20-inject_spec.js b/test/nodes/core/common/20-inject_spec.js index f760bb646..26c9e3118 100644 --- a/test/nodes/core/common/20-inject_spec.js +++ b/test/nodes/core/common/20-inject_spec.js @@ -106,6 +106,123 @@ describe('inject node', function() { }); }); + it('inject name of node as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "NR_NODE_NAME", payloadType: "env", wires: [["n2"]], z: "flow"}, + {id: "n2", type: "helper"}]; + helper.load(injectNode, flow, function () { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function (msg) { + try { + msg.should.have.property("payload", "NAME"); + done(); + } catch (err) { + done(err); + } + }); + n1.receive({}); + }); + }); + + it('inject id of node as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "NR_NODE_ID", payloadType: "env", wires: [["n2"]], z: "flow"}, + {id: "n2", type: "helper"}]; + helper.load(injectNode, flow, function () { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function (msg) { + try { + msg.should.have.property("payload", "n1"); + done(); + } catch (err) { + done(err); + } + }); + n1.receive({}); + }); + }); + + it('inject name of flow as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "NR_FLOW_NAME", payloadType: "env", wires: [["n2"]], z: "flow"}, + {id: "n2", type: "helper"}, + {id: "flow", type: "tab", label: "FLOW" }, + ]; + helper.load(injectNode, flow, function () { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function (msg) { + try { + msg.should.have.property("payload", "FLOW"); + done(); + } catch (err) { + done(err); + } + }); + n1.receive({}); + }); + }); + + it('inject id of flow as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "NR_FLOW_ID", payloadType: "env", wires: [["n2"]], z: "flow"}, + {id: "n2", type: "helper"}, + {id: "flow", type: "tab", name: "FLOW" }, + ]; + helper.load(injectNode, flow, function () { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function (msg) { + try { + msg.should.have.property("payload", "flow"); + done(); + } catch (err) { + done(err); + } + }); + n1.receive({}); + }); + }); + + it('inject name of group as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "NR_GROUP_NAME", payloadType: "env", wires: [["n2"]], z: "flow", g: "g0"}, + {id: "n2", type: "helper"}, + {id: "g0", type: "group", name: "GROUP" }, + ]; + helper.load(injectNode, flow, function () { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function (msg) { + try { + msg.should.have.property("payload", "GROUP"); + done(); + } catch (err) { + done(err); + } + }); + n1.receive({}); + }); + }); + + it('inject id of group as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "NR_GROUP_ID", payloadType: "env", wires: [["n2"]], z: "flow", g: "g0"}, + {id: "n2", type: "helper"}, + {id: "g0", type: "group", name: "GROUP" }, + ]; + helper.load(injectNode, flow, function () { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function (msg) { + try { + msg.should.have.property("payload", "g0"); + done(); + } catch (err) { + done(err); + } + }); + n1.receive({}); + }); + }); + + it('sets the value of flow context property', function (done) { var flow = [{id: "n1", type: "inject", topic: "t1", payload: "flowValue", payloadType: "flow", wires: [["n2"]], z: "flow"}, {id: "n2", type: "helper"}]; @@ -149,6 +266,7 @@ describe('inject node', function() { }); }); + it('sets the value of two persistable flow context property', function (done) { var flow = [{id: "n0", z: "flow", type: "inject", topic: "t0", payload: "#:(memory0)::val", payloadType: "flow", wires: [["n2"]]}, {id: "n1", z: "flow", type: "inject", topic: "t1", payload: "#:(memory1)::val", payloadType: "flow", wires: [["n2"]]}, diff --git a/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js b/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js index 0479b5117..c2e251447 100644 --- a/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js +++ b/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js @@ -201,6 +201,64 @@ describe('Subflow', function() { } util.inherits(TestEnvNode,Node); + var TestNameEnvNode = function(n) { + Node.call(this,n); + this._index = createCount++; + this.scope = n.scope; + this.foo = n.foo; + var node = this; + this.stopped = false; + this.received = null; + currentNodes[node.id] = node; + this.on('input',function(msg) { + var flow = node._flow; + var val = flow.getSetting("NR_NODE_NAME"); + node.received = val; + node.send({payload: val}); + }); + this.on('close',function() { + node.stopped = true; + stoppedNodes[node.id] = node; + delete currentNodes[node.id]; + }); + this.__updateWires = this.updateWires; + this.updateWires = function(newWires) { + rewiredNodes[node.id] = node; + node.newWires = newWires; + node.__updateWires(newWires); + }; + } + util.inherits(TestNameEnvNode,Node); + + var TestIDEnvNode = function(n) { + Node.call(this,n); + this._index = createCount++; + this.scope = n.scope; + this.foo = n.foo; + var node = this; + this.stopped = false; + this.received = null; + currentNodes[node.id] = node; + this.on('input',function(msg) { + var flow = node._flow; + var val = flow.getSetting("NR_NODE_ID"); + node.received = val; + node.send({payload: val}); + }); + this.on('close',function() { + node.stopped = true; + stoppedNodes[node.id] = node; + delete currentNodes[node.id]; + }); + this.__updateWires = this.updateWires; + this.updateWires = function(newWires) { + rewiredNodes[node.id] = node; + node.newWires = newWires; + node.__updateWires(newWires); + }; + } + util.inherits(TestIDEnvNode,Node); + before(function() { getType = sinon.stub(typeRegistry,"get").callsFake(function(type) { if (type=="test") { @@ -211,6 +269,10 @@ describe('Subflow', function() { return TestStatusNode; } else if (type=="testEnv"){ return TestEnvNode; + } else if (type=="testNameEnv"){ + return TestNameEnvNode; + } else if (type=="testIDEnv"){ + return TestIDEnvNode; } else { return TestAsyncNode; } @@ -880,6 +942,65 @@ describe('Subflow', function() { },150); }); + it("can access name of subflow as env var", function(done) { + var config = flowUtils.parseConfig([ + {id:"t1",type:"tab"}, + {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]}, + {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",name:"SFN",wires:["3"]}, + {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]}, + {id:"sf1",type:"subflow",name:"Subflow 2",info:"", + "in":[ {wires:[{id:"sf1-1"}]} ], + "out":[ {wires:[{id:"sf1-2",port:0}]} ]}, + {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]}, + {id:"sf1-2",type:"testNameEnv",z:"sf1",foo:"sf1.2",x:166,y:99,wires:[[]]} + ]); + var flow = Flow.create({ + getSetting: k=> process.env[k], + handleError: (a,b,c) => { console.log(a,b,c); } + },config,config.flows["t1"]); + + flow.start(); + + currentNodes["1"].receive({payload: "test"}); + setTimeout(function() { + currentNodes["3"].should.have.a.property("received", "SFN"); + + flow.stop().then(function() { + done(); + }); + },150); + }); + + it("can access id of subflow as env var", function(done) { + var config = flowUtils.parseConfig([ + {id:"t1",type:"tab"}, + {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]}, + {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",name:"SFN",wires:["3"]}, + {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]}, + {id:"sf1",type:"subflow",name:"Subflow 2",info:"", + "in":[ {wires:[{id:"sf1-1"}]} ], + "out":[ {wires:[{id:"sf1-2",port:0}]} ]}, + {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]}, + {id:"sf1-2",type:"testIDEnv",z:"sf1",foo:"sf1.2",x:166,y:99,wires:[[]]} + ]); + var flow = Flow.create({ + getSetting: k=> process.env[k], + handleError: (a,b,c) => { console.log(a,b,c); } + },config,config.flows["t1"]); + + flow.start(); + + currentNodes["1"].receive({payload: "test"}); + setTimeout(function() { + currentNodes["3"].should.have.a.property("received", "2"); + + flow.stop().then(function() { + done(); + }); + },150); + }); + + }); });