From 75bcd9e8d50183354321cac7bcad0751c704df0d Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Fri, 14 Jan 2022 23:40:12 +0900 Subject: [PATCH 1/8] 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); + }); + + }); }); From 289815e12878aabb4bdae86375295440771f765d Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Tue, 25 Jan 2022 20:46:01 +0900 Subject: [PATCH 2/8] add support of FLOW_ID & FLOW_NAME --- packages/node_modules/@node-red/runtime/lib/flows/Flow.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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..62ec10ce3 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js @@ -498,7 +498,13 @@ class Flow { * @return {[type]} [description] */ getSetting(key) { - const flow = this.flow; + const flow = this.flow; + if (key === "FLOW_NAME") { + return flow.label; + } + if (key === "FLOW_ID") { + return flow.id; + } if (flow.credentials === undefined) { flow.credentials = credentials.get(flow.id) || {}; } From 0ad60013aabd8397c3e6ae53b591b490fe09476d Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Tue, 25 Jan 2022 20:52:45 +0900 Subject: [PATCH 3/8] add test for env var access of FLOW_ID & FLOW_NAME --- test/nodes/core/common/20-inject_spec.js | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/nodes/core/common/20-inject_spec.js b/test/nodes/core/common/20-inject_spec.js index 00dfba40d..e7ea5b094 100644 --- a/test/nodes/core/common/20-inject_spec.js +++ b/test/nodes/core/common/20-inject_spec.js @@ -142,6 +142,46 @@ describe('inject node', function() { }); }); + it('inject name of flow as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "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: "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('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"}]; @@ -185,6 +225,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"]]}, From 8b23d341b4f61de04f7f9c817b3fbb4f35e91e6d Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Tue, 25 Jan 2022 21:04:43 +0900 Subject: [PATCH 4/8] add support for env var access of GROUP_ID & GROUP_NAME --- .../node_modules/@node-red/runtime/lib/flows/Flow.js | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 62ec10ce3..3538a9d30 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 === "GROUP_NAME") { + return [{ + val: group.name + }, null]; + } + if (name === "GROUP_ID") { + return [{ + val: group.id + }, null]; + } + if (group.credentials === undefined) { group.credentials = credentials.get(group.id) || {}; } From 983dad5b536b3c8d78f6c5bde9d7dc475b240178 Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Tue, 25 Jan 2022 21:07:38 +0900 Subject: [PATCH 5/8] add test for env var access of GROUP_ID & GROUP_NAME --- test/nodes/core/common/20-inject_spec.js | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/nodes/core/common/20-inject_spec.js b/test/nodes/core/common/20-inject_spec.js index e7ea5b094..a995c5c3a 100644 --- a/test/nodes/core/common/20-inject_spec.js +++ b/test/nodes/core/common/20-inject_spec.js @@ -182,6 +182,47 @@ describe('inject node', function() { }); }); + it('inject name of group as environment variable ', function (done) { + var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "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: "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"}]; From ba304c96512467716dec12595f238fc3040bde16 Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Wed, 26 Jan 2022 09:25:30 +0900 Subject: [PATCH 6/8] add NR_ prefix to special environment variables --- packages/node_modules/@node-red/runtime/lib/flows/Flow.js | 8 ++++---- .../node_modules/@node-red/runtime/lib/flows/Subflow.js | 4 ++-- packages/node_modules/@node-red/util/lib/util.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) 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 3538a9d30..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,12 +424,12 @@ class Flow { */ getGroupEnvSetting(node, group, name) { if (group) { - if (name === "GROUP_NAME") { + if (name === "NR_GROUP_NAME") { return [{ val: group.name }, null]; } - if (name === "GROUP_ID") { + if (name === "NR_GROUP_ID") { return [{ val: group.id }, null]; @@ -510,10 +510,10 @@ class Flow { */ getSetting(key) { const flow = this.flow; - if (key === "FLOW_NAME") { + if (key === "NR_FLOW_NAME") { return flow.label; } - if (key === "FLOW_ID") { + if (key === "NR_FLOW_ID") { return flow.id; } if (flow.credentials === undefined) { 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 55f4a0727..993beace4 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js @@ -372,10 +372,10 @@ class Subflow extends Flow { } const node = this.subflowInstance; if (node) { - if (name === "NODE_NAME") { + if (name === "NR_NODE_NAME") { return node.name; } - if (name === "NODE_ID") { + if (name === "NR_NODE_ID") { return node.id; } } diff --git a/packages/node_modules/@node-red/util/lib/util.js b/packages/node_modules/@node-red/util/lib/util.js index 48d3f810e..e5ea0f3e5 100644 --- a/packages/node_modules/@node-red/util/lib/util.js +++ b/packages/node_modules/@node-red/util/lib/util.js @@ -523,10 +523,10 @@ function setObjectProperty(msg,prop,value,createMissing) { */ function getSetting(node, name, flow_) { if (node) { - if (name === "NODE_NAME") { + if (name === "NR_NODE_NAME") { return node.name; } - if (name === "NODE_ID") { + if (name === "NR_NODE_ID") { return node.id; } } From 56580c400521074aa39d4e6db9359ec6e58b420b Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Wed, 26 Jan 2022 09:26:05 +0900 Subject: [PATCH 7/8] add test for NR_ prefix addition --- test/nodes/core/common/20-inject_spec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/nodes/core/common/20-inject_spec.js b/test/nodes/core/common/20-inject_spec.js index a995c5c3a..26c9e3118 100644 --- a/test/nodes/core/common/20-inject_spec.js +++ b/test/nodes/core/common/20-inject_spec.js @@ -107,7 +107,7 @@ 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"}, + 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"); @@ -125,7 +125,7 @@ describe('inject node', function() { }); 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"}, + 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"); @@ -143,7 +143,7 @@ describe('inject node', function() { }); it('inject name of flow as environment variable ', function (done) { - var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "FLOW_NAME", payloadType: "env", wires: [["n2"]], z: "flow"}, + 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" }, ]; @@ -163,7 +163,7 @@ describe('inject node', function() { }); it('inject id of flow as environment variable ', function (done) { - var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "FLOW_ID", payloadType: "env", wires: [["n2"]], z: "flow"}, + 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" }, ]; @@ -183,7 +183,7 @@ describe('inject node', function() { }); it('inject name of group as environment variable ', function (done) { - var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "GROUP_NAME", payloadType: "env", wires: [["n2"]], z: "flow", g: "g0"}, + 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" }, ]; @@ -203,7 +203,7 @@ describe('inject node', function() { }); it('inject id of group as environment variable ', function (done) { - var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "GROUP_ID", payloadType: "env", wires: [["n2"]], z: "flow", g: "g0"}, + 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" }, ]; From aa3f5001d50bb4a6f7d45024b7e86ef228e5bc0c Mon Sep 17 00:00:00 2001 From: Hiroyasu Nishiyama Date: Wed, 26 Jan 2022 10:52:41 +0900 Subject: [PATCH 8/8] additional update of test for NR_ prefix addition --- test/unit/@node-red/runtime/lib/flows/Subflow_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 ad5c1431f..c2e251447 100644 --- a/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js +++ b/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js @@ -212,7 +212,7 @@ describe('Subflow', function() { currentNodes[node.id] = node; this.on('input',function(msg) { var flow = node._flow; - var val = flow.getSetting("NODE_NAME"); + var val = flow.getSetting("NR_NODE_NAME"); node.received = val; node.send({payload: val}); }); @@ -241,7 +241,7 @@ describe('Subflow', function() { currentNodes[node.id] = node; this.on('input',function(msg) { var flow = node._flow; - var val = flow.getSetting("NODE_ID"); + var val = flow.getSetting("NR_NODE_ID"); node.received = val; node.send({payload: val}); });