@node-red/runtime 3.0.0-beta.3 → 3.0.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/api/flows.js +78 -1
- package/lib/api/settings.js +13 -1
- package/lib/flows/index.js +37 -12
- package/lib/index.js +3 -3
- package/locales/en-US/runtime.json +1 -0
- package/package.json +3 -3
package/lib/api/flows.js
CHANGED
|
@@ -255,5 +255,82 @@ var api = module.exports = {
|
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
return sendCredentials;
|
|
258
|
-
}
|
|
258
|
+
},
|
|
259
|
+
/**
|
|
260
|
+
* Gets running state of runtime flows
|
|
261
|
+
* @param {Object} opts
|
|
262
|
+
* @param {User} opts.user - the user calling the api
|
|
263
|
+
* @param {Object} opts.req - the request to log (optional)
|
|
264
|
+
* @return {{state:string, started:boolean}} - the current run state of the flows
|
|
265
|
+
* @memberof @node-red/runtime_flows
|
|
266
|
+
*/
|
|
267
|
+
getState: async function(opts) {
|
|
268
|
+
runtime.log.audit({event: "flows.getState"}, opts.req);
|
|
269
|
+
const result = {
|
|
270
|
+
state: runtime.flows.state()
|
|
271
|
+
}
|
|
272
|
+
return result;
|
|
273
|
+
},
|
|
274
|
+
/**
|
|
275
|
+
* Sets running state of runtime flows
|
|
276
|
+
* @param {Object} opts
|
|
277
|
+
* @param {Object} opts.req - the request to log (optional)
|
|
278
|
+
* @param {User} opts.user - the user calling the api
|
|
279
|
+
* @param {string} opts.state - the requested state. Valid values are "start" and "stop".
|
|
280
|
+
* @return {Promise<Flow>} - the active flow configuration
|
|
281
|
+
* @memberof @node-red/runtime_flows
|
|
282
|
+
*/
|
|
283
|
+
setState: async function(opts) {
|
|
284
|
+
opts = opts || {};
|
|
285
|
+
const makeError = (error, errcode, statusCode) => {
|
|
286
|
+
const message = typeof error == "object" ? error.message : error
|
|
287
|
+
const err = typeof error == "object" ? error : new Error(message||"Unexpected Error")
|
|
288
|
+
err.status = err.status || statusCode || 400;
|
|
289
|
+
err.code = err.code || errcode || "unexpected_error"
|
|
290
|
+
runtime.log.audit({
|
|
291
|
+
event: "flows.setState",
|
|
292
|
+
state: opts.state || "",
|
|
293
|
+
error: errcode || "unexpected_error",
|
|
294
|
+
message: err.code
|
|
295
|
+
}, opts.req);
|
|
296
|
+
return err
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const getState = () => {
|
|
300
|
+
return {
|
|
301
|
+
state: runtime.flows.state()
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if(!runtime.settings.runtimeState || runtime.settings.runtimeState.enabled !== true) {
|
|
306
|
+
throw (makeError("Method Not Allowed", "not_allowed", 405))
|
|
307
|
+
}
|
|
308
|
+
switch (opts.state) {
|
|
309
|
+
case "start":
|
|
310
|
+
try {
|
|
311
|
+
try {
|
|
312
|
+
runtime.settings.set('runtimeFlowState', opts.state);
|
|
313
|
+
} catch(err) {}
|
|
314
|
+
if (runtime.settings.safeMode) {
|
|
315
|
+
delete runtime.settings.safeMode
|
|
316
|
+
}
|
|
317
|
+
await runtime.flows.startFlows("full")
|
|
318
|
+
return getState()
|
|
319
|
+
} catch (err) {
|
|
320
|
+
throw (makeError(err, err.code, 500))
|
|
321
|
+
}
|
|
322
|
+
case "stop":
|
|
323
|
+
try {
|
|
324
|
+
try {
|
|
325
|
+
runtime.settings.set('runtimeFlowState', opts.state);
|
|
326
|
+
} catch(err) {}
|
|
327
|
+
await runtime.flows.stopFlows("full")
|
|
328
|
+
return getState()
|
|
329
|
+
} catch (err) {
|
|
330
|
+
throw (makeError(err, err.code, 500))
|
|
331
|
+
}
|
|
332
|
+
default:
|
|
333
|
+
throw (makeError(`Cannot change flows runtime state to '${opts.state}'}`, "invalid_run_state", 400))
|
|
334
|
+
}
|
|
335
|
+
},
|
|
259
336
|
}
|
package/lib/api/settings.js
CHANGED
|
@@ -91,7 +91,7 @@ var api = module.exports = {
|
|
|
91
91
|
safeSettings.context = runtime.nodes.listContextStores();
|
|
92
92
|
if (runtime.settings.editorTheme && runtime.settings.editorTheme.codeEditor) {
|
|
93
93
|
safeSettings.codeEditor = runtime.settings.editorTheme.codeEditor || {};
|
|
94
|
-
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "
|
|
94
|
+
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "monaco";
|
|
95
95
|
safeSettings.codeEditor.options = safeSettings.codeEditor.options || {};
|
|
96
96
|
}
|
|
97
97
|
safeSettings.libraries = runtime.library.getLibraries();
|
|
@@ -148,6 +148,18 @@ var api = module.exports = {
|
|
|
148
148
|
enabled: (runtime.settings.diagnostics && runtime.settings.diagnostics.enabled === false) ? false : true,
|
|
149
149
|
ui: (runtime.settings.diagnostics && runtime.settings.diagnostics.ui === false) ? false : true
|
|
150
150
|
}
|
|
151
|
+
if(safeSettings.diagnostics.enabled === false) {
|
|
152
|
+
safeSettings.diagnostics.ui = false; // cannot have UI without endpoint
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
safeSettings.runtimeState = {
|
|
156
|
+
//unless runtimeState.ui and runtimeState.enabled are explicitly true, they will default to false.
|
|
157
|
+
enabled: !!runtime.settings.runtimeState && runtime.settings.runtimeState.enabled === true,
|
|
158
|
+
ui: !!runtime.settings.runtimeState && runtime.settings.runtimeState.ui === true
|
|
159
|
+
}
|
|
160
|
+
if(safeSettings.runtimeState.enabled !== true) {
|
|
161
|
+
safeSettings.runtimeState.ui = false; // cannot have UI without endpoint
|
|
162
|
+
}
|
|
151
163
|
|
|
152
164
|
runtime.settings.exportNodeSettings(safeSettings);
|
|
153
165
|
runtime.plugins.exportPluginSettings(safeSettings);
|
package/lib/flows/index.js
CHANGED
|
@@ -36,6 +36,8 @@ var activeFlowConfig = null;
|
|
|
36
36
|
|
|
37
37
|
var activeFlows = {};
|
|
38
38
|
var started = false;
|
|
39
|
+
var state = 'stop'
|
|
40
|
+
|
|
39
41
|
var credentialsPendingReset = false;
|
|
40
42
|
|
|
41
43
|
var activeNodesToFlow = {};
|
|
@@ -50,6 +52,7 @@ function init(runtime) {
|
|
|
50
52
|
storage = runtime.storage;
|
|
51
53
|
log = runtime.log;
|
|
52
54
|
started = false;
|
|
55
|
+
state = 'stop';
|
|
53
56
|
if (!typeEventRegistered) {
|
|
54
57
|
events.on('type-registered',function(type) {
|
|
55
58
|
if (activeFlowConfig && activeFlowConfig.missingTypes.length > 0) {
|
|
@@ -214,19 +217,26 @@ function setFlows(_config,_credentials,type,muteLog,forceStart,user) {
|
|
|
214
217
|
// Flows are running (or should be)
|
|
215
218
|
|
|
216
219
|
// Stop the active flows (according to deploy type and the diff)
|
|
217
|
-
return stop(type,diff,muteLog).then(() => {
|
|
220
|
+
return stop(type,diff,muteLog,true).then(() => {
|
|
218
221
|
// Once stopped, allow context to remove anything no longer needed
|
|
219
222
|
return context.clean(activeFlowConfig)
|
|
220
223
|
}).then(() => {
|
|
224
|
+
if (!isLoad) {
|
|
225
|
+
log.info(log._("nodes.flows.updated-flows"));
|
|
226
|
+
}
|
|
221
227
|
// Start the active flows
|
|
222
|
-
start(type,diff,muteLog).then(() => {
|
|
228
|
+
start(type,diff,muteLog,true).then(() => {
|
|
223
229
|
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
|
224
230
|
});
|
|
225
231
|
// Return the new revision asynchronously to the actual start
|
|
226
232
|
return flowRevision;
|
|
227
233
|
}).catch(function(err) { })
|
|
228
234
|
} else {
|
|
235
|
+
if (!isLoad) {
|
|
236
|
+
log.info(log._("nodes.flows.updated-flows"));
|
|
237
|
+
}
|
|
229
238
|
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
|
239
|
+
return flowRevision;
|
|
230
240
|
}
|
|
231
241
|
});
|
|
232
242
|
}
|
|
@@ -259,9 +269,10 @@ function getFlows() {
|
|
|
259
269
|
return activeConfig;
|
|
260
270
|
}
|
|
261
271
|
|
|
262
|
-
async function start(type,diff,muteLog) {
|
|
263
|
-
type = type||"full";
|
|
272
|
+
async function start(type,diff,muteLog,isDeploy) {
|
|
273
|
+
type = type || "full";
|
|
264
274
|
started = true;
|
|
275
|
+
state = 'start'
|
|
265
276
|
var i;
|
|
266
277
|
// If there are missing types, report them, emit the necessary runtime event and return
|
|
267
278
|
if (activeFlowConfig.missingTypes.length > 0) {
|
|
@@ -283,7 +294,7 @@ async function start(type,diff,muteLog) {
|
|
|
283
294
|
log.info(log._("nodes.flows.missing-type-install-2"));
|
|
284
295
|
log.info(" "+settings.userDir);
|
|
285
296
|
}
|
|
286
|
-
events.emit("runtime-event",{id:"runtime-state",payload:{error:"missing-types", type:"warning",text:"notification.warnings.missing-types",types:activeFlowConfig.missingTypes},retain:true});
|
|
297
|
+
events.emit("runtime-event",{id:"runtime-state",payload:{state: 'stop', error:"missing-types", type:"warning",text:"notification.warnings.missing-types",types:activeFlowConfig.missingTypes},retain:true});
|
|
287
298
|
return;
|
|
288
299
|
}
|
|
289
300
|
|
|
@@ -297,7 +308,7 @@ async function start(type,diff,muteLog) {
|
|
|
297
308
|
missingModules.push({module:err[i].module.module, error: err[i].error.code || err[i].error.toString()})
|
|
298
309
|
log.info(` - ${err[i].module.spec} [${err[i].error.code || "unknown_error"}]`);
|
|
299
310
|
}
|
|
300
|
-
events.emit("runtime-event",{id:"runtime-state",payload:{error:"missing-modules", type:"warning",text:"notification.warnings.missing-modules",modules:missingModules},retain:true});
|
|
311
|
+
events.emit("runtime-event",{id:"runtime-state",payload:{state: 'stop', error:"missing-modules", type:"warning",text:"notification.warnings.missing-modules",modules:missingModules},retain:true});
|
|
301
312
|
return;
|
|
302
313
|
}
|
|
303
314
|
|
|
@@ -306,10 +317,23 @@ async function start(type,diff,muteLog) {
|
|
|
306
317
|
log.info("*****************************************************************")
|
|
307
318
|
log.info(log._("nodes.flows.safe-mode"));
|
|
308
319
|
log.info("*****************************************************************")
|
|
309
|
-
|
|
320
|
+
state = 'safe'
|
|
321
|
+
events.emit("runtime-event",{id:"runtime-state",payload:{state: 'safe', error:"safe-mode", type:"warning",text:"notification.warnings.safe-mode"},retain:true});
|
|
310
322
|
return;
|
|
311
323
|
}
|
|
312
324
|
|
|
325
|
+
let runtimeState
|
|
326
|
+
try {
|
|
327
|
+
runtimeState = settings.get('runtimeFlowState') || 'start'
|
|
328
|
+
} catch (err) {}
|
|
329
|
+
if (runtimeState === 'stop') {
|
|
330
|
+
log.info(log._("nodes.flows.stopped-flows"));
|
|
331
|
+
events.emit("runtime-event",{id:"runtime-state",payload:{ state: 'stop', deploy:isDeploy },retain:true});
|
|
332
|
+
state = 'stop'
|
|
333
|
+
started = false
|
|
334
|
+
return
|
|
335
|
+
}
|
|
336
|
+
|
|
313
337
|
if (!muteLog) {
|
|
314
338
|
if (type !== "full") {
|
|
315
339
|
log.info(log._("nodes.flows.starting-modified-"+type));
|
|
@@ -364,12 +388,10 @@ async function start(type,diff,muteLog) {
|
|
|
364
388
|
}
|
|
365
389
|
}
|
|
366
390
|
}
|
|
367
|
-
// Having created or updated all flows, now start them.
|
|
368
391
|
for (id in activeFlows) {
|
|
369
392
|
if (activeFlows.hasOwnProperty(id)) {
|
|
370
393
|
try {
|
|
371
394
|
activeFlows[id].start(diff);
|
|
372
|
-
|
|
373
395
|
// Create a map of node id to flow id and also a subflowInstance lookup map
|
|
374
396
|
var activeNodes = activeFlows[id].getActiveNodes();
|
|
375
397
|
Object.keys(activeNodes).forEach(function(nid) {
|
|
@@ -387,7 +409,7 @@ async function start(type,diff,muteLog) {
|
|
|
387
409
|
if (credentialsPendingReset === true) {
|
|
388
410
|
credentialsPendingReset = false;
|
|
389
411
|
} else {
|
|
390
|
-
events.emit("runtime-event",{id:"runtime-state",retain:true});
|
|
412
|
+
events.emit("runtime-event",{id:"runtime-state", payload:{ state: 'start', deploy:isDeploy}, retain:true});
|
|
391
413
|
}
|
|
392
414
|
|
|
393
415
|
if (!muteLog) {
|
|
@@ -400,7 +422,7 @@ async function start(type,diff,muteLog) {
|
|
|
400
422
|
return;
|
|
401
423
|
}
|
|
402
424
|
|
|
403
|
-
function stop(type,diff,muteLog) {
|
|
425
|
+
function stop(type,diff,muteLog,isDeploy) {
|
|
404
426
|
if (!started) {
|
|
405
427
|
return Promise.resolve();
|
|
406
428
|
}
|
|
@@ -420,6 +442,7 @@ function stop(type,diff,muteLog) {
|
|
|
420
442
|
}
|
|
421
443
|
}
|
|
422
444
|
started = false;
|
|
445
|
+
state = 'stop'
|
|
423
446
|
var promises = [];
|
|
424
447
|
var stopList;
|
|
425
448
|
var removedList = diff.removed;
|
|
@@ -471,6 +494,8 @@ function stop(type,diff,muteLog) {
|
|
|
471
494
|
}
|
|
472
495
|
}
|
|
473
496
|
events.emit("flows:stopped",{config: activeConfig, type: type, diff: diff});
|
|
497
|
+
|
|
498
|
+
events.emit("runtime-event",{ id:"runtime-state", payload:{ state: 'stop', deploy:isDeploy }, retain:true });
|
|
474
499
|
// Deprecated event
|
|
475
500
|
events.emit("nodes-stopped");
|
|
476
501
|
});
|
|
@@ -790,7 +815,7 @@ module.exports = {
|
|
|
790
815
|
stopFlows: stop,
|
|
791
816
|
|
|
792
817
|
get started() { return started },
|
|
793
|
-
|
|
818
|
+
state: () => { return state },
|
|
794
819
|
// handleError: handleError,
|
|
795
820
|
// handleStatus: handleStatus,
|
|
796
821
|
|
package/lib/index.js
CHANGED
|
@@ -215,7 +215,7 @@ function start() {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
return redNodes.loadContextsPlugin().then(function () {
|
|
218
|
-
redNodes.loadFlows().then(redNodes.startFlows).catch(function(err) {});
|
|
218
|
+
redNodes.loadFlows().then(() => { redNodes.startFlows() }).catch(function(err) {});
|
|
219
219
|
started = true;
|
|
220
220
|
});
|
|
221
221
|
});
|
|
@@ -399,12 +399,12 @@ module.exports = {
|
|
|
399
399
|
* @memberof @node-red/runtime
|
|
400
400
|
*/
|
|
401
401
|
version: externalAPI.version,
|
|
402
|
-
|
|
402
|
+
|
|
403
403
|
/**
|
|
404
404
|
* @memberof @node-red/diagnostics
|
|
405
405
|
*/
|
|
406
406
|
diagnostics:externalAPI.diagnostics,
|
|
407
|
-
|
|
407
|
+
|
|
408
408
|
storage: storage,
|
|
409
409
|
events: events,
|
|
410
410
|
hooks: hooks,
|
|
@@ -122,6 +122,7 @@
|
|
|
122
122
|
"stopped-flows": "Stopped flows",
|
|
123
123
|
"stopped": "Stopped",
|
|
124
124
|
"stopping-error": "Error stopping node: __message__",
|
|
125
|
+
"updated-flows": "Updated flows",
|
|
125
126
|
"added-flow": "Adding flow: __label__",
|
|
126
127
|
"updated-flow": "Updated flow: __label__",
|
|
127
128
|
"removed-flow": "Removed flow: __label__",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-red/runtime",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.4",
|
|
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.0.0-beta.
|
|
20
|
-
"@node-red/util": "3.0.0-beta.
|
|
19
|
+
"@node-red/registry": "3.0.0-beta.4",
|
|
20
|
+
"@node-red/util": "3.0.0-beta.4",
|
|
21
21
|
"async-mutex": "0.3.2",
|
|
22
22
|
"clone": "2.1.2",
|
|
23
23
|
"express": "4.18.1",
|