Compare commits
8 Commits
4396-fix-g
...
loadable-i
Author | SHA1 | Date | |
---|---|---|---|
|
638d0d2f3f | ||
|
eb940d6d57 | ||
|
9091935d77 | ||
|
34e8d2b051 | ||
|
0c2ab13c48 | ||
|
9489953a8f | ||
|
cef3a01042 | ||
|
0c042abcab |
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -30,5 +30,5 @@ the [forum](https://discourse.nodered.org) or
|
||||
|
||||
- [ ] I have read the [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
|
||||
- [ ] For non-bugfix PRs, I have discussed this change on the forum/slack team.
|
||||
- [ ] I have run `npm run test` to verify the unit tests pass
|
||||
- [ ] I have run `grunt` to verify the unit tests pass
|
||||
- [ ] I have added suitable unit tests to cover the new/changed functionality
|
||||
|
15
.github/dependabot.yml
vendored
@@ -1,15 +0,0 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
8
.github/workflows/release.yml
vendored
@@ -14,20 +14,20 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out node-red repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: 'node-red'
|
||||
- name: Check out node-red-docker repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'node-red/node-red-docker'
|
||||
path: 'node-red-docker'
|
||||
- name: Check out node-red.github.io repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'node-red/node-red.github.io'
|
||||
path: 'node-red.github.io'
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '16'
|
||||
- run: node ./node-red/.github/scripts/update-node-red-docker.js
|
||||
|
2
.github/workflows/tests.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
matrix:
|
||||
node-version: [16, 18, 20]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
|
1
.gitignore
vendored
@@ -27,4 +27,3 @@ docs
|
||||
.vscode
|
||||
.nyc_output
|
||||
sync.ffs_db
|
||||
package-lock.json
|
||||
|
@@ -16,9 +16,6 @@ behavior to the project's core team at team@nodered.org.
|
||||
Please raise any bug reports on the relevant project's issue tracker. Be sure to
|
||||
search the list to see if your issue has already been raised.
|
||||
|
||||
If your issue is more of a question on how to do something with Node-RED, please
|
||||
consider using the [community forum](https://discourse.nodered.org/).
|
||||
|
||||
A good bug report is one that make it easy for us to understand what you were
|
||||
trying to do and what went wrong.
|
||||
|
||||
@@ -38,18 +35,14 @@ For feature requests, please raise them on the [forum](https://discourse.nodered
|
||||
## Pull-Requests
|
||||
|
||||
If you want to raise a pull-request with a new feature, or a refactoring
|
||||
of existing code, please come and discuss it with us first. We prefer to
|
||||
do it that way to make sure your time and effort is well spent on something
|
||||
that fits with our goals.
|
||||
|
||||
If you've got a bug-fix or similar for us, then you are most welcome to
|
||||
get it raised - just make sure you link back to the issue it's fixing and
|
||||
try to include some tests!
|
||||
of existing code, it may well get rejected if you haven't discussed it on
|
||||
the [forum](https://discourse.nodered.org) first.
|
||||
|
||||
All contributors need to sign the OpenJS Foundation's Contributor License Agreement.
|
||||
It is an online process and quick to do. If you raise a pull-request without
|
||||
having signed the CLA, you will be prompted to do so automatically.
|
||||
|
||||
|
||||
### Code Branches
|
||||
|
||||
When raising a PR for a fix or a new feature, it is important to target the right branch.
|
||||
|
@@ -151,6 +151,7 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/history.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/validators.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "https://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -109,7 +109,7 @@
|
||||
"jquery-i18next": "1.2.1",
|
||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||
"marked": "4.3.0",
|
||||
"mermaid": "^10.4.0",
|
||||
"mermaid": "^9.4.3",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "9.2.2",
|
||||
"node-red-node-test-helper": "^0.3.2",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.1.0",
|
||||
"@node-red/editor-client": "3.1.0",
|
||||
"@node-red/util": "4.0.0-dev",
|
||||
"@node-red/editor-client": "4.0.0-dev",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.20.2",
|
||||
"clone": "2.1.2",
|
||||
|
@@ -1215,9 +1215,11 @@
|
||||
"validator": {
|
||||
"errors": {
|
||||
"invalid-json": "Invalid JSON data: __error__",
|
||||
"invalid-expr": "Invalid JSONata expression: __error__",
|
||||
"invalid-json-prop": "__prop__: invalid JSON data: __error__",
|
||||
"invalid-prop": "Invalid property expression",
|
||||
"invalid-prop-prop": "__prop__: invalid property expression",
|
||||
"invalid-num": "Invalid number",
|
||||
"invalid-num-prop": "__prop__: invalid number",
|
||||
"invalid-regexp": "Invalid input pattern",
|
||||
"invalid-regex-prop": "__prop__: invalid input pattern",
|
||||
"missing-required-prop": "__prop__: property value missing",
|
||||
|
@@ -119,7 +119,7 @@
|
||||
"searchInput": "Rechercher vos flux",
|
||||
"subflows": "Sous-flux",
|
||||
"createSubflow": "Créer un sous-flux",
|
||||
"selectionToSubflow": "Convertir en sous-flux",
|
||||
"selectionToSubflow": "Selection d'un sous-flux",
|
||||
"flows": "Flux",
|
||||
"add": "Ajouter",
|
||||
"rename": "Renommer",
|
||||
@@ -274,23 +274,23 @@
|
||||
"recoveredNodesInfo": "Les noeuds importés sur ce flux contiennent un mauvais identifiant de flux. Ces noeuds ont été ajoutés à ce flux afin que vous puissiez les restaurer ou les supprimer.",
|
||||
"recoveredNodesNotification": "<p>Noeuds importés sans identifiant de flux valide</p><p>Ils ont été ajoutés à un nouveau flux appelé '__flowName__'.</p>",
|
||||
"export": {
|
||||
"selected": "les noeuds sélectionnés",
|
||||
"current": "le flux actuel",
|
||||
"selected": "noeuds sélectionnés",
|
||||
"current": "flux actuel",
|
||||
"all": "tous les flux",
|
||||
"compact": "Condensé",
|
||||
"formatted": "Formaté",
|
||||
"compact": "condensé",
|
||||
"formatted": "formaté",
|
||||
"copy": "Copier dans le presse-papier",
|
||||
"export": "Exporter vers la bibliothèque",
|
||||
"exportAs": "Exporter comme",
|
||||
"exportAs": "Exporter en tant que",
|
||||
"overwrite": "Remplacer",
|
||||
"exists": "<p><b>\"__file__\"</b> existe déjà.</p><p>Voulez-vous le remplacer ?</p>"
|
||||
},
|
||||
"import": {
|
||||
"import": "Importer vers",
|
||||
"importSelected": "Importer la sélection",
|
||||
"importSelected": "Importation sélectionnée",
|
||||
"importCopy": "Importer une copie",
|
||||
"viewNodes": "Vérifier ces noeuds",
|
||||
"newFlow": "un nouveau flux",
|
||||
"viewNodes": "Afficher les noeuds...",
|
||||
"newFlow": "Nouveau flux",
|
||||
"replace": "Remplacer",
|
||||
"errors": {
|
||||
"notArray": "L'entrée n'est pas un tableau JSON",
|
||||
@@ -299,7 +299,7 @@
|
||||
"missingType": "L'entrée n'est pas un flux valide - l'élément '__index__' n'a pas de propriété 'type'"
|
||||
},
|
||||
"conflictNotification1": "Certains des noeuds que vous avez importés existent déjà dans votre espace de travail.",
|
||||
"conflictNotification2": "Sélectionnez les noeuds à importer et choisissez s'il faut remplacer les noeuds existants ou en importer une copie."
|
||||
"conflictNotification2": "Sélectionner les noeuds à importer et choisir s'il faut remplacer les noeuds existants ou en importer une copie."
|
||||
},
|
||||
"copyMessagePath": "Chemin copié",
|
||||
"copyMessageValue": "Valeur copiée",
|
||||
@@ -391,10 +391,10 @@
|
||||
"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:",
|
||||
"status": "Statut du noeud",
|
||||
"deleteSubflow": "Supprimer le sous-flux",
|
||||
"input": "entrées:",
|
||||
"output": "sorties:",
|
||||
"status": "statut du noeud",
|
||||
"deleteSubflow": "supprimer le sous-flux",
|
||||
"confirmDelete": "Voulez-vous vraiment supprimer ce sous-flux ?",
|
||||
"info": "Description",
|
||||
"category": "Catégorie",
|
||||
@@ -416,7 +416,6 @@
|
||||
},
|
||||
"errors": {
|
||||
"noNodesSelected": "<strong>Impossible de créer un sous-flux</strong> : aucun noeud sélectionné",
|
||||
"acrossMultipleGroups": "Impossible de créer un sous-flux sur plusieurs groupes",
|
||||
"multipleInputsToSelection": "<strong>Impossible de créer un sous-flux</strong> : plusieurs entrées pour la sélection"
|
||||
}
|
||||
},
|
||||
@@ -448,8 +447,8 @@
|
||||
"default": "Par défaut",
|
||||
"noDefaultLabel": "Aucune",
|
||||
"defaultLabel": "Utiliser l'étiquette par défaut",
|
||||
"searchIcons": "Rechercher une icône",
|
||||
"useDefault": "Icône par défaut",
|
||||
"searchIcons": "Icônes de recherche",
|
||||
"useDefault": "Utilisation par défaut",
|
||||
"description": "Description",
|
||||
"show": "Afficher",
|
||||
"hide": "Masquer",
|
||||
@@ -499,13 +498,13 @@
|
||||
"keyboard": {
|
||||
"title": "Raccourcis clavier",
|
||||
"keyboard": "Clavier",
|
||||
"filterActions": "Rechercher l'action",
|
||||
"shortcut": "Raccourci",
|
||||
"scope": "Portée",
|
||||
"filterActions": "Actions de filtrage",
|
||||
"shortcut": "raccourci",
|
||||
"scope": "portée",
|
||||
"unassigned": "Non attribué",
|
||||
"global": "Global",
|
||||
"workspace": "Espace de travail",
|
||||
"editor": "Boîte de dialogue d'édition",
|
||||
"global": "global",
|
||||
"workspace": "espace de travail",
|
||||
"editor": "boîte de dialogue d'édition",
|
||||
"selectAll": "Tout sélectionner",
|
||||
"selectNone": "Ne rien sélectionner",
|
||||
"selectAllConnected": "Sélectionner tous les éléments connectés",
|
||||
@@ -551,22 +550,22 @@
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "Pas d'information disponible",
|
||||
"filter": "Rechercher le noeud",
|
||||
"filter": "Filtrer les noeuds",
|
||||
"search": "Rechercher les modules",
|
||||
"addCategory": "Ajouter un nouveau...",
|
||||
"label": {
|
||||
"subflows": "Sous-flux",
|
||||
"network": "Réseau",
|
||||
"common": "Commun",
|
||||
"input": "Entrée",
|
||||
"output": "Sortie",
|
||||
"function": "Fonction",
|
||||
"sequence": "Séquence",
|
||||
"parser": "Analyseur",
|
||||
"social": "Social",
|
||||
"storage": "Stockage",
|
||||
"analysis": "Analyse",
|
||||
"advanced": "Avancé"
|
||||
"subflows": "sous-flux",
|
||||
"network": "réseau",
|
||||
"common": "commun",
|
||||
"input": "entrée",
|
||||
"output": "sortie",
|
||||
"function": "fonction",
|
||||
"sequence": "séquence",
|
||||
"parser": "analyseur",
|
||||
"social": "social",
|
||||
"storage": "stockage",
|
||||
"analysis": "analyse",
|
||||
"advanced": "avancé"
|
||||
},
|
||||
"actions": {
|
||||
"collapse-all": "Réduire toutes les catégories",
|
||||
@@ -587,7 +586,6 @@
|
||||
"editor": {
|
||||
"title": "Gérer la palette",
|
||||
"palette": "Palette",
|
||||
"allCatalogs": "Tous les catalogues",
|
||||
"times": {
|
||||
"seconds": "il y a quelques secondes",
|
||||
"minutes": "il y a quelques minutes",
|
||||
@@ -611,25 +609,24 @@
|
||||
"nodeCount_plural": "__label__ noeuds",
|
||||
"moduleCount": "__count__ module disponible",
|
||||
"moduleCount_plural": "__count__ modules disponibles",
|
||||
"inuse": "En cours d'utilisation",
|
||||
"enableall": "Activer tout",
|
||||
"disableall": "Désactiver tout",
|
||||
"enable": "Activer",
|
||||
"disable": "Désactiver",
|
||||
"remove": "Supprimer",
|
||||
"update": "Mettre à jour vers __version__",
|
||||
"updated": "Mis à jour",
|
||||
"install": "Installer",
|
||||
"installed": "Installé",
|
||||
"conflict": "Conflit",
|
||||
"inuse": "en cours d'utilisation",
|
||||
"enableall": "activer tout",
|
||||
"disableall": "désactiver tout",
|
||||
"enable": "activer",
|
||||
"disable": "désactiver",
|
||||
"remove": "supprimer",
|
||||
"update": "mettre à jour vers __version__",
|
||||
"updated": "mis à jour",
|
||||
"install": "installer",
|
||||
"installed": "installé",
|
||||
"conflict": "conflit",
|
||||
"conflictTip": "<p>Ce module ne peut pas être installé car il inclut un<br/>type de noeud qui a déjà été installé</p><p>Conflits avec <code>__module__</code></p>",
|
||||
"loading": "Chargement des catalogues...",
|
||||
"tab-nodes": "Noeuds",
|
||||
"tab-install": "Installer",
|
||||
"sort": "Trier:",
|
||||
"sortRelevance": "Pertinence",
|
||||
"sortAZ": "A-Z",
|
||||
"sortRecent": "Récent",
|
||||
"sort": "trier:",
|
||||
"sortAZ": "a-z",
|
||||
"sortRecent": "récent",
|
||||
"more": "+ __count__ en plus",
|
||||
"upload": "Charger le fichier tgz du module",
|
||||
"refresh": "Actualiser la liste des modules",
|
||||
@@ -670,7 +667,7 @@
|
||||
"info": {
|
||||
"name": "Information",
|
||||
"tabName": "Nom",
|
||||
"label": "Info",
|
||||
"label": "info",
|
||||
"node": "Noeud",
|
||||
"type": "Type",
|
||||
"group": "Groupe",
|
||||
@@ -684,10 +681,10 @@
|
||||
"properties": "Propriétés",
|
||||
"info": "Information",
|
||||
"desc": "Description",
|
||||
"blank": "Vide",
|
||||
"null": "Nul",
|
||||
"showMore": "Afficher en plus",
|
||||
"showLess": "Afficher en moins",
|
||||
"blank": "vide",
|
||||
"null": "nul",
|
||||
"showMore": "afficher en plus",
|
||||
"showLess": "afficher en moins",
|
||||
"flow": "Flux",
|
||||
"selection": "Sélection",
|
||||
"nodes": "__count__ noeuds",
|
||||
@@ -698,7 +695,7 @@
|
||||
"arrayItems": "__count__ éléments",
|
||||
"showTips": "Vous pouvez ouvrir les astuces à partir du panneau des paramètres",
|
||||
"outline": "Plan",
|
||||
"empty": "Vide",
|
||||
"empty": "vide",
|
||||
"globalConfig": "Noeuds de configuration globale",
|
||||
"triggerAction": "Déclencher une action",
|
||||
"find": "Rechercher dans l'espace de travail",
|
||||
@@ -709,7 +706,7 @@
|
||||
},
|
||||
"help": {
|
||||
"name": "Aide",
|
||||
"label": "Aide",
|
||||
"label": "aide",
|
||||
"search": "Aide à la recherche",
|
||||
"nodeHelp": "Aide sur les noeuds",
|
||||
"showHelp": "Afficher l'aide",
|
||||
@@ -720,23 +717,23 @@
|
||||
},
|
||||
"config": {
|
||||
"name": "Noeuds de configuration",
|
||||
"label": "Configuration",
|
||||
"label": "configuration",
|
||||
"global": "Tous les flux",
|
||||
"none": "Aucun",
|
||||
"subflows": "Sous-flux",
|
||||
"flows": "Flux",
|
||||
"filterAll": "Tout",
|
||||
"none": "aucun",
|
||||
"subflows": "sous-flux",
|
||||
"flows": "flux",
|
||||
"filterAll": "tout",
|
||||
"showAllConfigNodes": "Afficher tous les noeuds de configuration",
|
||||
"filterUnused": "Inutilisé",
|
||||
"filterUnused": "inutilisé",
|
||||
"showAllUnusedConfigNodes": "Afficher tous les noeuds de configuration inutilisés",
|
||||
"filtered": "__count__ caché(s)"
|
||||
},
|
||||
"context": {
|
||||
"name": "Données contextuelles",
|
||||
"label": "Contexte",
|
||||
"none": "Aucune sélection",
|
||||
"refresh": "Actualiser pour charger",
|
||||
"empty": "Vide",
|
||||
"label": "contexte",
|
||||
"none": "aucune sélection",
|
||||
"refresh": "actualiser pour charger",
|
||||
"empty": "vide",
|
||||
"node": "Noeud",
|
||||
"flow": "Flux",
|
||||
"global": "Global",
|
||||
@@ -747,10 +744,10 @@
|
||||
},
|
||||
"palette": {
|
||||
"name": "Gestion des palettes",
|
||||
"label": "Palette"
|
||||
"label": "palette"
|
||||
},
|
||||
"project": {
|
||||
"label": "Projet",
|
||||
"label": "projet",
|
||||
"name": "Projet",
|
||||
"description": "Description",
|
||||
"dependencies": "Dépendances",
|
||||
@@ -763,11 +760,11 @@
|
||||
"showProjectSettings": "Afficher les paramètres du projet",
|
||||
"projectSettings": {
|
||||
"title": "Paramètres du projet",
|
||||
"edit": "Modifier",
|
||||
"edit": "modifier",
|
||||
"none": "Vide",
|
||||
"install": "Installer",
|
||||
"removeFromProject": "Supprimer du projet",
|
||||
"addToProject": "Ajouter au projet",
|
||||
"install": "installer",
|
||||
"removeFromProject": "supprimer du projet",
|
||||
"addToProject": "ajouter au projet",
|
||||
"files": "Fichiers",
|
||||
"flow": "Flux",
|
||||
"credentials": "Identifiants",
|
||||
@@ -815,7 +812,7 @@
|
||||
"workflowAutoTip": "Les modifications sont validées automatiquement à chaque déploiement",
|
||||
"sshKeys": "Clés SSH",
|
||||
"sshKeysTip": "Vous permet de créer des connexions sécurisées aux référentiels Git distants.",
|
||||
"add": "Ajouter une clé",
|
||||
"add": "ajouter une clé",
|
||||
"addSshKey": "Ajouter une clé SSH",
|
||||
"addSshKeyTip": "Générer une nouvelle paire de clés publique/privée",
|
||||
"name": "Nom",
|
||||
@@ -851,7 +848,7 @@
|
||||
"none": "Vide",
|
||||
"conflictResolve": "Tous les conflits ont été résolus. Valider les modifications pour terminer la fusion.",
|
||||
"localFiles": "Fichiers locaux",
|
||||
"all": "Tout",
|
||||
"all": "tout",
|
||||
"unmergedChanges": "Modifications non fusionnées",
|
||||
"abortMerge": "Abandonner la fusion",
|
||||
"commit": "Valider",
|
||||
@@ -1100,9 +1097,9 @@
|
||||
"desc8": "Le fichier contenant les identifiants ne sera pas crypté et son contenu sera facilement lisible",
|
||||
"create-project-files": "Créer des fichiers de projet",
|
||||
"create-project": "Créer un projet",
|
||||
"already-exists": "Existe déjà",
|
||||
"already-exists": "existe déjà",
|
||||
"git-error": "Erreur Git",
|
||||
"git-auth-error": "Erreur d'authentification Git"
|
||||
"git-auth-error": "erreur d'authentification Git"
|
||||
},
|
||||
"create-success": {
|
||||
"success": "Vous avez créé avec succès votre premier projet !",
|
||||
@@ -1138,8 +1135,8 @@
|
||||
"desc2": "Avant de pouvoir cloner un référentiel sur ssh, vous devez ajouter une clé SSH pour y accéder.",
|
||||
"add-ssh-key": "Ajouter une clé ssh",
|
||||
"credentials-encryption-key": "Clé de chiffrement des identifiants",
|
||||
"already-exists-2": "Existe déjà",
|
||||
"git-error": "Erreur git",
|
||||
"already-exists-2": "existe déjà",
|
||||
"git-error": "erreur git",
|
||||
"con-failed": "La connexion a échoué",
|
||||
"not-git": "Ce n'est pas un dépôt git",
|
||||
"no-resource": "Référentiel introuvable",
|
||||
@@ -1151,8 +1148,8 @@
|
||||
"confirm": "Voulez-vous vraiment supprimer ce projet ?"
|
||||
},
|
||||
"create-project-list": {
|
||||
"search": "Rechercher vos projets",
|
||||
"current": "Actuel"
|
||||
"search": "rechercher vos projets",
|
||||
"current": "actuel"
|
||||
},
|
||||
"require-clean": {
|
||||
"confirm": "<p>Vous avez des modifications non déployées qui seront perdues.</p><p>Voulez-vous continuer ?</p>"
|
||||
@@ -1215,8 +1212,11 @@
|
||||
"validator": {
|
||||
"errors": {
|
||||
"invalid-json": "Données JSON invalides : __error__",
|
||||
"invalid-json-prop": "__prop__: données JSON invalides : __error__",
|
||||
"invalid-prop": "Expression de propriété non valide",
|
||||
"invalid-prop-prop": "__prop__: expression de propriété invalide",
|
||||
"invalid-num": "Numéro invalide",
|
||||
"invalid-num-prop": "__prop__: numéro invalide",
|
||||
"invalid-regexp": "Modèle d'entrée non valide",
|
||||
"invalid-regex-prop": "__prop__: modèle d'entrée non valide",
|
||||
"missing-required-prop": "__prop__: valeur de la propriété manquante",
|
||||
|
@@ -270,9 +270,5 @@
|
||||
"$moment": {
|
||||
"args": "[str]",
|
||||
"desc": "Obtient un objet de date à l'aide de la bibliothèque Moment."
|
||||
},
|
||||
"$clone": {
|
||||
"args": "valeur",
|
||||
"desc": "Cloner un objet en toute sécurité."
|
||||
}
|
||||
}
|
||||
|
@@ -1215,8 +1215,11 @@
|
||||
"validator": {
|
||||
"errors": {
|
||||
"invalid-json": "JSONデータが不正: __error__",
|
||||
"invalid-json-prop": "__prop__: JSONデータが不正: __error__",
|
||||
"invalid-prop": "プロパティ式が不正",
|
||||
"invalid-prop-prop": "__prop__: プロパティ式が不正",
|
||||
"invalid-num": "数値が不正",
|
||||
"invalid-num-prop": "__prop__: 数値が不正",
|
||||
"invalid-regexp": "入力パターンが不正",
|
||||
"invalid-regex-prop": "__prop__: 入力パターンが不正",
|
||||
"missing-required-prop": "__prop__: プロパティが未設定",
|
||||
|
@@ -1186,8 +1186,11 @@
|
||||
"validator": {
|
||||
"errors": {
|
||||
"invalid-json": "Dados JSON inválidos: __error__",
|
||||
"invalid-json-prop": "__prop__: dados JSON inválidos: __error__",
|
||||
"invalid-prop": "Expressão de propriedade inválida",
|
||||
"invalid-prop-prop": "__prop__: expressão de propriedade inválida",
|
||||
"invalid-num": "Número inválido",
|
||||
"invalid-num-prop": "__prop__: número inválido",
|
||||
"invalid-regexp": "Padrão de entrada inválido",
|
||||
"invalid-regex-prop": "__prop__: Padrão de entrada inválido",
|
||||
"missing-required-prop": "__prop__: valor de propriedade ausente",
|
||||
|
@@ -1199,8 +1199,11 @@
|
||||
"validator": {
|
||||
"errors": {
|
||||
"invalid-json": "无效的 JSON 数据: __error__",
|
||||
"invalid-json-prop": "__prop__: 无效的 JSON 数据: __error__",
|
||||
"invalid-prop": "无效的属性表达式",
|
||||
"invalid-prop-prop": "__prop__: 无效的属性表达式",
|
||||
"invalid-num": "无效的数字",
|
||||
"invalid-num-prop": "__prop__: 无效的数字",
|
||||
"invalid-regexp": "输入格式无效",
|
||||
"invalid-regex-prop": "__prop__: 输入格式无效",
|
||||
"missing-required-prop": "__prop__: 缺少属性值",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -797,8 +797,8 @@ RED.nodes = (function() {
|
||||
|
||||
if (node && node._def.onremove) {
|
||||
// Deprecated: never documented but used by some early nodes
|
||||
console.log("Deprecated API warning: node type ",node.type," has an onremove function - should be oneditdelete - please report");
|
||||
node._def.onremove.call(node);
|
||||
console.log("Deprecated API warning: node type ",node.type," has an onremove function - should be oneditremove - please report");
|
||||
node._def.onremove.call(n);
|
||||
}
|
||||
return {links:removedLinks,nodes:removedNodes};
|
||||
}
|
||||
|
@@ -168,8 +168,8 @@ RED.contextMenu = (function () {
|
||||
|
||||
menuItems.push(
|
||||
null,
|
||||
{ onselect: 'core:undo', label: RED._("keyboard.undoChange"), disabled: RED.history.list().length === 0 },
|
||||
{ onselect: 'core:redo', label: RED._("keyboard.redoChange"), disabled: RED.history.listRedo().length === 0 },
|
||||
{ onselect: 'core:undo', disabled: RED.history.list().length === 0 },
|
||||
{ onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
|
||||
null,
|
||||
{ onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !canEdit || !hasSelection },
|
||||
{ onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
|
||||
@@ -177,7 +177,7 @@ RED.contextMenu = (function () {
|
||||
{ onselect: 'core:delete-selection', disabled: !canEdit || !canDelete },
|
||||
{ onselect: 'core:delete-selection-and-reconnect', label: RED._('keyboard.deleteReconnect'), disabled: !canEdit || !canDelete },
|
||||
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
|
||||
{ onselect: 'core:select-all-nodes', label: RED._("keyboard.selectAll") },
|
||||
{ onselect: 'core:select-all-nodes' },
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -989,10 +989,9 @@ RED.diff = (function() {
|
||||
}
|
||||
if (localNode && remoteNode && typeof localNode[d] === "string") {
|
||||
if (/\n/.test(localNode[d]) || /\n/.test(remoteNode[d])) {
|
||||
var textDiff = $('<button class="red-ui-button red-ui-button-small red-ui-diff-text-diff-button"><i class="fa fa-file-o"> <i class="fa fa-caret-left"></i> <i class="fa fa-caret-right"></i> <i class="fa fa-file-o"></i></button>').on("click", function() {
|
||||
$('<button class="red-ui-button red-ui-button-small red-ui-diff-text-diff-button"><i class="fa fa-file-o"> <i class="fa fa-caret-left"></i> <i class="fa fa-caret-right"></i> <i class="fa fa-file-o"></i></button>').on("click", function() {
|
||||
showTextDiff(localNode[d],remoteNode[d]);
|
||||
}).appendTo(propertyNameCell);
|
||||
RED.popover.tooltip(textDiff, RED._("diff.compareChanges"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -115,9 +115,8 @@ RED.editor = (function() {
|
||||
var valid = validateNodeProperty(node, definition, prop, properties[prop]);
|
||||
if ((typeof valid) === "string") {
|
||||
result.push(valid);
|
||||
} else if (Array.isArray(valid)) {
|
||||
result = result.concat(valid)
|
||||
} else if(!valid) {
|
||||
}
|
||||
else if(!valid) {
|
||||
result.push(prop);
|
||||
}
|
||||
}
|
||||
@@ -166,7 +165,7 @@ RED.editor = (function() {
|
||||
// If the validator takes two arguments, it is a 3.x validator that
|
||||
// can return a String to mean 'invalid' and provide a reason
|
||||
if ((definition[property].validate.length === 2) &&
|
||||
((typeof valid) === "string") || Array.isArray(valid)) {
|
||||
((typeof valid) === "string")) {
|
||||
return valid;
|
||||
} else {
|
||||
// Otherwise, a 2.x returns a truth-like/false-like value that
|
||||
|
@@ -169,7 +169,7 @@
|
||||
var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop();
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
|
||||
RED.editor.mermaid.render()
|
||||
mermaid.init();
|
||||
},200);
|
||||
})
|
||||
if (options.header) {
|
||||
@@ -178,7 +178,7 @@
|
||||
|
||||
if (value) {
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
RED.editor.mermaid.render()
|
||||
mermaid.init();
|
||||
}
|
||||
panels = RED.panels.create({
|
||||
id:"red-ui-editor-type-markdown-panels",
|
||||
|
@@ -1,53 +0,0 @@
|
||||
RED.editor.mermaid = (function () {
|
||||
let initializing = false
|
||||
let loaded = false
|
||||
let pendingEvals = []
|
||||
let diagramIds = 0
|
||||
|
||||
function render(selector = '.mermaid') {
|
||||
// $(selector).hide()
|
||||
if (!loaded) {
|
||||
pendingEvals.push(selector)
|
||||
|
||||
if (!initializing) {
|
||||
initializing = true
|
||||
$.getScript(
|
||||
'vendor/mermaid/mermaid.min.js',
|
||||
function (data, stat, jqxhr) {
|
||||
mermaid.initialize({
|
||||
startOnLoad: false
|
||||
})
|
||||
loaded = true
|
||||
while(pendingEvals.length > 0) {
|
||||
const pending = pendingEvals.shift()
|
||||
render(pending)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
const nodes = document.querySelectorAll(selector)
|
||||
|
||||
nodes.forEach(async node => {
|
||||
if (!node.getAttribute('mermaid-processed')) {
|
||||
const mermaidContent = node.innerText
|
||||
node.setAttribute('mermaid-processed', true)
|
||||
try {
|
||||
const { svg } = await mermaid.render('mermaid-render-'+Date.now()+'-'+(diagramIds++), mermaidContent);
|
||||
node.innerHTML = svg
|
||||
} catch (err) {
|
||||
$('<div>').css({
|
||||
fontSize: '0.8em',
|
||||
border: '1px solid var(--red-ui-border-color-error)',
|
||||
padding: '5px',
|
||||
marginBottom: '10px',
|
||||
}).text(err.toString()).prependTo(node)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return {
|
||||
render: render,
|
||||
};
|
||||
})();
|
@@ -196,7 +196,7 @@
|
||||
}
|
||||
|
||||
$('<div class="form-row">'+
|
||||
'<label for="node-input-show-label" data-i18n="editor.label"></label>'+
|
||||
'<label for="node-input-show-label-btn" data-i18n="editor.label"></label>'+
|
||||
'<span style="margin-right: 2px;"/>'+
|
||||
'<input type="checkbox" id="node-input-show-label"/>'+
|
||||
'</div>').appendTo(dialogForm);
|
||||
|
46
packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// Mermaid diagram stub library for on-demand dynamic loading
|
||||
// Will be overwritten after script loading by $.getScript
|
||||
var mermaid = (function () {
|
||||
var enabled /* = undefined */;
|
||||
|
||||
var initializing = false;
|
||||
var initCalled = false;
|
||||
|
||||
function initialize(opt) {
|
||||
if (enabled === undefined) {
|
||||
if (RED.settings.markdownEditor &&
|
||||
RED.settings.markdownEditor.mermaid) {
|
||||
enabled = RED.settings.markdownEditor.mermaid.enabled;
|
||||
}
|
||||
else {
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
if (enabled) {
|
||||
initializing = true;
|
||||
$.getScript("vendor/mermaid/mermaid.min.js",
|
||||
function (data, stat, jqxhr) {
|
||||
$(".mermaid").show();
|
||||
// invoke loaded mermaid API
|
||||
initializing = false;
|
||||
mermaid.initialize(opt);
|
||||
if (initCalled) {
|
||||
mermaid.init();
|
||||
initCalled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (initializing) {
|
||||
$(".mermaid").hide();
|
||||
initCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
initialize: initialize,
|
||||
init: init,
|
||||
};
|
||||
})();
|
@@ -166,7 +166,7 @@ RED.projects.settings = (function() {
|
||||
var description = addTargetToExternalLinks($('<span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(desc)+'">'+desc+'</span>')).appendTo(container);
|
||||
description.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
||||
setTimeout(function () {
|
||||
RED.editor.mermaid.render()
|
||||
mermaid.init();
|
||||
}, 200);
|
||||
}
|
||||
|
||||
|
@@ -383,7 +383,6 @@ RED.sidebar.help = (function() {
|
||||
$(this).toggleClass('expanded',!isExpanded);
|
||||
})
|
||||
helpSection.parent().scrollTop(0);
|
||||
RED.editor.mermaid.render()
|
||||
}
|
||||
|
||||
function set(html,title) {
|
||||
|
@@ -464,7 +464,7 @@ RED.sidebar.info = (function() {
|
||||
}
|
||||
$(this).toggleClass('expanded',!isExpanded);
|
||||
});
|
||||
RED.editor.mermaid.render()
|
||||
mermaid.init();
|
||||
}
|
||||
|
||||
var tips = (function() {
|
||||
|
@@ -101,8 +101,28 @@ RED.utils = (function() {
|
||||
|
||||
renderer.code = function (code, lang) {
|
||||
if(lang === "mermaid") {
|
||||
return `<pre class='mermaid'>${code}</pre>`;
|
||||
} else {
|
||||
// mermaid diagram rendering
|
||||
if (mermaidIsEnabled === undefined) {
|
||||
if (RED.settings.markdownEditor &&
|
||||
RED.settings.markdownEditor.mermaid) {
|
||||
mermaidIsEnabled = RED.settings.markdownEditor.mermaid.enabled;
|
||||
}
|
||||
else {
|
||||
mermaidIsEnabled = true;
|
||||
}
|
||||
}
|
||||
if (mermaidIsEnabled) {
|
||||
if (!mermaidIsInitialized) {
|
||||
mermaidIsInitialized = true;
|
||||
mermaid.initialize({startOnLoad:false});
|
||||
}
|
||||
return `<pre class='mermaid'>${code}</pre>`;
|
||||
}
|
||||
else {
|
||||
return `<details><summary>${RED._("markdownEditor.mermaid.summary")}</summary><pre><code>${code}</code></pre></details>`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return "<pre><code>" +code +"</code></pre>";
|
||||
}
|
||||
};
|
||||
@@ -897,51 +917,6 @@ RED.utils = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a typed property is valid according to the type.
|
||||
* Returns true if valid.
|
||||
* Return String error message if invalid
|
||||
* @param {*} propertyType
|
||||
* @param {*} propertyValue
|
||||
* @returns true if valid, String if invalid
|
||||
*/
|
||||
function validateTypedProperty(propertyValue, propertyType, opt) {
|
||||
|
||||
let error
|
||||
if (propertyType === 'json') {
|
||||
try {
|
||||
JSON.parse(propertyValue);
|
||||
} catch(err) {
|
||||
error = RED._("validator.errors.invalid-json", {
|
||||
error: err.message
|
||||
})
|
||||
}
|
||||
} else if (propertyType === 'msg' || propertyType === 'flow' || propertyType === 'global' ) {
|
||||
if (!RED.utils.validatePropertyExpression(propertyValue)) {
|
||||
error = RED._("validator.errors.invalid-prop")
|
||||
}
|
||||
} else if (propertyType === 'num') {
|
||||
if (!/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(propertyValue)) {
|
||||
error = RED._("validator.errors.invalid-num")
|
||||
}
|
||||
} else if (propertyType === 'jsonata') {
|
||||
try {
|
||||
jsonata(propertyValue)
|
||||
} catch(err) {
|
||||
error = RED._("validator.errors.invalid-expr", {
|
||||
error: err.message
|
||||
})
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
if (opt && opt.label) {
|
||||
return opt.label+': '+error
|
||||
}
|
||||
return error
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function getMessageProperty(msg,expr) {
|
||||
var result = null;
|
||||
var msgPropParts;
|
||||
@@ -1143,6 +1118,22 @@ RED.utils = (function() {
|
||||
if (def.category === 'subflows') {
|
||||
return RED.settings.apiRootUrl+"icons/node-red/subflow.svg";
|
||||
}
|
||||
|
||||
if (node?.type) {
|
||||
// this regex might be too restrictive/specific but got to start somewhere
|
||||
const re = new RegExp("^\/"+node.type+"\/icon\/.*\.svg$","i");
|
||||
if (typeof def.icon === "function") {
|
||||
try {
|
||||
const di = def.icon.call(node);
|
||||
if (re.test(di)) { return RED.settings.authTokensSuffix.replace(/-/,'/') + di; }
|
||||
}
|
||||
catch(e) { console.log("Bad Icon",e) }
|
||||
}
|
||||
else {
|
||||
if (re.test(def.icon)) { return RED.settings.authTokensSuffix.replace(/-/,'/') + def.icon; }
|
||||
}
|
||||
}
|
||||
|
||||
return RED.settings.apiRootUrl+"icons/node-red/arrow-in.svg";
|
||||
}
|
||||
|
||||
@@ -1476,7 +1467,6 @@ RED.utils = (function() {
|
||||
getDarkerColor: getDarkerColor,
|
||||
parseModuleList: parseModuleList,
|
||||
checkModuleAllowed: checkModuleAllowed,
|
||||
getBrowserInfo: getBrowserInfo,
|
||||
validateTypedProperty: validateTypedProperty
|
||||
getBrowserInfo: getBrowserInfo
|
||||
}
|
||||
})();
|
||||
|
@@ -43,13 +43,43 @@ RED.validators = {
|
||||
typedInput: function(ptypeName,isConfig,mopt) {
|
||||
return function(v, opt) {
|
||||
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
|
||||
const result = RED.utils.validateTypedProperty(v, ptype, opt)
|
||||
if (result === true || opt) {
|
||||
// Valid, or opt provided - return result as-is
|
||||
return result
|
||||
if (ptype === 'json') {
|
||||
try {
|
||||
JSON.parse(v);
|
||||
return true;
|
||||
} catch(err) {
|
||||
if (opt && opt.label) {
|
||||
return RED._("validator.errors.invalid-json-prop", {
|
||||
error: err.message,
|
||||
prop: opt.label,
|
||||
});
|
||||
}
|
||||
return opt ? RED._("validator.errors.invalid-json", {
|
||||
error: err.message
|
||||
}) : false;
|
||||
}
|
||||
} else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
|
||||
if (RED.utils.validatePropertyExpression(v)) {
|
||||
return true;
|
||||
}
|
||||
if (opt && opt.label) {
|
||||
return RED._("validator.errors.invalid-prop-prop", {
|
||||
prop: opt.label
|
||||
});
|
||||
}
|
||||
return opt ? RED._("validator.errors.invalid-prop") : false;
|
||||
} else if (ptype === 'num') {
|
||||
if (/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v)) {
|
||||
return true;
|
||||
}
|
||||
if (opt && opt.label) {
|
||||
return RED._("validator.errors.invalid-num-prop", {
|
||||
prop: opt.label
|
||||
});
|
||||
}
|
||||
return opt ? RED._("validator.errors.invalid-num") : false;
|
||||
}
|
||||
// No opt - need to return false for backwards compatibilty
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@@ -825,7 +825,6 @@ div.red-ui-projects-dialog-ssh-public-key {
|
||||
margin-top: 0 !important;
|
||||
padding: 5px 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 3px 3px 0px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -275,7 +275,7 @@
|
||||
value: [],
|
||||
type: "link in[]",
|
||||
validate: function (v, opt) {
|
||||
if (((this.linkType || "static") === "static" && v.length > 0)
|
||||
if ((this.linkType === "static" && v.length > 0)
|
||||
|| this.linkType === "dynamic") {
|
||||
return true;
|
||||
}
|
||||
|
@@ -103,6 +103,7 @@
|
||||
} else if (type === "istype") {
|
||||
r.v = rule.find(".node-input-rule-type-value").typedInput('type');
|
||||
r.vt = rule.find(".node-input-rule-type-value").typedInput('type');
|
||||
r.vt = (r.vt === "number") ? "num" : "str";
|
||||
} else if (type === "jsonata_exp") {
|
||||
r.v = rule.find(".node-input-rule-exp-value").typedInput('value');
|
||||
r.vt = rule.find(".node-input-rule-exp-value").typedInput('type');
|
||||
@@ -167,33 +168,7 @@
|
||||
label:RED._("node-red:common.label.payload"),
|
||||
validate: RED.validators.typedInput("propertyType", false)},
|
||||
propertyType: { value:"msg" },
|
||||
rules: {
|
||||
value:[{t:"eq", v:"", vt:"str"}],
|
||||
validate: function (rules, opt) {
|
||||
let msg;
|
||||
const errors = []
|
||||
if (!rules || rules.length === 0) { return true }
|
||||
for (var i=0;i<rules.length;i++) {
|
||||
const opt = { label: RED._('node-red:switch.label.rule')+' '+(i+1) }
|
||||
const r = rules[i];
|
||||
if (r.hasOwnProperty('v')) {
|
||||
if ((msg = RED.utils.validateTypedProperty(r.v,r.vt,opt)) !== true) {
|
||||
errors.push(msg)
|
||||
}
|
||||
}
|
||||
if (r.hasOwnProperty('v2')) {
|
||||
if ((msg = RED.utils.validateTypedProperty(r.v2,r.v2t,opt)) !== true) {
|
||||
errors.push(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors.length) {
|
||||
console.log(errors)
|
||||
return errors
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
rules: {value:[{t:"eq", v:"", vt:"str"}]},
|
||||
checkall: {value:"true", required:true},
|
||||
repair: {value:false},
|
||||
outputs: {value:1}
|
||||
@@ -243,11 +218,7 @@
|
||||
if (i > 0) {
|
||||
var lastRule = $("#node-input-rule-container").editableList('getItemAt',i-1);
|
||||
var exportedRule = exportRule(lastRule.element);
|
||||
if (exportedRule.t === "istype") {
|
||||
opt.r.vt = (exportedRule.vt === "number") ? "num" : "str";
|
||||
} else {
|
||||
opt.r.vt = exportedRule.vt;
|
||||
}
|
||||
opt.r.vt = exportedRule.vt;
|
||||
opt.r.v = "";
|
||||
// We could copy the value over as well and preselect it (see the 'activeElement' code below)
|
||||
// But not sure that feels right. Is copying over the last value 'expected' behaviour?
|
||||
|
@@ -19,42 +19,71 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
function isInvalidProperty(v,vt) {
|
||||
if (/msg|flow|global/.test(vt)) {
|
||||
if (!RED.utils.validatePropertyExpression(v)) {
|
||||
return RED._("node-red:change.errors.invalid-prop", {
|
||||
property: v
|
||||
});
|
||||
}
|
||||
} else if (vt === "jsonata") {
|
||||
try{ jsonata(v); } catch(e) {
|
||||
return RED._("node-red:change.errors.invalid-expr", {
|
||||
error: e.message
|
||||
});
|
||||
}
|
||||
} else if (vt === "json") {
|
||||
try{ JSON.parse(v); } catch(e) {
|
||||
return RED._("node-red:change.errors.invalid-json-data", {
|
||||
error: e.message
|
||||
});
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RED.nodes.registerType('change', {
|
||||
color: "#E2D96E",
|
||||
category: 'function',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
rules:{
|
||||
value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],
|
||||
validate: function(rules, opt) {
|
||||
let msg;
|
||||
const errors = []
|
||||
if (!rules || rules.length === 0) { return true }
|
||||
for (var i=0;i<rules.length;i++) {
|
||||
const opt = { label: RED._('node-red:change.label.rule')+' '+(i+1) }
|
||||
const r = rules[i];
|
||||
if (r.t === 'set' || r.t === 'change' || r.t === 'delete' || r.t === 'move') {
|
||||
if ((msg = RED.utils.validateTypedProperty(r.p,r.pt,opt)) !== true) {
|
||||
errors.push(msg)
|
||||
}
|
||||
rules:{value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],validate: function(rules, opt) {
|
||||
var msg;
|
||||
if (!rules || rules.length === 0) { return true }
|
||||
for (var i=0;i<rules.length;i++) {
|
||||
var r = rules[i];
|
||||
if (r.t === 'set') {
|
||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
||||
return msg;
|
||||
}
|
||||
if (r.t === 'set' || r.t === 'change' || r.t === 'move') {
|
||||
if ((msg = RED.utils.validateTypedProperty(r.to,r.tot,opt)) !== true) {
|
||||
errors.push(msg)
|
||||
}
|
||||
if (msg = isInvalidProperty(r.to,r.tot)) {
|
||||
return msg;
|
||||
}
|
||||
if (r.t === 'change') {
|
||||
if ((msg = RED.utils.validateTypedProperty(r.from,r.fromt,opt)) !== true) {
|
||||
errors.push(msg)
|
||||
}
|
||||
} else if (r.t === 'change') {
|
||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
||||
return msg;
|
||||
}
|
||||
if(msg = isInvalidProperty(r.from,r.fromt)) {
|
||||
return msg;
|
||||
}
|
||||
if(msg = isInvalidProperty(r.to,r.tot)) {
|
||||
return msg;
|
||||
}
|
||||
} else if (r.t === 'delete') {
|
||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
||||
return msg;
|
||||
}
|
||||
} else if (r.t === 'move') {
|
||||
if (msg = isInvalidProperty(r.p,r.pt)) {
|
||||
return msg;
|
||||
}
|
||||
if (msg = isInvalidProperty(r.to,r.tot)) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
if (errors.length) {
|
||||
return errors
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
return true;
|
||||
}},
|
||||
// legacy
|
||||
action: {value:""},
|
||||
property: {value:""},
|
||||
|
@@ -153,7 +153,7 @@
|
||||
}
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#dialog-form .node-text-editor").css("height",height+"px");
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
this.editor.resize();
|
||||
}
|
||||
});
|
||||
|
@@ -284,7 +284,7 @@ module.exports = function(RED) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
else if (!msg.hasOwnProperty("reset")) {
|
||||
else {
|
||||
if (maxKeptMsgsCount(node) > 0) {
|
||||
if (node.intervalID === -1) {
|
||||
node.send(msg);
|
||||
|
@@ -452,6 +452,10 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
formData.append(opt, val);
|
||||
} else if (typeof val === 'object' && val.hasOwnProperty('value')) {
|
||||
formData.append(opt,val.value,val.options || {});
|
||||
} else if (Array.isArray(val)) {
|
||||
for (var i=0; i<val.length; i++) {
|
||||
formData.append(opt, val[i])
|
||||
}
|
||||
} else {
|
||||
formData.append(opt,JSON.stringify(val));
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ module.exports = function(RED) {
|
||||
if (!(notemplate && (msg.hasOwnProperty("parts") && msg.parts.hasOwnProperty("index") && msg.parts.index > 0))) {
|
||||
template = clean(node.template);
|
||||
}
|
||||
const ou = [];
|
||||
var ou = "";
|
||||
if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
|
||||
if (node.hdrout !== "none" && node.hdrSent === false) {
|
||||
if ((template.length === 1) && (template[0] === '')) {
|
||||
@@ -74,7 +74,7 @@ module.exports = function(RED) {
|
||||
template = Object.keys(msg.payload[0]);
|
||||
}
|
||||
}
|
||||
ou.push(template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep));
|
||||
ou += template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep) + node.ret;
|
||||
if (node.hdrout === "once") { node.hdrSent = true; }
|
||||
}
|
||||
for (var s = 0; s < msg.payload.length; s++) {
|
||||
@@ -93,7 +93,7 @@ module.exports = function(RED) {
|
||||
msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
|
||||
}
|
||||
}
|
||||
ou.push(msg.payload[s].join(node.sep));
|
||||
ou += msg.payload[s].join(node.sep) + node.ret;
|
||||
}
|
||||
else {
|
||||
if ((template.length === 1) && (template[0] === '') && (msg.hasOwnProperty("columns"))) {
|
||||
@@ -105,7 +105,6 @@ module.exports = function(RED) {
|
||||
node.warn(RED._("csv.errors.obj_csv"));
|
||||
tmpwarn = false;
|
||||
}
|
||||
const row = [];
|
||||
for (var p in msg.payload[0]) {
|
||||
/* istanbul ignore else */
|
||||
if (msg.payload[s].hasOwnProperty(p)) {
|
||||
@@ -119,22 +118,21 @@ module.exports = function(RED) {
|
||||
}
|
||||
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
||||
q = q.replace(/"/g, '""');
|
||||
row.push(node.quo + q + node.quo);
|
||||
ou += node.quo + q + node.quo + node.sep;
|
||||
}
|
||||
else if (q.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
|
||||
row.push(node.quo + q + node.quo);
|
||||
ou += node.quo + q + node.quo + node.sep;
|
||||
}
|
||||
else { row.push(q); } // otherwise just add
|
||||
else { ou += q + node.sep; } // otherwise just add
|
||||
}
|
||||
}
|
||||
}
|
||||
ou.push(row.join(node.sep)); // add separator
|
||||
ou = ou.slice(0,-1) + node.ret;
|
||||
}
|
||||
else {
|
||||
const row = [];
|
||||
for (var t=0; t < template.length; t++) {
|
||||
if (template[t] === '') {
|
||||
row.push('');
|
||||
ou += node.sep;
|
||||
}
|
||||
else {
|
||||
var tt = template[t];
|
||||
@@ -148,20 +146,19 @@ module.exports = function(RED) {
|
||||
p = RED.util.ensureString(p);
|
||||
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
||||
p = p.replace(/"/g, '""');
|
||||
row.push(node.quo + p + node.quo);
|
||||
ou += node.quo + p + node.quo + node.sep;
|
||||
}
|
||||
else if (p.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
|
||||
row.push(node.quo + p + node.quo);
|
||||
ou += node.quo + p + node.quo + node.sep;
|
||||
}
|
||||
else { row.push(p); } // otherwise just add
|
||||
else { ou += p + node.sep; } // otherwise just add
|
||||
}
|
||||
}
|
||||
ou.push(row.join(node.sep)); // add separator
|
||||
ou = ou.slice(0,-1) + node.ret; // remove final "comma" and add "newline"
|
||||
}
|
||||
}
|
||||
}
|
||||
// join lines, don't forget to add the last new line
|
||||
msg.payload = ou.join(node.ret) + node.ret;
|
||||
msg.payload = ou;
|
||||
msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
|
||||
if (msg.payload !== '') { send(msg); }
|
||||
done();
|
||||
|
BIN
packages/node_modules/@node-red/nodes/icons/arduino.png
vendored
Normal file
After Width: | Height: | Size: 603 B |
@@ -1 +0,0 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff"><path d="m9.7884 22.379c-5.2427-0.41732-9.6475 5.7885-7.4975 10.585 2.0949 5.2041 9.9782 6.6154 13.727 2.4477 3.633-3.5613 5.0332-9.0411 9.4821-11.853 4.5205-3.0872 11.797-0.172 12.68 5.3144 0.86 5.2537-4.8017 10.364-9.9231 8.8205-3.7873-0.85449-6.5051-4.0905-8.0487-7.4975-1.9019-3.2526-4.3882-6.7257-8.2693-7.6077-0.6891-0.15656-1.4003-0.21831-2.1059-0.21721z" stroke-width="3.3"/><path d="m6.7012 29.821h6.6154" stroke-width="1.4"/><path d="m26.988 29.821h5.5128m-2.8115-2.7564v5.5128" stroke-width="1.8"/></g></svg>
|
Before Width: | Height: | Size: 635 B |
BIN
packages/node_modules/@node-red/nodes/icons/bluetooth.png
vendored
Normal file
After Width: | Height: | Size: 2.3 KiB |
@@ -1 +0,0 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m8.3474 17.75 22.298 22.444-10.747 13.013v-46.497l10.747 12.428-22.298 21.859" fill="none" stroke="#fff" stroke-width="4"/></svg>
|
Before Width: | Height: | Size: 225 B |
BIN
packages/node_modules/@node-red/nodes/icons/leveldb.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
@@ -1 +0,0 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m2.7078 12.986c0 7.7994-0.36386 21.569 0 32.545s35.118 9.8751 34.848 0c-0.26959-9.8751 0-24.82 0-32.545 0-7.7243-34.848-7.7995-34.848 0z" fill="none" stroke="#fff"/><g fill="#fff"><path d="m3.8741 13.406v8.955c0.021834 3.5781 19.543 5.0789 25.575 3.2543 0 0 0.02229-2.6683 0.02998-2.6673l5.5325 0.7238c0.64508 0.0844 1.1345-0.74597 1.134-1.3284v-8.573l-0.99896 0.93349-15.217-2.2765c4.5883 2.1798 9.808 4.1312 9.808 4.1312-9.3667 3.1562-25.846-0.31965-25.864-3.1525z"/><path d="m3.886 26.607v8.1052c3.2188 6.1087 29.901 5.8574 32.272 0v-8.1052c-3.3598 4.6685-29.204 5.1534-32.272 0z"/><path d="m4.0032 39.082v7.1522c2.556 7.4622 28.918 7.6072 32.272 0v-7.1522c-3.2345 4.9471-29.087 5.359-32.272 0z"/></g></svg>
|
Before Width: | Height: | Size: 806 B |
BIN
packages/node_modules/@node-red/nodes/icons/mongodb.png
vendored
Normal file
After Width: | Height: | Size: 414 B |
@@ -1 +0,0 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m23.515 13.831c-4.7594-5.8789-2.6084-5.7751-7.3474 0-8.0368 10.477-8.3322 24.431 2.5476 32.935 0.13181 2.0418 0.46056 4.9803 0.46056 4.9803h1.315s0.32875-2.9219 0.46017-4.9803c2.8458-2.2339 16.799-14.619 2.5641-32.935z" fill="#fff"/></svg>
|
Before Width: | Height: | Size: 335 B |
BIN
packages/node_modules/@node-red/nodes/icons/mouse.png
vendored
Normal file
After Width: | Height: | Size: 671 B |
@@ -1 +0,0 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-width="3"><path d="m6 30c6 5 24 4 29-0.07"/><path d="m21 33 0.1-19c0.02-4 4-3 4-6s-4-2-4-5"/><path d="m6 22c0-11 29-10 29 0v21c0 18-29 19-29 0s4e-7 -11 0-21z"/></g></svg>
|
Before Width: | Height: | Size: 293 B |
BIN
packages/node_modules/@node-red/nodes/icons/rbe.png
vendored
Normal file
After Width: | Height: | Size: 252 B |
@@ -1 +0,0 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m29 12s0.1 30 0.05 31-3 5-7 5-19 0.04-19 0.04c6-4 9-5 17-5 0 0 4-0.1 4-2 0-2 8e-3 -29 8e-3 -29z" fill="#fff"/><path d="m12 47s-0.1-30-0.05-31 3-5 7-5 19-0.04 19-0.04c-6 4-9 5-17 5 0 0-4 0.1-4 2 0 2-8e-3 29-8e-3 29z" fill="#fff"/></svg>
|
Before Width: | Height: | Size: 331 B |
BIN
packages/node_modules/@node-red/nodes/icons/redis.png
vendored
Normal file
After Width: | Height: | Size: 736 B |
@@ -1 +0,0 @@
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-width="3"><path class="cls-4" d="m17.639 30.221c-1.7087-0.88225-12.465-5.6284-14.414-6.636-1.9492-1.0075-1.9868-1.7073-0.075164-2.5188 1.9117-0.81145 12.643-5.3861 14.91-6.2738 2.2675-0.8877 3.0517-0.91493 4.9785-0.14704 1.9267 0.76789 12.026 5.1329 13.923 5.8898 1.8966 0.75699 1.9843 1.386 0.02631 2.4861-1.958 1.1001-12.1 5.6611-14.285 6.8729s-3.355 1.2091-5.0636 0.32685z"/><path class="cls-4" d="m32.23 25.251c2.8239 1.2039 4.155 1.764 4.7307 1.9938 1.8966 0.75699 1.9843 1.386 0.0263 2.4861s-12.1 5.6611-14.285 6.8729c-2.1848 1.2117-3.3548 1.209-5.0634 0.32676-1.7087-0.88225-12.465-5.6284-14.414-6.636-1.9492-1.0075-1.9868-1.7073-0.075164-2.5188 10.883-4.6196-9.1087 3.8612 4.9598-2.1076"/><path class="cls-4" d="m32.23 31.961c2.8239 1.2039 4.155 1.764 4.7307 1.9938 1.8966 0.75699 1.9843 1.386 0.0263 2.4861s-12.1 5.6611-14.285 6.8729c-2.1848 1.2117-3.3548 1.209-5.0634 0.32676-1.7087-0.88225-12.465-5.6284-14.414-6.636-1.9492-1.0075-1.9868-1.7073-0.075164-2.5188 10.883-4.6196-9.1087 3.8612 4.9598-2.1076"/></g></svg>
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -36,5 +36,5 @@
|
||||
<p><b>Remarque</b> : Les options <i>"Intervalle entre les heures"</i> et <i>"à une heure précise"</i> utilisent le système cron standard.
|
||||
Cela signifie que pour la première option, vous pouvez envoyer un message à intervalle régulier entre les heures voulues.
|
||||
Si vous voulez envoyer un message toutes les minutes à partir de maintenant, utiliser l'option <i>"intervalle"</i>.</p>
|
||||
<p><b>Remarque</b> : Pour inclure une nouvelle ligne dans une chaîne, vous devez utiliser soit un noeud de fonction soit le noeud template pour créer la charge utile.</p>
|
||||
<p><b>Remarque</b> : Pour inclure une nouvelle ligne dans une chaîne, vous devez utiliser un noeud de fonction pour créer la charge utile.</p>
|
||||
</script>
|
||||
|
@@ -11,11 +11,11 @@
|
||||
"expand": "Développer"
|
||||
},
|
||||
"status": {
|
||||
"connected": "Connecté",
|
||||
"not-connected": "Pas connecté",
|
||||
"disconnected": "Déconnecté",
|
||||
"connecting": "Connexion",
|
||||
"error": "Erreur",
|
||||
"connected": "connecté",
|
||||
"not-connected": "pas connecté",
|
||||
"disconnected": "déconnecté",
|
||||
"connecting": "connexion",
|
||||
"error": "erreur",
|
||||
"ok": "OK"
|
||||
},
|
||||
"notification": {
|
||||
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"inject": {
|
||||
"inject": "Injecter",
|
||||
"injectNow": "Injecter maintenant",
|
||||
"injectNow": "injecter maintenant",
|
||||
"repeat": "répéter = __repeat__",
|
||||
"crontab": "crontab = __crontab__",
|
||||
"stopped": "arrêté",
|
||||
@@ -98,7 +98,7 @@
|
||||
"catchUncaught": "catch : non capturé",
|
||||
"label": {
|
||||
"source": "Détecter les erreurs de",
|
||||
"selectAll": "Tout sélectionner",
|
||||
"selectAll": "tout sélectionner",
|
||||
"uncaught": "Ignorer les erreurs gérées par les autres noeuds Catch"
|
||||
},
|
||||
"scope": {
|
||||
@@ -112,7 +112,7 @@
|
||||
"statusNodes": "statut : __number__",
|
||||
"label": {
|
||||
"source": "Signaler l'état de",
|
||||
"sortByType": "Trier par type"
|
||||
"sortByType": "trier par type"
|
||||
},
|
||||
"scope": {
|
||||
"all": "tous les noeuds",
|
||||
@@ -148,23 +148,23 @@
|
||||
"deactivated": "Désactivé avec succès : __label__"
|
||||
},
|
||||
"sidebar": {
|
||||
"label": "Débogage",
|
||||
"label": "débogage",
|
||||
"name": "Messages de débogage",
|
||||
"filterAll": "Tous les noeuds",
|
||||
"filterSelected": "Noeuds sélectionnés",
|
||||
"filterCurrent": "Flux actuel",
|
||||
"filterAll": "tous les noeuds",
|
||||
"filterSelected": "noeuds sélectionnés",
|
||||
"filterCurrent": "flux actuel",
|
||||
"debugNodes": "noeuds de débogage",
|
||||
"clearLog": "Tous les messages",
|
||||
"clearFilteredLog": "Les messages filtrés",
|
||||
"clearLog": "Effacer les messages",
|
||||
"clearFilteredLog": "Effacer les messages filtrés",
|
||||
"filterLog": "Filtrer les messages",
|
||||
"openWindow": "Ouvrir dans une nouvelle fenêtre",
|
||||
"copyPath": "Copier le chemin",
|
||||
"copyPayload": "Copier la valeur",
|
||||
"pinPath": "Épingler le chemin",
|
||||
"selectAll": "Tout sélectionner",
|
||||
"selectNone": "Ne rien sélectionner",
|
||||
"all": "Tout",
|
||||
"filtered": "Filtrés"
|
||||
"selectAll": "tout sélectionner",
|
||||
"selectNone": "ne rien sélectionner",
|
||||
"all": "tout",
|
||||
"filtered": "filtré"
|
||||
},
|
||||
"messageMenu": {
|
||||
"collapseAll": "Réduire tous les chemins",
|
||||
@@ -177,11 +177,11 @@
|
||||
"linkIn": "Lien entrant",
|
||||
"linkOut": "Lien sortant",
|
||||
"linkCall": "Appel de lien",
|
||||
"linkOutReturn": "Retour de lien",
|
||||
"linkOutReturn": "retour de lien",
|
||||
"outMode": "Mode",
|
||||
"sendToAll": "Envoyer à tous les noeuds de liaison connectés",
|
||||
"returnToCaller": "Retour au noeud de liaison appelant",
|
||||
"timeout": "Temps mort",
|
||||
"timeout": "temps mort",
|
||||
"linkCallType": "Type de liaison",
|
||||
"staticLinkCall": "Lien fixe",
|
||||
"dynamicLinkCall": "Lien dynamique (msg.target)",
|
||||
@@ -225,7 +225,7 @@
|
||||
"command": "Commande",
|
||||
"append": "Joindre",
|
||||
"timeout": "Temps mort",
|
||||
"timeoutplace": "Facultatif",
|
||||
"timeoutplace": "facultatif",
|
||||
"return": "Sortie",
|
||||
"seconds": "secondes",
|
||||
"stdout": "stdout",
|
||||
@@ -234,7 +234,7 @@
|
||||
"winHide": "Masquer la console"
|
||||
},
|
||||
"placeholder": {
|
||||
"extraparams": "Paramètres d'entrée supplémentaires"
|
||||
"extraparams": "paramètres d'entrée supplémentaires"
|
||||
},
|
||||
"opt": {
|
||||
"exec": "lorsque la commande est terminée - mode exec",
|
||||
@@ -319,7 +319,7 @@
|
||||
"queuemsg": "Mettre en file d'attente les messages intermédiaires",
|
||||
"dropmsg": "Supprimer les messages intermédiaires",
|
||||
"sendmsg": "Envoyer les messages intermédiaires sur la 2ème sortie",
|
||||
"allowrate": "Autoriser msg.rate (en ms) à remplacer le débit",
|
||||
"allowrate": "autoriser msg.rate (en ms) à remplacer le débit",
|
||||
"label": {
|
||||
"delay": "retard",
|
||||
"variable": "variable",
|
||||
@@ -349,7 +349,7 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"too-many": "Trop de messages en attente dans le noeud 'Delay'",
|
||||
"too-many": "trop de messages en attente dans le noeud 'Delay'",
|
||||
"invalid-timeout": "Valeur de délai invalide",
|
||||
"invalid-rate": "Valeur de taux invalide",
|
||||
"invalid-rate-unit": "Valeur de débit invalide",
|
||||
@@ -359,8 +359,8 @@
|
||||
},
|
||||
"trigger": {
|
||||
"send": "Envoyer",
|
||||
"then": "Puis",
|
||||
"then-send": "Puis envoyer",
|
||||
"then": "puis",
|
||||
"then-send": "puis envoyer",
|
||||
"output": {
|
||||
"string": "la chaîne",
|
||||
"number": "le nombre",
|
||||
@@ -381,9 +381,9 @@
|
||||
"m": "Minutes",
|
||||
"h": "Heures"
|
||||
},
|
||||
"extend": " Prolonger le délai si un nouveau message arrive",
|
||||
"override": "Remplacer le délai avec msg.delay",
|
||||
"second": " Envoyer un deuxième message à une sortie séparée",
|
||||
"extend": " prolonger le délai si un nouveau message arrive",
|
||||
"override": "remplacer le délai avec msg.delay",
|
||||
"second": " envoyer un deuxième message à une sortie séparée",
|
||||
"label": {
|
||||
"trigger": "déclencher",
|
||||
"trigger-block": "déclencher et bloquer",
|
||||
@@ -408,7 +408,7 @@
|
||||
"mqtt": {
|
||||
"label": {
|
||||
"broker": "Serveur",
|
||||
"example": "expl. localhost",
|
||||
"example": "par exemple. localhost",
|
||||
"output": "Sortie",
|
||||
"qos": "QoS",
|
||||
"retain": "Conserver",
|
||||
@@ -438,7 +438,7 @@
|
||||
"sessionExpiry": "Expiration de la session (secondes)",
|
||||
"topicAlias": "Alias",
|
||||
"payloadFormatIndicator": "Formater",
|
||||
"payloadFormatIndicatorFalse": "Octets non spécifiés (par défaut)",
|
||||
"payloadFormatIndicatorFalse": "octets non spécifiés (par défaut)",
|
||||
"payloadFormatIndicatorTrue": "Charge utile encodée en UTF-8",
|
||||
"protocolVersion": "Protocole",
|
||||
"protocolVersion3": "MQTT V3.1 (hérité)",
|
||||
@@ -493,8 +493,8 @@
|
||||
"false": "faux",
|
||||
"tip": "Conseil : laisser le sujet, le qos ou le contenu vide si vous souhaitez les définir via les propriétés du msg.",
|
||||
"errors": {
|
||||
"not-defined": "Sujet non défini",
|
||||
"missing-config": "Configuration du courtier manquante",
|
||||
"not-defined": "sujet non défini",
|
||||
"missing-config": "configuration du courtier manquante",
|
||||
"invalid-topic": "Sujet invalide spécifié",
|
||||
"nonclean-missingclientid": "Aucun ID client défini, utilisation d'une session propre",
|
||||
"invalid-json-string": "Chaîne JSON invalide",
|
||||
@@ -514,7 +514,7 @@
|
||||
"upload": "Accepter les téléchargements de fichiers ?",
|
||||
"status": "Code d'état",
|
||||
"headers": "En-têtes",
|
||||
"other": "Autre",
|
||||
"other": "autre",
|
||||
"paytoqs": {
|
||||
"ignore": "Ignorer",
|
||||
"query": "Joindre aux paramètres de chaîne de requête",
|
||||
@@ -625,7 +625,7 @@
|
||||
"chars": "caractères",
|
||||
"close": "Fermer",
|
||||
"optional": "(facultatif)",
|
||||
"reattach": "Rattacher le délimiteur"
|
||||
"reattach": "rattacher le délimiteur"
|
||||
},
|
||||
"type": {
|
||||
"listen": "Écoute sur",
|
||||
@@ -633,8 +633,8 @@
|
||||
"reply": "Répondre sur TCP"
|
||||
},
|
||||
"output": {
|
||||
"stream": "Flux de",
|
||||
"single": "Unique",
|
||||
"stream": "flux de",
|
||||
"single": "unique",
|
||||
"buffer": "Tampon",
|
||||
"string": "Chaîne",
|
||||
"base64": "Chaîne en Base64"
|
||||
@@ -657,15 +657,15 @@
|
||||
"connections_plural": "__count__ connexions"
|
||||
},
|
||||
"errors": {
|
||||
"connection-lost": "Connexion perdue avec __host__:__port__",
|
||||
"timeout": "Délai d'expiration du port __port__ du socket fermé",
|
||||
"cannot-listen": "Impossible d'écouter sur le port __port__, erreur : __error__",
|
||||
"error": "Erreur : __error__",
|
||||
"socket-error": "Erreur de courtier depuis __host__:__port__",
|
||||
"connection-lost": "connexion perdue avec __host__:__port__",
|
||||
"timeout": "délai d'expiration du port __port__ du socket fermé",
|
||||
"cannot-listen": "impossible d'écouter sur le port __port__, erreur : __error__",
|
||||
"error": "erreur : __error__",
|
||||
"socket-error": "erreur de courtier depuis __host__:__port__",
|
||||
"no-host": "Hôte et/ou port non défini",
|
||||
"connect-timeout": "Délai de connexion",
|
||||
"connect-fail": "La connexion a échoué",
|
||||
"bad-string": "Échec de la conversion en chaîne",
|
||||
"connect-timeout": "délai de connexion",
|
||||
"connect-fail": "la connexion a échoué",
|
||||
"bad-string": "échec de la conversion en chaîne",
|
||||
"invalid-host": "Hôte invalide",
|
||||
"invalid-port": "Port invalide"
|
||||
}
|
||||
@@ -722,7 +722,7 @@
|
||||
},
|
||||
"errors": {
|
||||
"access-error": "Erreur d'accès UDP, vous aurez peut-être besoin d'un accès root pour les ports inférieurs à 1024",
|
||||
"error": "Erreur : __erreur__",
|
||||
"error": "erreur : __erreur__",
|
||||
"bad-mcaddress": "Mauvaise adresse de multidiffusion",
|
||||
"interface": "Doit être l'adresse IP de l'interface requise",
|
||||
"ip-notset": "udp : adresse IP non définie",
|
||||
@@ -730,7 +730,7 @@
|
||||
"port-invalid": "udp : numéro de port non valide",
|
||||
"alreadyused": "udp : port __port__ déjà utilisé",
|
||||
"ifnotfound": "udp : interface __iface__ introuvable",
|
||||
"invalid-group": "Groupe de multidiffusion invalide"
|
||||
"invalid-group": "groupe de multidiffusion invalide"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
@@ -738,15 +738,15 @@
|
||||
"label": {
|
||||
"property": "Propriété",
|
||||
"rule": "règle",
|
||||
"repair": "Recréer des séquences du messages",
|
||||
"value-rules": "Règles de valeur",
|
||||
"sequence-rules": "Règles de séquence"
|
||||
"repair": "recréer des séquences du messages",
|
||||
"value-rules": "règles de valeur",
|
||||
"sequence-rules": "règles de séquence"
|
||||
},
|
||||
"previous": "valeur précédente",
|
||||
"and": "et",
|
||||
"checkall": "Vérifier toutes les règles",
|
||||
"stopfirst": "Arrêter après la première concordance",
|
||||
"ignorecase": "Ignorer la casse",
|
||||
"checkall": "vérifier toutes les règles",
|
||||
"stopfirst": "arrêter après la première concordance",
|
||||
"ignorecase": "ignorer la casse",
|
||||
"rules": {
|
||||
"btwn": "est entre",
|
||||
"cont": "contient",
|
||||
@@ -767,7 +767,7 @@
|
||||
},
|
||||
"errors": {
|
||||
"invalid-expr": "Expression JSONata non valide : __error__",
|
||||
"too-many": "Trop de messages en attente dans le noeud de commutation"
|
||||
"too-many": "trop de messages en attente dans le noeud de commutation"
|
||||
}
|
||||
},
|
||||
"change": {
|
||||
@@ -840,13 +840,13 @@
|
||||
"entrée": "Entrée",
|
||||
"skip-s": "Passer en premier",
|
||||
"skip-e": "lignes",
|
||||
"firstrow": "La première ligne contient les noms des colonnes",
|
||||
"firstrow": "la première ligne contient les noms des colonnes",
|
||||
"output": "Sortie",
|
||||
"includerow": "Inclure la ligne du nom de la colonne",
|
||||
"includerow": "inclure la ligne du nom de la colonne",
|
||||
"newline": "Nouvelle ligne",
|
||||
"usestrings": "Analyser les valeurs numériques",
|
||||
"include_empty_strings": "Inclure les chaînes vides",
|
||||
"include_null_values": "Inclure les valeurs nulles"
|
||||
"usestrings": "analyser les valeurs numériques",
|
||||
"include_empty_strings": "inclure les chaînes vides",
|
||||
"include_null_values": "inclure les valeurs nulles"
|
||||
},
|
||||
"placeholder": {
|
||||
"columns": "noms de colonnes séparés par des virgules"
|
||||
@@ -936,8 +936,8 @@
|
||||
},
|
||||
"file": {
|
||||
"label": {
|
||||
"write": "Écrire le fichier",
|
||||
"read": "Lire le fichier",
|
||||
"write": "écrire le fichier",
|
||||
"read": "lire le fichier",
|
||||
"filename": "Nom du fichier",
|
||||
"path": "chemin",
|
||||
"action": "Action",
|
||||
@@ -972,8 +972,8 @@
|
||||
"appendedfile": "ajouté au fichier : __file__"
|
||||
},
|
||||
"encoding": {
|
||||
"none": "Par défaut",
|
||||
"setbymsg": "Défini par msg.encoding",
|
||||
"none": "par défaut",
|
||||
"setbymsg": "défini par msg.encoding",
|
||||
"native": "Natif",
|
||||
"unicode": "Unicode",
|
||||
"japanese": "Japonais",
|
||||
@@ -990,10 +990,10 @@
|
||||
"errors": {
|
||||
"nofilename": "Aucun nom de fichier spécifié",
|
||||
"invaliddelete": "Attention : suppression non valide. Veuiller utiliser une option de suppression spécifique dans la boîte de dialogue de configuration.",
|
||||
"deletefail": "Échec de la suppression du fichier : __error__",
|
||||
"writefail": "Échec de l'écriture dans le fichier : __error__",
|
||||
"appendfail": "Échec de l'ajout au fichier : __error__",
|
||||
"createfail": "Échec de la création du fichier : __error__"
|
||||
"deletefail": "échec de la suppression du fichier : __error__",
|
||||
"writefail": "échec de l'écriture dans le fichier : __error__",
|
||||
"appendfail": "échec de l'ajout au fichier : __error__",
|
||||
"createfail": "échec de la création du fichier : __error__"
|
||||
},
|
||||
"tip": "Astuce : Le nom du fichier doit être un chemin absolu, sinon il sera relatif au répertoire de travail du processus Node-RED."
|
||||
},
|
||||
@@ -1018,9 +1018,9 @@
|
||||
"reduce": "réduire la séquence",
|
||||
"custom": "manuel"
|
||||
},
|
||||
"combine": "Combiner chaque",
|
||||
"combine": "Combine each",
|
||||
"completeMessage": "message complet",
|
||||
"create": "Créer",
|
||||
"create": "créer",
|
||||
"type": {
|
||||
"string": "une Chaîne",
|
||||
"array": "un Tableau",
|
||||
@@ -1028,13 +1028,13 @@
|
||||
"object": "un Objet clé/valeur",
|
||||
"merged": "un Objet fusionné"
|
||||
},
|
||||
"using": "En utilisant la valeur du",
|
||||
"key": "comme clé",
|
||||
"using": "en utilisant la valeur de",
|
||||
"key": "comme la clé",
|
||||
"joinedUsing": "joint en utilisant",
|
||||
"send": "Envoyer le message :",
|
||||
"afterCount": "Après un nombre de parties du message",
|
||||
"count": "nombre",
|
||||
"subsequent": "Et tous les messages suivants.",
|
||||
"afterCount": "Après un certain nombre de parties du message",
|
||||
"count": "compter",
|
||||
"subsequent": "et tous les messages suivants.",
|
||||
"afterTimeout": "Après un délai d'attente après le premier message",
|
||||
"seconds": "secondes",
|
||||
"complete": "Après un message avec la propriété <code>msg.complete</code> définie",
|
||||
@@ -1068,10 +1068,10 @@
|
||||
"order": "Sens",
|
||||
"ascending": "croissant",
|
||||
"descending": "descendant",
|
||||
"as-number": "Comme nombre",
|
||||
"as-number": "comme nombre",
|
||||
"invalid-exp": "Expression JSONata invalide dans le noeud sort: __message__",
|
||||
"too-many": "Trop de messages en attente dans le noeud sort",
|
||||
"clear": "Effacer le message en attente dans le noeud sort"
|
||||
"clear": "effacer le message en attente dans le noeud sort"
|
||||
},
|
||||
"batch": {
|
||||
"batch": "Regrouper",
|
||||
@@ -1084,21 +1084,21 @@
|
||||
"count": {
|
||||
"label": "Nombre de messages",
|
||||
"overlap": "Chevauchement",
|
||||
"count": "nombre",
|
||||
"count": "compter",
|
||||
"invalid": "Comptage et chevauchement invalides"
|
||||
},
|
||||
"interval": {
|
||||
"label": "Intervalle",
|
||||
"seconds": "secondes",
|
||||
"empty": "Envoyer un message vide lorsqu'aucun message n'arrive"
|
||||
"empty": "envoyer un message vide lorsqu'aucun message n'arrive"
|
||||
},
|
||||
"concat": {
|
||||
"topics-label": "Sujets",
|
||||
"topic": "sujet"
|
||||
},
|
||||
"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",
|
||||
"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",
|
||||
"error": {
|
||||
"invalid-count": "Compte invalide",
|
||||
"invalid-overlap": "Recouvrement invalide",
|
||||
@@ -1132,7 +1132,7 @@
|
||||
"out": "par rapport à la dernière valeur de sortie valide"
|
||||
},
|
||||
"warn": {
|
||||
"nonumber": "Aucun numéro trouvé dans la charge utile"
|
||||
"nonumber": "aucun numéro trouvé dans la charge utile"
|
||||
}
|
||||
},
|
||||
"global-config": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/nodes",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/registry",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.1.0",
|
||||
"@node-red/util": "4.0.0-dev",
|
||||
"clone": "2.1.2",
|
||||
"fs-extra": "11.1.1",
|
||||
"semver": "7.5.4",
|
||||
|
@@ -161,8 +161,7 @@ class Flow {
|
||||
for (let i = 0; i < configNodes.length; i++) {
|
||||
const node = this.flow.configs[configNodes[i]]
|
||||
if (node.type === 'global-config' && node.env) {
|
||||
const globalCreds = credentials.get(node.id)?.map || {}
|
||||
const nodeEnv = await flowUtil.evaluateEnvProperties(this, node.env, globalCreds)
|
||||
const nodeEnv = await flowUtil.evaluateEnvProperties(this, node.env, credentials.get(node.id))
|
||||
this._env = { ...this._env, ...nodeEnv }
|
||||
}
|
||||
}
|
||||
|
@@ -80,7 +80,6 @@ function mapEnvVarProperties(obj,prop,flow,config) {
|
||||
}
|
||||
|
||||
async function evaluateEnvProperties(flow, env, credentials) {
|
||||
credentials = credentials || {}
|
||||
const pendingEvaluations = []
|
||||
const evaluatedEnv = {}
|
||||
const envTypes = []
|
||||
@@ -113,7 +112,6 @@ async function evaluateEnvProperties(flow, env, credentials) {
|
||||
if (pendingEvaluations.length > 0) {
|
||||
await Promise.all(pendingEvaluations)
|
||||
}
|
||||
// Now loop over the env types and evaluate them properly
|
||||
for (let i = 0; i < envTypes.length; i++) {
|
||||
let { name, value, type } = envTypes[i]
|
||||
// If an env-var wants to lookup itself, delegate straight to the parent
|
||||
@@ -124,17 +122,7 @@ async function evaluateEnvProperties(flow, env, credentials) {
|
||||
if (evaluatedEnv.hasOwnProperty(value)) {
|
||||
value = evaluatedEnv[value]
|
||||
} else {
|
||||
value = redUtil.evaluateNodeProperty(value, type, {_flow: {
|
||||
// Provide a hook so when it tries to look up a flow setting,
|
||||
// we can insert the just-evaluated value which hasn't yet
|
||||
// been set on the flow object - otherwise delegate up to the flow
|
||||
getSetting: function(name) {
|
||||
if (evaluatedEnv.hasOwnProperty(name)){
|
||||
return evaluatedEnv[name]
|
||||
}
|
||||
return flow.getSetting(name)
|
||||
}
|
||||
}}, null, null);
|
||||
value = redUtil.evaluateNodeProperty(value, type, {_flow: flow}, null, null);
|
||||
}
|
||||
evaluatedEnv[name] = value
|
||||
}
|
||||
|
@@ -42,7 +42,6 @@ function Node(n) {
|
||||
this._closeCallbacks = [];
|
||||
this._inputCallback = null;
|
||||
this._inputCallbacks = null;
|
||||
this._expectedDoneCount = 0;
|
||||
|
||||
if (n.name) {
|
||||
this.name = n.name;
|
||||
@@ -160,9 +159,6 @@ Node.prototype.on = function(event, callback) {
|
||||
if (event == "close") {
|
||||
this._closeCallbacks.push(callback);
|
||||
} else if (event === "input") {
|
||||
if (callback.length === 3) {
|
||||
this._expectedDoneCount++
|
||||
}
|
||||
if (this._inputCallback) {
|
||||
this._inputCallbacks = [this._inputCallback, callback];
|
||||
this._inputCallback = null;
|
||||
@@ -222,17 +218,19 @@ Node.prototype._emitInput = function(arg) {
|
||||
} else if (node._inputCallbacks) {
|
||||
// Multiple callbacks registered. Call each one, tracking eventual completion
|
||||
var c = node._inputCallbacks.length;
|
||||
let doneCount = 0
|
||||
for (var i=0;i<c;i++) {
|
||||
var cb = node._inputCallbacks[i];
|
||||
if (cb.length === 2) {
|
||||
c++;
|
||||
}
|
||||
try {
|
||||
cb.call(
|
||||
node,
|
||||
arg,
|
||||
function() { node.send.apply(node,arguments) },
|
||||
function(err) {
|
||||
doneCount++;
|
||||
if (doneCount === node._expectedDoneCount) {
|
||||
c--;
|
||||
if (c === 0) {
|
||||
node._complete(arg,err);
|
||||
}
|
||||
}
|
||||
@@ -259,9 +257,6 @@ Node.prototype._removeListener = Node.prototype.removeListener;
|
||||
Node.prototype.removeListener = function(name, listener) {
|
||||
var index;
|
||||
if (name === "input") {
|
||||
if (listener.length === 3) {
|
||||
this._expectedDoneCount--
|
||||
}
|
||||
if (this._inputCallback && this._inputCallback === listener) {
|
||||
// Removing the only callback
|
||||
this._inputCallback = null;
|
||||
|
@@ -48,7 +48,7 @@
|
||||
"port-in-use": "Erreur : port utilisé",
|
||||
"uncaught-exception": "Exception non reconnue :",
|
||||
"admin-ui-disabled": "Interface d'administration désactivée",
|
||||
"now-running": "Le serveur est disponible à l'adresse __listenpath__",
|
||||
"now-running": "Le serveur tourne maintenant sur __listenpath__",
|
||||
"failed-to-start": "Échec lors du démarrage du serveur :",
|
||||
"headless-mode": "Fonctionne en mode sans interface graphique (headless)",
|
||||
"httpadminauth-deprecated": "L'utilisation de httpAdminAuth est DÉCONSEILLÉE. Utiliser adminAuth à la place",
|
||||
@@ -100,7 +100,7 @@
|
||||
"error": "Erreur lors du chargement des identifiants : __message__",
|
||||
"error-saving": "Erreur lors de l'enregistrement des identifiants : __message__",
|
||||
"not-registered": "Le type d'identifiant '__type__' n'a pas été enregistré",
|
||||
"system-key-warning": "\n\n--------------------------------------------------------------------------------------------------------\nVotre fichier contenant les identifiants de flux est chiffré à l'aide d'une clé générée par le système.\n\nSi la clé générée par le système est perdue pour une raison quelconque, votre fichier contenant\nles identifiants ne sera pas récupérable, vous devrez le supprimer et ressaisir vos identifiants.\n\nVous pouvez définir votre propre clé en utilisant l'option 'credentialSecret' dans\nvotre fichier de paramètres. Node-RED rechiffrera alors votre fichier contenant les identifiants\nà l'aide de la clé que vous avez choisie la prochaine fois que vous déploierez une modification.\n--------------------------------------------------------------------------------------------------------\n",
|
||||
"system-key-warning": "\n\n---------------------------------------------------------------------\nVotre fichier contenant les identifiants de flux est chiffré à l'aide d'une clé générée par le système.\n\nSi la clé générée par le système est perdue pour une raison quelconque, votre fichier contenant\nles identifiants ne sera pas récupérable, vous devrez le supprimer et ressaisir vos identifiants.\n\nVous pouvez définir votre propre clé en utilisant l'option 'credentialSecret' dans\nvotre fichier de paramètres. Node-RED rechiffrera alors votre fichier contenant les identifiants\nà l'aide de la clé que vous avez choisie la prochaine fois que vous déploierez une modification.\n---------------------------------------------------------------------\n",
|
||||
"unencrypted": "Utilisation d'identifiants non chiffrés",
|
||||
"encryptedNotFound": "Identifiants chiffrés introuvables"
|
||||
},
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/runtime",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/registry": "3.1.0",
|
||||
"@node-red/util": "3.1.0",
|
||||
"@node-red/registry": "4.0.0-dev",
|
||||
"@node-red/util": "4.0.0-dev",
|
||||
"async-mutex": "0.4.0",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.18.2",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/util",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
10
packages/node_modules/node-red/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.1.0",
|
||||
"version": "4.0.0-dev",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "https://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,10 +31,10 @@
|
||||
"flow"
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/editor-api": "3.1.0",
|
||||
"@node-red/runtime": "3.1.0",
|
||||
"@node-red/util": "3.1.0",
|
||||
"@node-red/nodes": "3.1.0",
|
||||
"@node-red/editor-api": "4.0.0-dev",
|
||||
"@node-red/runtime": "4.0.0-dev",
|
||||
"@node-red/util": "4.0.0-dev",
|
||||
"@node-red/nodes": "4.0.0-dev",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.18.2",
|
||||
|
@@ -1718,9 +1718,13 @@ describe('function node', function() {
|
||||
describe("init function", function() {
|
||||
|
||||
it('should delay handling messages until init completes', function(done) {
|
||||
const timeoutMS = 200;
|
||||
// Since helper.load uses process.nextTick timers might occasionally finish
|
||||
// a couple of milliseconds too early, so give some leeway to the check.
|
||||
const timeoutCheckMargin = 5;
|
||||
var flow = [{id:"n1",type:"function",wires:[["n2"]],initialize: `
|
||||
return new Promise((resolve,reject) => {
|
||||
setTimeout(resolve,200)
|
||||
setTimeout(resolve, ${timeoutMS});
|
||||
})`,
|
||||
func:"return msg;"
|
||||
},
|
||||
@@ -1733,9 +1737,10 @@ describe('function node', function() {
|
||||
msg.delta = Date.now() - msg.payload;
|
||||
receivedMsgs.push(msg)
|
||||
if (receivedMsgs.length === 5) {
|
||||
var errors = receivedMsgs.filter(msg => msg.delta < 200)
|
||||
let deltas = receivedMsgs.map(msg => msg.delta);
|
||||
var errors = deltas.filter(delta => delta < (timeoutMS - timeoutCheckMargin))
|
||||
if (errors.length > 0) {
|
||||
done(new Error(`Message received before init completed - was ${msg.delta} expected >300`))
|
||||
done(new Error(`Message received before init completed - delta values ${JSON.stringify(deltas)} expected to be > ${timeoutMS - timeoutCheckMargin}`))
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
|
@@ -2538,4 +2538,38 @@ describe('HTTP Request Node', function() {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('multipart form posts', function() {
|
||||
it('should send arrays as multiple entries', function (done) {
|
||||
const flow = [
|
||||
{
|
||||
id: 'n1', type: 'http request', wires: [['n2']], method: 'POST', ret: 'obj', url: getTestURL('/file-upload'), headers: [
|
||||
]
|
||||
},
|
||||
{ id: "n2", type: "helper" }
|
||||
];
|
||||
helper.load(httpRequestNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on('input', function(msg){
|
||||
try {
|
||||
msg.payload.body.should.have.property('foo')
|
||||
msg.payload.body.list.should.deepEqual(['a','b','c'])
|
||||
done()
|
||||
} catch (e) {
|
||||
done(e)
|
||||
}
|
||||
});
|
||||
n1.receive({
|
||||
headers: {
|
||||
'content-type': 'multipart/form-data'
|
||||
},
|
||||
payload: {
|
||||
foo: 'bar',
|
||||
list: [ 'a', 'b', 'c' ]
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
})
|
||||
});
|
||||
|
@@ -26,7 +26,6 @@ var flowUtils = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
|
||||
var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
|
||||
var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
|
||||
var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
|
||||
var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials");
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
|
||||
|
||||
@@ -62,7 +61,6 @@ describe('Flow', function() {
|
||||
this.scope = n.scope;
|
||||
var node = this;
|
||||
this.foo = n.foo;
|
||||
this.bar = n.bar;
|
||||
this.handled = 0;
|
||||
this.stopped = false;
|
||||
currentNodes[node.id] = node;
|
||||
@@ -1237,12 +1235,11 @@ describe('Flow', function() {
|
||||
})
|
||||
|
||||
describe("#env", function () {
|
||||
afterEach(() => {
|
||||
delete process.env.V0;
|
||||
delete process.env.V1;
|
||||
credentials.get.restore?.()
|
||||
})
|
||||
it("can instantiate a node with environment variable property values of group and tab", async function () {
|
||||
after(function() {
|
||||
delete process.env.V0;
|
||||
delete process.env.V1;
|
||||
})
|
||||
process.env.V0 = "gv0";
|
||||
process.env.V1 = "gv1";
|
||||
process.env.V3 = "gv3";
|
||||
@@ -1286,6 +1283,10 @@ describe('Flow', function() {
|
||||
});
|
||||
|
||||
it("can access environment variable property using $parent", async function () {
|
||||
after(function() {
|
||||
delete process.env.V0;
|
||||
delete process.env.V1;
|
||||
})
|
||||
process.env.V0 = "gv0";
|
||||
process.env.V1 = "gv1";
|
||||
var config = flowUtils.parseConfig([
|
||||
@@ -1320,6 +1321,9 @@ describe('Flow', function() {
|
||||
});
|
||||
|
||||
it("can define environment variable using JSONata", async function () {
|
||||
after(function() {
|
||||
delete process.env.V0;
|
||||
})
|
||||
var config = flowUtils.parseConfig([
|
||||
{id:"t1",type:"tab",env:[
|
||||
{"name": "V0", value: "1+2", type: "jsonata"}
|
||||
@@ -1342,6 +1346,9 @@ describe('Flow', function() {
|
||||
});
|
||||
|
||||
it("can access global environment variables defined as JSONata values", async function () {
|
||||
after(function() {
|
||||
delete process.env.V0;
|
||||
})
|
||||
var config = flowUtils.parseConfig([
|
||||
{id:"t1",type:"tab",env:[
|
||||
{"name": "V0", value: "1+2", type: "jsonata"}
|
||||
@@ -1363,21 +1370,15 @@ describe('Flow', function() {
|
||||
await flow.stop()
|
||||
});
|
||||
it("global flow can access global-config defined environment variables", async function () {
|
||||
sinon.stub(credentials,"get").callsFake(function(id) {
|
||||
if (id === 'gc') {
|
||||
return { map: { GC_CRED: 'gc_cred' }}
|
||||
}
|
||||
return null
|
||||
after(function() {
|
||||
delete process.env.V0;
|
||||
})
|
||||
|
||||
const config = flowUtils.parseConfig([
|
||||
{id:"gc", type:"global-config", env:[
|
||||
{"name": "GC0", value: "3+4", type: "jsonata"},
|
||||
{"name": "GC_CRED", type: "cred"},
|
||||
|
||||
{"name": "GC0", value: "3+4", type: "jsonata"}
|
||||
]},
|
||||
{id:"t1",type:"tab" },
|
||||
{id:"1",x:10,y:10,z:"t1",type:"test",foo:"${GC0}", bar:"${GC_CRED}", wires:[]},
|
||||
{id:"1",x:10,y:10,z:"t1",type:"test",foo:"${GC0}",wires:[]},
|
||||
]);
|
||||
// Two-arg call - makes this the global flow that handles global-config nodes
|
||||
const globalFlow = Flow.create({getSetting:v=>process.env[v]},config);
|
||||
@@ -1389,7 +1390,6 @@ describe('Flow', function() {
|
||||
|
||||
var activeNodes = flow.getActiveNodes();
|
||||
activeNodes["1"].foo.should.equal(7);
|
||||
activeNodes["1"].bar.should.equal('gc_cred');
|
||||
|
||||
await flow.stop()
|
||||
await globalFlow.stop()
|
||||
|
@@ -183,35 +183,6 @@ describe('Node', function() {
|
||||
n.receive(message);
|
||||
});
|
||||
|
||||
|
||||
it('calls parent flow handleComplete when multiple callbacks provided', function(done) {
|
||||
var n = new RedNode({id:'123',type:'abc', _flow: {
|
||||
handleComplete: function(node,msg) {
|
||||
try {
|
||||
doneCount.should.equal(2)
|
||||
msg.should.deepEqual(message);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
var message = {payload:"hello world"};
|
||||
let doneCount = 0
|
||||
n.on('input',function(msg, nodeSend, nodeDone) {
|
||||
doneCount++
|
||||
nodeDone();
|
||||
});
|
||||
// Include a callback without explicit done signature
|
||||
n.on('input',function(msg) { });
|
||||
n.on('input',function(msg, nodeSend, nodeDone) {
|
||||
doneCount++
|
||||
nodeDone();
|
||||
});
|
||||
n.receive(message);
|
||||
});
|
||||
|
||||
it('triggers onComplete hook when done callback provided', function(done) {
|
||||
var handleCompleteCalled = false;
|
||||
var hookCalled = false;
|
||||
|