@node-red/runtime 3.1.0-beta.2 → 3.1.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/flows/Flow.js +140 -164
- package/lib/flows/Group.js +55 -0
- package/lib/flows/Subflow.js +19 -52
- package/lib/flows/index.js +14 -20
- package/lib/flows/util.js +478 -414
- package/lib/index.js +9 -0
- package/lib/nodes/index.js +0 -1
- package/package.json +4 -4
package/lib/flows/Flow.js
CHANGED
|
@@ -14,19 +14,20 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
**/
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const clone = require("clone");
|
|
18
|
+
const redUtil = require("@node-red/util").util;
|
|
19
19
|
const events = require("@node-red/util").events;
|
|
20
|
-
|
|
20
|
+
const flowUtil = require("./util");
|
|
21
21
|
const context = require('../nodes/context');
|
|
22
22
|
const hooks = require("@node-red/util").hooks;
|
|
23
23
|
const credentials = require("../nodes/credentials");
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
let Subflow;
|
|
26
|
+
let Log;
|
|
27
|
+
let Group;
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
let nodeCloseTimeout = 15000;
|
|
30
|
+
let asyncMessageDelivery = true;
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* This class represents a flow within the runtime. It is responsible for
|
|
@@ -52,6 +53,8 @@ class Flow {
|
|
|
52
53
|
this.isGlobalFlow = false;
|
|
53
54
|
}
|
|
54
55
|
this.id = this.flow.id || "global";
|
|
56
|
+
this.groups = {}
|
|
57
|
+
this.groupOrder = []
|
|
55
58
|
this.activeNodes = {};
|
|
56
59
|
this.subflowInstanceNodes = {};
|
|
57
60
|
this.catchNodes = [];
|
|
@@ -59,6 +62,11 @@ class Flow {
|
|
|
59
62
|
this.path = this.id;
|
|
60
63
|
// Ensure a context exists for this flow
|
|
61
64
|
this.context = context.getFlowContext(this.id,this.parent.id);
|
|
65
|
+
|
|
66
|
+
// env is an array of env definitions
|
|
67
|
+
// _env is an object for direct lookup of env name -> value
|
|
68
|
+
this.env = this.flow.env
|
|
69
|
+
this._env = {}
|
|
62
70
|
}
|
|
63
71
|
|
|
64
72
|
/**
|
|
@@ -136,7 +144,7 @@ class Flow {
|
|
|
136
144
|
* @param {[type]} msg [description]
|
|
137
145
|
* @return {[type]} [description]
|
|
138
146
|
*/
|
|
139
|
-
start(diff) {
|
|
147
|
+
async start(diff) {
|
|
140
148
|
this.trace("start "+this.TYPE+" ["+this.path+"]");
|
|
141
149
|
var node;
|
|
142
150
|
var newNode;
|
|
@@ -145,6 +153,52 @@ class Flow {
|
|
|
145
153
|
this.statusNodes = [];
|
|
146
154
|
this.completeNodeMap = {};
|
|
147
155
|
|
|
156
|
+
|
|
157
|
+
if (this.isGlobalFlow) {
|
|
158
|
+
// This is the global flow. It needs to go find the `global-config`
|
|
159
|
+
// node and extract any env properties from it
|
|
160
|
+
const configNodes = Object.keys(this.flow.configs);
|
|
161
|
+
for (let i = 0; i < configNodes.length; i++) {
|
|
162
|
+
const node = this.flow.configs[configNodes[i]]
|
|
163
|
+
if (node.type === 'global-config' && node.env) {
|
|
164
|
+
const nodeEnv = await flowUtil.evaluateEnvProperties(this, node.env, credentials.get(node.id))
|
|
165
|
+
this._env = { ...this._env, ...nodeEnv }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (this.env) {
|
|
171
|
+
this._env = { ...this._env, ...await flowUtil.evaluateEnvProperties(this, this.env, credentials.get(this.id)) }
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Initialise the group objects. These must be done in the right order
|
|
175
|
+
// starting from outer-most to inner-most so that the parent hierarchy
|
|
176
|
+
// is maintained.
|
|
177
|
+
this.groups = {}
|
|
178
|
+
this.groupOrder = []
|
|
179
|
+
const groupIds = Object.keys(this.flow.groups || {})
|
|
180
|
+
while (groupIds.length > 0) {
|
|
181
|
+
const id = groupIds.shift()
|
|
182
|
+
const groupDef = this.flow.groups[id]
|
|
183
|
+
if (!groupDef.g || this.groups[groupDef.g]) {
|
|
184
|
+
// The parent of this group is available - either another group
|
|
185
|
+
// or the top-level flow (this)
|
|
186
|
+
const parent = this.groups[groupDef.g] || this
|
|
187
|
+
this.groups[groupDef.id] = new Group(parent, groupDef)
|
|
188
|
+
this.groupOrder.push(groupDef.id)
|
|
189
|
+
} else {
|
|
190
|
+
// Try again once we've processed the other groups
|
|
191
|
+
groupIds.push(id)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (let i = 0; i < this.groupOrder.length; i++) {
|
|
196
|
+
// Start the groups in the right order so they
|
|
197
|
+
// can setup their env vars knowning their parent
|
|
198
|
+
// will have been started
|
|
199
|
+
await this.groups[this.groupOrder[i]].start()
|
|
200
|
+
}
|
|
201
|
+
|
|
148
202
|
var configNodes = Object.keys(this.flow.configs);
|
|
149
203
|
var configNodeAttempts = {};
|
|
150
204
|
while (configNodes.length > 0) {
|
|
@@ -177,7 +231,7 @@ class Flow {
|
|
|
177
231
|
}
|
|
178
232
|
}
|
|
179
233
|
if (readyToCreate) {
|
|
180
|
-
newNode = flowUtil.createNode(this,node);
|
|
234
|
+
newNode = await flowUtil.createNode(this,node);
|
|
181
235
|
if (newNode) {
|
|
182
236
|
this.activeNodes[id] = newNode;
|
|
183
237
|
}
|
|
@@ -203,7 +257,7 @@ class Flow {
|
|
|
203
257
|
if (node.d !== true) {
|
|
204
258
|
if (!node.subflow) {
|
|
205
259
|
if (!this.activeNodes[id]) {
|
|
206
|
-
newNode = flowUtil.createNode(this,node);
|
|
260
|
+
newNode = await flowUtil.createNode(this,node);
|
|
207
261
|
if (newNode) {
|
|
208
262
|
this.activeNodes[id] = newNode;
|
|
209
263
|
}
|
|
@@ -221,7 +275,7 @@ class Flow {
|
|
|
221
275
|
node
|
|
222
276
|
);
|
|
223
277
|
this.subflowInstanceNodes[id] = subflow;
|
|
224
|
-
subflow.start();
|
|
278
|
+
await subflow.start();
|
|
225
279
|
this.activeNodes[id] = subflow.node;
|
|
226
280
|
|
|
227
281
|
// this.subflowInstanceNodes[id] = nodes.map(function(n) { return n.id});
|
|
@@ -404,8 +458,7 @@ class Flow {
|
|
|
404
458
|
* @return {Node} group node
|
|
405
459
|
*/
|
|
406
460
|
getGroupNode(id) {
|
|
407
|
-
|
|
408
|
-
return groups[id];
|
|
461
|
+
return this.groups[id];
|
|
409
462
|
}
|
|
410
463
|
|
|
411
464
|
/**
|
|
@@ -416,95 +469,8 @@ class Flow {
|
|
|
416
469
|
return this.activeNodes;
|
|
417
470
|
}
|
|
418
471
|
|
|
419
|
-
/*!
|
|
420
|
-
* Get value of environment variable defined in group node.
|
|
421
|
-
* @param {String} group - group node
|
|
422
|
-
* @param {String} name - name of variable
|
|
423
|
-
* @return {Object} object containing the value in val property or null if not defined
|
|
424
|
-
*/
|
|
425
|
-
getGroupEnvSetting(node, group, name) {
|
|
426
|
-
if (group) {
|
|
427
|
-
if (name === "NR_GROUP_NAME") {
|
|
428
|
-
return [{
|
|
429
|
-
val: group.name
|
|
430
|
-
}, null];
|
|
431
|
-
}
|
|
432
|
-
if (name === "NR_GROUP_ID") {
|
|
433
|
-
return [{
|
|
434
|
-
val: group.id
|
|
435
|
-
}, null];
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if (group.credentials === undefined) {
|
|
439
|
-
group.credentials = credentials.get(group.id) || {};
|
|
440
|
-
}
|
|
441
|
-
if (!name.startsWith("$parent.")) {
|
|
442
|
-
if (group.env) {
|
|
443
|
-
if (!group._env) {
|
|
444
|
-
const envs = group.env;
|
|
445
|
-
const entries = envs.map((env) => {
|
|
446
|
-
if (env.type === "cred") {
|
|
447
|
-
const cred = group.credentials;
|
|
448
|
-
if (cred.hasOwnProperty(env.name)) {
|
|
449
|
-
env.value = cred[env.name];
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
return [env.name, env];
|
|
453
|
-
});
|
|
454
|
-
group._env = Object.fromEntries(entries);
|
|
455
|
-
}
|
|
456
|
-
const env = group._env[name];
|
|
457
|
-
if (env) {
|
|
458
|
-
let value = env.value;
|
|
459
|
-
const type = env.type;
|
|
460
|
-
if ((type !== "env") ||
|
|
461
|
-
(value !== name)) {
|
|
462
|
-
if (type === "env") {
|
|
463
|
-
value = value.replace(new RegExp("\\${"+name+"}","g"),"${$parent."+name+"}");
|
|
464
|
-
}
|
|
465
|
-
if (type === "bool") {
|
|
466
|
-
const val
|
|
467
|
-
= ((value === "true") ||
|
|
468
|
-
(value === true));
|
|
469
|
-
return [{
|
|
470
|
-
val: val
|
|
471
|
-
}, null];
|
|
472
|
-
}
|
|
473
|
-
if (type === "cred") {
|
|
474
|
-
return [{
|
|
475
|
-
val: value
|
|
476
|
-
}, null];
|
|
477
|
-
}
|
|
478
|
-
try {
|
|
479
|
-
var val = redUtil.evaluateNodeProperty(value, type, node, null, null);
|
|
480
|
-
return [{
|
|
481
|
-
val: val
|
|
482
|
-
}, null];
|
|
483
|
-
}
|
|
484
|
-
catch (e) {
|
|
485
|
-
this.error(e);
|
|
486
|
-
return [null, null];
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
else {
|
|
493
|
-
name = name.substring(8);
|
|
494
|
-
}
|
|
495
|
-
if (group.g) {
|
|
496
|
-
const parent = this.getGroupNode(group.g);
|
|
497
|
-
return this.getGroupEnvSetting(node, parent, name);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
return [null, name];
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
|
|
504
472
|
/**
|
|
505
|
-
* Get a flow setting value.
|
|
506
|
-
* flow which, as defined in ./index.js returns `process.env[key]`.
|
|
507
|
-
* This lays the groundwork for Subflow to have instance-specific settings
|
|
473
|
+
* Get a flow setting value.
|
|
508
474
|
* @param {[type]} key [description]
|
|
509
475
|
* @return {[type]} [description]
|
|
510
476
|
*/
|
|
@@ -516,54 +482,14 @@ class Flow {
|
|
|
516
482
|
if (key === "NR_FLOW_ID") {
|
|
517
483
|
return flow.id;
|
|
518
484
|
}
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
if (flow.env) {
|
|
523
|
-
if (!key.startsWith("$parent.")) {
|
|
524
|
-
if (!flow._env) {
|
|
525
|
-
const envs = flow.env;
|
|
526
|
-
const entries = envs.map((env) => {
|
|
527
|
-
if (env.type === "cred") {
|
|
528
|
-
const cred = flow.credentials;
|
|
529
|
-
if (cred.hasOwnProperty(env.name)) {
|
|
530
|
-
env.value = cred[env.name];
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
return [env.name, env]
|
|
534
|
-
});
|
|
535
|
-
flow._env = Object.fromEntries(entries);
|
|
536
|
-
}
|
|
537
|
-
const env = flow._env[key];
|
|
538
|
-
if (env) {
|
|
539
|
-
let value = env.value;
|
|
540
|
-
const type = env.type;
|
|
541
|
-
if ((type !== "env") || (value !== key)) {
|
|
542
|
-
if (type === "env") {
|
|
543
|
-
value = value.replace(new RegExp("\\${"+key+"}","g"),"${$parent."+key+"}");
|
|
544
|
-
}
|
|
545
|
-
try {
|
|
546
|
-
if (type === "bool") {
|
|
547
|
-
const val = ((value === "true") ||
|
|
548
|
-
(value === true));
|
|
549
|
-
return val;
|
|
550
|
-
}
|
|
551
|
-
if (type === "cred") {
|
|
552
|
-
return value;
|
|
553
|
-
}
|
|
554
|
-
var val = redUtil.evaluateNodeProperty(value, type, null, null, null);
|
|
555
|
-
return val;
|
|
556
|
-
}
|
|
557
|
-
catch (e) {
|
|
558
|
-
this.error(e);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
}
|
|
485
|
+
if (!key.startsWith("$parent.")) {
|
|
486
|
+
if (this._env.hasOwnProperty(key)) {
|
|
487
|
+
return this._env[key]
|
|
562
488
|
}
|
|
563
|
-
|
|
489
|
+
} else {
|
|
564
490
|
key = key.substring(8);
|
|
565
|
-
}
|
|
566
491
|
}
|
|
492
|
+
// Delegate to the parent flow.
|
|
567
493
|
return this.parent.getSetting(key);
|
|
568
494
|
}
|
|
569
495
|
|
|
@@ -601,15 +527,40 @@ class Flow {
|
|
|
601
527
|
// Delegate status to any nodes using this config node
|
|
602
528
|
for (let userNode in node.users) {
|
|
603
529
|
if (node.users.hasOwnProperty(userNode)) {
|
|
604
|
-
node.users[userNode]._flow.handleStatus(node,statusMessage,node.users[userNode],true);
|
|
530
|
+
handled = node.users[userNode]._flow.handleStatus(node,statusMessage,node.users[userNode],true) || handled;
|
|
605
531
|
}
|
|
606
532
|
}
|
|
607
|
-
handled = true;
|
|
608
533
|
} else {
|
|
609
|
-
|
|
610
|
-
|
|
534
|
+
const candidateNodes = [];
|
|
535
|
+
this.statusNodes.forEach(targetStatusNode => {
|
|
536
|
+
if (targetStatusNode.g && targetStatusNode.scope === 'group' && !reportingNode.g) {
|
|
537
|
+
// Status node inside a group, reporting node not in a group - skip it
|
|
538
|
+
return
|
|
539
|
+
}
|
|
540
|
+
if (Array.isArray(targetStatusNode.scope) && targetStatusNode.scope.indexOf(reportingNode.id) === -1) {
|
|
611
541
|
return;
|
|
612
542
|
}
|
|
543
|
+
let distance = 0
|
|
544
|
+
if (reportingNode.g) {
|
|
545
|
+
// Reporting node inside a group. Calculate the distance between it and the status node
|
|
546
|
+
let containingGroup = this.groups[reportingNode.g]
|
|
547
|
+
while (containingGroup && containingGroup.id !== targetStatusNode.g) {
|
|
548
|
+
distance++
|
|
549
|
+
containingGroup = this.groups[containingGroup.g]
|
|
550
|
+
}
|
|
551
|
+
if (!containingGroup && targetStatusNode.g && targetStatusNode.scope === 'group') {
|
|
552
|
+
// This status node is in a group, but not in the same hierachy
|
|
553
|
+
// the reporting node is in
|
|
554
|
+
return
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
candidateNodes.push({ d: distance, n: targetStatusNode })
|
|
558
|
+
})
|
|
559
|
+
candidateNodes.sort((A,B) => {
|
|
560
|
+
return A.d - B.d
|
|
561
|
+
})
|
|
562
|
+
candidateNodes.forEach(candidate => {
|
|
563
|
+
const targetStatusNode = candidate.n
|
|
613
564
|
var message = {
|
|
614
565
|
status: clone(statusMessage)
|
|
615
566
|
}
|
|
@@ -662,26 +613,50 @@ class Flow {
|
|
|
662
613
|
// Delegate status to any nodes using this config node
|
|
663
614
|
for (let userNode in node.users) {
|
|
664
615
|
if (node.users.hasOwnProperty(userNode)) {
|
|
665
|
-
node.users[userNode]._flow.handleError(node,logMessage,msg,node.users[userNode]);
|
|
616
|
+
handled = node.users[userNode]._flow.handleError(node,logMessage,msg,node.users[userNode]) || handled;
|
|
666
617
|
}
|
|
667
618
|
}
|
|
668
|
-
handled = true;
|
|
669
619
|
} else {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
620
|
+
const candidateNodes = [];
|
|
621
|
+
this.catchNodes.forEach(targetCatchNode => {
|
|
622
|
+
if (targetCatchNode.g && targetCatchNode.scope === 'group' && !reportingNode.g) {
|
|
623
|
+
// Catch node inside a group, reporting node not in a group - skip it
|
|
624
|
+
return
|
|
625
|
+
}
|
|
626
|
+
if (Array.isArray(targetCatchNode.scope) && targetCatchNode.scope.indexOf(reportingNode.id) === -1) {
|
|
627
|
+
// Catch node has a scope set and it doesn't include the reporting node
|
|
674
628
|
return;
|
|
675
629
|
}
|
|
676
|
-
|
|
630
|
+
let distance = 0
|
|
631
|
+
if (reportingNode.g) {
|
|
632
|
+
// Reporting node inside a group. Calculate the distance between it and the catch node
|
|
633
|
+
let containingGroup = this.groups[reportingNode.g]
|
|
634
|
+
while (containingGroup && containingGroup.id !== targetCatchNode.g) {
|
|
635
|
+
distance++
|
|
636
|
+
containingGroup = this.groups[containingGroup.g]
|
|
637
|
+
}
|
|
638
|
+
if (!containingGroup && targetCatchNode.g && targetCatchNode.scope === 'group') {
|
|
639
|
+
// This catch node is in a group, but not in the same hierachy
|
|
640
|
+
// the reporting node is in
|
|
641
|
+
return
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
candidateNodes.push({ d: distance, n: targetCatchNode })
|
|
645
|
+
})
|
|
646
|
+
candidateNodes.sort((A,B) => {
|
|
647
|
+
return A.d - B.d
|
|
648
|
+
})
|
|
649
|
+
let handledByUncaught = false
|
|
650
|
+
candidateNodes.forEach(candidate => {
|
|
651
|
+
const targetCatchNode = candidate.n
|
|
652
|
+
if (targetCatchNode.uncaught && !handledByUncaught) {
|
|
653
|
+
// This node only wants errors that haven't already been handled
|
|
677
654
|
if (handled) {
|
|
678
|
-
|
|
679
|
-
return;
|
|
655
|
+
return
|
|
680
656
|
}
|
|
681
|
-
|
|
682
|
-
handledByUncaught = true;
|
|
657
|
+
handledByUncaught = true
|
|
683
658
|
}
|
|
684
|
-
|
|
659
|
+
let errorMessage;
|
|
685
660
|
if (msg) {
|
|
686
661
|
errorMessage = redUtil.cloneMessage(msg);
|
|
687
662
|
} else {
|
|
@@ -808,7 +783,7 @@ function handlePreRoute(flow, sendEvent, reportError) {
|
|
|
808
783
|
return;
|
|
809
784
|
} else if (err !== false) {
|
|
810
785
|
sendEvent.destination.node = flow.getNode(sendEvent.destination.id);
|
|
811
|
-
if (sendEvent.destination.node) {
|
|
786
|
+
if (sendEvent.destination.node && typeof sendEvent.destination.node === 'object') {
|
|
812
787
|
if (sendEvent.cloneMessage) {
|
|
813
788
|
sendEvent.msg = redUtil.cloneMessage(sendEvent.msg);
|
|
814
789
|
}
|
|
@@ -858,9 +833,10 @@ module.exports = {
|
|
|
858
833
|
asyncMessageDelivery = !runtime.settings.runtimeSyncDelivery
|
|
859
834
|
Log = runtime.log;
|
|
860
835
|
Subflow = require("./Subflow");
|
|
836
|
+
Group = require("./Group").Group
|
|
861
837
|
},
|
|
862
838
|
create: function(parent,global,conf) {
|
|
863
|
-
return new Flow(parent,global,conf)
|
|
839
|
+
return new Flow(parent,global,conf)
|
|
864
840
|
},
|
|
865
841
|
Flow: Flow
|
|
866
842
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const flowUtil = require("./util");
|
|
2
|
+
const credentials = require("../nodes/credentials");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This class represents a group within the runtime.
|
|
6
|
+
*/
|
|
7
|
+
class Group {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Create a Group object.
|
|
11
|
+
* @param {[type]} parent The parent flow/group
|
|
12
|
+
* @param {[type]} groupDef This group's definition
|
|
13
|
+
*/
|
|
14
|
+
constructor(parent, groupDef) {
|
|
15
|
+
this.TYPE = 'group'
|
|
16
|
+
this.name = groupDef.name
|
|
17
|
+
this.parent = parent
|
|
18
|
+
this.group = groupDef
|
|
19
|
+
this.id = this.group.id
|
|
20
|
+
this.g = this.group.g
|
|
21
|
+
this.env = this.group.env
|
|
22
|
+
this._env = {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async start() {
|
|
26
|
+
if (this.env) {
|
|
27
|
+
this._env = await flowUtil.evaluateEnvProperties(this, this.env, credentials.get(this.id))
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get a group setting value.
|
|
32
|
+
* @param {[type]} key [description]
|
|
33
|
+
* @return {[type]} [description]
|
|
34
|
+
*/
|
|
35
|
+
getSetting(key) {
|
|
36
|
+
if (key === "NR_GROUP_NAME") {
|
|
37
|
+
return this.name;
|
|
38
|
+
}
|
|
39
|
+
if (key === "NR_GROUP_ID") {
|
|
40
|
+
return this.id;
|
|
41
|
+
}
|
|
42
|
+
if (!key.startsWith("$parent.")) {
|
|
43
|
+
if (this._env.hasOwnProperty(key)) {
|
|
44
|
+
return this._env[key]
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
key = key.substring(8);
|
|
48
|
+
}
|
|
49
|
+
return this.parent.getSetting(key);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = {
|
|
54
|
+
Group
|
|
55
|
+
}
|
package/lib/flows/Subflow.js
CHANGED
|
@@ -119,7 +119,7 @@ class Subflow extends Flow {
|
|
|
119
119
|
this.templateCredentials = credentials.get(subflowDef.id) || {};
|
|
120
120
|
this.instanceCredentials = credentials.get(id) || {};
|
|
121
121
|
|
|
122
|
-
var env =
|
|
122
|
+
var env = {};
|
|
123
123
|
if (this.subflowDef.env) {
|
|
124
124
|
this.subflowDef.env.forEach(e => {
|
|
125
125
|
env[e.name] = e;
|
|
@@ -145,7 +145,7 @@ class Subflow extends Flow {
|
|
|
145
145
|
}
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
|
-
this.env = env;
|
|
148
|
+
this.env = Object.values(env);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
/**
|
|
@@ -156,7 +156,7 @@ class Subflow extends Flow {
|
|
|
156
156
|
* @param {[type]} diff [description]
|
|
157
157
|
* @return {[type]} [description]
|
|
158
158
|
*/
|
|
159
|
-
start(diff) {
|
|
159
|
+
async start(diff) {
|
|
160
160
|
var self = this;
|
|
161
161
|
// Create a subflow node to accept inbound messages and route appropriately
|
|
162
162
|
var Node = require("../nodes/Node");
|
|
@@ -310,7 +310,7 @@ class Subflow extends Flow {
|
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
|
-
super.start(diff);
|
|
313
|
+
return super.start(diff);
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
/**
|
|
@@ -335,68 +335,35 @@ class Subflow extends Flow {
|
|
|
335
335
|
}
|
|
336
336
|
/**
|
|
337
337
|
* Get environment variable of subflow
|
|
338
|
-
* @param {String}
|
|
338
|
+
* @param {String} key name of env var
|
|
339
339
|
* @return {Object} val value of env var
|
|
340
340
|
*/
|
|
341
|
-
getSetting(
|
|
342
|
-
if (!/^\$parent\./.test(name)) {
|
|
343
|
-
var env = this.env;
|
|
344
|
-
if (env && env.hasOwnProperty(name)) {
|
|
345
|
-
var val = env[name];
|
|
346
|
-
// If this is an env type property we need to be careful not
|
|
347
|
-
// to get into lookup loops.
|
|
348
|
-
// 1. if the value to lookup is the same as this one, go straight to parent
|
|
349
|
-
// 2. otherwise, check if it is a compound env var ("foo $(bar)")
|
|
350
|
-
// and if so, substitute any instances of `name` with $parent.name
|
|
351
|
-
// See https://github.com/node-red/node-red/issues/2099
|
|
352
|
-
if (val.type !== 'env' || val.value !== name) {
|
|
353
|
-
let value = val.value;
|
|
354
|
-
var type = val.type;
|
|
355
|
-
if (type === 'env') {
|
|
356
|
-
value = value.replace(new RegExp("\\${"+name+"}","g"),"${$parent."+name+"}");
|
|
357
|
-
}
|
|
358
|
-
try {
|
|
359
|
-
return evaluateInputValue(value, type, this.node);
|
|
360
|
-
}
|
|
361
|
-
catch (e) {
|
|
362
|
-
this.error(e);
|
|
363
|
-
return undefined;
|
|
364
|
-
}
|
|
365
|
-
} else {
|
|
366
|
-
// This _is_ an env property pointing at itself - go to parent
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
} else {
|
|
370
|
-
// name starts $parent. ... so delegate to parent automatically
|
|
371
|
-
name = name.substring(8);
|
|
372
|
-
}
|
|
341
|
+
getSetting(key) {
|
|
373
342
|
const node = this.subflowInstance;
|
|
374
343
|
if (node) {
|
|
375
|
-
if (
|
|
344
|
+
if (key === "NR_NODE_NAME" || key === "NR_SUBFLOW_NAME") {
|
|
376
345
|
return node.name;
|
|
377
346
|
}
|
|
378
|
-
if (
|
|
347
|
+
if (key === "NR_NODE_ID" || key === "NR_SUBFLOW_ID") {
|
|
379
348
|
return node.id;
|
|
380
349
|
}
|
|
381
|
-
if (
|
|
350
|
+
if (key === "NR_NODE_PATH" || key === "NR_SUBFLOW_PATH") {
|
|
382
351
|
return node._path;
|
|
383
352
|
}
|
|
384
353
|
}
|
|
385
|
-
if (
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if (result) {
|
|
389
|
-
return result.val;
|
|
354
|
+
if (!key.startsWith("$parent.")) {
|
|
355
|
+
if (this._env.hasOwnProperty(key)) {
|
|
356
|
+
return this._env[key]
|
|
390
357
|
}
|
|
391
|
-
|
|
358
|
+
} else {
|
|
359
|
+
key = key.substring(8);
|
|
392
360
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
if (
|
|
396
|
-
|
|
397
|
-
return val;
|
|
361
|
+
// Push the request up to the parent.
|
|
362
|
+
// Unlike a Flow, the parent of a Subflow could be a Group
|
|
363
|
+
if (node.g) {
|
|
364
|
+
return this.parent.getGroupNode(node.g).getSetting(key)
|
|
398
365
|
}
|
|
399
|
-
return
|
|
366
|
+
return this.parent.getSetting(key)
|
|
400
367
|
}
|
|
401
368
|
|
|
402
369
|
/**
|