diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b3b7bca..039047537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,17 @@ Nodes - Add ability to use pfx or p12 file for TLS connection settings option (#4907) @dceejay +#### 4.1.6: Maintenance Release + + - Allow palette.theme to be set via theme plugin and include icons (#5500) @knolleary + - Ensure config sidebar tooltip handles html content (#5501) @knolleary + - Allow node-red integrator access to available updates (#5499) @Steve-Mcl + - Add frontend pre and post debug message hooks (#5495) @Steve-Mcl + - Fix: allow middle-click panning over links and ports (#5496) @lklivingstone + - Support ctrl key to select configuration nodes (#5486) @kazuhitoyokoi + - Add § as shortcut meta-key (#5482) @gorenje + - Update dependencies (#5502) @knolleary + #### 4.1.5: Maintenance Release - chore: bump tar to 7.5.7 (#5472) @bryopsida diff --git a/package-lock.json b/package-lock.json index 6f0d28cd8..5eaf54d21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,13 @@ "version": "5.0.0-beta.2", "license": "Apache-2.0", "dependencies": { - "acorn": "8.15.0", - "acorn-walk": "8.3.4", - "ajv": "8.17.1", + "@node-rs/bcrypt": "^1.10.7", + "acorn": "8.16.0", + "acorn-walk": "8.3.5", + "ajv": "8.18.0", "async-mutex": "0.5.0", "basic-auth": "2.0.1", - "bcryptjs": "3.0.2", + "bcryptjs": "3.0.3", "body-parser": "1.20.4", "chalk": "^4.1.2", "cheerio": "1.0.0-rc.10", @@ -45,7 +46,7 @@ "mime": "3.0.0", "moment": "2.30.1", "moment-timezone": "0.5.48", - "mqtt": "5.11.0", + "mqtt": "5.15.0", "multer": "2.0.2", "mustache": "4.2.0", "node-red-admin": "^4.1.3", @@ -57,9 +58,9 @@ "passport-http-bearer": "1.0.1", "passport-oauth2-client-password": "0.1.2", "raw-body": "3.0.0", - "rfdc": "^1.3.1", - "semver": "7.7.1", - "tar": "7.5.7", + "rfdc": "1.4.1", + "semver": "7.7.4", + "tar": "7.5.9", "tough-cookie": "5.1.2", "uglify-js": "3.19.3", "uuid": "9.0.1", @@ -91,11 +92,11 @@ "jquery-i18next": "1.2.1", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "marked": "4.3.0", - "mermaid": "11.9.0", + "mermaid": "11.12.3", "minami": "1.2.3", "mocha": "9.2.2", "node-red-node-test-helper": "^0.3.3", - "nodemon": "3.1.9", + "nodemon": "3.1.14", "proxy": "^1.0.2", "sass": "1.62.1", "should": "13.2.3", @@ -107,7 +108,7 @@ "node": ">=18.5" }, "optionalDependencies": { - "@node-rs/bcrypt": "1.10.7" + "@node-rs/bcrypt": "^1.10.7" } }, "node_modules/@antfu/install-pkg": { @@ -124,16 +125,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@antfu/utils": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", - "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -213,9 +204,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -302,60 +293,46 @@ "license": "MIT" }, "node_modules/@chevrotain/cst-dts-gen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", - "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.1.1.tgz", + "integrity": "sha512-fRHyv6/f542qQqiRGalrfJl/evD39mAvbJLCekPazhiextEatq1Jx1K/i9gSd5NNO0ds03ek0Cbo/4uVKmOBcw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@chevrotain/gast": "11.0.3", - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/gast": "11.1.1", + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "node_modules/@chevrotain/cst-dts-gen/node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true, - "license": "MIT" - }, "node_modules/@chevrotain/gast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", - "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.1.1.tgz", + "integrity": "sha512-Ko/5vPEYy1vn5CbCjjvnSO4U7GgxyGm+dfUZZJIWTlQFkXkyym0jFYrWEU10hyCjrA7rQtiHtBr0EaZqvHFZvg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/types": "11.1.1", + "lodash-es": "4.17.23" } }, - "node_modules/@chevrotain/gast/node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true, - "license": "MIT" - }, "node_modules/@chevrotain/regexp-to-ast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", - "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.1.1.tgz", + "integrity": "sha512-ctRw1OKSXkOrR8VTvOxrQ5USEc4sNrfwXHa1NuTcR7wre4YbjPcKw+82C2uylg/TEwFRgwLmbhlln4qkmDyteg==", "dev": true, "license": "Apache-2.0" }, "node_modules/@chevrotain/types": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", - "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.1.tgz", + "integrity": "sha512-wb2ToxG8LkgPYnKe9FH8oGn3TMCBdnwiuNC5l5y+CtlaVRbCytU0kbVsk6CGrqTL4ZN4ksJa0TXOYbxpbthtqw==", "dev": true, "license": "Apache-2.0" }, "node_modules/@chevrotain/utils": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", - "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.1.1.tgz", + "integrity": "sha512-71eTYMzYXYSFPrbg/ZwftSaSDld7UYlS8OQa3lNnn9jzNtpFbaReRRyghzqS7rI3CDaorqpPJJcXGHK+FE1TVQ==", "dev": true, "license": "Apache-2.0" }, @@ -398,47 +375,17 @@ "license": "MIT" }, "node_modules/@iconify/utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", - "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", "dev": true, "license": "MIT", "dependencies": { - "@antfu/install-pkg": "^1.0.0", - "@antfu/utils": "^8.1.0", + "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", - "debug": "^4.4.0", - "globals": "^15.14.0", - "kolorist": "^1.8.0", - "local-pkg": "^1.0.0", - "mlly": "^1.7.4" + "mlly": "^1.8.0" } }, - "node_modules/@iconify/utils/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@iconify/utils/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -504,13 +451,13 @@ } }, "node_modules/@mermaid-js/parser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", - "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.0.0.tgz", + "integrity": "sha512-vvK0Hi/VWndxoh03Mmz6wa1KDriSPjS2XMZL/1l19HFwygiObEEoEwSDxOqyLzzAI6J2PU3261JjTMTO7x+BPw==", "dev": true, "license": "MIT", "dependencies": { - "langium": "3.3.1" + "langium": "^4.0.0" } }, "node_modules/@napi-rs/wasm-runtime": { @@ -860,6 +807,23 @@ "node": ">= 14" } }, + "node_modules/@prantlf/jsonlint/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@sindresorhus/is": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", @@ -1329,9 +1293,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -1341,9 +1305,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -1398,9 +1362,9 @@ "license": "MIT" }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -1839,9 +1803,9 @@ "dev": true }, "node_modules/bcryptjs": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", - "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", + "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==", "license": "BSD-3-Clause", "bin": { "bcrypt": "bin/bcrypt" @@ -2016,6 +1980,18 @@ "node": ">=8" } }, + "node_modules/broker-factory": { + "version": "3.1.13", + "resolved": "https://registry.npmjs.org/broker-factory/-/broker-factory-3.1.13.tgz", + "integrity": "sha512-H2VALe31mEtO/SRcNp4cUU5BAm1biwhc/JaF77AigUuni/1YT0FLCJfbUxwIEs9y6Kssjk2fmXgf+Y9ALvmKlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "fast-unique-numbers": "^9.0.26", + "tslib": "^2.8.1", + "worker-factory": "^7.0.48" + } + }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -2267,18 +2243,18 @@ } }, "node_modules/chevrotain": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", - "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.1.tgz", + "integrity": "sha512-f0yv5CPKaFxfsPTBzX7vGuim4oIC1/gcS7LUGdBSwl2dU6+FON6LVUksdOo1qJjoUvXNn45urgh8C+0a24pACQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@chevrotain/cst-dts-gen": "11.0.3", - "@chevrotain/gast": "11.0.3", - "@chevrotain/regexp-to-ast": "11.0.3", - "@chevrotain/types": "11.0.3", - "@chevrotain/utils": "11.0.3", - "lodash-es": "4.17.21" + "@chevrotain/cst-dts-gen": "11.1.1", + "@chevrotain/gast": "11.1.1", + "@chevrotain/regexp-to-ast": "11.1.1", + "@chevrotain/types": "11.1.1", + "@chevrotain/utils": "11.1.1", + "lodash-es": "4.17.23" } }, "node_modules/chevrotain-allstar": { @@ -2294,13 +2270,6 @@ "chevrotain": "^11.0.0" } }, - "node_modules/chevrotain/node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true, - "license": "MIT" - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2624,9 +2593,9 @@ } }, "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", "dev": true, "license": "MIT" }, @@ -3184,9 +3153,9 @@ } }, "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", "dev": true, "license": "ISC", "engines": { @@ -3442,9 +3411,9 @@ } }, "node_modules/dagre-d3-es": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", - "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", + "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4125,13 +4094,6 @@ ], "license": "MIT" }, - "node_modules/exsolve": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", - "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", - "dev": true, - "license": "MIT" - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -4170,16 +4132,16 @@ "license": "MIT" }, "node_modules/fast-unique-numbers": { - "version": "8.0.13", - "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", - "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", + "version": "9.0.26", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-9.0.26.tgz", + "integrity": "sha512-3Mtq8p1zQinjGyWfKeuBunbuFoixG72AUkk4VvzbX4ykCW9Q4FzRaNyIlfQhUjnKw2ARVP+/CKnoyr6wfHftig==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.8", - "tslib": "^2.6.2" + "@babel/runtime": "^7.28.6", + "tslib": "^2.8.1" }, "engines": { - "node": ">=16.1.0" + "node": ">=18.2.0" } }, "node_modules/fast-uri": { @@ -4777,19 +4739,6 @@ "which": "bin/which" } }, - "node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globule": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", @@ -6399,9 +6348,9 @@ } }, "node_modules/jsdoc-api/node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", "dev": true, "license": "MIT", "dependencies": { @@ -6772,28 +6721,22 @@ "graceful-fs": "^4.1.9" } }, - "node_modules/kolorist": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "dev": true, - "license": "MIT" - }, "node_modules/langium": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", - "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.1.tgz", + "integrity": "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==", "dev": true, "license": "MIT", "dependencies": { - "chevrotain": "~11.0.3", - "chevrotain-allstar": "~0.3.0", + "chevrotain": "~11.1.1", + "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", - "vscode-uri": "~3.0.8" + "vscode-uri": "~3.1.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=20.10.0", + "npm": ">=10.2.3" } }, "node_modules/layout-base": { @@ -6952,24 +6895,6 @@ "node": ">=4" } }, - "node_modules/local-pkg": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", - "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mlly": "^1.7.4", - "pkg-types": "^2.3.0", - "quansync": "^0.2.11" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -6987,16 +6912,16 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, "node_modules/lodash-es": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", - "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "dev": true, "license": "MIT" }, @@ -7327,28 +7252,28 @@ } }, "node_modules/mermaid": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.9.0.tgz", - "integrity": "sha512-YdPXn9slEwO0omQfQIsW6vS84weVQftIyyTGAZCwM//MGhPzL1+l6vO6bkf0wnP4tHigH1alZ5Ooy3HXI2gOag==", + "version": "11.12.3", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.3.tgz", + "integrity": "sha512-wN5ZSgJQIC+CHJut9xaKWsknLxaFBwCPwPkGTSUYrTiHORWvpT8RxGk849HPnpUAQ+/9BPRqYb80jTpearrHzQ==", "dev": true, "license": "MIT", "dependencies": { - "@braintree/sanitize-url": "^7.0.4", - "@iconify/utils": "^2.1.33", - "@mermaid-js/parser": "^0.6.2", + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.1", + "@mermaid-js/parser": "^1.0.0", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.11", - "dayjs": "^1.11.13", + "dagre-d3-es": "7.0.13", + "dayjs": "^1.11.18", "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", - "lodash-es": "^4.17.21", - "marked": "^16.0.0", + "lodash-es": "^4.17.23", + "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", @@ -7532,25 +7457,6 @@ "ufo": "^1.6.1" } }, - "node_modules/mlly/node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/mlly/node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, "node_modules/mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", @@ -7666,9 +7572,9 @@ } }, "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -7749,28 +7655,27 @@ } }, "node_modules/mqtt": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.11.0.tgz", - "integrity": "sha512-VDqfADTNvohwcY02NgxPb7OojIeDrNQ1q62r/DcM+bnIWY8LBi3nMTvdEaFEp6Bu4ejBIpHjJVthUEgnvGLemA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.15.0.tgz", + "integrity": "sha512-KC+wAssYk83Qu5bT8YDzDYgUJxPhbLeVsDvpY2QvL28PnXYJzC2WkKruyMUgBAZaQ7h9lo9k2g4neRNUUxzgMw==", "license": "MIT", "dependencies": { - "@types/readable-stream": "^4.0.18", - "@types/ws": "^8.5.14", + "@types/readable-stream": "^4.0.21", + "@types/ws": "^8.18.1", "commist": "^3.2.0", "concat-stream": "^2.0.0", - "debug": "^4.4.0", + "debug": "^4.4.1", "help-me": "^5.0.0", "lru-cache": "^10.4.3", "minimist": "^1.2.8", "mqtt-packet": "^9.0.2", "number-allocator": "^1.0.14", "readable-stream": "^4.7.0", - "reinterval": "^1.1.0", "rfdc": "^1.4.1", - "socks": "^2.8.3", + "socks": "^2.8.6", "split2": "^4.2.0", - "worker-timers": "^7.1.8", - "ws": "^8.18.0" + "worker-timers": "^8.0.23", + "ws": "^8.18.3" }, "bin": { "mqtt": "build/bin/mqtt.js", @@ -8077,6 +7982,15 @@ "node": ">=6" } }, + "node_modules/node-red-admin/node_modules/bcryptjs": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", + "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", + "license": "BSD-3-Clause", + "bin": { + "bcrypt": "bin/bcrypt" + } + }, "node_modules/node-red-node-test-helper": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/node-red-node-test-helper/-/node-red-node-test-helper-0.3.5.tgz", @@ -8226,16 +8140,16 @@ } }, "node_modules/nodemon": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", - "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", "dev": true, "license": "MIT", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", + "minimatch": "^10.2.1", "pstree.remy": "^1.1.8", "semver": "^7.5.3", "simple-update-notifier": "^2.0.0", @@ -8254,6 +8168,29 @@ "url": "https://opencollective.com/nodemon" } }, + "node_modules/nodemon/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", + "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/nodemon/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -8283,16 +8220,19 @@ } }, "node_modules/nodemon/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", + "integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/nodemon/node_modules/ms": { @@ -9348,15 +9288,15 @@ } }, "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", "dev": true, "license": "MIT", "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", - "pathe": "^2.0.3" + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" } }, "node_modules/points-on-curve": { @@ -9511,9 +9451,9 @@ } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -9525,23 +9465,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/quansync": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", - "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/antfu" - }, - { - "type": "individual", - "url": "https://github.com/sponsors/sxzz" - } - ], - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9785,9 +9708,9 @@ } }, "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "license": "ISC", "dependencies": { @@ -9883,12 +9806,6 @@ "node": ">=0.10.0" } }, - "node_modules/reinterval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", - "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==", - "license": "MIT" - }, "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -10129,9 +10046,9 @@ "license": "BlueOak-1.0.0" }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -11012,9 +10929,9 @@ "dev": true }, "node_modules/tar": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", - "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", + "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", @@ -11357,9 +11274,9 @@ "license": "MIT" }, "node_modules/ufo": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.2.tgz", - "integrity": "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", "dev": true, "license": "MIT" }, @@ -11572,9 +11489,9 @@ "license": "MIT" }, "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "dev": true, "license": "MIT" }, @@ -11685,38 +11602,51 @@ "node": ">=0.10.0" } }, - "node_modules/worker-timers": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz", - "integrity": "sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==", + "node_modules/worker-factory": { + "version": "7.0.48", + "resolved": "https://registry.npmjs.org/worker-factory/-/worker-factory-7.0.48.tgz", + "integrity": "sha512-CGmBy3tJvpBPjUvb0t4PrpKubUsfkI1Ohg0/GGFU2RvA9j/tiVYwKU8O7yu7gH06YtzbeJLzdUR29lmZKn5pag==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.24.5", - "tslib": "^2.6.2", - "worker-timers-broker": "^6.1.8", - "worker-timers-worker": "^7.0.71" + "@babel/runtime": "^7.28.6", + "fast-unique-numbers": "^9.0.26", + "tslib": "^2.8.1" + } + }, + "node_modules/worker-timers": { + "version": "8.0.30", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-8.0.30.tgz", + "integrity": "sha512-8P7YoMHWN0Tz7mg+9oEhuZdjBIn2z6gfjlJqFcHiDd9no/oLnMGCARCDkV1LR3ccQus62ZdtIp7t3aTKrMLHOg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "tslib": "^2.8.1", + "worker-timers-broker": "^8.0.15", + "worker-timers-worker": "^9.0.13" } }, "node_modules/worker-timers-broker": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz", - "integrity": "sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==", + "version": "8.0.15", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-8.0.15.tgz", + "integrity": "sha512-Te+EiVUMzG5TtHdmaBZvBrZSFNauym6ImDaCAnzQUxvjnw+oGjMT2idmAOgDy30vOZMLejd0bcsc90Axu6XPWA==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.24.5", - "fast-unique-numbers": "^8.0.13", - "tslib": "^2.6.2", - "worker-timers-worker": "^7.0.71" + "@babel/runtime": "^7.28.6", + "broker-factory": "^3.1.13", + "fast-unique-numbers": "^9.0.26", + "tslib": "^2.8.1", + "worker-timers-worker": "^9.0.13" } }, "node_modules/worker-timers-worker": { - "version": "7.0.71", - "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz", - "integrity": "sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==", + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-9.0.13.tgz", + "integrity": "sha512-qjn18szGb1kjcmh2traAdki1eiIS5ikFo+L90nfMOvSRpuDw1hAcR1nzkP2+Hkdqz5thIRnfuWx7QSpsEUsA6Q==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.24.5", - "tslib": "^2.6.2" + "@babel/runtime": "^7.28.6", + "tslib": "^2.8.1", + "worker-factory": "^7.0.48" } }, "node_modules/workerpool": { @@ -11969,9 +11899,9 @@ } }, "node_modules/zip-stream/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index bb9ee3a8b..bc9ca6ace 100644 --- a/package.json +++ b/package.json @@ -26,12 +26,12 @@ } ], "dependencies": { - "acorn": "8.15.0", - "acorn-walk": "8.3.4", - "ajv": "8.17.1", + "acorn": "8.16.0", + "acorn-walk": "8.3.5", + "ajv": "8.18.0", "async-mutex": "0.5.0", "basic-auth": "2.0.1", - "bcryptjs": "3.0.2", + "bcryptjs": "3.0.3", "body-parser": "1.20.4", "chalk": "^4.1.2", "cheerio": "1.0.0-rc.10", @@ -62,7 +62,7 @@ "mime": "3.0.0", "moment": "2.30.1", "moment-timezone": "0.5.48", - "mqtt": "5.11.0", + "mqtt": "5.15.0", "multer": "2.0.2", "mustache": "4.2.0", "node-red-admin": "^4.1.3", @@ -74,9 +74,9 @@ "passport-http-bearer": "1.0.1", "passport-oauth2-client-password": "0.1.2", "raw-body": "3.0.0", - "rfdc": "^1.3.1", - "semver": "7.7.1", - "tar": "7.5.7", + "rfdc": "1.4.1", + "semver": "7.7.4", + "tar": "7.5.9", "tough-cookie": "5.1.2", "uglify-js": "3.19.3", "uuid": "9.0.1", @@ -111,11 +111,11 @@ "jquery-i18next": "1.2.1", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "marked": "4.3.0", - "mermaid": "11.9.0", + "mermaid": "11.12.3", "minami": "1.2.3", "mocha": "9.2.2", "node-red-node-test-helper": "^0.3.3", - "nodemon": "3.1.9", + "nodemon": "3.1.14", "proxy": "^1.0.2", "sass": "1.62.1", "should": "13.2.3", diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/settings.js b/packages/node_modules/@node-red/editor-api/lib/admin/settings.js index 425d42415..6939fdfd1 100644 --- a/packages/node_modules/@node-red/editor-api/lib/admin/settings.js +++ b/packages/node_modules/@node-red/editor-api/lib/admin/settings.js @@ -53,10 +53,10 @@ module.exports = { var opts = { user: req.user } - runtimeAPI.settings.getRuntimeSettings(opts).then(function(result) { + runtimeAPI.settings.getRuntimeSettings(opts).then(async function(result) { if (!settings.disableEditor) { result.editorTheme = result.editorTheme||{}; - var themeSettings = theme.settings(); + const themeSettings = await theme.settings(); if (themeSettings) { // result.editorTheme may already exist with the palette // disabled. Need to merge that into the receive settings diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/theme.js b/packages/node_modules/@node-red/editor-api/lib/editor/theme.js index cca608037..a20918775 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/theme.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/theme.js @@ -42,7 +42,13 @@ var defaultContext = { var settings; var theme = null; +/** + * themeContext is an object passed to the mustache template to generate the editor index.html. +*/ var themeContext = clone(defaultContext); +/** + * themeSettings is an object passed to the editor client as the "editorTheme" property of the settings object + */ var themeSettings = null; var activeTheme = null; @@ -91,6 +97,119 @@ function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) { return result } +/** + * Check if a theme is enabled and load its settings. + * This is done lazily as it has to happen after the plugins have been loaded, but before the editor is served. + */ +async function loadThemePlugin () { + if (activeTheme && !activeThemeInitialised) { + const themePlugin = await runtimeAPI.plugins.getPlugin({ + id:activeTheme + }); + if (themePlugin) { + if (themePlugin.css) { + const cssFiles = serveFilesFromTheme( + themePlugin.css, + themeApp, + "/css/", + themePlugin.path + ); + themeContext.page.css = cssFiles.concat(themeContext.page.css || []) + // Mutating `theme` is not ideal, but currently necessary as debug (packages/node_modules/@node-red/nodes/core/common/21-debug.js) + // accesses RED.settings.editorTheme.page._.css directly to apply theme to the debug pop-out window. + theme.page = theme.page || {_:{}} + theme.page._.css = cssFiles.concat(theme.page._.css || []) + } + if (themePlugin.scripts) { + const scriptFiles = serveFilesFromTheme( + themePlugin.scripts, + themeApp, + "/scripts/", + themePlugin.path + ) + themeContext.page.scripts = scriptFiles.concat(themeContext.page.scripts || []) + theme.page = theme.page || {_:{}} + theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || []) + } + // check and load page settings from theme + if (themePlugin.page) { + if (themePlugin.page.favicon && !theme.page.favicon) { + const result = serveFilesFromTheme( + [themePlugin.page.favicon], + themeApp, + "/", + themePlugin.path + ) + if(result && result.length > 0) { + // update themeContext page favicon + themeContext.page.favicon = result[0] + } + } + if (themePlugin.page.tabicon && themePlugin.page.tabicon.icon && !theme.page.tabicon) { + const result = serveFilesFromTheme( + [themePlugin.page.tabicon.icon], + themeApp, + "/page/", + themePlugin.path + ) + if(result && result.length > 0) { + // update themeContext page tabicon + themeContext.page.tabicon.icon = result[0] + themeContext.page.tabicon.colour = themeContext.page.tabicon.colour || themeContext.page.tabicon.colour + } + } + // if the plugin has a title AND the users settings.js does NOT + if (themePlugin.page.title && !theme.page.title) { + themeContext.page.title = themePlugin.page.title || themeContext.page.title + } + } + // check and load header settings from theme + if (themePlugin.header) { + if (themePlugin.header.image && !theme.header.image) { + const result = serveFilesFromTheme( + [themePlugin.header.image], + themeApp, + "/header/", + themePlugin.path + ) + if(result && result.length > 0) { + // update themeContext header image + themeContext.header.image = result[0] + } + } + // if the plugin has a title AND the users settings.js does NOT have a title + if (themePlugin.header.title && !theme.header.title) { + themeContext.header.title = themePlugin.header.title || themeContext.header.title + } + // if the plugin has a header url AND the users settings.js does NOT + if (themePlugin.header.url && !theme.header.url) { + themeContext.header.url = themePlugin.header.url || themeContext.header.url + } + } + + if (Array.isArray(themePlugin.palette?.theme)) { + themeSettings.palette = themeSettings.palette || {}; + themeSettings.palette.theme = themePlugin.palette.theme; + // The theme is providing its own palette theme. It *might* include icons that need namespacing + // to the theme plugin module. + themePlugin.palette.theme.forEach(themeRule => { + if (themeRule.icon && themeRule.icon.indexOf("/") === -1) { + themeRule.icon = `${themePlugin.module}/${themeRule.icon}`; + } + }) + } + + // These settings are not exposed under `editorTheme`, so we don't have a merge strategy for them + // If they're defined in the theme plugin, they replace any settings.js values. + // But, this direct manipulation of `theme` is not ideal and relies on mutating a passed-in object + theme.codeEditor = theme.codeEditor || {} + theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options); + theme.mermaid = Object.assign({}, themePlugin.mermaid, theme.mermaid) + } + activeThemeInitialised = true; + } +} + module.exports = { init: function(_settings, _runtimeAPI) { settings = _settings; @@ -232,6 +351,7 @@ module.exports = { res.json(themeContext); }) + // Copy the settings that need passing to the editor into themeSettings. if (theme.hasOwnProperty("menu")) { themeSettings.menu = theme.menu; } @@ -263,104 +383,11 @@ module.exports = { return themeApp; }, context: async function() { - if (activeTheme && !activeThemeInitialised) { - const themePlugin = await runtimeAPI.plugins.getPlugin({ - id:activeTheme - }); - if (themePlugin) { - if (themePlugin.css) { - const cssFiles = serveFilesFromTheme( - themePlugin.css, - themeApp, - "/css/", - themePlugin.path - ); - themeContext.page.css = cssFiles.concat(themeContext.page.css || []) - theme.page = theme.page || {_:{}} - theme.page._.css = cssFiles.concat(theme.page._.css || []) - } - if (themePlugin.scripts) { - const scriptFiles = serveFilesFromTheme( - themePlugin.scripts, - themeApp, - "/scripts/", - themePlugin.path - ) - themeContext.page.scripts = scriptFiles.concat(themeContext.page.scripts || []) - theme.page = theme.page || {_:{}} - theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || []) - } - // check and load page settings from theme - if (themePlugin.page) { - if (themePlugin.page.favicon && !theme.page.favicon) { - const result = serveFilesFromTheme( - [themePlugin.page.favicon], - themeApp, - "/", - themePlugin.path - ) - if(result && result.length > 0) { - // update themeContext page favicon - themeContext.page.favicon = result[0] - theme.page = theme.page || {_:{}} - theme.page._.favicon = result[0] - } - } - if (themePlugin.page.tabicon && themePlugin.page.tabicon.icon && !theme.page.tabicon) { - const result = serveFilesFromTheme( - [themePlugin.page.tabicon.icon], - themeApp, - "/page/", - themePlugin.path - ) - if(result && result.length > 0) { - // update themeContext page tabicon - themeContext.page.tabicon.icon = result[0] - themeContext.page.tabicon.colour = themeContext.page.tabicon.colour || themeContext.page.tabicon.colour - theme.page = theme.page || {_:{}} - theme.page._.tabicon = theme.page._.tabicon || {} - theme.page._.tabicon.icon = themeContext.page.tabicon.icon - theme.page._.tabicon.colour = themeContext.page.tabicon.colour - } - } - // if the plugin has a title AND the users settings.js does NOT - if (themePlugin.page.title && !theme.page.title) { - themeContext.page.title = themePlugin.page.title || themeContext.page.title - } - } - // check and load header settings from theme - if (themePlugin.header) { - if (themePlugin.header.image && !theme.header.image) { - const result = serveFilesFromTheme( - [themePlugin.header.image], - themeApp, - "/header/", - themePlugin.path - ) - if(result && result.length > 0) { - // update themeContext header image - themeContext.header.image = result[0] - } - } - // if the plugin has a title AND the users settings.js does NOT have a title - if (themePlugin.header.title && !theme.header.title) { - themeContext.header.title = themePlugin.header.title || themeContext.header.title - } - // if the plugin has a header url AND the users settings.js does NOT - if (themePlugin.header.url && !theme.header.url) { - themeContext.header.url = themePlugin.header.url || themeContext.header.url - } - } - theme.codeEditor = theme.codeEditor || {} - theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options); - - theme.mermaid = Object.assign({}, themePlugin.mermaid, theme.mermaid) - } - activeThemeInitialised = true; - } + await loadThemePlugin(); return themeContext; }, - settings: function() { + settings: async function() { + await loadThemePlugin(); return themeSettings; }, serveFile: function(baseUrl,file) { diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json index 5ae7bf3a9..e12e4a871 100644 --- a/packages/node_modules/@node-red/editor-api/package.json +++ b/packages/node_modules/@node-red/editor-api/package.json @@ -18,7 +18,7 @@ "dependencies": { "@node-red/util": "5.0.0-beta.2", "@node-red/editor-client": "5.0.0-beta.2", - "bcryptjs": "3.0.2", + "bcryptjs": "3.0.3", "body-parser": "1.20.4", "clone": "2.1.2", "cors": "2.8.5", diff --git a/packages/node_modules/@node-red/editor-client/src/js/hooks.js b/packages/node_modules/@node-red/editor-client/src/js/hooks.js index 096c8e5b5..d7a3c1a97 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/hooks.js +++ b/packages/node_modules/@node-red/editor-client/src/js/hooks.js @@ -1,135 +1,206 @@ -RED.hooks = (function() { +RED.hooks = (function () { + // At the time of writing this PR, VALID_HOOKS were not enforced. There may be a good reason for this + // so the below flag has been added to permit this behaviour. If desired, this can be set to false to + // enforce that only known hooks can be added/triggered. + const knownHooksOnly = false - var VALID_HOOKS = [ + const VALID_HOOKS = Object.freeze({ + viewRemoveNode: true, + viewAddNode: true, + viewRemovePort: true, + viewAddPort: true, + viewRedrawNode: true, + debugPreProcessMessage: true, + debugPostProcessMessage: true + }) - ] + /** + * @typedef {keyof typeof VALID_HOOKS} HookId - A string literal type representing a hook identifier (sans label). + * + * @typedef {Object} HookItem - An item in the linked list of hooks for a given HookId + * @property {function} cb - The callback function to be called when the hook is triggered + * @property {HookItem|null} previousHook - The previous hook in the linked list + * @property {HookItem|null} nextHook - The next hook in the linked list + * @property {boolean} removed - Flag indicating if the hook has been removed + * + * @typedef {Record} Hooks - A mapping of HookIds to the head of their linked list of HookItems + */ - var hooks = { } - var labelledHooks = { } + + /** @type {Hooks} - A mapping of HookIds to the head of their linked list of HookItems */ + let hooks = {} + + /** @type {Record>} - A mapping of labels to their hooks */ + let labelledHooks = {} function add(hookId, callback) { - var parts = hookId.split("."); - var id = parts[0], label = parts[1]; + const { label, id } = parseLabelledHook(hookId) - // if (VALID_HOOKS.indexOf(id) === -1) { - // throw new Error("Invalid hook '"+id+"'"); - // } - if (label && labelledHooks[label] && labelledHooks[label][id]) { - throw new Error("Hook "+hookId+" already registered") + if (knownHooksOnly && !isKnownHook(id)) { + throw new Error("Invalid hook '" + id + "'") + } + if (label && labelledHooks[label] && labelledHooks[label][id]) { + throw new Error("Hook " + hookId + " already registered") + } + if (typeof callback !== "function") { + throw new Error("Invalid hook '" + hookId + "'. Callback must be a function") } - var hookItem = {cb:callback, previousHook: null, nextHook: null } - var tailItem = hooks[id]; + /** @type {HookItem} */ + const hookItem = { cb: callback, previousHook: null, nextHook: null } + + let tailItem = hooks[id] if (tailItem === undefined) { - hooks[id] = hookItem; + hooks[id] = hookItem } else { - while(tailItem.nextHook !== null) { + while (tailItem.nextHook !== null) { tailItem = tailItem.nextHook } - tailItem.nextHook = hookItem; - hookItem.previousHook = tailItem; + tailItem.nextHook = hookItem + hookItem.previousHook = tailItem } if (label) { - labelledHooks[label] = labelledHooks[label]||{}; - labelledHooks[label][id] = hookItem; + labelledHooks[label] = labelledHooks[label] || {} + labelledHooks[label][id] = hookItem } } + function remove(hookId) { - var parts = hookId.split("."); - var id = parts[0], label = parts[1]; - if ( !label) { - throw new Error("Cannot remove hook without label: "+hookId) + const { label, id } = parseLabelledHook(hookId) + if (!label) { + throw new Error("Cannot remove hook without label: " + hookId) } if (labelledHooks[label]) { if (id === "*") { // Remove all hooks for this label - var hookList = Object.keys(labelledHooks[label]); - for (var i=0;i { + invokeStack(hookItem, payload, function (err) { + if (err !== undefined && err !== false) { + if (!(err instanceof Error)) { + err = new Error(err) + } + err.hook = id + reject(err) + } else { + resolve(err) + } + }) + }) + } else { + invokeStack(hookItem, payload, done) + } + } + + /** + * @private + */ + function invokeStack(hookItem, payload, done) { function callNextHook(err) { if (!hookItem || err) { - if (done) { done(err) } - return err; + done(err) + return } if (hookItem.removed) { - hookItem = hookItem.nextHook; - return callNextHook(); + hookItem = hookItem.nextHook + callNextHook() + return } - var callback = hookItem.cb; + const callback = hookItem.cb if (callback.length === 1) { try { - let result = callback(payload); + let result = callback(payload) if (result === false) { // Halting the flow - if (done) { done(false) } - return result; + done(false) + return } - hookItem = hookItem.nextHook; - return callNextHook(); - } catch(e) { - console.warn(e); - if (done) { done(e);} - return e; + if (result && typeof result.then === 'function') { + result.then(handleResolve, callNextHook) + return + } + hookItem = hookItem.nextHook + callNextHook() + } catch (e) { + done(e) + return } } else { - // There is a done callback try { - callback(payload,function(result) { - if (result === undefined) { - hookItem = hookItem.nextHook; - callNextHook(); - } else { - if (done) { done(result)} - } - }) - } catch(e) { - console.warn(e); - if (done) { done(e) } - return e; + callback(payload, handleResolve) + } catch (e) { + done(e) + return } } } - - return callNextHook(); + function handleResolve(result) { + if (result === undefined) { + hookItem = hookItem.nextHook + callNextHook() + } else { + done(result) + } + } + callNextHook() } function clear() { @@ -137,20 +208,48 @@ RED.hooks = (function() { labelledHooks = {} } + /** + * Check if a hook with the given id exists + * @param {string} hookId The hook identifier, which may include a label (e.g. "viewAddNode.myLabel") + * @returns {boolean} + */ function has(hookId) { - var parts = hookId.split("."); - var id = parts[0], label = parts[1]; + const { label, id } = parseLabelledHook(hookId) if (label) { return !!(labelledHooks[label] && labelledHooks[label][id]) } return !!hooks[id] } - return { - has: has, - clear: clear, - add: add, - remove: remove, - trigger: trigger + function isKnownHook(hookId) { + const { id } = parseLabelledHook(hookId) + return !!VALID_HOOKS[id] } -})(); + + /** + * Split a hook identifier into its id and label components. + * @param {*} hookId A hook identifier, which may include a label (e.g. "viewAddNode.myLabel") + * @returns {{label: string, id: HookId}} + * @private + */ + function parseLabelledHook(hookId) { + if (typeof hookId !== "string") { + return { label: '', id: '' } + } + const parts = hookId.split(".") + const id = parts[0] + const label = parts[1] + return { label, id } + } + + VALID_HOOKS['all'] = true // Special wildcard to allow hooks to indicate they should be triggered for all ids + + return { + has, + clear, + add, + remove, + trigger, + isKnownHook + } +})() diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js b/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js index 431197458..de5c788ac 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js @@ -43,6 +43,7 @@ RED.keyboard = (function() { "-":189, ".":190, "/":191, + "§":192, // <- top left key MacOS "\\":220, "'":222, "?":191, // <- QWERTY specific diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js index e2773f4f6..1a34d1927 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js @@ -40,6 +40,12 @@ RED.palette.editor = (function() { // Install tab - search input let searchInput; + // Core and Package Updates + /** @type {Array<{package: string, current: string, available: string}>} */ + const moduleUpdates = [] + const updateStatusState = { version: null, moduleCount: 0 } + + const SMALL_CATALOGUE_SIZE = 40 const typesInUse = {}; @@ -1825,8 +1831,6 @@ RED.palette.editor = (function() { const updateStatusWidget = $(''); let updateStatusWidgetPopover; - const updateStatusState = { moduleCount: 0 } - let updateAvailable = []; function addUpdateInfoToStatusBar() { updateStatusWidgetPopover = RED.popover.create({ @@ -1835,7 +1839,7 @@ RED.palette.editor = (function() { interactive: true, direction: "bottom", content: function () { - const count = updateAvailable.length || 0; + const count = moduleUpdates.length || 0 const content = $('
'); if (updateStatusState.version) { $(`${RED._("telemetry.updateAvailableDesc", updateStatusState)}`).appendTo(content) @@ -1845,7 +1849,7 @@ RED.palette.editor = (function() { updateStatusWidgetPopover.close() RED.actions.invoke("core:manage-palette", { view: "nodes", - filter: '"' + updateAvailable.join('", "') + '"' + filter: '"' + moduleUpdates.map(u => u.package).join('", "') + '"' }); }).appendTo(content) } @@ -1867,7 +1871,7 @@ RED.palette.editor = (function() { function refreshUpdateStatus() { clearTimeout(pendingRefreshTimeout) pendingRefreshTimeout = setTimeout(() => { - updateAvailable = []; + moduleUpdates.length = 0 for (const module of Object.keys(nodeEntries)) { if (loadedIndex.hasOwnProperty(module)) { const moduleInfo = nodeEntries[module].info; @@ -1875,35 +1879,51 @@ RED.palette.editor = (function() { // Module updated continue; } + const current = moduleInfo.version + const latest = loadedIndex[module].version if (updateAllowed && - semVerCompare(loadedIndex[module].version, moduleInfo.version) > 0 && + semVerCompare(latest, current) > 0 && RED.utils.checkModuleAllowed(module, null, updateAllowList, updateDenyList) ) { - updateAvailable.push(module); + moduleUpdates.push({ package: module, current, latest }) } } } - updateStatusState.moduleCount = updateAvailable.length; + updateStatusState.moduleCount = moduleUpdates.length updateStatus(); }, 200) } function updateStatus() { - if (updateStatusState.moduleCount || updateStatusState.version) { + const updates = RED.palette.editor.getAvailableUpdates() + if (updates.count > 0) { updateStatusWidget.empty(); - let count = updateStatusState.moduleCount || 0; - if (updateStatusState.version) { - count ++ - } - $(` ${RED._("telemetry.updateAvailable", { count: count })}`).appendTo(updateStatusWidget); + $(` ${RED._("telemetry.updateAvailable", { count: updates.count })}`).appendTo(updateStatusWidget); RED.statusBar.show("red-ui-status-package-update"); } else { RED.statusBar.hide("red-ui-status-package-update"); } + RED.events.emit("registry:updates-available", updates) + } + + function getAvailableUpdates () { + const palette = [...moduleUpdates] + let core = null + let count = palette.length + if (updateStatusState.version) { + core = { current: RED.settings.version, latest: updateStatusState.version } + count ++ + } + return { + count, + core, + palette + } } return { - init: init, - install: install + init, + install, + getAvailableUpdates } })(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js index 9af711e09..22ade35c9 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js @@ -210,7 +210,7 @@ RED.sidebar.config = (function() { nodeDiv.addClass("red-ui-palette-node-config-invalid"); RED.popover.tooltip(nodeDivAnnotations, function () { if (node.validationErrors && node.validationErrors.length > 0) { - return RED._("editor.errors.invalidProperties") + "
- " + node.validationErrors.join("
- "); + return $('' + RED._("editor.errors.invalidProperties") + "
- " + node.validationErrors.join("
- ") + '
'); } }) } @@ -218,7 +218,7 @@ RED.sidebar.config = (function() { nodeDiv.on('click',function(e) { e.stopPropagation(); RED.view.select(false); - if (e.metaKey) { + if (e.metaKey || e.ctrlKey) { $(this).toggleClass("selected"); } else { $(content).find(".red-ui-palette-node").removeClass("selected"); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js index fa91059db..436cd3221 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js @@ -1110,20 +1110,36 @@ RED.utils = (function() { return result; } + /** + * Get the default icon for a given node based on its definition. + * @param {*} def + * @param {*} node + * @returns + */ function getDefaultNodeIcon(def,node) { def = def || {}; var icon_url; if (node && node.type === "subflow") { icon_url = "node-red/subflow.svg"; - } else if (typeof def.icon === "function") { - try { - icon_url = def.icon.call(node); - } catch(err) { - console.log("Definition error: "+def.type+".icon",err); - icon_url = "arrow-in.svg"; - } } else { - icon_url = def.icon; + let themeRule = nodeIconCache[def.type] + if (themeRule === undefined) { + // If undefined, we've not checked the theme yet + nodeIconCache[def.type] = getThemeOverrideForNode(def, 'icon') || null; + themeRule = nodeIconCache[def.type]; + } + if (themeRule) { + icon_url = themeRule.icon; + } else if (typeof def.icon === "function") { + try { + icon_url = def.icon.call(node); + } catch(err) { + console.log("Definition error: "+def.type+".icon",err); + icon_url = "arrow-in.svg"; + } + } else { + icon_url = def.icon; + } } var iconPath = separateIconPath(icon_url); @@ -1249,48 +1265,60 @@ RED.utils = (function() { return label } - var nodeColorCache = {}; + let nodeColorCache = {}; + let nodeIconCache = {} function clearNodeColorCache() { nodeColorCache = {}; } - function getNodeColor(type, def) { - def = def || {}; - var result = def.color; - var paletteTheme = RED.settings.theme('palette.theme') || []; + /** + * Checks if there is a theme override for the given node definition and property + * @param {*} def node definition + * @param {*} property either 'color' or 'icon' + * @returns the theme override value if there is a match, otherwise null + */ + function getThemeOverrideForNode(def, property) { + const paletteTheme = RED.settings.theme('palette.theme') || []; if (paletteTheme.length > 0) { - if (!nodeColorCache.hasOwnProperty(type)) { - nodeColorCache[type] = def.color; - var l = paletteTheme.length; - for (var i = 0; i < l; i++ ){ - var themeRule = paletteTheme[i]; - if (themeRule.hasOwnProperty('category')) { - if (!themeRule.hasOwnProperty('_category')) { - themeRule._category = new RegExp(themeRule.category); - } - if (!themeRule._category.test(def.category)) { - continue; - } + for (let i = 0; i < paletteTheme.length; i++ ){ + const themeRule = paletteTheme[i]; + if (themeRule.hasOwnProperty('category')) { + if (!themeRule.hasOwnProperty('_category')) { + themeRule._category = new RegExp(themeRule.category); } - if (themeRule.hasOwnProperty('type')) { - if (!themeRule.hasOwnProperty('_type')) { - themeRule._type = new RegExp(themeRule.type); - } - if (!themeRule._type.test(type)) { - continue; - } + if (!themeRule._category.test(def.category)) { + continue; } - nodeColorCache[type] = themeRule.color || def.color; - break; + } + if (themeRule.hasOwnProperty('type')) { + if (!themeRule.hasOwnProperty('_type')) { + themeRule._type = new RegExp(themeRule.type); + } + if (!themeRule._type.test(def.type)) { + continue; + } + } + // We have found a rule that matches - now see if it provides the requested property + if (themeRule.hasOwnProperty(property)) { + return themeRule; } } - result = nodeColorCache[type]; } - if (result) { - return result; - } else { - return "#ddd"; + return null; + } + + function getNodeColor(type, def) { + def = def || {}; + if (!nodeColorCache.hasOwnProperty(type)) { + const paletteTheme = RED.settings.theme('palette.theme') || []; + if (paletteTheme.length > 0) { + const themeRule = getThemeOverrideForNode(def, 'color'); + nodeColorCache[type] = themeRule?.color || def.color; + } else { + nodeColorCache[type] = def.color; + } } + return nodeColorCache[type] || "#ddd"; } function addSpinnerOverlay(container,contain) { 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 a6f8041d6..937dd28de 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 @@ -4032,7 +4032,7 @@ RED.view = (function() { clearSuggestedFlow(); RED.contextMenu.hide(); evt = evt || d3.event; - if (evt === 1) { + if (evt.button !== 0) { return; } if (mouse_mode === RED.state.SELECTING_NODE) { @@ -4897,7 +4897,7 @@ RED.view = (function() { d3.event.stopPropagation(); return; } - if (d3.event.button === 2) { + if (d3.event.button !== 0) { return } mousedown_link = d; diff --git a/packages/node_modules/@node-red/nodes/core/common/lib/debug/debug-utils.js b/packages/node_modules/@node-red/nodes/core/common/lib/debug/debug-utils.js index 4074985af..20a62ea5c 100644 --- a/packages/node_modules/@node-red/nodes/core/common/lib/debug/debug-utils.js +++ b/packages/node_modules/@node-red/nodes/core/common/lib/debug/debug-utils.js @@ -433,12 +433,28 @@ RED.debug = (function() { if (o) { stack.push(o); } if (!busy && (stack.length > 0)) { busy = true; - processDebugMessage(stack.shift()); - setTimeout(function() { - busy = false; - handleDebugMessage(); - }, 15); // every 15mS = 66 times a second - if (stack.length > numMessages) { stack = stack.splice(-numMessages); } + const message = stack.shift() + // call any preDebugLog hooks, allowing them to modify the message or block it from being displayed + RED.hooks.trigger('debugPreProcessMessage', { message }).then(result => { + if (result === false) { + return false; // A hook returned false - halt processing of this message + } + return processDebugMessage(message); + }).then(processArtifacts => { + if (processArtifacts === false) { + return false; // A hook returned false - halt processing of this message + } + const { message, element, payload } = processArtifacts || {}; + return RED.hooks.trigger('debugPostProcessMessage', { message, element, payload }); + }).catch(err => { + console.error("Error in debug process message hooks", err); + }).finally(() => { + setTimeout(function() { + busy = false; + handleDebugMessage(); + }, 15); // every 15mS = 66 times a second + if (stack.length > numMessages) { stack = stack.splice(-numMessages); } + }) } } else { debugPausedMessageCount++ @@ -564,10 +580,13 @@ RED.debug = (function() { sourceId: sourceNode && sourceNode.id, rootPath: path, nodeSelector: config.messageSourceClick, - enablePinning: true + enablePinning: true, + tools: o.tools // permit preDebugLog hooks to add extra tools to the element }); // Do this in a separate step so the element functions aren't stripped debugMessage.appendTo(el); + // add the meta row tools container, even if there are no tools, so that the postProcessDebugMessage hook can add tools + const tools = $('').appendTo(metaRow) // NOTE: relying on function error to have a "type" that all other msgs don't if (o.hasOwnProperty("type") && (o.type === "function")) { var errorLvlType = 'error'; @@ -579,7 +598,6 @@ RED.debug = (function() { msg.addClass('red-ui-debug-msg-level-' + errorLvl); $('function : (' + errorLvlType + ')').appendTo(metaRow); } else { - var tools = $('').appendTo(metaRow); var filterMessage = $('').appendTo(tools); filterMessage.on("click", function(e) { e.preventDefault(); @@ -635,6 +653,14 @@ RED.debug = (function() { if (atBottom) { messageList.scrollTop(sbc.scrollHeight); } + + // return artifacts to permit postProcessDebugMessage hooks to modify the message element, access the + // processed payload or otherwise modify the message after it has been generated. + return { + message: o, // original debug message object, useful for any hook that might have tagged additional info onto it + element: msg, // the top-level element for this debug message + payload // the reconstructed debug message + } } function clearMessageList(clearFilter, filteredOnly) { diff --git a/packages/node_modules/@node-red/nodes/package.json b/packages/node_modules/@node-red/nodes/package.json index 38a5a3868..48b2d9118 100644 --- a/packages/node_modules/@node-red/nodes/package.json +++ b/packages/node_modules/@node-red/nodes/package.json @@ -15,9 +15,9 @@ } ], "dependencies": { - "acorn": "8.15.0", - "acorn-walk": "8.3.4", - "ajv": "8.17.1", + "acorn": "8.16.0", + "acorn-walk": "8.3.5", + "ajv": "8.18.0", "body-parser": "1.20.4", "cheerio": "1.0.0-rc.10", "content-type": "1.0.5", @@ -35,7 +35,7 @@ "is-utf8": "0.2.1", "js-yaml": "4.1.1", "media-typer": "1.1.0", - "mqtt": "5.11.0", + "mqtt": "5.15.0", "multer": "2.0.2", "mustache": "4.2.0", "node-watch": "0.7.4", diff --git a/packages/node_modules/@node-red/registry/package.json b/packages/node_modules/@node-red/registry/package.json index 1c7925811..7d4672fb8 100644 --- a/packages/node_modules/@node-red/registry/package.json +++ b/packages/node_modules/@node-red/registry/package.json @@ -19,8 +19,8 @@ "@node-red/util": "5.0.0-beta.2", "clone": "2.1.2", "fs-extra": "11.3.0", - "semver": "7.7.1", - "tar": "7.5.7", + "semver": "7.7.4", + "tar": "7.5.9", "uglify-js": "3.19.3" } } diff --git a/packages/node_modules/@node-red/runtime/package.json b/packages/node_modules/@node-red/runtime/package.json index 3060b6726..37032cfd1 100644 --- a/packages/node_modules/@node-red/runtime/package.json +++ b/packages/node_modules/@node-red/runtime/package.json @@ -25,7 +25,7 @@ "fs-extra": "11.3.0", "got": "12.6.1", "json-stringify-safe": "5.0.1", - "rfdc": "^1.3.1", - "semver": "7.7.1" + "rfdc": "1.4.1", + "semver": "7.7.4" } } diff --git a/packages/node_modules/node-red/package.json b/packages/node_modules/node-red/package.json index a47892c6e..eaf3aa05e 100644 --- a/packages/node_modules/node-red/package.json +++ b/packages/node_modules/node-red/package.json @@ -36,13 +36,13 @@ "@node-red/util": "5.0.0-beta.2", "@node-red/nodes": "5.0.0-beta.2", "basic-auth": "2.0.1", - "bcryptjs": "3.0.2", + "bcryptjs": "3.0.3", "cors": "2.8.5", "express": "4.22.1", "fs-extra": "11.3.0", "node-red-admin": "^4.1.3", "nopt": "5.0.0", - "semver": "7.7.1" + "semver": "7.7.4" }, "optionalDependencies": { "@node-rs/bcrypt": "1.10.7" diff --git a/test/unit/@node-red/editor-api/lib/editor/theme_spec.js b/test/unit/@node-red/editor-api/lib/editor/theme_spec.js index 995662de3..e20868c2a 100644 --- a/test/unit/@node-red/editor-api/lib/editor/theme_spec.js +++ b/test/unit/@node-red/editor-api/lib/editor/theme_spec.js @@ -53,7 +53,7 @@ describe("api/editor/theme", function () { context.asset.should.have.a.property("main", "red/main.min.js"); context.asset.should.have.a.property("vendorMonaco", "vendor/monaco/monaco-bootstrap.js"); - should.not.exist(theme.settings()); + should.not.exist(await theme.settings()); }); it("uses non-minified js files when in dev mode", async function () { @@ -158,7 +158,7 @@ describe("api/editor/theme", function () { context.should.have.a.property("login"); context.login.should.have.a.property("image", "theme/login/image"); - var settings = theme.settings(); + var settings = await theme.settings(); settings.should.have.a.property("deployButton"); settings.deployButton.should.have.a.property("type", "simple"); settings.deployButton.should.have.a.property("label", "Save"); @@ -199,7 +199,7 @@ describe("api/editor/theme", function () { }); - it("test explicit userMenu set to true in theme setting", function () { + it("test explicit userMenu set to true in theme setting", async function () { theme.init({ editorTheme: { userMenu: true, @@ -208,7 +208,7 @@ describe("api/editor/theme", function () { theme.app(); - var settings = theme.settings(); + var settings = await theme.settings(); settings.should.have.a.property("userMenu"); settings.userMenu.should.be.eql(true);