@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.
@@ -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 nodeEnv = await flowUtil.evaluateEnvProperties(this, node.env, credentials.get(node.id))
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
  }
@@ -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
- node.wires[wires[j].port] = node.wires[wires[j].port].concat(newWires[i]);
258
- modifiedNodes[node.id] = node;
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 (!node._originalWires) {
287
- node._originalWires = clone(node.wires);
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 (!node._originalWires) {
306
- node._originalWires = clone(node.wires);
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
- var v = obj[prop];
60
+ const v = obj[prop];
61
61
  if (Buffer.isBuffer(v)) {
62
62
  return;
63
63
  } else if (Array.isArray(v)) {
64
- for (var i=0;i<v.length;i++) {
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
- var envVar = v.substring(2,v.length-1);
70
- var r = redUtil.getSetting(config, envVar, flow);
71
- obj[prop] = r ? r : obj[prop];
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: flow}, null, null);
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
- c--;
233
- if (c === 0) {
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;
@@ -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 tourne maintenant sur __listenpath__",
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---------------------------------------------------------------------\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",
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.0",
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.0",
20
- "@node-red/util": "3.1.0",
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",