Merge branch 'dev' into 4219-missing-error-logging-for-config-nodes

This commit is contained in:
bvmensvoort
2023-06-22 20:14:56 +02:00
308 changed files with 52848 additions and 12438 deletions

View File

@@ -416,23 +416,50 @@ class Flow {
return this.activeNodes;
}
/*!
* Get value of environment variable defined in group node.
* @param {String} group - group node
* @param {String} name - name of variable
* @return {Object} object containing the value in val property or null if not defined
/**
* Group callback signature
*
* @callback GroupEnvCallback
* @param {Error} err The error object (or null)
* @param {[result: {val:Any}, name: String]} result The result of the callback
* @returns {void}
*/
getGroupEnvSetting(node, group, name) {
/**
* @function getGroupEnvSetting
* Get a group setting value synchronously.
* This currently automatically defers to the parent
* @overload
* @param {Object} node
* @param {Object} group
* @param {String} name
* @returns {Any}
*
* Get a group setting value asynchronously.
* @overload
* @param {Object} node
* @param {Object} group
* @param {String} name
* @param {GroupEnvCallback} callback
* @returns {void}
*/
getGroupEnvSetting(node, group, name, callback) {
/** @type {GroupEnvCallback} */
const returnOrCallback = (err, [result, newName]) => {
if (callback) {
callback(err, [result, newName]);
return
}
return [result, newName];
}
if (group) {
if (name === "NR_GROUP_NAME") {
return [{
val: group.name
}, null];
return returnOrCallback(null, [{ val: group.name }, null]);
}
if (name === "NR_GROUP_ID") {
return [{
val: group.id
}, null];
return returnOrCallback(null, [{ val: group.id }, null]);
}
if (group.credentials === undefined) {
@@ -457,33 +484,32 @@ class Flow {
if (env) {
let value = env.value;
const type = env.type;
if ((type !== "env") ||
(value !== name)) {
if ((type !== "env") || (value !== name)) {
if (type === "env") {
value = value.replace(new RegExp("\\${"+name+"}","g"),"${$parent."+name+"}");
}
if (type === "bool") {
const val
= ((value === "true") ||
(value === true));
return [{
val: val
}, null];
} else if (type === "bool") {
const val = ((value === "true") || (value === true));
return returnOrCallback(null, [{ val: val }, null])
}
if (type === "cred") {
return [{
val: value
}, null];
return returnOrCallback(null, [{ val: value }, null])
}
try {
var val = redUtil.evaluateNodeProperty(value, type, node, null, null);
return [{
val: val
}, null];
if (!callback) {
var val = redUtil.evaluateNodeProperty(value, type, node, null, null);
return [{ val: val }, null];
} else {
redUtil.evaluateNodeProperty(value, type, node, null, (err, value) => {
return returnOrCallback(err, [{ val: value }, null])
});
return
}
}
catch (e) {
this.error(e);
return [null, null];
if (!callback) {
this.error(e);
}
return returnOrCallback(e, null);
}
}
}
@@ -494,27 +520,47 @@ class Flow {
}
if (group.g) {
const parent = this.getGroupNode(group.g);
return this.getGroupEnvSetting(node, parent, name);
const gVal = this.getGroupEnvSetting(node, parent, name, callback);
if (callback) {
return;
}
return gVal;
}
}
return [null, name];
return returnOrCallback(null, [null, name]);
}
/**
* Settings callback signature
*
* @callback SettingsCallback
* @param {Error} err The error object (or null)
* @param {Any} result The result of the callback
* @returns {void}
*/
/**
* Get a flow setting value. This currently automatically defers to the parent
* flow which, as defined in ./index.js returns `process.env[key]`.
* This lays the groundwork for Subflow to have instance-specific settings
* @param {[type]} key [description]
* @return {[type]} [description]
* @param {String} key The settings key
* @param {SettingsCallback} callback Optional callback function
* @return {Any}
*/
getSetting(key) {
getSetting(key, callback) {
/** @type {SettingsCallback} */
const returnOrCallback = (err, result) => {
if (callback) {
callback(err, result);
return
}
return result;
}
const flow = this.flow;
if (key === "NR_FLOW_NAME") {
return flow.label;
return returnOrCallback(null, flow.label);
}
if (key === "NR_FLOW_ID") {
return flow.id;
return returnOrCallback(null, flow.id);
}
if (flow.credentials === undefined) {
flow.credentials = credentials.get(flow.id) || {};
@@ -544,15 +590,14 @@ class Flow {
}
try {
if (type === "bool") {
const val = ((value === "true") ||
(value === true));
return val;
const val = ((value === "true") || (value === true));
return returnOrCallback(null, val);
}
if (type === "cred") {
return value;
return returnOrCallback(null, value);
}
var val = redUtil.evaluateNodeProperty(value, type, null, null, null);
return val;
return returnOrCallback(null, val);
}
catch (e) {
this.error(e);
@@ -564,7 +609,11 @@ class Flow {
key = key.substring(8);
}
}
return this.parent.getSetting(key);
const pVal = this.parent.getSetting(key, callback);
if (callback) {
return;
}
return pVal;
}
/**
@@ -605,10 +654,36 @@ class Flow {
}
}
} else {
this.statusNodes.forEach(function(targetStatusNode) {
if (targetStatusNode.scope && targetStatusNode.scope.indexOf(reportingNode.id) === -1) {
const candidateNodes = [];
this.statusNodes.forEach(targetStatusNode => {
if (targetStatusNode.g && targetStatusNode.scope === 'group' && !reportingNode.g) {
// Status node inside a group, reporting node not in a group - skip it
return
}
if (Array.isArray(targetStatusNode.scope) && targetStatusNode.scope.indexOf(reportingNode.id) === -1) {
return;
}
let distance = 0
if (reportingNode.g) {
// Reporting node inside a group. Calculate the distance between it and the status node
let containingGroup = this.global.groups[reportingNode.g]
while (containingGroup && containingGroup.id !== targetStatusNode.g) {
distance++
containingGroup = this.global.groups[containingGroup.g]
}
if (!containingGroup && targetStatusNode.g && targetStatusNode.scope === 'group') {
// This status node is in a group, but not in the same hierachy
// the reporting node is in
return
}
}
candidateNodes.push({ d: distance, n: targetStatusNode })
})
candidateNodes.sort((A,B) => {
return A.d - B.d
})
candidateNodes.forEach(candidate => {
const targetStatusNode = candidate.n
var message = {
status: clone(statusMessage)
}
@@ -665,21 +740,46 @@ class Flow {
}
}
} else {
var handledByUncaught = false;
this.catchNodes.forEach(function(targetCatchNode) {
if (targetCatchNode.scope && targetCatchNode.scope.indexOf(reportingNode.id) === -1) {
const candidateNodes = [];
this.catchNodes.forEach(targetCatchNode => {
if (targetCatchNode.g && targetCatchNode.scope === 'group' && !reportingNode.g) {
// Catch node inside a group, reporting node not in a group - skip it
return
}
if (Array.isArray(targetCatchNode.scope) && targetCatchNode.scope.indexOf(reportingNode.id) === -1) {
// Catch node has a scope set and it doesn't include the reporting node
return;
}
if (!targetCatchNode.scope && targetCatchNode.uncaught && !handledByUncaught) {
if (handled) {
// This has been handled by a !uncaught catch node
return;
let distance = 0
if (reportingNode.g) {
// Reporting node inside a group. Calculate the distance between it and the catch node
let containingGroup = this.global.groups[reportingNode.g]
while (containingGroup && containingGroup.id !== targetCatchNode.g) {
distance++
containingGroup = this.global.groups[containingGroup.g]
}
if (!containingGroup && targetCatchNode.g && targetCatchNode.scope === 'group') {
// This catch node is in a group, but not in the same hierachy
// the reporting node is in
return
}
// This is an uncaught error
handledByUncaught = true;
}
var errorMessage;
candidateNodes.push({ d: distance, n: targetCatchNode })
})
candidateNodes.sort((A,B) => {
return A.d - B.d
})
let handledByUncaught = false
candidateNodes.forEach(candidate => {
const targetCatchNode = candidate.n
if (targetCatchNode.uncaught && !handledByUncaught) {
// This node only wants errors that haven't already been handled
if (handled) {
return
}
handledByUncaught = true
}
let errorMessage;
if (msg) {
errorMessage = redUtil.cloneMessage(msg);
} else {