From 90c2758624504f5415ddb4488f39f636ea7a1296 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 13 Mar 2025 10:49:15 +0000 Subject: [PATCH 1/3] Add code to error object sent by Catch node --- .../@node-red/runtime/lib/flows/Flow.js | 3 +++ .../node_modules/@node-red/util/lib/util.js | 21 +++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js index 0b6045326..4fe42d839 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js @@ -675,6 +675,9 @@ class Flow { count: count } }; + if (logMessage.hasOwnProperty('code')) { + errorMessage.error.code = logMessage.code; + } if (logMessage.hasOwnProperty('stack')) { errorMessage.error.stack = logMessage.stack; } diff --git a/packages/node_modules/@node-red/util/lib/util.js b/packages/node_modules/@node-red/util/lib/util.js index d205700a5..e966d53a7 100644 --- a/packages/node_modules/@node-red/util/lib/util.js +++ b/packages/node_modules/@node-red/util/lib/util.js @@ -838,14 +838,20 @@ function encodeObject(msg,opts) { data: { name: msg.msg.name, message: hasOwnProperty.call(msg.msg, 'message') ? msg.msg.message : msg.msg.toString(), + code: msg.msg.code, cause: cause + "", stack: msg.msg.stack, } } - // Remove cause if not defined - if (!cause) { + // We optimistically added these properties to the object + // to ensure they are shown above 'stack'. But we don't want + // to include them if they are undefined + if (cause === undefined) { delete value.data.cause } + if (msg.msg.code === undefined) { + delete value.data.code + } msg.msg = JSON.stringify(value); } else if (msg.msg instanceof Buffer) { msg.format = "buffer["+msg.msg.length+"]"; @@ -914,20 +920,27 @@ function encodeObject(msg,opts) { } } else if (value instanceof Error || /Error/.test(value?.__proto__?.name)) { const cause = value.cause + const code = value.code value = { __enc__: true, type: 'error', data: { name: value.name, message: hasOwnProperty.call(value, 'message') ? value.message : value.toString(), + code, cause: cause + "", stack: value.stack, } } - // Remove cause if not defined - if (!cause) { + // We optimistically added these properties to the object + // to ensure they are shown above 'stack'. But we don't want + // to include them if they are undefined + if (cause === undefined) { delete value.data.cause } + if (code === undefined) { + delete value.data.code + } } else if (Array.isArray(value) && value.length > debuglength) { value = { __enc__: true, From 5251e848b9d5914fe7e7f92a6968cf08968ad429 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 24 Mar 2025 16:34:01 +0000 Subject: [PATCH 2/3] Properly handle scale factor in getLinksAtPoint for firefox --- .../@node-red/editor-client/src/js/ui/palette.js | 2 +- .../@node-red/editor-client/src/js/ui/view.js | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js index be17776fa..5c9c9e5d2 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js @@ -401,7 +401,7 @@ RED.palette = (function() { } else { // Firefox doesn't do getIntersectionList and that // makes us sad - nodes = RED.view.getLinksAtPoint(mouseX,mouseY); + nodes = RED.view.getLinksAtPoint(mouseX / RED.view.scale(), mouseY / RED.view.scale()); } var mx = mouseX / RED.view.scale(); var my = mouseY / RED.view.scale(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index 198af0850..e447d203f 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -1908,7 +1908,7 @@ RED.view = (function() { } else { // Firefox doesn"t do getIntersectionList and that // makes us sad - nodes = RED.view.getLinksAtPoint(mouseX*scaleFactor,mouseY*scaleFactor); + nodes = RED.view.getLinksAtPoint(mouseX, mouseY); } for (var i=0;i= bb.x && y >= bb.y && x <= bb.x+bb.width && y <= bb.y+bb.height) { result.push(links[i]) } From a5383f4064f94a162870f1e50792a8741f7cba34 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 24 Mar 2025 17:38:21 +0000 Subject: [PATCH 3/3] Bump i18next to 24.x and auto-migrate message catalog format --- package.json | 2 +- .../@node-red/editor-client/src/js/i18n.js | 1 - .../node_modules/@node-red/util/lib/i18n.js | 22 ++++++++++++++++++- .../node_modules/@node-red/util/package.json | 2 +- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d2fb401b6..7891fd6e7 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "hash-sum": "2.0.0", "hpagent": "1.2.0", "https-proxy-agent": "5.0.1", - "i18next": "21.10.0", + "i18next": "24.2.3", "iconv-lite": "0.6.3", "is-utf8": "0.2.1", "js-yaml": "4.1.0", diff --git a/packages/node_modules/@node-red/editor-client/src/js/i18n.js b/packages/node_modules/@node-red/editor-client/src/js/i18n.js index b8c03b85b..e5b479ea5 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/i18n.js +++ b/packages/node_modules/@node-red/editor-client/src/js/i18n.js @@ -27,7 +27,6 @@ RED.i18n = (function() { apiRootUrl = options.apiRootUrl||""; var preferredLanguage = localStorage.getItem("editor-language") || detectLanguage(); var opts = { - compatibilityJSON: 'v3', backend: { loadPath: apiRootUrl+'locales/__ns__?lng=__lng__', }, diff --git a/packages/node_modules/@node-red/util/lib/i18n.js b/packages/node_modules/@node-red/util/lib/i18n.js index 4f1cf110f..7207d4990 100644 --- a/packages/node_modules/@node-red/util/lib/i18n.js +++ b/packages/node_modules/@node-red/util/lib/i18n.js @@ -80,6 +80,21 @@ function mergeCatalog(fallback,catalog) { } } +function migrateMessageCatalogV3toV4(catalog) { + const keys = Object.keys(catalog) + keys.forEach(key => { + if (typeof catalog[key] === 'object') { + catalog[key] = migrateMessageCatalogV3toV4(catalog[key]) + } else if (key.endsWith('_plural')) { + const otherKey = key.replace('_plural', '_other') + if (!catalog[otherKey]) { + catalog[otherKey] = catalog[key] + } + delete catalog[key] + } + }) + return catalog +} async function readFile(lng, ns) { if (/[^a-z\-]/i.test(lng)) { @@ -92,6 +107,12 @@ async function readFile(lng, ns) { const content = await fs.promises.readFile(file, "utf8"); resourceCache[ns] = resourceCache[ns] || {}; resourceCache[ns][lng] = JSON.parse(content.replace(/^\uFEFF/, '')); + + // Message catalogues are in i18next v3 format. That is no longer supported + // by i18next so we need to migrate any catalog to the v4 format. + // This primarily means mapping `FOO_plural` to `FOO_other` + resourceCache[ns][lng] = migrateMessageCatalogV3toV4(resourceCache[ns][lng]) + var baseLng = lng.split('-')[0]; if (baseLng !== lng && resourceCache[ns][baseLng]) { mergeCatalog(resourceCache[ns][baseLng], resourceCache[ns][lng]); @@ -139,7 +160,6 @@ function init(settings) { initPromise = new Promise((resolve,reject) => { i18n.use(MessageFileLoader); var opt = { - compatibilityJSON: 'v3', // debug: true, defaultNS: "runtime", ns: [], diff --git a/packages/node_modules/@node-red/util/package.json b/packages/node_modules/@node-red/util/package.json index 5bfeb6508..0d44513de 100644 --- a/packages/node_modules/@node-red/util/package.json +++ b/packages/node_modules/@node-red/util/package.json @@ -16,7 +16,7 @@ ], "dependencies": { "fs-extra": "11.2.0", - "i18next": "21.10.0", + "i18next": "24.2.3", "json-stringify-safe": "5.0.1", "jsonata": "2.0.5", "lodash.clonedeep": "^4.5.0",