Compare commits

..

5 Commits

Author SHA1 Message Date
Nick O'Leary
0c2be73a88 Add more debug 2024-03-22 15:59:55 +00:00
Nick O'Leary
884bbe01f0 Add trace for who last started the stack 2024-03-21 20:48:35 +00:00
Nick O'Leary
bd57bce2d3 update workflow 2024-03-21 20:22:56 +00:00
Nick O'Leary
331ed78854 bump test helper 2024-03-21 20:21:36 +00:00
Nick O'Leary
abe579d332 Fix async tidy up handling in core tests 2024-03-21 19:27:37 +00:00
18 changed files with 47 additions and 93 deletions

View File

@@ -2,7 +2,7 @@ name: Run tests
on:
push:
branches: [ master, dev ]
branches: [ master, dev, debug-tests ]
pull_request:
branches: [ master, dev ]

View File

@@ -1,12 +1,3 @@
#### 3.1.8: Maintenance Release
- Add validation and error handling on subflow instance properties (#4632) @knolleary
- Hide import/export context menu if disabled in theme (#4633) @knolleary
- Show change indicator on subflow tabs (#4631) @knolleary
- Bump dependencies (#4630) @knolleary
- Reset workspace index when clearing nodes (#4619) @knolleary
- Remove typo in global config (#4613) @kazuhitoyokoi
#### 3.1.7: Maintenance Release
- Add Japanese translation for v3.1.6 (#4603) @kazuhitoyokoi

View File

@@ -1,6 +1,6 @@
{
"name": "node-red",
"version": "3.1.8",
"version": "3.1.7",
"description": "Low-code programming for event-driven applications",
"homepage": "https://nodered.org",
"license": "Apache-2.0",
@@ -41,7 +41,7 @@
"cors": "2.8.5",
"cronosjs": "1.7.1",
"denque": "2.1.0",
"express": "4.19.2",
"express": "4.18.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.3",
"node-red-admin": "^3.1.2",
"node-watch": "0.7.4",
"nopt": "5.0.0",
"oauth2orize": "1.11.1",
@@ -112,7 +112,7 @@
"mermaid": "^10.4.0",
"minami": "1.2.3",
"mocha": "9.2.2",
"node-red-node-test-helper": "^0.3.3",
"node-red-node-test-helper": "^0.3.4-debug",
"nodemon": "2.0.20",
"proxy": "^1.0.2",
"sass": "1.62.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
"version": "3.1.8",
"version": "3.1.7",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,14 +16,14 @@
}
],
"dependencies": {
"@node-red/util": "3.1.8",
"@node-red/editor-client": "3.1.8",
"@node-red/util": "3.1.7",
"@node-red/editor-client": "3.1.7",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"clone": "2.1.2",
"cors": "2.8.5",
"express-session": "1.17.3",
"express": "4.19.2",
"express": "4.18.2",
"memorystore": "1.6.7",
"mime": "3.0.0",
"multer": "1.4.5-lts.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-client",
"version": "3.1.8",
"version": "3.1.7",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -547,16 +547,12 @@ RED.nodes = (function() {
* @param {String} z tab id
*/
checkTabState: function (z) {
const ws = workspaces[z] || subflows[z]
const ws = workspaces[z]
if (ws) {
const contentsChanged = tabDirtyMap[z].size > 0 || tabDeletedNodesMap[z].size > 0
if (Boolean(ws.contentsChanged) !== contentsChanged) {
ws.contentsChanged = contentsChanged
if (ws.type === 'tab') {
RED.events.emit("flows:change", ws);
} else {
RED.events.emit("subflows:change", ws);
}
RED.events.emit("flows:change", ws);
}
}
}
@@ -1029,22 +1025,7 @@ RED.nodes = (function() {
RED.nodes.registerType("subflow:"+sf.id, {
defaults:{
name:{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
}
}}
env:{value:[]}
},
icon: function() { return sf.icon||"subflow.svg" },
category: sf.category || "subflows",

View File

@@ -118,16 +118,10 @@ RED.contextMenu = (function () {
onselect: 'core:split-wire-with-link-nodes',
disabled: !canEdit || !hasLinks
},
null
null,
{ onselect: 'core:show-import-dialog', label: RED._('common.label.import')},
{ onselect: 'core:show-examples-import-dialog', label: RED._('menu.label.importExample') }
)
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) {
@@ -200,14 +194,8 @@ 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 },
)
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") }
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
{ onselect: 'core:select-all-nodes', label: RED._("keyboard.selectAll") },
)
}

View File

@@ -662,9 +662,6 @@ 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();
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/nodes",
"version": "3.1.8",
"version": "3.1.7",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/registry",
"version": "3.1.8",
"version": "3.1.7",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,7 +16,7 @@
}
],
"dependencies": {
"@node-red/util": "3.1.8",
"@node-red/util": "3.1.7",
"clone": "2.1.2",
"fs-extra": "11.1.1",
"semver": "7.5.4",

View File

@@ -44,9 +44,11 @@ var activeNodesToFlow = {};
var typeEventRegistered = false;
let lastStarterStack
function init(runtime) {
if (started) {
throw new Error("Cannot init without a stop");
throw new Error("Cannot init without a stop:" + lastStarterStack);
}
settings = runtime.settings;
storage = runtime.storage;
@@ -269,12 +271,12 @@ function getFlows() {
return activeConfig;
}
async function start(type,diff,muteLog,isDeploy) {
async function start(type,diff,muteLog,isDeploy, traceError) {
type = type || "full";
if (diff && diff.globalConfigChanged) {
type = 'full'
}
lastStarterStack = traceError || new Error('Flows started here').stack
started = true;
state = 'start'
var i;
@@ -334,6 +336,7 @@ async function start(type,diff,muteLog,isDeploy) {
log.info(log._("nodes.flows.stopped-flows"));
events.emit("runtime-event",{id:"runtime-state",payload:{ state: 'stop', deploy:isDeploy },retain:true});
state = 'stop'
lastStarterStack = null
started = false
return
}
@@ -454,6 +457,7 @@ function stop(type,diff,muteLog,isDeploy) {
if (diff.globalConfigChanged) {
type = 'full'
}
lastStarterStack = null
started = false;
state = 'stop'
var promises = [];

View File

@@ -106,22 +106,14 @@ 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 {
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()}`)
value = redUtil.evaluateNodeProperty(value, type, {_flow: flow}, null, null);
if (typeof value === 'object') {
value = { value: value, __clone__: true}
}
}
evaluatedEnv[name] = value

View File

@@ -131,6 +131,7 @@ function getVersion() {
* @memberof @node-red/runtime
*/
function start() {
const startedCaller = new Error('runtime/lib/index.start started here').stack
return i18n.registerMessageCatalog("runtime",path.resolve(path.join(__dirname,"..","locales")),"runtime.json")
.then(function() { return storage.init(runtime)})
.then(function() { return settings.load(storage)})
@@ -233,7 +234,7 @@ function start() {
}
}
return redNodes.loadContextsPlugin().then(function () {
redNodes.loadFlows().then(() => { redNodes.startFlows() }).catch(function(err) {});
redNodes.loadFlows().then(() => { redNodes.startFlows(null, null, null, null, startedCaller) }).catch(function(err) {});
started = true;
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/runtime",
"version": "3.1.8",
"version": "3.1.7",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,11 +16,11 @@
}
],
"dependencies": {
"@node-red/registry": "3.1.8",
"@node-red/util": "3.1.8",
"@node-red/registry": "3.1.7",
"@node-red/util": "3.1.7",
"async-mutex": "0.4.0",
"clone": "2.1.2",
"express": "4.19.2",
"express": "4.18.2",
"fs-extra": "11.1.1",
"json-stringify-safe": "5.0.1"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/util",
"version": "3.1.8",
"version": "3.1.7",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -1,6 +1,6 @@
{
"name": "node-red",
"version": "3.1.8",
"version": "3.1.7",
"description": "Low-code programming for event-driven applications",
"homepage": "https://nodered.org",
"license": "Apache-2.0",
@@ -31,15 +31,15 @@
"flow"
],
"dependencies": {
"@node-red/editor-api": "3.1.8",
"@node-red/runtime": "3.1.8",
"@node-red/util": "3.1.8",
"@node-red/nodes": "3.1.8",
"@node-red/editor-api": "3.1.7",
"@node-red/runtime": "3.1.7",
"@node-red/util": "3.1.7",
"@node-red/nodes": "3.1.7",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
"express": "4.19.2",
"express": "4.18.2",
"fs-extra": "11.1.1",
"node-red-admin": "^3.1.3",
"node-red-admin": "^3.1.2",
"nopt": "5.0.0",
"semver": "7.5.4"
},

View File

@@ -43,7 +43,7 @@ describe('inject node', function() {
});
}
afterEach(async function() {
afterEach(function(done) {
helper.unload().then(function () {
return Context.clean({allNodes: {}});
}).then(function () {

View File

@@ -66,7 +66,7 @@ describe('websocket Node', function() {
afterEach(function() {
closeAll();
helper.unload();
return helper.unload();
});
describe('websocket-listener', function() {