@node-red/runtime 3.1.0 → 3.1.2
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/api/settings.js +3 -0
- package/lib/flows/Flow.js +2 -1
- package/lib/flows/Subflow.js +32 -10
- package/lib/flows/util.js +20 -6
- package/lib/nodes/Node.js +10 -5
- package/locales/fr/runtime.json +2 -2
- package/package.json +3 -3
package/lib/api/settings.js
CHANGED
|
@@ -99,6 +99,9 @@ var api = module.exports = {
|
|
|
99
99
|
safeSettings.markdownEditor = runtime.settings.editorTheme.markdownEditor || {};
|
|
100
100
|
safeSettings.markdownEditor.mermaid = safeSettings.markdownEditor.mermaid || { enabled: true };
|
|
101
101
|
}
|
|
102
|
+
if (runtime.settings.editorTheme.mermaid) {
|
|
103
|
+
safeSettings.mermaid = runtime.settings.editorTheme.mermaid
|
|
104
|
+
}
|
|
102
105
|
}
|
|
103
106
|
safeSettings.libraries = runtime.library.getLibraries();
|
|
104
107
|
if (util.isArray(runtime.settings.paletteCategories)) {
|
package/lib/flows/Flow.js
CHANGED
|
@@ -161,7 +161,8 @@ class Flow {
|
|
|
161
161
|
for (let i = 0; i < configNodes.length; i++) {
|
|
162
162
|
const node = this.flow.configs[configNodes[i]]
|
|
163
163
|
if (node.type === 'global-config' && node.env) {
|
|
164
|
-
const
|
|
164
|
+
const globalCreds = credentials.get(node.id)?.map || {}
|
|
165
|
+
const nodeEnv = await flowUtil.evaluateEnvProperties(this, node.env, globalCreds)
|
|
165
166
|
this._env = { ...this._env, ...nodeEnv }
|
|
166
167
|
}
|
|
167
168
|
}
|
package/lib/flows/Subflow.js
CHANGED
|
@@ -73,9 +73,20 @@ class Subflow extends Flow {
|
|
|
73
73
|
id: subflowInstance.id,
|
|
74
74
|
configs: {},
|
|
75
75
|
nodes: {},
|
|
76
|
+
groups: {},
|
|
76
77
|
subflows: {}
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
if (subflowDef.groups) {
|
|
81
|
+
// Clone all of the subflow group definitions and give them new IDs
|
|
82
|
+
for (i in subflowDef.groups) {
|
|
83
|
+
if (subflowDef.groups.hasOwnProperty(i)) {
|
|
84
|
+
node = createNodeInSubflow(subflowInstance.id,subflowDef.groups[i]);
|
|
85
|
+
node_map[node._alias] = node;
|
|
86
|
+
subflowInternalFlowConfig.groups[node.id] = node;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
79
90
|
if (subflowDef.configs) {
|
|
80
91
|
// Clone all of the subflow config node definitions and give them new IDs
|
|
81
92
|
for (i in subflowDef.configs) {
|
|
@@ -101,6 +112,7 @@ class Subflow extends Flow {
|
|
|
101
112
|
|
|
102
113
|
remapSubflowNodes(subflowInternalFlowConfig.configs,node_map);
|
|
103
114
|
remapSubflowNodes(subflowInternalFlowConfig.nodes,node_map);
|
|
115
|
+
remapSubflowNodes(subflowInternalFlowConfig.groups,node_map);
|
|
104
116
|
|
|
105
117
|
// console.log("Instance config\n",JSON.stringify(subflowInternalFlowConfig,"",2));
|
|
106
118
|
|
|
@@ -237,7 +249,7 @@ class Subflow extends Flow {
|
|
|
237
249
|
for (j=0;j<wires.length;j++) {
|
|
238
250
|
if (wires[j].id != self.subflowDef.id) {
|
|
239
251
|
node = self.node_map[wires[j].id];
|
|
240
|
-
if (node._originalWires) {
|
|
252
|
+
if (node && node._originalWires) {
|
|
241
253
|
node.wires = clone(node._originalWires);
|
|
242
254
|
}
|
|
243
255
|
}
|
|
@@ -254,8 +266,10 @@ class Subflow extends Flow {
|
|
|
254
266
|
subflowInstanceModified = true;
|
|
255
267
|
} else {
|
|
256
268
|
node = self.node_map[wires[j].id];
|
|
257
|
-
|
|
258
|
-
|
|
269
|
+
if (node) {
|
|
270
|
+
node.wires[wires[j].port] = node.wires[wires[j].port].concat(newWires[i]);
|
|
271
|
+
modifiedNodes[node.id] = node;
|
|
272
|
+
}
|
|
259
273
|
}
|
|
260
274
|
}
|
|
261
275
|
}
|
|
@@ -283,10 +297,14 @@ class Subflow extends Flow {
|
|
|
283
297
|
this.node._updateWires(subflowInstanceConfig.wires);
|
|
284
298
|
} else {
|
|
285
299
|
var node = self.node_map[wires[j].id];
|
|
286
|
-
if (
|
|
287
|
-
|
|
300
|
+
if (node) {
|
|
301
|
+
if (!node._originalWires) {
|
|
302
|
+
node._originalWires = clone(node.wires);
|
|
303
|
+
}
|
|
304
|
+
node.wires[wires[j].port] = (node.wires[wires[j].port]||[]).concat(this.subflowInstance.wires[i]);
|
|
305
|
+
} else {
|
|
306
|
+
this.error("Unknown node referenced inside subflow: " + wires[j].id)
|
|
288
307
|
}
|
|
289
|
-
node.wires[wires[j].port] = (node.wires[wires[j].port]||[]).concat(this.subflowInstance.wires[i]);
|
|
290
308
|
}
|
|
291
309
|
}
|
|
292
310
|
}
|
|
@@ -302,11 +320,15 @@ class Subflow extends Flow {
|
|
|
302
320
|
this.node._updateWires(subflowInstanceConfig.wires);
|
|
303
321
|
} else {
|
|
304
322
|
var node = self.node_map[wires[j].id];
|
|
305
|
-
if (
|
|
306
|
-
|
|
323
|
+
if (node) {
|
|
324
|
+
if (!node._originalWires) {
|
|
325
|
+
node._originalWires = clone(node.wires);
|
|
326
|
+
}
|
|
327
|
+
node.wires[wires[j].port] = (node.wires[wires[j].port]||[]);
|
|
328
|
+
node.wires[wires[j].port].push(subflowStatusId);
|
|
329
|
+
} else {
|
|
330
|
+
this.error("Unknown node referenced inside subflow: " + wires[j].id)
|
|
307
331
|
}
|
|
308
|
-
node.wires[wires[j].port] = (node.wires[wires[j].port]||[]);
|
|
309
|
-
node.wires[wires[j].port].push(subflowStatusId);
|
|
310
332
|
}
|
|
311
333
|
}
|
|
312
334
|
}
|
package/lib/flows/util.js
CHANGED
|
@@ -57,18 +57,20 @@ var EnvVarPropertyRE = /^\${(\S+)}$/;
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
function mapEnvVarProperties(obj,prop,flow,config) {
|
|
60
|
-
|
|
60
|
+
const v = obj[prop];
|
|
61
61
|
if (Buffer.isBuffer(v)) {
|
|
62
62
|
return;
|
|
63
63
|
} else if (Array.isArray(v)) {
|
|
64
|
-
for (
|
|
64
|
+
for (let i=0;i<v.length;i++) {
|
|
65
65
|
mapEnvVarProperties(v,i,flow,config);
|
|
66
66
|
}
|
|
67
67
|
} else if (typeof obj[prop] === 'string') {
|
|
68
68
|
if (obj[prop][0] === "$" && (EnvVarPropertyRE_old.test(v) || EnvVarPropertyRE.test(v)) ) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
const envVar = v.substring(2,v.length-1);
|
|
70
|
+
const r = redUtil.getSetting(config, envVar, flow);
|
|
71
|
+
if (r !== undefined && r !== '') {
|
|
72
|
+
obj[prop] = r
|
|
73
|
+
}
|
|
72
74
|
}
|
|
73
75
|
} else {
|
|
74
76
|
for (var p in v) {
|
|
@@ -80,6 +82,7 @@ function mapEnvVarProperties(obj,prop,flow,config) {
|
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
async function evaluateEnvProperties(flow, env, credentials) {
|
|
85
|
+
credentials = credentials || {}
|
|
83
86
|
const pendingEvaluations = []
|
|
84
87
|
const evaluatedEnv = {}
|
|
85
88
|
const envTypes = []
|
|
@@ -112,6 +115,7 @@ async function evaluateEnvProperties(flow, env, credentials) {
|
|
|
112
115
|
if (pendingEvaluations.length > 0) {
|
|
113
116
|
await Promise.all(pendingEvaluations)
|
|
114
117
|
}
|
|
118
|
+
// Now loop over the env types and evaluate them properly
|
|
115
119
|
for (let i = 0; i < envTypes.length; i++) {
|
|
116
120
|
let { name, value, type } = envTypes[i]
|
|
117
121
|
// If an env-var wants to lookup itself, delegate straight to the parent
|
|
@@ -122,7 +126,17 @@ async function evaluateEnvProperties(flow, env, credentials) {
|
|
|
122
126
|
if (evaluatedEnv.hasOwnProperty(value)) {
|
|
123
127
|
value = evaluatedEnv[value]
|
|
124
128
|
} else {
|
|
125
|
-
value = redUtil.evaluateNodeProperty(value, type, {_flow:
|
|
129
|
+
value = redUtil.evaluateNodeProperty(value, type, {_flow: {
|
|
130
|
+
// Provide a hook so when it tries to look up a flow setting,
|
|
131
|
+
// we can insert the just-evaluated value which hasn't yet
|
|
132
|
+
// been set on the flow object - otherwise delegate up to the flow
|
|
133
|
+
getSetting: function(name) {
|
|
134
|
+
if (evaluatedEnv.hasOwnProperty(name)){
|
|
135
|
+
return evaluatedEnv[name]
|
|
136
|
+
}
|
|
137
|
+
return flow.getSetting(name)
|
|
138
|
+
}
|
|
139
|
+
}}, null, null);
|
|
126
140
|
}
|
|
127
141
|
evaluatedEnv[name] = value
|
|
128
142
|
}
|
package/lib/nodes/Node.js
CHANGED
|
@@ -42,6 +42,7 @@ function Node(n) {
|
|
|
42
42
|
this._closeCallbacks = [];
|
|
43
43
|
this._inputCallback = null;
|
|
44
44
|
this._inputCallbacks = null;
|
|
45
|
+
this._expectedDoneCount = 0;
|
|
45
46
|
|
|
46
47
|
if (n.name) {
|
|
47
48
|
this.name = n.name;
|
|
@@ -159,6 +160,9 @@ Node.prototype.on = function(event, callback) {
|
|
|
159
160
|
if (event == "close") {
|
|
160
161
|
this._closeCallbacks.push(callback);
|
|
161
162
|
} else if (event === "input") {
|
|
163
|
+
if (callback.length === 3) {
|
|
164
|
+
this._expectedDoneCount++
|
|
165
|
+
}
|
|
162
166
|
if (this._inputCallback) {
|
|
163
167
|
this._inputCallbacks = [this._inputCallback, callback];
|
|
164
168
|
this._inputCallback = null;
|
|
@@ -218,19 +222,17 @@ Node.prototype._emitInput = function(arg) {
|
|
|
218
222
|
} else if (node._inputCallbacks) {
|
|
219
223
|
// Multiple callbacks registered. Call each one, tracking eventual completion
|
|
220
224
|
var c = node._inputCallbacks.length;
|
|
225
|
+
let doneCount = 0
|
|
221
226
|
for (var i=0;i<c;i++) {
|
|
222
227
|
var cb = node._inputCallbacks[i];
|
|
223
|
-
if (cb.length === 2) {
|
|
224
|
-
c++;
|
|
225
|
-
}
|
|
226
228
|
try {
|
|
227
229
|
cb.call(
|
|
228
230
|
node,
|
|
229
231
|
arg,
|
|
230
232
|
function() { node.send.apply(node,arguments) },
|
|
231
233
|
function(err) {
|
|
232
|
-
|
|
233
|
-
if (
|
|
234
|
+
doneCount++;
|
|
235
|
+
if (doneCount === node._expectedDoneCount) {
|
|
234
236
|
node._complete(arg,err);
|
|
235
237
|
}
|
|
236
238
|
}
|
|
@@ -257,6 +259,9 @@ Node.prototype._removeListener = Node.prototype.removeListener;
|
|
|
257
259
|
Node.prototype.removeListener = function(name, listener) {
|
|
258
260
|
var index;
|
|
259
261
|
if (name === "input") {
|
|
262
|
+
if (listener.length === 3) {
|
|
263
|
+
this._expectedDoneCount--
|
|
264
|
+
}
|
|
260
265
|
if (this._inputCallback && this._inputCallback === listener) {
|
|
261
266
|
// Removing the only callback
|
|
262
267
|
this._inputCallback = null;
|
package/locales/fr/runtime.json
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"port-in-use": "Erreur : port utilisé",
|
|
49
49
|
"uncaught-exception": "Exception non reconnue :",
|
|
50
50
|
"admin-ui-disabled": "Interface d'administration désactivée",
|
|
51
|
-
"now-running": "Le serveur
|
|
51
|
+
"now-running": "Le serveur est disponible à l'adresse __listenpath__",
|
|
52
52
|
"failed-to-start": "Échec lors du démarrage du serveur :",
|
|
53
53
|
"headless-mode": "Fonctionne en mode sans interface graphique (headless)",
|
|
54
54
|
"httpadminauth-deprecated": "L'utilisation de httpAdminAuth est DÉCONSEILLÉE. Utiliser adminAuth à la place",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"error": "Erreur lors du chargement des identifiants : __message__",
|
|
101
101
|
"error-saving": "Erreur lors de l'enregistrement des identifiants : __message__",
|
|
102
102
|
"not-registered": "Le type d'identifiant '__type__' n'a pas été enregistré",
|
|
103
|
-
"system-key-warning": "\n\n
|
|
103
|
+
"system-key-warning": "\n\n--------------------------------------------------------------------------------------------------------\nVotre fichier contenant les identifiants de flux est chiffré à l'aide d'une clé générée par le système.\n\nSi la clé générée par le système est perdue pour une raison quelconque, votre fichier contenant\nles identifiants ne sera pas récupérable, vous devrez le supprimer et ressaisir vos identifiants.\n\nVous pouvez définir votre propre clé en utilisant l'option 'credentialSecret' dans\nvotre fichier de paramètres. Node-RED rechiffrera alors votre fichier contenant les identifiants\nà l'aide de la clé que vous avez choisie la prochaine fois que vous déploierez une modification.\n--------------------------------------------------------------------------------------------------------\n",
|
|
104
104
|
"unencrypted": "Utilisation d'identifiants non chiffrés",
|
|
105
105
|
"encryptedNotFound": "Identifiants chiffrés introuvables"
|
|
106
106
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-red/runtime",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@node-red/registry": "3.1.
|
|
20
|
-
"@node-red/util": "3.1.
|
|
19
|
+
"@node-red/registry": "3.1.2",
|
|
20
|
+
"@node-red/util": "3.1.2",
|
|
21
21
|
"async-mutex": "0.4.0",
|
|
22
22
|
"clone": "2.1.2",
|
|
23
23
|
"express": "4.18.2",
|