From 75bcd9e8d50183354321cac7bcad0751c704df0d Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Fri, 14 Jan 2022 23:40:12 +0900 Subject: [PATCH] add support for accessing node id & name as env var --- .../@node-red/runtime/lib/flows/Subflow.js | 8 ++ .../node_modules/@node-red/util/lib/util.js | 8 ++ test/nodes/core/common/20-inject_spec.js | 36 ++++++ .../runtime/lib/flows/Subflow_spec.js | 121 ++++++++++++++++++ 4 files changed, 173 insertions(+) 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..55f4a0727 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 === "NODE_NAME") { + return node.name; + } + if (name === "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..48d3f810e 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 === "NODE_NAME") { + return node.name; + } + if (name === "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..00dfba40d 100644 --- a/test/nodes/core/common/20-inject_spec.js +++ b/test/nodes/core/common/20-inject_spec.js @@ -106,6 +106,42 @@ 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: "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: "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('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"}]; 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..ad5c1431f 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("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("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); + }); + + }); });