From 3ca045394a0385f5f7a866f8e31dd24fed869a38 Mon Sep 17 00:00:00 2001 From: Kazuhito Yokoi Date: Sat, 16 Mar 2024 18:51:13 +0900 Subject: [PATCH 01/10] Remove typo in global config --- .../@node-red/nodes/locales/ja/common/91-global-config.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node_modules/@node-red/nodes/locales/ja/common/91-global-config.html b/packages/node_modules/@node-red/nodes/locales/ja/common/91-global-config.html index 2eda840ec..ad28f5392 100644 --- a/packages/node_modules/@node-red/nodes/locales/ja/common/91-global-config.html +++ b/packages/node_modules/@node-red/nodes/locales/ja/common/91-global-config.html @@ -1,3 +1,3 @@ p + From ae5e1570ae4b4da52e7c2dcd238d85fbef5d6e27 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 21 Mar 2024 11:14:34 +0000 Subject: [PATCH 02/10] Reset workspace index when clearing nodes Fixes #4600 --- .../@node-red/editor-client/src/js/ui/workspaces.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js index 2fa78f679..d338ee651 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js @@ -491,6 +491,11 @@ RED.workspaces = (function() { createWorkspaceTabs(); RED.events.on("sidebar:resize",workspace_tabs.resize); + RED.events.on("workspace:clear", () => { + // Reset the index used to generate new flow names + workspaceIndex = 0 + }) + RED.actions.add("core:show-next-tab",function() { var oldActive = activeWorkspace; workspace_tabs.nextTab(); From d7dcceef60c3fb5bf2756b36a9dc13e9e83a27be Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 21 Mar 2024 11:32:29 +0000 Subject: [PATCH 03/10] Add debug for http tests --- test/nodes/core/network/21-httprequest_spec.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/nodes/core/network/21-httprequest_spec.js b/test/nodes/core/network/21-httprequest_spec.js index 4d159e402..8ddf8542f 100644 --- a/test/nodes/core/network/21-httprequest_spec.js +++ b/test/nodes/core/network/21-httprequest_spec.js @@ -81,6 +81,7 @@ describe('HTTP Request Node', function() { */ }; testSslServer = stoppable(https.createServer(sslOptions,testApp)); + console.log('> start testSslServer') testSslServer.listen(testSslPort, function(err){ if (err) { console.log(err); @@ -97,6 +98,7 @@ describe('HTTP Request Node', function() { requestCert: true }; testSslClientServer = stoppable(https.createServer(sslClientOptions, testApp)); + console.log('> start testSslClientServer.listen') testSslClientServer.listen(testSslClientPort, function(err){ console.log("ssl-client", err) }); @@ -109,7 +111,10 @@ describe('HTTP Request Node', function() { res.setHeader("x-testproxy-header", "foobar") } }) - testProxyServer.listen(testProxyPort) + console.log('> testProxyServer') + testProxyServer.listen(testProxyPort, function(err) { + console.log('testProxyServer start', err) + }) testProxyAuthPort += 1 testProxyServerAuth = stoppable(httpProxy(http.createServer())) @@ -131,7 +136,10 @@ describe('HTTP Request Node', function() { res.setHeader("x-testproxy-header", "foobar") } }) - testProxyServerAuth.listen(testProxyAuthPort) + console.log('> testProxyServerAuth') + testProxyServerAuth.listen(testProxyAuthPort, function(err) { + console.log('testProxyServerAuth start', err) + }) done(err); }); @@ -429,7 +437,11 @@ describe('HTTP Request Node', function() { if (err) { done(err); } - helper.startServer(done); + console.log('> helper.startServer') + helper.startServer(function(err) { + console.log('> helper started') + done(err) + }); }); }); From 02f7cdd5aa5f5e50025b7da955a84286d5fda7b7 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 21 Mar 2024 15:03:37 +0000 Subject: [PATCH 04/10] Ensure all httpRequest test servers are ready before tests run --- .../nodes/core/network/21-httprequest_spec.js | 62 +++++++++++++------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/test/nodes/core/network/21-httprequest_spec.js b/test/nodes/core/network/21-httprequest_spec.js index 8ddf8542f..6459a2122 100644 --- a/test/nodes/core/network/21-httprequest_spec.js +++ b/test/nodes/core/network/21-httprequest_spec.js @@ -60,6 +60,7 @@ describe('HTTP Request Node', function() { function startServer(done) { testPort += 1; testServer = stoppable(http.createServer(testApp)); + const promises = [] testServer.listen(testPort,function(err) { testSslPort += 1; console.log("ssl port", testSslPort); @@ -82,13 +83,16 @@ describe('HTTP Request Node', function() { }; testSslServer = stoppable(https.createServer(sslOptions,testApp)); console.log('> start testSslServer') - testSslServer.listen(testSslPort, function(err){ - if (err) { - console.log(err); - } else { - console.log("started testSslServer"); - } - }); + promises.push(new Promise((resolve, reject) => { + testSslServer.listen(testSslPort, function(err){ + console.log(' done testSslServer') + if (err) { + reject(err) + } else { + resolve() + } + }); + })) testSslClientPort += 1; var sslClientOptions = { @@ -98,11 +102,17 @@ describe('HTTP Request Node', function() { requestCert: true }; testSslClientServer = stoppable(https.createServer(sslClientOptions, testApp)); - console.log('> start testSslClientServer.listen') - testSslClientServer.listen(testSslClientPort, function(err){ - console.log("ssl-client", err) - }); - + console.log('> start testSslClientServer') + promises.push(new Promise((resolve, reject) => { + testSslClientServer.listen(testSslClientPort, function(err){ + console.log(' done testSslClientServer') + if (err) { + reject(err) + } else { + resolve() + } + }); + })) testProxyPort += 1; testProxyServer = stoppable(httpProxy(http.createServer())) @@ -112,9 +122,16 @@ describe('HTTP Request Node', function() { } }) console.log('> testProxyServer') - testProxyServer.listen(testProxyPort, function(err) { - console.log('testProxyServer start', err) - }) + promises.push(new Promise((resolve, reject) => { + testProxyServer.listen(testProxyPort, function(err) { + console.log(' done testProxyServer') + if (err) { + reject(err) + } else { + resolve() + } + }) + })) testProxyAuthPort += 1 testProxyServerAuth = stoppable(httpProxy(http.createServer())) @@ -137,11 +154,18 @@ describe('HTTP Request Node', function() { } }) console.log('> testProxyServerAuth') - testProxyServerAuth.listen(testProxyAuthPort, function(err) { - console.log('testProxyServerAuth start', err) - }) + promises.push(new Promise((resolve, reject) => { + testProxyServerAuth.listen(testProxyAuthPort, function(err) { + console.log(' done testProxyServerAuth') + if (err) { + reject(err) + } else { + resolve() + } + }) + })) - done(err); + Promise.all(promises).then(() => { done() }).catch(done) }); } From 7fc64a84e8aa09ae9b5a256b57424562705415be Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 21 Mar 2024 15:16:49 +0000 Subject: [PATCH 05/10] Bump test helper --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aa61af324..4462adb1c 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "mermaid": "^10.4.0", "minami": "1.2.3", "mocha": "9.2.2", - "node-red-node-test-helper": "^0.3.2", + "node-red-node-test-helper": "^0.3.3", "nodemon": "2.0.20", "proxy": "^1.0.2", "sass": "1.62.1", From 5679d264b6c726a8b586a64dd494dd5b794777a3 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 27 Mar 2024 18:00:06 +0000 Subject: [PATCH 06/10] Bump dependencies --- package.json | 4 ++-- packages/node_modules/@node-red/editor-api/package.json | 2 +- packages/node_modules/@node-red/runtime/package.json | 2 +- packages/node_modules/node-red/package.json | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4462adb1c..9876ddaf2 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "cors": "2.8.5", "cronosjs": "1.7.1", "denque": "2.1.0", - "express": "4.18.2", + "express": "4.19.2", "express-session": "1.17.3", "form-data": "4.0.0", "fs-extra": "11.1.1", @@ -64,7 +64,7 @@ "mqtt": "4.3.7", "multer": "1.4.5-lts.1", "mustache": "4.2.0", - "node-red-admin": "^3.1.2", + "node-red-admin": "^3.1.3", "node-watch": "0.7.4", "nopt": "5.0.0", "oauth2orize": "1.11.1", diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json index 39fbc748f..9270731a5 100644 --- a/packages/node_modules/@node-red/editor-api/package.json +++ b/packages/node_modules/@node-red/editor-api/package.json @@ -23,7 +23,7 @@ "clone": "2.1.2", "cors": "2.8.5", "express-session": "1.17.3", - "express": "4.18.2", + "express": "4.19.2", "memorystore": "1.6.7", "mime": "3.0.0", "multer": "1.4.5-lts.1", diff --git a/packages/node_modules/@node-red/runtime/package.json b/packages/node_modules/@node-red/runtime/package.json index d27ef3d8d..f5c415805 100644 --- a/packages/node_modules/@node-red/runtime/package.json +++ b/packages/node_modules/@node-red/runtime/package.json @@ -20,7 +20,7 @@ "@node-red/util": "3.1.7", "async-mutex": "0.4.0", "clone": "2.1.2", - "express": "4.18.2", + "express": "4.19.2", "fs-extra": "11.1.1", "json-stringify-safe": "5.0.1" } diff --git a/packages/node_modules/node-red/package.json b/packages/node_modules/node-red/package.json index 6c9043fda..2ad21450e 100644 --- a/packages/node_modules/node-red/package.json +++ b/packages/node_modules/node-red/package.json @@ -37,9 +37,9 @@ "@node-red/nodes": "3.1.7", "basic-auth": "2.0.1", "bcryptjs": "2.4.3", - "express": "4.18.2", + "express": "4.19.2", "fs-extra": "11.1.1", - "node-red-admin": "^3.1.2", + "node-red-admin": "^3.1.3", "nopt": "5.0.0", "semver": "7.5.4" }, From 6a8230ec1e6bff27680ac55d7a3e80191be8842e Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 27 Mar 2024 18:10:04 +0000 Subject: [PATCH 07/10] Show change icon on subflow tabs Fixes #4626 --- .../node_modules/@node-red/editor-client/src/js/nodes.js | 8 ++++++-- .../@node-red/editor-client/src/js/ui/workspaces.js | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index f80a2a8d1..f643376b1 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -547,12 +547,16 @@ RED.nodes = (function() { * @param {String} z tab id */ checkTabState: function (z) { - const ws = workspaces[z] + const ws = workspaces[z] || subflows[z] if (ws) { const contentsChanged = tabDirtyMap[z].size > 0 || tabDeletedNodesMap[z].size > 0 if (Boolean(ws.contentsChanged) !== contentsChanged) { ws.contentsChanged = contentsChanged - RED.events.emit("flows:change", ws); + if (ws.type === 'tab') { + RED.events.emit("flows:change", ws); + } else { + RED.events.emit("subflows:change", ws); + } } } } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js index d338ee651..57a9de470 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js @@ -662,6 +662,9 @@ RED.workspaces = (function() { RED.events.on("flows:change", (ws) => { $("#red-ui-tab-"+(ws.id.replace(".","-"))).toggleClass('red-ui-workspace-changed',!!(ws.contentsChanged || ws.changed || ws.added)); }) + RED.events.on("subflows:change", (ws) => { + $("#red-ui-tab-"+(ws.id.replace(".","-"))).toggleClass('red-ui-workspace-changed',!!(ws.contentsChanged || ws.changed || ws.added)); + }) hideWorkspace(); } From 014691346a774e1609516332c419f856665d88c5 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 27 Mar 2024 18:23:12 +0000 Subject: [PATCH 08/10] Handle malformed env var values and log errors --- .../@node-red/runtime/lib/flows/util.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/node_modules/@node-red/runtime/lib/flows/util.js b/packages/node_modules/@node-red/runtime/lib/flows/util.js index 76dbe2223..e753075b5 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/util.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/util.js @@ -106,14 +106,22 @@ async function evaluateEnvProperties(flow, env, credentials) { result = { value: result, __clone__: true} } evaluatedEnv[name] = result + } else { + evaluatedEnv[name] = undefined + flow.error(`Error evaluating env property '${name}': ${err.toString()}`) } resolve() }); })) } else { - value = redUtil.evaluateNodeProperty(value, type, {_flow: flow}, null, null); - if (typeof value === 'object') { - value = { value: value, __clone__: true} + try { + value = redUtil.evaluateNodeProperty(value, type, {_flow: flow}, null, null); + if (typeof value === 'object') { + value = { value: value, __clone__: true} + } + } catch (err) { + value = undefined + flow.error(`Error evaluating env property '${name}': ${err.toString()}`) } } evaluatedEnv[name] = value From 19213434f974522403ce56fbebaaedb945d4ebb2 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 27 Mar 2024 19:08:25 +0000 Subject: [PATCH 09/10] Add validation to subflow instance env properties --- .../@node-red/editor-client/src/js/nodes.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index f80a2a8d1..480480b38 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -1025,7 +1025,22 @@ RED.nodes = (function() { RED.nodes.registerType("subflow:"+sf.id, { defaults:{ name:{value:""}, - env:{value:[]} + env:{value:[], validate: function(value) { + const errors = [] + if (value) { + value.forEach(env => { + const r = RED.utils.validateTypedProperty(env.value, env.type) + if (r !== true) { + errors.push(env.name+': '+r) + } + }) + } + if (errors.length === 0) { + return true + } else { + return errors + } + }} }, icon: function() { return sf.icon||"subflow.svg" }, category: sf.category || "subflows", From 952656679910c58332c8ee1c92c220bb27645507 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 28 Mar 2024 11:00:10 +0000 Subject: [PATCH 10/10] Hide import/export context menu if disabled in theme --- .../editor-client/src/js/ui/contextMenu.js | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js index 093e7995f..dae3f6fa6 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js @@ -118,10 +118,16 @@ RED.contextMenu = (function () { onselect: 'core:split-wire-with-link-nodes', disabled: !canEdit || !hasLinks }, - null, - { onselect: 'core:show-import-dialog', label: RED._('common.label.import')}, - { onselect: 'core:show-examples-import-dialog', label: RED._('menu.label.importExample') } + null ) + if (RED.settings.theme("menu.menu-item-import-library", true)) { + insertOptions.push( + { onselect: 'core:show-import-dialog', label: RED._('common.label.import')}, + { onselect: 'core:show-examples-import-dialog', label: RED._('menu.label.importExample') } + ) + } + + if (hasSelection && canEdit) { const nodeOptions = [] if (!hasMultipleSelection && !isGroup) { @@ -194,8 +200,14 @@ RED.contextMenu = (function () { { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !canEdit || !RED.view.clipboard() }, { onselect: 'core:delete-selection', label: RED._('keyboard.deleteSelected'), disabled: !canEdit || !canDelete }, { onselect: 'core:delete-selection-and-reconnect', label: RED._('keyboard.deleteReconnect'), disabled: !canEdit || !canDelete }, - { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") }, - { onselect: 'core:select-all-nodes', label: RED._("keyboard.selectAll") }, + ) + if (RED.settings.theme("menu.menu-item-export-library", true)) { + menuItems.push( + { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") } + ) + } + menuItems.push( + { onselect: 'core:select-all-nodes', label: RED._("keyboard.selectAll") } ) }