diff --git a/CHANGELOG.md b/CHANGELOG.md index 15e35cd8b..4b55ac4c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,76 @@ +#### 4.0.5: Maintenance Release + +Editor + + - Refix link call node can call out of a subflow (#4908) @GogoVega + +#### 4.0.4: Maintenance Release + +Editor + + - Fix `link call` node can call out of a subflow (#4892) @GogoVega + - Fix wrong unlock state when event is triggered after deployment (#4889) @GogoVega + - i18n(App) update with latest language file changes (#4903) @joebordes + - fix typo: depreciated (#4895) @dxdc + +Runtime + + - Update dev dependencies (#4893) @knolleary + +Nodes + + - MQTT: Allow msg.userProperties to have number values (#4900) @hardillb + +#### 4.0.3: Maintenance Release + +Editor + + - Refresh page title after changing tab name (#4850) @kazuhitoyokoi + - Add Japanese translations for v4.0.2 (again) (#4853) @kazuhitoyokoi + - Stay in quick-add mode following context menu insert (#4883) @knolleary + - Do not include Junction type in quick-add for virtual links (#4879) @knolleary + - Multiplayer cursor tracking (#4845) @knolleary + - Hide add-flow options when disabled via editorTheme (#4869) @knolleary + - Fix env-var config select when multiple defined (#4872) @knolleary + - Fix subflow outbound-link filter (#4857) @GogoVega + - Add French translations for v4.0.2 (#4856) @GogoVega + - Fix moving link wires (#4851) @knolleary + - Adjust type search dialog position to prevent x-overflow (#4844) @Steve-Mcl + - fix: modulesInUse might be undefined (#4838) @lorenz-maurer + - Add Japanese translations for v4.0.2 (#4849) @kazuhitoyokoi + - Fix menu to enable/disable selection when it's a group (#4828) @GogoVega + +Runtime + + - Update dependencies (#4874) @knolleary + - GitHub: Add citation file to enable "Cite this repository" feature (#4861) @lobis + - Remove use of util.log (#4875) @knolleary + +Nodes + + - Fix invalid property error in range node example (#4855) + - Fix typo in flow example name (#4854) @kazuhitoyokoi + - Move SNI, ALPN and Verify Server cert out of check (#4882) @hardillb + - Set status of mqtt nodes to "disconnected" when deregistered from broker (#4878) @Steve-Mcl + - MQTT: Ensure will payload is a string (#4873) @knolleary + - Let batch node terminate "early" if msg.parts set to end of sequence (#4829) @dceejay + - Fix unintentional Capitalisation in Split node name (#4835) @dceejay + +#### 4.0.2: Maintenance Release + +Editor + + - Use a more subtle border on the header (#4818) @bonanitech + - Improve the editor's French translations (#4824) @GogoVega + - Clean up orphaned editors (#4821) @Steve-Mcl + - Fix node validation if the property is not required (#4812) @GogoVega + - Ensure mermaid.min.js is cached properly between loads of the editor (#4817) @knolleary + +Runtime + + - Allow auth cookie name to be customised (#4815) @knolleary + - Guard against undefined sessions in multiplayer (#4816) @knolleary + #### 4.0.1: Maintenance Release Editor diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..9372ad005 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,7 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +title: "Node-RED" +authors: + - family-names: "OpenJS Foundation" + - family-names: "Contributors" +url: "https://nodered.org" diff --git a/package.json b/package.json index e7e988f75..c7fe644f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red", - "version": "4.0.1", + "version": "4.0.5", "description": "Low-code programming for event-driven applications", "homepage": "https://nodered.org", "license": "Apache-2.0", @@ -26,26 +26,26 @@ } ], "dependencies": { - "acorn": "8.11.3", - "acorn-walk": "8.3.2", - "ajv": "8.14.0", + "acorn": "8.12.1", + "acorn-walk": "8.3.4", + "ajv": "8.17.1", "async-mutex": "0.5.0", "basic-auth": "2.0.1", "bcryptjs": "2.4.3", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "cheerio": "1.0.0-rc.10", "clone": "2.1.2", "content-type": "1.0.5", - "cookie": "0.6.0", - "cookie-parser": "1.4.6", + "cookie": "0.7.2", + "cookie-parser": "1.4.7", "cors": "2.8.5", "cronosjs": "1.7.1", "denque": "2.1.0", - "express": "4.19.2", - "express-session": "1.18.0", + "express": "4.21.1", + "express-session": "1.18.1", "form-data": "4.0.0", "fs-extra": "11.2.0", - "got": "12.6.0", + "got": "12.6.1", "hash-sum": "2.0.0", "hpagent": "1.2.0", "https-proxy-agent": "5.0.1", @@ -60,11 +60,11 @@ "memorystore": "1.6.7", "mime": "3.0.0", "moment": "2.30.1", - "moment-timezone": "0.5.45", + "moment-timezone": "0.5.46", "mqtt": "5.7.0", "multer": "1.4.5-lts.1", "mustache": "4.2.0", - "node-red-admin": "^4.0.0", + "node-red-admin": "^4.0.1", "node-watch": "0.7.4", "nopt": "5.0.0", "oauth2orize": "1.12.0", @@ -72,11 +72,11 @@ "passport": "0.7.0", "passport-http-bearer": "1.0.1", "passport-oauth2-client-password": "0.1.2", - "raw-body": "2.5.2", + "raw-body": "3.0.0", "rfdc": "^1.3.1", - "semver": "7.5.4", - "tar": "7.2.0", - "tough-cookie": "4.1.4", + "semver": "7.6.3", + "tar": "7.4.3", + "tough-cookie": "^5.0.0", "uglify-js": "3.17.4", "uuid": "9.0.1", "ws": "7.5.10", @@ -86,10 +86,10 @@ "@node-rs/bcrypt": "1.10.4" }, "devDependencies": { - "dompurify": "2.4.1", + "dompurify": "2.5.7", "grunt": "1.6.1", "grunt-chmod": "~1.1.1", - "grunt-cli": "~1.4.3", + "grunt-cli": "~1.5.0", "grunt-concurrent": "3.0.0", "grunt-contrib-clean": "2.0.1", "grunt-contrib-compress": "2.0.0", @@ -100,7 +100,7 @@ "grunt-contrib-watch": "1.1.0", "grunt-jsdoc": "2.4.1", "grunt-jsdoc-to-markdown": "6.0.0", - "grunt-jsonlint": "2.1.3", + "grunt-jsonlint": "3.0.0", "grunt-mkdir": "~1.1.0", "grunt-npm-command": "~0.1.2", "grunt-sass": "~3.1.0", @@ -110,11 +110,11 @@ "jquery-i18next": "1.2.1", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "marked": "4.3.0", - "mermaid": "^10.4.0", + "mermaid": "11.3.0", "minami": "1.2.3", "mocha": "9.2.2", "node-red-node-test-helper": "^0.3.3", - "nodemon": "2.0.20", + "nodemon": "3.1.7", "proxy": "^1.0.2", "sass": "1.62.1", "should": "13.2.3", diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json index 02c261e22..e58f2e9fb 100644 --- a/packages/node_modules/@node-red/editor-api/package.json +++ b/packages/node_modules/@node-red/editor-api/package.json @@ -1,6 +1,6 @@ { "name": "@node-red/editor-api", - "version": "4.0.1", + "version": "4.0.5", "license": "Apache-2.0", "main": "./lib/index.js", "repository": { @@ -16,14 +16,14 @@ } ], "dependencies": { - "@node-red/util": "4.0.1", - "@node-red/editor-client": "4.0.1", + "@node-red/util": "4.0.5", + "@node-red/editor-client": "4.0.5", "bcryptjs": "2.4.3", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "clone": "2.1.2", "cors": "2.8.5", - "express-session": "1.18.0", - "express": "4.19.2", + "express-session": "1.18.1", + "express": "4.21.1", "memorystore": "1.6.7", "mime": "3.0.0", "multer": "1.4.5-lts.1", diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json index a88890125..9bdd55155 100644 --- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json @@ -375,7 +375,10 @@ "flowAdded": "flow added", "moved": "moved", "movedTo": "moved to __id__", - "movedFrom": "moved from __id__" + "movedFrom": "moved from __id__", + "none": "none", + "position": "position", + "wires": "wires" }, "nodeCount": "__count__ node", "nodeCount_plural": "__count__ nodes", @@ -384,9 +387,14 @@ "reviewChanges": "Review Changes", "noBinaryFileShowed": "Cannot show binary file contents", "viewCommitDiff": "View Commit Changes", + "commit": "Commit", "compareChanges": "Compare Changes", "saveConflict": "Save conflict resolution", "conflictHeader": "__resolved__ of __unresolved__ conflicts resolved", + "localChanges": "Local Changes", + "remoteChanges": "Remote Changes", + "useLocalChanges": "use local changes", + "useRemoteChanges": "use remote changes", "commonVersionError": "Common Version doesn't contain valid JSON:", "oldVersionError": "Old Version doesn't contain valid JSON:", "newVersionError": "New Version doesn't contain valid JSON:" @@ -554,7 +562,9 @@ "types": { "local": "Local", "examples": "Examples" - } + }, + "type": "Type", + "name": "Name" }, "palette": { "noInfo": "no information available", @@ -803,6 +813,7 @@ "branches": "Branches", "noBranches": "No branches", "deleteConfirm": "Are you sure you want to delete the local branch '__name__'? This cannot be undone.", + "deleteBranch": "Delete branch", "unmergedConfirm": "The local branch '__name__' has unmerged changes that will be lost. Are you sure you want to delete it?", "deleteUnmergedBranch": "Delete unmerged branch", "gitRemotes": "Git remotes", diff --git a/packages/node_modules/@node-red/editor-client/locales/es-ES/editor.json b/packages/node_modules/@node-red/editor-client/locales/es-ES/editor.json index 2655dfe27..eb2ef79d2 100644 --- a/packages/node_modules/@node-red/editor-client/locales/es-ES/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/es-ES/editor.json @@ -27,7 +27,8 @@ "lock": "Bloquear", "unlock": "Desbloquear", "locked": "Bloqueado", - "unlocked": "Desbloqueado" + "unlocked": "Desbloqueado", + "format": "Formato" }, "type": { "string": "texto", @@ -303,7 +304,8 @@ "missingType": "La entrada no es un flujo válido - elemento __index__ falta la propiedad 'type'" }, "conflictNotification1": "Algunos de los nodos que estás importando ya existen en tu espacio de trabajo.", - "conflictNotification2": "Selecciona qué nodos importar y si reemplazar los nodos existentes o importar una copia de los mismos." + "conflictNotification2": "Selecciona qué nodos importar y si reemplazar los nodos existentes o importar una copia de los mismos.", + "alreadyExists": "Este nodo ya existe" }, "copyMessagePath": "Ruta copiada", "copyMessageValue": "Valor copiado", @@ -371,8 +373,12 @@ "deleted": "eliminado", "flowDeleted": "flujo eliminado", "flowAdded": "flujo añadido", + "moved": "movido", "movedTo": "movido a __id__", - "movedFrom": "movido desde __id__" + "movedFrom": "movido desde __id__", + "none": "ninguno", + "position": "posición", + "wires": "conectores" }, "nodeCount": "__count__ nodo", "nodeCount_plural": "__count__ nodos", @@ -381,9 +387,14 @@ "reviewChanges": "Revisar Cambios", "noBinaryFileShowed": "No se puede mostrar el contenido del archivo binario", "viewCommitDiff": "Ver cambios de commit", + "commit": "Commit", "compareChanges": "Comparar Cambios", "saveConflict": "Guardar resolución de conflictos", "conflictHeader": "__resolved__ de __unresolved__ conflictos resueltos", + "localChanges": "Cambios Locales", + "remoteChanges": "Cambios Remotos", + "useLocalChanges": "utilizar cambios locales", + "useRemoteChanges": "utilizar cambios remotos", "commonVersionError": "La versión común no contiene JSON válido:", "oldVersionError": "La versión anterior no contiene JSON válido:", "newVersionError": "La versión nueva no contiene JSON válido:" @@ -551,7 +562,9 @@ "types": { "local": "Local", "examples": "Ejemplos" - } + }, + "type": "Tipo", + "name": "Nombre" }, "palette": { "noInfo": "no hay información disponible", @@ -613,6 +626,8 @@ }, "nodeCount": "__label__ nodo", "nodeCount_plural": "__label__ nodos", + "pluginCount": "__count__ extensión", + "pluginCount_plural": "__count__ extensiones", "moduleCount": "__count__ módulo disponible", "moduleCount_plural": "__count__ módulos disponibles", "inuse": "en uso", @@ -640,6 +655,7 @@ "errors": { "catalogLoadFailed": "
La carga del catálogo de nodos ha fallado
Revise la consola del navegador para mas información
", "installFailed": "Fallo al instalar: __module__
__message__
Revise el log para mas información
", + "installTimeout": "La instalación continúa en segundo plano.
Los nodos aparecerán en la paleta cuando finalice. Consulta el registro para obtener más información.
", "removeFailed": "Fallo al eliminar: __module__
__message__
Revise el log para mas información
", "updateFailed": "Fallo al actualizar: __module__
__message__
Revise el log para mas información
", "enableFailed": "Fallo al activar: __module__
__message__
Revise el log para mas información
", @@ -654,6 +670,9 @@ "body":"Eliminando '__module__'
La eliminación del nodo lo desinstalará de Node-RED. Es posible que el nodo siga utilizando recursos hasta que Node-RED sea reiniciado.
", "title": "Eliminar nodos" }, + "removePlugin": { + "body": "Extensión __module__ eliminada. Vuelve a cargar el editor para borrar los elementos sobrantes.
" + }, "update": { "body":"Actualizando '__module__'
La actualización del nodo requerirá un reinicio manual de Node-RED para completarse. Debe ser reiniciado manualmente.
", "title": "Actualizar nodos" @@ -665,7 +684,8 @@ "review": "Abrir información del nodo", "install": "Instalar", "remove": "Eliminar", - "update": "Actualizar" + "update": "Actualizar", + "understood": "Entendido" } } } @@ -718,6 +738,7 @@ "nodeHelp": "Ayuda de nodo", "showHelp": "Mostrar ayuda", "showInOutline": "Mostrar en controno", + "hideTopics": "Esconder temas", "showTopics": "Mostrar temas", "noHelp": "No hay ningun tema de ayuda seleccionado", "changeLog": "Registro de Cambios" @@ -792,6 +813,7 @@ "branches": "Ramas", "noBranches": "Sin ramas", "deleteConfirm": "¿Estás seguro de que quieres eliminar la rama local '__name__'? Esta acción no puede deshacerse.", + "deleteBranch": "Eliminar rama", "unmergedConfirm": "La rama local '__name__' tiene cambios no fusionados que se perderán. ¿Estás seguro de que quieres eliminarla?", "deleteUnmergedBranch": "Eliminar rama no fusionada", "gitRemotes": "Git remotes", @@ -913,6 +935,8 @@ } }, "typedInput": { + "selected": "__count__ seleccionado", + "selected_plural": "__count__ seleccionados", "type": { "str": "texto", "num": "número", @@ -923,7 +947,14 @@ "date": "marca tiempo", "jsonata": "expresión", "env": "variable de entorno", - "cred": "credencial" + "cred": "credencial", + "conf-types": "nodo configuración" + }, + "date": { + "format": { + "timestamp": "milisegundos desde epoch", + "object": "Objeto de fecha de JavaScript" + } } }, "editableList": { @@ -1205,6 +1236,18 @@ "diagnostics": { "title": "Información Sistema" }, + "languages": { + "de": "Deutsch", + "en-US": "English", + "es-ES": "Español (España)", + "fr": "Français", + "ja": "日本語", + "ko": "Korean", + "pt-BR": "Português (Brasil)", + "ru": "Русский", + "zh-CN": "简体中文", + "zh-TW": "繁體中文" + }, "validator": { "errors": { "invalid-json": "Datos JSON inválidos: __error__", diff --git a/packages/node_modules/@node-red/editor-client/locales/fr/editor.json b/packages/node_modules/@node-red/editor-client/locales/fr/editor.json index bacd5b70f..fbd6f2849 100644 --- a/packages/node_modules/@node-red/editor-client/locales/fr/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/fr/editor.json @@ -27,7 +27,8 @@ "lock": "Verrouiller", "unlock": "Déverrouiller", "locked": "Verrouillé", - "unlocked": "Déverrouillé" + "unlocked": "Déverrouillé", + "format": "Format" }, "type": { "string": "chaîne de caractères", @@ -54,10 +55,10 @@ "workspace": { "defaultName": "Flux __number__", "editFlow": "Modifier le flux : __name__", - "confirmDelete": "Confirmation de la suppression", - "delete": "Etes-vous sûr de vouloir supprimer '__label__'?", - "dropFlowHere": "Déposer le flux ici", - "dropImageHere": "Déposer l'image ici", + "confirmDelete": "Confirmer la suppression", + "delete": "Êtes-vous sûr de vouloir supprimer '__label__' ?", + "dropFlowHere": "Lâchez le flux ici", + "dropImageHere": "Lâchez l'image ici", "addFlow": "Ajouter un flux", "addFlowToRight": "Ajouter un flux à droite", "closeFlow": "Fermer le flux", @@ -74,7 +75,7 @@ "enabled": "Activé", "disabled": "Désactivé", "info": "Description", - "selectNodes": "Cliquer sur les noeuds pour sélectionner", + "selectNodes": "Cliquer pour sélectionner", "enableFlow": "Activer le flux", "disableFlow": "Désactiver le flux", "lockFlow": "Verrouiller le flux", @@ -98,7 +99,7 @@ "rtl": "De droite à gauche", "auto": "Contextuel", "language": "Langue", - "browserDefault": "Navigateur par défaut" + "browserDefault": "Par défaut du Navigateur" }, "sidebar": { "show": "Afficher la barre latérale" @@ -134,7 +135,7 @@ "disableSelectedNodes": "Désactiver les noeuds sélectionnés", "showSelectedNodeLabels": "Afficher les étiquettes des noeuds sélectionnés", "hideSelectedNodeLabels": "Masquer les étiquettes des noeuds sélectionnés", - "showWelcomeTours": "Afficher les visites guidées pour les nouvelles versions", + "showWelcomeTours": "Afficher les visites guidées des nouvelles versions", "help": "Site web de Node-RED", "projects": "Projets", "projects-new": "Nouveau projet", @@ -143,7 +144,7 @@ "showNodeLabelDefault": "Afficher l'étiquette des noeuds nouvellement ajoutés", "codeEditor": "Éditeur de code", "groups": "Groupes", - "groupSelection": "Grouper cette sélection", + "groupSelection": "Grouper la sélection", "ungroupSelection": "Dégrouper la sélection", "groupMergeSelection": "Fusionner la sélection", "groupRemoveSelection": "Supprimer du groupe", @@ -155,7 +156,7 @@ "alignMiddle": "Aligner au milieu", "alignBottom": "Aligner en bas", "distributeHorizontally": "Répartir horizontalement", - "distributeVertically": "Distribuer verticalement", + "distributeVertically": "Répartir verticalement", "moveToBack": "Déplacer vers l'arrière", "moveToFront": "Déplacer vers l'avant", "moveBackwards": "Reculer", @@ -163,21 +164,21 @@ } }, "actions": { - "toggle-navigator": "Basculer de navigateur", - "zoom-out": "Dézoomer", - "zoom-reset": "Réinitialiser le zoom", + "toggle-navigator": "Basculer l'affichage du navigateur", + "zoom-out": "Réduire", + "zoom-reset": "Réinitialiser", "zoom-in": "Agrandir", "search-flows": "Rechercher le flux", "search-prev": "Précédent", "search-next": "Suivant", - "search-counter": "\"__term__\" __result__ de __count__" + "search-counter": "\"__term__\" __result__ sur __count__" }, "user": { "loggedInAs": "Connecté en tant que __name__", "username": "Nom d'utilisateur", "password": "Mot de passe", - "login": "Connexion", - "loginFailed": "Échec de la connexion", + "login": "Se connecter", + "loginFailed": "Échec de connexion", "notAuthorized": "Pas autorisé", "errors": { "settings": "Vous devez être connecté pour accéder aux paramètres", @@ -193,16 +194,16 @@ "warning": "Attention : __message__", "warnings": { "undeployedChanges": "Le noeud a des modifications non déployées", - "nodeActionDisabled": "Actions de noeud désactivées", - "nodeActionDisabledSubflow": "Actions de noeud désactivées dans le sous-flux", + "nodeActionDisabled": "Les actions du noeud sont désactivées", + "nodeActionDisabledSubflow": "Les actions de noeud sont désactivées à l'intérieur du sous-flux", "missing-types": "Flux arrêtés en raison de types de noeuds manquants.
", "missing-modules": "Flux arrêtés en raison de modules manquants.
", - "safe-mode": "Flux arrêtés en mode sans échec.
Vous pouvez modifier vos flux et déployer les changements pour redémarrer.
", + "safe-mode": "Flux arrêtés en mode sans échec.
Vous pouvez modifier vos flux et déployer ensuite les changements afin de démarrer vos flux.
", "restartRequired": "Node-RED doit être redémarré pour mettre à jour les modules", - "credentials_load_failed": "Les flux se sont arrêtés car les informations d'identification n'ont pas pu être déchiffrées.
Le fichier d'informations d'identification du flux est chiffré, mais la clé de chiffrement du projet est manquante ou invalide.
", - "credentials_load_failed_reset": "Les informations d'identification n'ont pas pu être déchiffrées
Le fichier d'informations d'identification du flux est chiffré, mais la clé de chiffrement du projet est manquante ou invalide.
Le fichier d'informations d'identification du flux sera réinitialisé lors du prochain déploiement. Toutes les informations d'identification de flux existantes seront perdues.
", + "credentials_load_failed": "Les flux se sont arrêtés car les informations d'identification n'ont pas pu être déchiffrées.
Le fichier d'informations d'identification du flux est chiffré mais la clé de chiffrement du projet est manquante ou invalide.
", + "credentials_load_failed_reset": "Les informations d'identification n'ont pas pu être déchiffrées
Le fichier d'informations d'identification du flux est chiffré mais la clé de chiffrement du projet est manquante ou invalide.
Le fichier d'informations d'identification du flux sera réinitialisé lors du prochain déploiement. Toutes les informations d'identification des flux existants seront perdues.
", "missing_flow_file": "Fichier contenant les flux introuvable.
Le projet n'est pas configuré avec un fichier de flux.
", - "missing_package_file": "Fichier de paquetage du projet introuvable.
Il manque au projet un fichier package.json.
", + "missing_package_file": "Fichier de paquetage du projet introuvable.
Il manque au projet le fichier package.json
.
Le projet est vide.
Voulez-vous créer un ensemble de fichiers de projet par défaut ?
Sinon, vous devrez ajouter manuellement des fichiers au projet (en dehors de l'éditeur).
Le projet '__project__' est introuvable.
", "git_merge_conflict": "La fusion automatique des modifications a échoué.
Corriger les conflits non fusionnés, puis valider le résultat.
" @@ -219,7 +220,7 @@ }, "project": { "change-branch": "Changer pour une branche locale '__project__'", - "merge-abort": "Git fusion abandonnée", + "merge-abort": "Fusion Git abandonnée", "loaded": "Projet '__project__' chargé", "updated": "Projet '__project__' mis à jour", "pull": "Projet '__project__' rechargé", @@ -352,7 +353,7 @@ "backgroundUpdate": "Les flux sur le serveur ont été mis à jour.", "conflictChecking": "Vérifier si les modifications peuvent être fusionnées automatiquement", "conflictAutoMerge": "Les modifications n'incluent aucun conflit et peuvent être fusionnées automatiquement.", - "conflictManualMerge": "Les changements incluent des conflits qui doivent être résolus avant de pouvoir être déployés.", + "conflictManualMerge": "Les modifications incluent des conflits qui doivent être résolus avant de pouvoir être déployées.", "plusNMore": "+ __count__ en plus" } }, @@ -372,19 +373,28 @@ "deleted": "supprimé", "flowDeleted": "flux supprimé", "flowAdded": "flux ajouté", + "moved": "déplacé", "movedTo": "déplacé vers __id__", - "movedFrom": "déplacé depuis __id__" + "movedFrom": "déplacé depuis __id__", + "none": "aucun", + "position": "position", + "wires": "câbles" }, "nodeCount": "__count__ noeud", "nodeCount_plural": "__count__ noeuds", "local": "Changements locaux", - "remote": "Modifications à distance", + "remote": "Changements distants", "reviewChanges": "Examiner les modifications", "noBinaryFileShowed": "Impossible d'afficher le contenu du fichier binaire", - "viewCommitDiff": "Afficher les modifications de validation", + "viewCommitDiff": "Afficher les modifications de la validation", + "commit": "Validation", "compareChanges": "Comparer les modifications", "saveConflict": "Enregistrer la résolution des conflits", "conflictHeader": "__resolved__ sur __unresolved__ conflit(s) résolu(s)", + "localChanges": "Modifications locales", + "remoteChanges": "Modifications distantes", + "useLocalChanges": "utiliser les modifications locales", + "useRemoteChanges": "utiliser les modifications distantes", "commonVersionError": "La version commune ne contient pas de JSON valide :", "oldVersionError": "L'ancienne version ne contient pas de JSON valide :", "newVersionError": "La nouvelle version ne contient pas de JSON valide :" @@ -395,9 +405,9 @@ "edit": "Modifier le modèle du sous-flux", "subflowInstances": "Il existe __count__ instance de ce modèle de sous-flux", "subflowInstances_plural": "Il existe __count__ instances de ce modèle de sous-flux", - "editSubflowProperties": "modifier les propriétés", - "input": "Entrées:", - "output": "Sorties:", + "editSubflowProperties": "Modifier les propriétés", + "input": "Entrées :", + "output": "Sorties :", "status": "Statut du noeud", "deleteSubflow": "Supprimer le sous-flux", "confirmDelete": "Voulez-vous vraiment supprimer ce sous-flux ?", @@ -411,7 +421,7 @@ "version": "Version", "versionPlaceholder": "x.y.z", "keys": "Mots clés", - "keysPlaceholder": "Mots clés séparés par des virgules", + "keysPlaceholder": "Mots clés séparés par une virgule", "author": "Auteur", "authorPlaceholder": "Votre nomÉchec du chargement du catalogue de noeuds.
Vérifier la console du navigateur pour plus d'informations
", @@ -651,7 +663,7 @@ }, "confirm": { "install": { - "body": "Installation de '__module__'
Avant l'installation, veuiller lire la documentation du noeud. Certains noeuds ont des dépendances qui ne peuvent pas être résolues automatiquement et peuvent nécessiter un redémarrage de Node-RED.
", + "body": "Installation de '__module__'
Avant l'installation, veuillez lire la documentation du noeud. Certains noeuds ont des dépendances qui ne peuvent pas être résolues automatiquement et peuvent nécessiter un redémarrage de Node-RED.
", "title": "Installer les noeuds" }, "remove": { @@ -666,7 +678,7 @@ "title": "Mettre à jour les noeuds" }, "cannotUpdate": { - "body": "Une mise à jour pour ce noeud est disponible, mais il n'est pas installé dans un emplacement que le gestionnaire de palette peut mettre à jour.Impossible d'extraire les modifications à distance ; vos modifications locales non mises en place seraient écrasées.
Valider vos modifications et réessayer.
", - "showUnstagedChanges": "Afficher les modifications non mise en place", + "unablePull": "Impossible d'extraire les modifications à distance; vos modifications locales non mises en place seraient écrasées.
Valider vos modifications et réessayer.
", + "showUnstagedChanges": "Afficher les modifications non indexées", "connectionFailed": "Impossible de se connecter au référentiel distant: ", "pullUnrelatedHistory": "Le réferentiel distant a un historique de validations sans rapport.
Êtes-vous sûr de vouloir extraire les modifications dans votre référentiel local ?
", - "pullChanges": "Tirer les changements", + "pullChanges": "Tirer les changements distants", "history": "Historique", "projectHistory": "Historique du projet", "daysAgo": "il y a __count__ jour", @@ -974,7 +987,7 @@ "result": "Résultat", "format": "Format", "compatMode": "Mode de compatibilité activé", - "compatModeDesc": " L'expression actuelle semble toujours faire référence à msg
et sera donc évaluée en mode de compatibilité. Veuiller mettre à jour l'expression pour ne pas utiliser msg
car ce mode sera supprimé à l'avenir.
Lorsque la prise en charge de JSONata a été ajoutée pour la première fois à Node-RED, il fallait que l'expression référencie l'objet msg
. Par exemple, msg.payload
serait utilisé pour accéder à la charge utile.
Cela n'est plus nécessaire car l'expression sera évaluée directement par rapport au message. Pour accéder à la charge utile, l'expression doit être simplement charge utile
.
L'expression actuelle semble toujours faire référence à msg
et sera donc évaluée en mode de compatibilité. Veuillez mettre à jour l'expression pour ne pas utiliser msg
car ce mode sera supprimé à l'avenir.
Lorsque la prise en charge de JSONata a été ajoutée pour la première fois à Node-RED, il fallait que l'expression référencie l'objet msg
. Par exemple, msg.payload
serait utilisé pour accéder à la charge utile.
Cela n'est plus nécessaire car l'expression sera évaluée directement par rapport au message. Pour accéder à la charge utile, l'expression doit être simplement charge utile
.
' + RED._("deploy.successfulDeploy") + '
', "success"); } const flowsToLock = new Set() + // Node's properties cannot be modified if its workspace is locked. function ensureUnlocked(id) { + // TODO: `RED.nodes.subflow` is useless const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null); const isLocked = flow ? flow.locked : false; if (flow && isLocked) { @@ -642,6 +644,7 @@ RED.deploy = (function() { delete confNode.credentials; } }); + // Subflow cannot be locked RED.nodes.eachSubflow(function (subflow) { if (subflow.changed) { subflow.changed = false; @@ -650,12 +653,18 @@ RED.deploy = (function() { }); RED.nodes.eachWorkspace(function (ws) { if (ws.changed || ws.added) { - ensureUnlocked(ws.z) + // Ensure the Workspace is unlocked to modify its properties. + ensureUnlocked(ws.id); ws.changed = false; delete ws.added + if (flowsToLock.has(ws)) { + ws.locked = true; + flowsToLock.delete(ws); + } RED.events.emit("flows:change", ws) } }); + // Ensures all workspaces to be locked have been locked. flowsToLock.forEach(flow => { flow.locked = true }) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js b/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js index ebdf683e3..26cdceb7e 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js @@ -497,7 +497,7 @@ RED.diff = (function() { } }) if (c === 0) { - result.text("none"); + result.text(RED._("diff.type.none")); } else { list.appendTo(result); } @@ -821,7 +821,7 @@ RED.diff = (function() { conflict = true; } row = $("msg.payload
based on type:",
"object": "Object",
"objectSend": "Send a message for each key/value pair",
"strBuff": "String / Buffer",
"array": "Array",
+ "splitThe": "Split the",
"splitUsing": "Split using",
"splitLength": "Fixed length of",
"stream": "Handle as a stream of messages",
@@ -1113,6 +1114,7 @@
"too-many": "too many pending messages in batch node",
"unexpected": "unexpected mode",
"no-parts": "no parts property in message",
+ "honourParts": "Allow msg.parts to also complete batch operation.",
"error": {
"invalid-count": "Invalid count",
"invalid-overlap": "Invalid overlap",
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/network/10-mqtt.html b/packages/node_modules/@node-red/nodes/locales/en-US/network/10-mqtt.html
index f4b0012ce..68f89ae4a 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/network/10-mqtt.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/network/10-mqtt.html
@@ -48,7 +48,8 @@
La plantilla de columnas puede contener una lista ordenada de nombres de columnas. Al convertir CSV en un objeto, los nombres de las columnas se utilizarán como nombres de propiedades. Alternativamente, los nombres de las columnas se pueden tomar de la primera fila del CSV.
+La plantilla de columnas puede contener una lista ordenada de nombres de columnas. Al convertir CSV en un objeto, los nombres de las columnas se utilizarán como nombres de propiedades. Alternativamente, los nombres de las columnas se pueden tomar de la primera fila del CSV. +
Cuando se selecciona el analizador RFC, la plantilla de columna debe ser compatible con RFC4180.
+Al convertir a CSV, la plantilla de columnas se utiliza para identificar qué propiedades extraer del objeto y en qué orden.
Si la plantilla de columnas está en blanco, puede utilizar una lista simple de propiedades separadas por comas proporcionada en msg.columns
para determinar qué extraer y en qué orden. Si ninguno de los dos está presente, todas las propiedades del objeto se muestran en el orden en que se encuentran en la primera fila.
Si la entrada es una matriz, entonces la plantilla de columnas solo se usa para generar opcionalmente una fila de títulos de columnas.
@@ -46,4 +48,5 @@Si genera varios mensajes, tendrán su propiedad parts
configurada y formarán una secuencia de mensajes completa.
Si el nodo está configurado para enviar encabezados de columna solo una vez, si se configura msg.reset
en cualquier valor hará que el nodo reenvíe los encabezados.
Nota: la plantilla de columna debe estar separada por comas, incluso si se elige un separador diferente para los datos.
+Nota: en el modo RFC, se generarán errores detectables para encabezados CSV mal formados y datos de carga útil de entrada no válidos
diff --git a/packages/node_modules/@node-red/nodes/locales/fr/messages.json b/packages/node_modules/@node-red/nodes/locales/fr/messages.json index 99002f48f..238763e3b 100644 --- a/packages/node_modules/@node-red/nodes/locales/fr/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/fr/messages.json @@ -1017,6 +1017,7 @@ "objectSend": "Envoie un message pour chaque paire clé/valeur", "strBuff": "Chaîne / Tampon", "array": "Tableau", + "splitThe": "Diviser le", "splitUsing": "Diviser en utilisant", "splitLength": "Longueur fixe de", "stream": "Gérer comme un flux de messages", @@ -1046,6 +1047,7 @@ "joinedUsing": "joint en utilisant", "send": "Envoyer le message :", "afterCount": "Après un nombre de parties du message", + "useparts": "Utiliser la propriété msg.parts existante", "count": "nombre", "subsequent": "Et tous les messages suivants.", "afterTimeout": "Après un délai d'attente après le premier message", @@ -1112,6 +1114,7 @@ "too-many": "Trop de messages en attente dans le noeud batch", "unexpected": "Mode inattendu", "no-parts": "Aucune propriété de pièces dans le message", + "honourParts": "Autoriser msg.parts à compléter les opération par lots", "error": { "invalid-count": "Compte invalide", "invalid-overlap": "Recouvrement invalide", diff --git a/packages/node_modules/@node-red/nodes/locales/ja/messages.json b/packages/node_modules/@node-red/nodes/locales/ja/messages.json index fe81a80ad..1693f879e 100644 --- a/packages/node_modules/@node-red/nodes/locales/ja/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/ja/messages.json @@ -1017,6 +1017,7 @@ "objectSend": "各key/valueペアのメッセージを送信", "strBuff": "文字列 / バッファ", "array": "配列", + "splitThe": "に基づく", "splitUsing": "分割", "splitLength": "固定長", "stream": "メッセージのストリームとして処理", @@ -1046,6 +1047,7 @@ "joinedUsing": "連結文字", "send": "メッセージ送信:", "afterCount": "指定数のメッセージパーツを受信後", + "useparts": "既存のmsg.partsプロパティを使用", "count": "合計値", "subsequent": "後続のメッセージ毎", "afterTimeout": "最初のメッセージ受信からのタイムアウト後", @@ -1112,6 +1114,7 @@ "too-many": "batchノード内で保持しているメッセージが多すぎます", "unexpected": "想定外のモード", "no-parts": "メッセージにpartsプロパティがありません", + "honourParts": "msg.partsを用いたbatch操作を許可", "error": { "invalid-count": "メッセージ数が不正", "invalid-overlap": "オーバラップが不正", diff --git a/packages/node_modules/@node-red/nodes/locales/pt-BR/messages.json b/packages/node_modules/@node-red/nodes/locales/pt-BR/messages.json index 274053bc6..51e1fd897 100644 --- a/packages/node_modules/@node-red/nodes/locales/pt-BR/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/pt-BR/messages.json @@ -44,7 +44,7 @@ "global": "contexto global", "str": "Cadeia de caracteres", "num": "número", - "bool": "booliano", + "bool": "booliano", "json": "objeto", "bin": "Armazenamento temporário", "date": "Carimbo de data/hora", @@ -352,8 +352,8 @@ } }, "trigger": { - "send": "Enviar", - "then": "então", + "send": "Enviar", + "then": "então", "then-send": "então enviem", "output": { "string": "a cadeia de caracteres", @@ -446,7 +446,7 @@ "staticTopic": "Assinar um tópico único", "dynamicTopic": "Assinatura dinâmica", "auto-connect": "Conectar automaticamente", - "auto-mode-depreciated": "Esta opção está deprecada. Favor utilizar o novo modo de auto-detecção." + "auto-mode-depreciated": "Esta opção está deprecada. Favor utilizar o novo modo de auto-detecção." }, "sections-label": { "birth-message": "Mensagem enviada na conexão (mensagem de nascimento)", @@ -466,8 +466,8 @@ "close-topic": "Deixe em branco para desativar a mensagem de fechamento" }, "state": { - "connected": "Conectado ao negociante: _ broker _", - "disconnected": "Desconectado do negociante: _ broker _", + "connected": "Conectado ao negociante: _ broker _", + "disconnected": "Desconectado do negociante: _ broker _", "connect-failed": "Falha na conexão com o negociante: __broker__", "broker-disconnected": "Cliente de negociante __broker__ desconectado: __reasonCode__ __reasonString__" }, @@ -898,7 +898,7 @@ "o2j": "Objeto para opções JSON", "pretty": "Formatar cadeia de caracteres JSON", "action": "Ação", - "property": "Propriedade", + "property": "Propriedade", "actions": { "toggle": "Converter entre cadeia de caracteres JSON e Objeto", "str": "Sempre converter em cadeia de caracteres JSON", @@ -929,7 +929,7 @@ "write": "escrever arquivo", "read": "ler arquivo", "filename": "Nome do arquivo", - "path": "caminho", + "path": "caminho", "action": "Ação", "addnewline": "Adicionar nova linha (\\n) a cada carga útil?", "createdir": "Criar diretório se não existir?", @@ -994,6 +994,7 @@ "objectSend": "Envia uma mensagem para cada par chave/valor", "strBuff": "Cadeia de caracteres / Armazenamento Temporário", "array": "Matriz", + "splitThe": "Dividir", "splitUsing": "Dividir usando", "splitLength": "Comprimento fixo de", "stream": "Tratar como uma transmissão de mensagens", @@ -1066,9 +1067,9 @@ "batch" : { "batch": "lote", "mode": { - "label": "Modo", - "num-msgs": "Agrupar por número de mensagens", - "interval": "Agrupar por intervalo de tempo", + "label": "Modo", + "num-msgs": "Agrupar por número de mensagens", + "interval": "Agrupar por intervalo de tempo", "concat": "Concatenar sequências" }, "count": { diff --git a/packages/node_modules/@node-red/nodes/locales/ru/messages.json b/packages/node_modules/@node-red/nodes/locales/ru/messages.json index d2bb5777e..2694ac6a5 100644 --- a/packages/node_modules/@node-red/nodes/locales/ru/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/ru/messages.json @@ -874,6 +874,7 @@ "objectSend":"Отправлять сообщение для каждой пары ключ/значение", "strBuff":"Строка / Буфер", "array":"Массив", + "splitThe": "Pазделить", "splitUsing":"С помощью", "splitLength":"Фикс. длина", "stream":"Обрабатывать как поток сообщений", diff --git a/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json b/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json index 7a0ea4ae4..7d5616a8f 100644 --- a/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json @@ -997,6 +997,7 @@ "objectSend": "每个键值对作为单个消息发送", "strBuff": "字符串 / Buffer", "array": "数组", + "splitThe": "Split", "splitUsing": "拆分使用", "splitLength": "固定长度", "stream": "作为消息流处理", diff --git a/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json b/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json index f43531fb1..7d16c5817 100644 --- a/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json @@ -866,6 +866,7 @@ "objectSend": "每個鍵值對作為單個消息發送", "strBuff": "字串 / Buffer", "array": "陣列", + "splitThe": "Split", "splitUsing": "拆分使用", "splitLength": "固定長度", "stream": "作為消息流處理", diff --git a/packages/node_modules/@node-red/nodes/package.json b/packages/node_modules/@node-red/nodes/package.json index 0d2372866..84db88466 100644 --- a/packages/node_modules/@node-red/nodes/package.json +++ b/packages/node_modules/@node-red/nodes/package.json @@ -1,6 +1,6 @@ { "name": "@node-red/nodes", - "version": "4.0.1", + "version": "4.0.5", "license": "Apache-2.0", "repository": { "type": "git", @@ -15,20 +15,20 @@ } ], "dependencies": { - "acorn": "8.11.3", - "acorn-walk": "8.3.2", - "ajv": "8.14.0", - "body-parser": "1.20.2", + "acorn": "8.12.1", + "acorn-walk": "8.3.4", + "ajv": "8.17.1", + "body-parser": "1.20.3", "cheerio": "1.0.0-rc.10", "content-type": "1.0.5", - "cookie-parser": "1.4.6", - "cookie": "0.6.0", + "cookie-parser": "1.4.7", + "cookie": "0.7.2", "cors": "2.8.5", "cronosjs": "1.7.1", "denque": "2.1.0", "form-data": "4.0.0", "fs-extra": "11.2.0", - "got": "12.6.0", + "got": "12.6.1", "hash-sum": "2.0.0", "hpagent": "1.2.0", "https-proxy-agent": "5.0.1", @@ -40,8 +40,8 @@ "mustache": "4.2.0", "node-watch": "0.7.4", "on-headers": "1.0.2", - "raw-body": "2.5.2", - "tough-cookie": "4.1.4", + "raw-body": "3.0.0", + "tough-cookie": "^5.0.0", "uuid": "9.0.1", "ws": "7.5.10", "xml2js": "0.6.2", diff --git a/packages/node_modules/@node-red/registry/package.json b/packages/node_modules/@node-red/registry/package.json index 821e50d69..9437a5beb 100644 --- a/packages/node_modules/@node-red/registry/package.json +++ b/packages/node_modules/@node-red/registry/package.json @@ -1,6 +1,6 @@ { "name": "@node-red/registry", - "version": "4.0.1", + "version": "4.0.5", "license": "Apache-2.0", "main": "./lib/index.js", "repository": { @@ -16,11 +16,11 @@ } ], "dependencies": { - "@node-red/util": "4.0.1", + "@node-red/util": "4.0.5", "clone": "2.1.2", "fs-extra": "11.2.0", - "semver": "7.5.4", - "tar": "7.2.0", + "semver": "7.6.3", + "tar": "7.4.3", "uglify-js": "3.17.4" } } 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 fa25a26d0..6b7f659b9 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/util.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/util.js @@ -113,6 +113,10 @@ async function evaluateEnvProperties(flow, env, credentials) { resolve() }); })) + } else if (type === "conf-type" && /^\${[^}]+}$/.test(value)) { + // Get the config node from the parent subflow + const name = value.substring(2, value.length - 1); + value = flow.getSetting(name); } else { try { value = redUtil.evaluateNodeProperty(value, type, {_flow: flow}, null, null); diff --git a/packages/node_modules/@node-red/runtime/lib/multiplayer/index.js b/packages/node_modules/@node-red/runtime/lib/multiplayer/index.js index 08cb0d5a1..85a90e977 100644 --- a/packages/node_modules/@node-red/runtime/lib/multiplayer/index.js +++ b/packages/node_modules/@node-red/runtime/lib/multiplayer/index.js @@ -110,7 +110,8 @@ module.exports = { const payload = { session: sessionId, workspace: opts.data.workspace, - node: opts.data.node + node: opts.data.node, + cursor: opts.data.cursor } runtime.events.emit('comms', { topic: 'multiplayer/location', diff --git a/packages/node_modules/@node-red/runtime/locales/es-ES/runtime.json b/packages/node_modules/@node-red/runtime/locales/es-ES/runtime.json index 9fba64ad3..d1c2c44a9 100644 --- a/packages/node_modules/@node-red/runtime/locales/es-ES/runtime.json +++ b/packages/node_modules/@node-red/runtime/locales/es-ES/runtime.json @@ -25,6 +25,7 @@ "removing-modules": "Eliminando módulos de la configuración", "added-types": "Tipos de nodos añadidos:", "removed-types": "Tipos de nodos eliminados:", + "removed-plugins": "Extensiones eliminadas:", "install": { "invalid": "Nombre de módulo no válido", "installing": "Instalando módulo: __name__, versión: __version__", diff --git a/packages/node_modules/@node-red/runtime/package.json b/packages/node_modules/@node-red/runtime/package.json index 68f0cef52..a160c402c 100644 --- a/packages/node_modules/@node-red/runtime/package.json +++ b/packages/node_modules/@node-red/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@node-red/runtime", - "version": "4.0.1", + "version": "4.0.5", "license": "Apache-2.0", "main": "./lib/index.js", "repository": { @@ -16,11 +16,11 @@ } ], "dependencies": { - "@node-red/registry": "4.0.1", - "@node-red/util": "4.0.1", + "@node-red/registry": "4.0.5", + "@node-red/util": "4.0.5", "async-mutex": "0.5.0", "clone": "2.1.2", - "express": "4.19.2", + "express": "4.21.1", "fs-extra": "11.2.0", "json-stringify-safe": "5.0.1", "rfdc": "^1.3.1" diff --git a/packages/node_modules/@node-red/util/lib/log.js b/packages/node_modules/@node-red/util/lib/log.js index 341019080..7b7e9b2dc 100644 --- a/packages/node_modules/@node-red/util/lib/log.js +++ b/packages/node_modules/@node-red/util/lib/log.js @@ -75,12 +75,28 @@ LogHandler.prototype.shouldReportMessage = function(msglevel) { msglevel <= this.logLevel; } + +// Older versions of Node-RED used the deprecated util.log function. +// With Node.js 22, use of that function causes warnings. So here we +// are replicating the same format output to ensure we don't break any +// log parsing that happens in the real world. +const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; +const utilLog = function (msg) { + const d = new Date(); + const time = [ + d.getHours().toString().padStart(2, '0'), + d.getMinutes().toString().padStart(2, '0'), + d.getSeconds().toString().padStart(2, '0') + ].join(':'); + console.log(`${d.getDate()} ${months[d.getMonth()]} ${time} - ${msg}`) +} + var consoleLogger = function(msg) { if (msg.level == log.METRIC || msg.level == log.AUDIT) { - util.log("["+levelNames[msg.level]+"] "+JSON.stringify(msg)); + utilLog("["+levelNames[msg.level]+"] "+JSON.stringify(msg)); } else { if (verbose && msg.msg && msg.msg.stack) { - util.log("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+msg.msg.stack); + utilLog("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+msg.msg.stack); } else { var message = msg.msg; try { @@ -91,7 +107,7 @@ var consoleLogger = function(msg) { message = 'Exception trying to log: '+util.inspect(message); } - util.log("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+message); + utilLog("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+message); } } } diff --git a/packages/node_modules/@node-red/util/package.json b/packages/node_modules/@node-red/util/package.json index 34a4765c5..c02ab3805 100644 --- a/packages/node_modules/@node-red/util/package.json +++ b/packages/node_modules/@node-red/util/package.json @@ -1,6 +1,6 @@ { "name": "@node-red/util", - "version": "4.0.1", + "version": "4.0.5", "license": "Apache-2.0", "repository": { "type": "git", @@ -21,6 +21,6 @@ "jsonata": "2.0.5", "lodash.clonedeep": "^4.5.0", "moment": "2.30.1", - "moment-timezone": "0.5.45" + "moment-timezone": "0.5.46" } } diff --git a/packages/node_modules/node-red/package.json b/packages/node_modules/node-red/package.json index 9cf0615f6..0969024ff 100644 --- a/packages/node_modules/node-red/package.json +++ b/packages/node_modules/node-red/package.json @@ -1,6 +1,6 @@ { "name": "node-red", - "version": "4.0.1", + "version": "4.0.5", "description": "Low-code programming for event-driven applications", "homepage": "https://nodered.org", "license": "Apache-2.0", @@ -31,18 +31,18 @@ "flow" ], "dependencies": { - "@node-red/editor-api": "4.0.1", - "@node-red/runtime": "4.0.1", - "@node-red/util": "4.0.1", - "@node-red/nodes": "4.0.1", + "@node-red/editor-api": "4.0.5", + "@node-red/runtime": "4.0.5", + "@node-red/util": "4.0.5", + "@node-red/nodes": "4.0.5", "basic-auth": "2.0.1", "bcryptjs": "2.4.3", "cors": "2.8.5", - "express": "4.19.2", + "express": "4.21.1", "fs-extra": "11.2.0", - "node-red-admin": "^4.0.0", + "node-red-admin": "^4.0.1", "nopt": "5.0.0", - "semver": "7.5.4" + "semver": "7.6.3" }, "optionalDependencies": { "@node-rs/bcrypt": "1.10.4" diff --git a/scripts/generate-publish-script.js b/scripts/generate-publish-script.js index 0b2a75cd0..c31b2dd9e 100644 --- a/scripts/generate-publish-script.js +++ b/scripts/generate-publish-script.js @@ -36,10 +36,12 @@ function generateScript() { packages.forEach(name => { const tarName = name.replace(/@/,"").replace(/\//,"-") lines.push(`npm publish ${tarName}-${version}.tgz ${tagArg}\n`); - if (updateNextToLatest) { - lines.push(`npm dist-tag add ${name}@${version} next\n`); - } }) + if (updateNextToLatest) { + packages.forEach(name => { + lines.push(`npm dist-tag add ${name}@${version} next\n`); + }) + } resolve(lines.join("")) }); } diff --git a/test/nodes/core/function/89-delay_spec.js b/test/nodes/core/function/89-delay_spec.js index 46b0037bc..4fbf3df54 100644 --- a/test/nodes/core/function/89-delay_spec.js +++ b/test/nodes/core/function/89-delay_spec.js @@ -1009,6 +1009,29 @@ describe('delay Node', function() { }); }); + it('sending a msg with reset to empty queue doesnt send anything', function(done) { + this.timeout(2000); + var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(delayNode, flow, function() { + var delayNode1 = helper.getNode("delayNode1"); + var helperNode1 = helper.getNode("helperNode1"); + var t = Date.now(); + var c = 0; + helperNode1.on("input", function(msg) { + console.log("Shold not get here") + done(e); + }); + + setTimeout( function() { + if (c === 0) { done(); } + }, 250); + + // send test messages + delayNode1.receive({payload:1,topic:"foo",reset:true}); // send something with blank topic + }); + }); + /* Messaging API support */ function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) { const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js"); diff --git a/test/nodes/core/function/89-trigger_spec.js b/test/nodes/core/function/89-trigger_spec.js index 33401e540..913298901 100644 --- a/test/nodes/core/function/89-trigger_spec.js +++ b/test/nodes/core/function/89-trigger_spec.js @@ -111,7 +111,15 @@ describe('trigger node', function() { try { if (rval) { msg.should.have.property("payload"); - should.deepEqual(msg.payload, rval); + if (type == "date" && val == "1") { + should.deepEqual(Math.round(msg.payload/1000000), Math.round(Date.now()/1000000)); + } + else if (type == "date" && val == "iso") { + should.deepEqual(msg.payload.substr(0,11), rval.substr(0,11)); + } + else { + should.deepEqual(msg.payload, rval); + } } else { msg.should.have.property("payload", val); @@ -126,6 +134,7 @@ describe('trigger node', function() { }); it('should output 2st value when triggered ('+type+')', function(done) { + if (type == "date" && val == "1") { val = "0"; } var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"foo", op1type:"str", op2:val, op2type:type, duration:"20", wires:[["n2"]] }, {id:"n2", type:"helper"} ]; process.env[val] = rval; @@ -142,7 +151,15 @@ describe('trigger node', function() { else { if (rval) { msg.should.have.property("payload"); - should.deepEqual(msg.payload, rval); + if (type == "date" && val == "0") { + ;(Math.round(msg.payload/1000000)).should.be.approximately(parseInt(Date.now()/1000000), 1); + } + else if (type == "date" && val == "iso") { + should.deepEqual(msg.payload.substr(0,11), rval.substr(0,11)); + } + else { + should.deepEqual(msg.payload, rval); + } } else { msg.should.have.property("payload", val); @@ -166,6 +183,9 @@ describe('trigger node', function() { var val_buf = "[1,2,3,4,5]"; basicTest("bin", val_buf, Buffer.from(JSON.parse(val_buf))); basicTest("env", "NR-TEST", "env-val"); + basicTest("date", "1", Date.now()); + basicTest("date", "iso", (new Date()).toISOString()); + // basicTest("date", "object", Date.now()); it('should output 1 then 0 when triggered (default)', function(done) { var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:"20", wires:[["n2"]] }, diff --git a/test/nodes/core/sequence/19-batch_spec.js b/test/nodes/core/sequence/19-batch_spec.js index 2ebcb8d4d..b4025a3f8 100644 --- a/test/nodes/core/sequence/19-batch_spec.js +++ b/test/nodes/core/sequence/19-batch_spec.js @@ -98,7 +98,7 @@ describe('BATCH node', function() { var n2 = helper.getNode("n2"); check_data(n1, n2, results, done); for(var i = 0; i < 6; i++) { - n1.receive({payload: i}); + n1.receive({payload: i, parts: { count:6, index:i }}); } }); } @@ -168,6 +168,25 @@ describe('BATCH node', function() { check_count(flow, results, done); }); + it('should create seq. with count (more sent than count)', function(done) { + var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 4, overlap: 0, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]}, + {id:"n2", type:"helper"}]; + var results = [ + [0, 1, 2, 3] + ]; + check_count(flow, results, done); + }); + + it('should create seq. with count and terminate early if parts honoured', function(done) { + var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 4, overlap: 0, interval: 10, allowEmptySequence:false, honourParts:true, topics: [], wires:[["n2"]]}, + {id:"n2", type:"helper"}]; + var results = [ + [0, 1, 2, 3], + [4, 5] + ]; + check_count(flow, results, done); + }); + it('should create seq. with count and overlap', function(done) { var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 3, overlap: 2, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]}, {id:"n2", type:"helper"}]; @@ -455,7 +474,7 @@ describe('BATCH node', function() { function mapiDoneTestHelper(done, mode, count, overlap, interval, allowEmptySequence, msgAndTimings) { const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js"); const catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js"); - const flow = [{id:"batchNode1", type:"batch", name: "BatchNode", mode, count, overlap, interval, + const flow = [{id:"batchNode1", type:"batch", name: "BatchNode", mode, count, overlap, interval, allowEmptySequence, topics: [{topic: "TA"}], wires:[[]]}, {id:"completeNode1",type:"complete",scope: ["batchNode1"],uncaught:false,wires:[["helperNode1"]]}, {id:"catchNode1", type:"catch",scope: ["batchNode1"],uncaught:false,wires:[["helperNode1"]]}, @@ -482,13 +501,13 @@ describe('BATCH node', function() { } it('should call done() when message is sent (mode: count)', function(done) { - mapiDoneTestHelper(done, "count", 2, 0, 2, false, [ + mapiDoneTestHelper(done, "count", 2, 0, 2, false, [ { msg: {payload: 0}, delay: 0, avr: 0, var: 100}, { msg: {payload: 1}, delay: 0, avr: 0, var: 100} ]); }); it('should call done() when reset (mode: count)', function(done) { - mapiDoneTestHelper(done, "count", 2, 0, 2, false, [ + mapiDoneTestHelper(done, "count", 2, 0, 2, false, [ { msg: {payload: 0}, delay: 0, avr: 200, var: 100}, { msg: {payload: 1, reset:true}, delay: 200, avr: 200, var: 100} ]); diff --git a/test/unit/@node-red/util/lib/log_spec.js b/test/unit/@node-red/util/lib/log_spec.js index 056f37672..8fe09b3bf 100644 --- a/test/unit/@node-red/util/lib/log_spec.js +++ b/test/unit/@node-red/util/lib/log_spec.js @@ -24,38 +24,38 @@ var log = NR_TEST_UTILS.require("@node-red/util").log; describe("@node-red/util/log", function() { beforeEach(function () { - var spy = sinon.stub(util, 'log').callsFake(function(arg){}); + var spy = sinon.stub(console, 'log').callsFake(function(arg){}); var settings = {logging: { console: { level: 'metric', metrics: true } } }; log.init(settings); }); afterEach(function() { - util.log.restore(); + console.log.restore(); }); it('it can raise an error', function() { var ret = log.error("This is an error"); - sinon.assert.calledWithMatch(util.log,"[error] This is an error"); + sinon.assert.calledWithMatch(console.log,"[error] This is an error"); }); it('it can raise a trace', function() { var ret = log.trace("This is a trace"); - sinon.assert.calledWithMatch(util.log,"[trace] This is a trace"); + sinon.assert.calledWithMatch(console.log,"[trace] This is a trace"); }); it('it can raise a debug', function() { var ret = log.debug("This is a debug"); - sinon.assert.calledWithMatch(util.log,"[debug] This is a debug"); + sinon.assert.calledWithMatch(console.log,"[debug] This is a debug"); }); it('it can raise a info', function() { var ret = log.info("This is an info"); - sinon.assert.calledWithMatch(util.log,"[info] This is an info"); + sinon.assert.calledWithMatch(console.log,"[info] This is an info"); }); it('it can raise a warn', function() { var ret = log.warn("This is a warn"); - sinon.assert.calledWithMatch(util.log,"[warn] This is a warn"); + sinon.assert.calledWithMatch(console.log,"[warn] This is a warn"); }); it('it can raise a metric', function() { @@ -66,9 +66,10 @@ describe("@node-red/util/log", function() { metrics.msgid = "12345"; metrics.value = "the metric payload"; var ret = log.log(metrics); - util.log.calledOnce.should.be.true(); - util.log.firstCall.args[0].indexOf("[metric] ").should.equal(0); - var body = JSON.parse(util.log.firstCall.args[0].substring(9)); + console.log.calledOnce.should.be.true(); + console.log.firstCall.args[0].indexOf("[metric]").should.not.equal(-1); + const parts = console.log.firstCall.args[0].split("[metric] ") + var body = JSON.parse(parts[1]) body.should.have.a.property("nodeid","testid"); body.should.have.a.property("event","node.test.testevent"); body.should.have.a.property("msgid","12345"); @@ -86,13 +87,13 @@ describe("@node-red/util/log", function() { it('it logs node type and name if provided',function() { log.log({level:log.INFO,type:"nodeType",msg:"test",name:"nodeName",id:"nodeId"}); - util.log.calledOnce.should.be.true(); - util.log.firstCall.args[0].indexOf("[nodeType:nodeName]").should.not.equal(-1); + console.log.calledOnce.should.be.true(); + console.log.firstCall.args[0].indexOf("[nodeType:nodeName]").should.not.equal(-1); }); it('it logs node type and id if no name provided',function() { log.log({level:log.INFO,type:"nodeType",msg:"test",id:"nodeId"}); - util.log.calledOnce.should.be.true(); - util.log.firstCall.args[0].indexOf("[nodeType:nodeId]").should.not.equal(-1); + console.log.calledOnce.should.be.true(); + console.log.firstCall.args[0].indexOf("[nodeType:nodeId]").should.not.equal(-1); }); it('ignores lower level messages and metrics', function() { @@ -104,12 +105,12 @@ describe("@node-red/util/log", function() { log.debug("This is a debug"); log.trace("This is a trace"); log.log({level:log.METRIC,msg:"testMetric"}); - sinon.assert.calledWithMatch(util.log,"[error] This is an error"); - sinon.assert.calledWithMatch(util.log,"[warn] This is a warn"); - sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info"); - sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug"); - sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace"); - sinon.assert.neverCalledWithMatch(util.log,"[metric] "); + sinon.assert.calledWithMatch(console.log,"[error] This is an error"); + sinon.assert.calledWithMatch(console.log,"[warn] This is a warn"); + sinon.assert.neverCalledWithMatch(console.log,"[info] This is an info"); + sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug"); + sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace"); + sinon.assert.neverCalledWithMatch(console.log,"[metric] "); }); it('ignores lower level messages but accepts metrics', function() { var settings = {logging: { console: { level: 'log', metrics: true } } }; @@ -120,12 +121,12 @@ describe("@node-red/util/log", function() { log.debug("This is a debug"); log.trace("This is a trace"); log.log({level:log.METRIC,msg:"testMetric"}); - sinon.assert.calledWithMatch(util.log,"[error] This is an error"); - sinon.assert.calledWithMatch(util.log,"[warn] This is a warn"); - sinon.assert.calledWithMatch(util.log,"[info] This is an info"); - sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug"); - sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace"); - sinon.assert.calledWithMatch(util.log,"[metric] "); + sinon.assert.calledWithMatch(console.log,"[error] This is an error"); + sinon.assert.calledWithMatch(console.log,"[warn] This is a warn"); + sinon.assert.calledWithMatch(console.log,"[info] This is an info"); + sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug"); + sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace"); + sinon.assert.calledWithMatch(console.log,"[metric] "); }); it('default settings set to INFO and metrics off', function() { @@ -136,12 +137,12 @@ describe("@node-red/util/log", function() { log.debug("This is a debug"); log.trace("This is a trace"); log.log({level:log.METRIC,msg:"testMetric"}); - sinon.assert.calledWithMatch(util.log,"[error] This is an error"); - sinon.assert.calledWithMatch(util.log,"[warn] This is a warn"); - sinon.assert.calledWithMatch(util.log,"[info] This is an info"); - sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug"); - sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace"); - sinon.assert.neverCalledWithMatch(util.log,"[metric] "); + sinon.assert.calledWithMatch(console.log,"[error] This is an error"); + sinon.assert.calledWithMatch(console.log,"[warn] This is a warn"); + sinon.assert.calledWithMatch(console.log,"[info] This is an info"); + sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug"); + sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace"); + sinon.assert.neverCalledWithMatch(console.log,"[metric] "); }); it('no logger used if custom logger handler does not exist', function() { var settings = {logging: { customLogger: { level: 'trace', metrics: true } } }; @@ -152,12 +153,12 @@ describe("@node-red/util/log", function() { log.debug("This is a debug"); log.trace("This is a trace"); log.log({level:log.METRIC,msg:"testMetric"}); - sinon.assert.neverCalledWithMatch(util.log,"[error] This is an error"); - sinon.assert.neverCalledWithMatch(util.log,"[warn] This is a warn"); - sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info"); - sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug"); - sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace"); - sinon.assert.neverCalledWithMatch(util.log,"[metric] "); + sinon.assert.neverCalledWithMatch(console.log,"[error] This is an error"); + sinon.assert.neverCalledWithMatch(console.log,"[warn] This is a warn"); + sinon.assert.neverCalledWithMatch(console.log,"[info] This is an info"); + sinon.assert.neverCalledWithMatch(console.log,"[debug] This is a debug"); + sinon.assert.neverCalledWithMatch(console.log,"[trace] This is a trace"); + sinon.assert.neverCalledWithMatch(console.log,"[metric] "); }); it('add a custom log handler directly', function() { @@ -244,7 +245,7 @@ describe("@node-red/util/log", function() { }, }; var ret = log.info(msg.msg); - sinon.assert.calledWithMatch(util.log,"my special message"); + sinon.assert.calledWithMatch(console.log,"my special message"); });