mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
64 Commits
fix-regex-
...
fix-change
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e4c45ac6a | ||
|
|
f060309002 | ||
|
|
fc3d86e6ff | ||
|
|
d657817211 | ||
|
|
954649007c | ||
|
|
b0d9903fe2 | ||
|
|
6375f3c445 | ||
|
|
2328f418be | ||
|
|
22b6564847 | ||
|
|
25c8bfefe2 | ||
|
|
30f4524821 | ||
|
|
9e4c3a7200 | ||
|
|
5b7e84c1b0 | ||
|
|
e6097e4968 | ||
|
|
0f2829097b | ||
|
|
e2a9f940e2 | ||
|
|
3eb2b2ac5d | ||
|
|
ce7b0a3b5e | ||
|
|
7bd7c99dd4 | ||
|
|
b0d12c4125 | ||
|
|
745607b5bc | ||
|
|
cc5a770b16 | ||
|
|
fbde0091de | ||
|
|
a533943a40 | ||
|
|
e11f17672c | ||
|
|
c038c99f9d | ||
|
|
5f159c1fbd | ||
|
|
cd8ca8981b | ||
|
|
a5d7f7acce | ||
|
|
a032c2e326 | ||
|
|
9d770ed436 | ||
|
|
ae753940f3 | ||
|
|
d0d22c333c | ||
|
|
266ba17ebb | ||
|
|
0d0d5bafb0 | ||
|
|
58b951e134 | ||
|
|
30956b5441 | ||
|
|
9540cfe749 | ||
|
|
31b17faa2a | ||
|
|
5c6b8e9e50 | ||
|
|
5a36e8fb11 | ||
|
|
7d4c857a43 | ||
|
|
598bcf675f | ||
|
|
5365786386 | ||
|
|
c9b0a7c2dd | ||
|
|
371d8042d6 | ||
|
|
be343cb21e | ||
|
|
e9eabd6881 | ||
|
|
abccdc7f21 | ||
|
|
4ae914f729 | ||
|
|
86ac955b79 | ||
|
|
9734691cac | ||
|
|
d94f3a477d | ||
|
|
d53cd209f7 | ||
|
|
65cacb39d2 | ||
|
|
b008a6a2aa | ||
|
|
5c29feec63 | ||
|
|
14a3366850 | ||
|
|
5ea0c6fca1 | ||
|
|
f454c29b8c | ||
|
|
fe5132be1d | ||
|
|
b50ba3e0e4 | ||
|
|
4fb40f9077 | ||
|
|
660a2e0ed6 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,3 +1,23 @@
|
||||
#### 3.0.2: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
- Fix workspace chart bottom property (#3812) @bonanitech
|
||||
- Update german translation (#3802) @Dennis14e
|
||||
- Support color reset to the default in subflow and group (#3801) @kazuhitoyokoi
|
||||
- Allow generateNodeNames to handle names containing regex control chars (#3817) @knolleary
|
||||
- Hide scrollbars until they're needed (#3808) @bonanitech
|
||||
- Include junctions/groups when exporting subflows plus related fixes (#3816) @knolleary
|
||||
- remove console.log (#3820) @Steve-Mcl
|
||||
|
||||
Runtime
|
||||
|
||||
- Register subflow module instance node with parent flow (#3818) @knolleary
|
||||
|
||||
Nodes
|
||||
|
||||
- HTTP Request: Allow HTTP Headers not in spec (#3776) @hardillb
|
||||
|
||||
#### 3.0.1: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
12
package.json
12
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -40,7 +40,7 @@
|
||||
"cookie-parser": "1.4.6",
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.0.1",
|
||||
"denque": "2.1.0",
|
||||
"express": "4.18.1",
|
||||
"express-session": "1.17.3",
|
||||
"form-data": "4.0.0",
|
||||
@@ -49,7 +49,7 @@
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "1.0.0",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
"i18next": "21.8.14",
|
||||
"i18next": "21.8.16",
|
||||
"iconv-lite": "0.6.3",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "4.1.0",
|
||||
@@ -76,7 +76,7 @@
|
||||
"semver": "7.3.7",
|
||||
"tar": "6.1.11",
|
||||
"tough-cookie": "4.0.0",
|
||||
"uglify-js": "3.16.2",
|
||||
"uglify-js": "3.16.3",
|
||||
"uuid": "8.3.2",
|
||||
"ws": "7.5.6",
|
||||
"xml2js": "0.4.23"
|
||||
@@ -85,7 +85,7 @@
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.3.9",
|
||||
"dompurify": "2.3.10",
|
||||
"grunt": "1.5.3",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.4.3",
|
||||
@@ -114,7 +114,7 @@
|
||||
"node-red-node-test-helper": "^0.3.0",
|
||||
"nodemon": "2.0.19",
|
||||
"proxy": "^1.0.2",
|
||||
"sass": "1.53.0",
|
||||
"sass": "1.54.2",
|
||||
"should": "13.2.3",
|
||||
"sinon": "11.1.2",
|
||||
"stoppable": "^1.1.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.0.1",
|
||||
"@node-red/editor-client": "3.0.1",
|
||||
"@node-red/util": "3.0.2",
|
||||
"@node-red/editor-client": "3.0.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.20.0",
|
||||
"clone": "2.1.2",
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
"search": "Flows durchsuchen",
|
||||
"searchInput": "Flows durchsuchen",
|
||||
"subflows": "Subflow",
|
||||
"createSubflow": "Subflow",
|
||||
"createSubflow": "Hinzufügen",
|
||||
"selectionToSubflow": "Auswahl in Subflow umwandeln",
|
||||
"flows": "Flow",
|
||||
"add": "Hinzufügen",
|
||||
@@ -152,7 +152,8 @@
|
||||
"zoom-in": "Vergrößern",
|
||||
"search-flows": "Flows durchsuchen",
|
||||
"search-prev": "Vorherige",
|
||||
"search-next": "Nächste"
|
||||
"search-next": "Nächste",
|
||||
"search-counter": "\"__term__\" __result__ von __count__"
|
||||
},
|
||||
"user": {
|
||||
"loggedInAs": "Angemeldet als __name__",
|
||||
@@ -168,7 +169,11 @@
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"warning": "<strong>Warnung:</strong> __message__",
|
||||
"state": {
|
||||
"flowsStopped": "Flows gestoppt",
|
||||
"flowsStarted": "Flows gestartet"
|
||||
},
|
||||
"warning": "<strong>Warnung</strong>: __message__",
|
||||
"warnings": {
|
||||
"undeployedChanges": "Node hat nicht übernommene (deploy) Änderungen",
|
||||
"nodeActionDisabled": "Node-Aktionen deaktiviert",
|
||||
@@ -177,15 +182,15 @@
|
||||
"missing-modules": "<p>Flows angehalten aufgrund fehlender Module</p>",
|
||||
"safe-mode": "<p>Flows sind im abgesicherten Modus gestoppt.</p><p>Flows können bearbeitet und übernommen (deploy) werden, um sie neu zu starten.</p>",
|
||||
"restartRequired": "Node-RED muss neu gestartet werden, damit die Module nach Upgrade aktiviert werden",
|
||||
"credentials_load_failed": "<p>Flows gestoppt, da die Berechtigungen nicht entschlüsselt werden konnten.</p><p>Die Datei mit dem Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>",
|
||||
"credentials_load_failed_reset": "<p>Die Berechtigungen konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Berechtigungen wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Berechtigungen werden gelöscht.</p>",
|
||||
"credentials_load_failed": "<p>Flows gestoppt, da die Credentials nicht entschlüsselt werden konnten.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>",
|
||||
"credentials_load_failed_reset": "<p>Die Credentials konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Credentials wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Credentials werden gelöscht.</p>",
|
||||
"missing_flow_file": "<p>Die Flow-Datei des Projekts wurde nicht gefunden.</p><p>Das Projekt ist nicht mit einer Flow-Datei konfiguriert.</p>",
|
||||
"missing_package_file": "<p>Die Paket-Datei des Projekts wurde nicht gefunden.</p><p>In dem Projekt fehlt die 'package.json'-Datei.</p>",
|
||||
"project_empty": "<p>Das Projekt ist leer.</p><p>Soll ein Standardsatz an Projektdateien erstellen werden?<br/>Andernfalls müssen die Dateien manuell außerhalb des Editors dem Projekt hinzugefügt werden.</p>",
|
||||
"project_not_found": "<p>Das Projekt '__project__' wurde nicht gefunden.</p>",
|
||||
"git_merge_conflict": "<p>Der automatische Merge der Änderungen ist fehlgeschlagen.</p><p>Die Merge-Konflikte müssen behoben und die Ergebnisse ins Repository übertragen werden (commit).</p>"
|
||||
},
|
||||
"error": "<strong>Fehler:</strong> __message__",
|
||||
"error": "<strong>Fehler</strong>: __message__",
|
||||
"errors": {
|
||||
"lostConnection": "Verbindung zum Server verloren. Verbindung wird erneut hergestellt ...",
|
||||
"lostConnectionReconnect": "Verbindung zum Server verloren. Wiederherstellung der Verbindung in __time__s.",
|
||||
@@ -203,7 +208,7 @@
|
||||
"pull": "Projekt '__project__' erneut geladen",
|
||||
"revert": "Änderungen im Projekt '__project__' rückgängig gemacht",
|
||||
"merge-complete": "Git-Merge abgeschlossen",
|
||||
"setupCredentials": "Berechtigungen einrichten",
|
||||
"setupCredentials": "Credentials einrichten",
|
||||
"setupProjectFiles": "Projektdateien einrichten",
|
||||
"no": "Nein, Danke",
|
||||
"createDefault": "Standardprojektdateien erstellen",
|
||||
@@ -211,7 +216,7 @@
|
||||
},
|
||||
"label": {
|
||||
"manage-project-dep": "Projektabhängigkeiten verwalten",
|
||||
"setup-cred": "Berechtigungen einrichten",
|
||||
"setup-cred": "Credentials einrichten",
|
||||
"setup-project": "Projektdateien einrichten",
|
||||
"create-default-package": "Standardpaketdatei erstellen",
|
||||
"no-thanks": "Nein, Danke",
|
||||
@@ -295,6 +300,10 @@
|
||||
"modifiedFlowsDesc": "Übernimmt nur Flows, die geänderte Nodes enthalten",
|
||||
"modifiedNodes": "Geänderte Nodes",
|
||||
"modifiedNodesDesc": "Übernimmt nur Nodes, die sich geändert haben",
|
||||
"startFlows": "Start",
|
||||
"startFlowsDesc": "Flows starten",
|
||||
"stopFlows": "Stop",
|
||||
"stopFlowsDesc": "Flows stoppen",
|
||||
"restartFlows": "Flows neustarten",
|
||||
"restartFlowsDesc": "Startet die aktuell übernommenen Flows (ohne vorheriges Deploy)",
|
||||
"successfulDeploy": "Erfolgreich übernommen (deploy)",
|
||||
@@ -376,7 +385,7 @@
|
||||
"confirmDelete": "Sind Sie sicher mit dem Löschen dieses Subflows?",
|
||||
"info": "Beschreibung",
|
||||
"category": "Kategorie",
|
||||
"module": "Module",
|
||||
"module": "Modul",
|
||||
"license": "Lizenz",
|
||||
"licenseNone": "Keine",
|
||||
"licenseOther": "Andere",
|
||||
@@ -434,7 +443,7 @@
|
||||
"icon": "Icon",
|
||||
"inputType": "Eingangstyp",
|
||||
"selectType": "Wähle Typen ...",
|
||||
"loadCredentials": "Lade Node-Berechtigungen",
|
||||
"loadCredentials": "Lade Node-Credentials",
|
||||
"inputs": {
|
||||
"input": "Eingang",
|
||||
"select": "Auswahl",
|
||||
@@ -450,7 +459,7 @@
|
||||
"json": "JSON",
|
||||
"bin": "buffer",
|
||||
"env": "Umgebungsvariable",
|
||||
"cred": "Berechtigung"
|
||||
"cred": "Credentials"
|
||||
},
|
||||
"menu": {
|
||||
"input": "Eingang",
|
||||
@@ -470,7 +479,7 @@
|
||||
"errors": {
|
||||
"scopeChange": "Wenn Sie den Geltungsbereich (scope) ändern, wird er für Nodes in anderen Flows nicht verfügbar sein",
|
||||
"invalidProperties": "Ungültige Eigenschaften:",
|
||||
"credentialLoadFailed": "Laden der Node-Berechtigungen fehlgeschlagen"
|
||||
"credentialLoadFailed": "Laden der Node-Credentials fehlgeschlagen"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
@@ -683,7 +692,8 @@
|
||||
"showHelp": "Hilfe zeigen",
|
||||
"showInOutline": "Zeige im Editor",
|
||||
"showTopics": "Zeige Hilfethemen",
|
||||
"noHelp": "Kein Hilfethema ausgewählt"
|
||||
"noHelp": "Kein Hilfethema ausgewählt",
|
||||
"changeLog": "Änderungsprotokoll"
|
||||
},
|
||||
"config": {
|
||||
"name": "Konfigurations-Node",
|
||||
@@ -737,7 +747,7 @@
|
||||
"addToProject": "Zu Projekt hinzufügen",
|
||||
"files": "Dateien",
|
||||
"flow": "Flow",
|
||||
"credentials": "Berechtigungen",
|
||||
"credentials": "Credentials",
|
||||
"package": "Paket",
|
||||
"packageCreate": "Datei wird erstellt beim Speichern der Änderungen",
|
||||
"fileNotExist": "Datei existiert nicht",
|
||||
@@ -750,7 +760,7 @@
|
||||
"changeTheEncryptionKey": "Schlüssel ändern",
|
||||
"currentKey": "Aktueller Schlüssel",
|
||||
"newKey": "Neuer Schlüssel",
|
||||
"credentialsAlert": "Dadurch werden alle vorhandenen Berechtigungen gelöscht",
|
||||
"credentialsAlert": "Dadurch werden alle vorhandenen Credentials gelöscht",
|
||||
"versionControl": "Versionsverwaltung (Git)",
|
||||
"branches": "Branches",
|
||||
"noBranches": "Keine Branches",
|
||||
@@ -886,7 +896,7 @@
|
||||
"date": "timestamp",
|
||||
"jsonata": "JSONata",
|
||||
"env": "Umgebungsvariable",
|
||||
"cred": "Berechtigung"
|
||||
"cred": "Credentials"
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
@@ -1026,7 +1036,7 @@
|
||||
"passphrase": "Passphrase",
|
||||
"ssh-key-desc": "Bevor Sie ein Repository über SSH lokal klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zugreifen zu können",
|
||||
"ssh-key-add": "SSH-Schlüssel hinzufügen",
|
||||
"credential-key": "Schlüssel für Berechtigungen",
|
||||
"credential-key": "Schlüssel für Credentials",
|
||||
"cant-get-ssh-key": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden",
|
||||
"already-exists2": "bereits vorhanden",
|
||||
"git-error": "Git-Fehler",
|
||||
@@ -1038,27 +1048,27 @@
|
||||
"create": "Erstellen Sie Ihre Projektdateien",
|
||||
"desc0": "Ein Projekt enthält Ihre Flow-Dateien, eine README-Datei und die 'package.json'-Datei.",
|
||||
"desc1": "Es kann alle anderen Dateien enthalten, die im Git-Repository verwaltet werden sollen.",
|
||||
"desc2": "Ihre vorhandenen Flow- und Berechtigungs-Dateien werden in das Projekt kopiert.",
|
||||
"desc2": "Ihre vorhandenen Flow- und Credential-Dateien werden in das Projekt kopiert.",
|
||||
"flow-file": "Flow-Datei",
|
||||
"credentials-file": "Datei mit Berechtigungen"
|
||||
"credentials-file": "Datei mit Credentials"
|
||||
},
|
||||
"encryption-config": {
|
||||
"setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Berechtigungen",
|
||||
"desc0": "Die Datei mit den Flow-Berechtigungen kann verschlüsselt werden, um ihren Inhalt zu schützen.",
|
||||
"desc1": "Wenn Sie diese Berechtigungen in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.",
|
||||
"desc2": "Die Datei mit den Flow-Berechtigungen ist derzeit nicht verschlüsselt.",
|
||||
"setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Credentials",
|
||||
"desc0": "Die Datei mit den Flow-Credentials kann verschlüsselt werden, um ihren Inhalt zu schützen.",
|
||||
"desc1": "Wenn Sie diese Credentials in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.",
|
||||
"desc2": "Die Datei mit den Flow-Credentials ist derzeit nicht verschlüsselt.",
|
||||
"desc3": "D.h. ihr Inhalt (z.B. Passwörter und Zugriffs-Tokens) kann von jedem mit Zugriff auf die Datei gelesen werden.",
|
||||
"desc4": "Wenn Sie diese Berechtigungen in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.",
|
||||
"desc5": "Ihre Datei mit den Flow-Berechtigungen wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.",
|
||||
"desc6": "Die Datei mit den Flow-Berechtigungen wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.",
|
||||
"desc4": "Wenn Sie diese Credentials in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.",
|
||||
"desc5": "Ihre Datei mit den Flow-Credentials wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.",
|
||||
"desc6": "Die Datei mit den Flow-Credentials wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.",
|
||||
"desc7": "Der Schlüssel wird separat von den Projektdateien gespeichert. Sie müssen den Schlüssel angeben, damit dieses Projekt auch in einem anderen Node-RED-System verwendet werden kann.",
|
||||
"credentials": "Berechtigung",
|
||||
"credentials": "Credentials",
|
||||
"enable": "Verschlüsselung aktivieren",
|
||||
"disable": "Verschlüsselung deaktivieren",
|
||||
"disabled": "deaktiviert",
|
||||
"copy": "Vorhandenen Schlüssel ersetzen",
|
||||
"use-custom": "Eigenen Schlüssel verwenden",
|
||||
"desc8": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden",
|
||||
"desc8": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden",
|
||||
"create-project-files": "Projektdateien erstellen",
|
||||
"create-project": "Projekt erstellen",
|
||||
"already-exists": "bereits vorhanden",
|
||||
@@ -1083,12 +1093,12 @@
|
||||
"desc": "Beschreibung",
|
||||
"opt": "Optional",
|
||||
"flow-file": "Flow-Datei",
|
||||
"credentials": "Berechtigungen",
|
||||
"credentials": "Credentials",
|
||||
"enable-encryption": "Verschlüsselung aktivieren",
|
||||
"disable-encryption": "Verschlüsselung deaktivieren",
|
||||
"encryption-key": "Schlüssel",
|
||||
"desc0": "Eine Floskel, mit der Sie Ihre Berechtigungen schützen",
|
||||
"desc1": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden",
|
||||
"desc0": "Eine Ausdruck, mit der Sie Ihre Credentials schützen",
|
||||
"desc1": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden",
|
||||
"git-url": "Git-Repository-URL",
|
||||
"protocols": "https://, ssh:// oder file://",
|
||||
"auth-failed": "Authentifizierung fehlgeschlagen",
|
||||
@@ -1098,7 +1108,7 @@
|
||||
"passphrase": "Passphrase",
|
||||
"desc2": "Bevor Sie ein Repository über SSH klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zu zugreifen",
|
||||
"add-ssh-key": "Einen SSH-Schlüssel hinzufügen",
|
||||
"credentials-encryption-key": "Schlüssel für Berechtigungen",
|
||||
"credentials-encryption-key": "Schlüssel für Credentials",
|
||||
"already-exists-2": "bereits vorhanden",
|
||||
"git-error": "Git-Fehler",
|
||||
"con-failed": "Verbindung fehlgeschlagen",
|
||||
@@ -1156,7 +1166,8 @@
|
||||
"tourGuide": {
|
||||
"takeATour": "Tour starten",
|
||||
"start": "Start",
|
||||
"next": "Nächste"
|
||||
"next": "Nächste",
|
||||
"welcomeTours": "Welcome Tours"
|
||||
},
|
||||
"diagnostics": {
|
||||
"title": "System-Informationen"
|
||||
|
||||
@@ -936,6 +936,9 @@
|
||||
"invalid-expr": "Invalid JSONata expression:\n __message__",
|
||||
"invalid-msg": "Invalid example JSON message:\n __message__",
|
||||
"context-unsupported": "Cannot test context functions\n $flowContext or $globalContext",
|
||||
"env-unsupported": "Cannot test $env function",
|
||||
"moment-unsupported": "Cannot test $moment function",
|
||||
"clone-unsupported": "Cannot test $clone function",
|
||||
"eval": "Error evaluating expression:\n __message__"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -935,8 +935,11 @@
|
||||
"errors": {
|
||||
"invalid-expr": "不正なJSONata式:\n __message__",
|
||||
"invalid-msg": "不正なJSONメッセージ例:\n __message__",
|
||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト機能をテストできません",
|
||||
"eval": "表現評価エラー:\n __message__"
|
||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト関数をテストできません",
|
||||
"env-unsupported": "$env関数はテストできません",
|
||||
"moment-unsupported": "$moment関数はテストできません",
|
||||
"clone-unsupported": "$clone関数はテストできません",
|
||||
"eval": "式評価エラー:\n __message__"
|
||||
}
|
||||
},
|
||||
"monaco": {
|
||||
@@ -1168,8 +1171,7 @@
|
||||
"takeATour": "ツアーを開始",
|
||||
"start": "開始",
|
||||
"next": "次へ",
|
||||
"welcomeTours": "ウェルカムツアー",
|
||||
"tours": "ツアー"
|
||||
"welcomeTours": "ウェルカムツアー"
|
||||
},
|
||||
"diagnostics": {
|
||||
"title": "システム情報"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -868,14 +868,7 @@ RED.nodes = (function() {
|
||||
var node;
|
||||
|
||||
if (allNodes.hasTab(id)) {
|
||||
removedNodes = allNodes.getNodes(id).filter(n => {
|
||||
if (n.type === 'junction') {
|
||||
removedJunctions.push(n)
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
removedNodes = allNodes.getNodes(id).slice()
|
||||
}
|
||||
for (i in configNodes) {
|
||||
if (configNodes.hasOwnProperty(i)) {
|
||||
@@ -885,6 +878,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
removedJunctions = RED.nodes.junctions(id)
|
||||
|
||||
for (i=0;i<removedNodes.length;i++) {
|
||||
var result = removeNode(removedNodes[i].id);
|
||||
@@ -1331,7 +1325,6 @@ RED.nodes = (function() {
|
||||
} else {
|
||||
nodeSet = [sf];
|
||||
}
|
||||
console.log(nodeSet);
|
||||
return createExportableNodeSet(nodeSet);
|
||||
}
|
||||
/**
|
||||
@@ -1367,6 +1360,10 @@ RED.nodes = (function() {
|
||||
exportedConfigNodes[n.id] = true;
|
||||
}
|
||||
});
|
||||
|
||||
subflowSet = subflowSet.concat(RED.nodes.junctions(subflowId))
|
||||
subflowSet = subflowSet.concat(RED.nodes.groups(subflowId))
|
||||
|
||||
var exportableSubflow = createExportableNodeSet(subflowSet, exportedIds, exportedSubflows, exportedConfigNodes);
|
||||
nns = exportableSubflow.concat(nns);
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
this.element.css("maxHeight",null);
|
||||
}
|
||||
if (this.options.height !== 'auto') {
|
||||
this.uiContainer.css("overflow-y","scroll");
|
||||
this.uiContainer.css("overflow-y","auto");
|
||||
if (!isNaN(this.options.height)) {
|
||||
this.uiHeight = this.options.height;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ RED.editor.codeEditor.monaco = (function() {
|
||||
"node-red-util": {package: "node-red", module: "util", path: "node-red/util.d.ts" },
|
||||
"node-red-func": {package: "node-red", module: "func", path: "node-red/func.d.ts" },
|
||||
}
|
||||
const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] ];
|
||||
const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] , knownModules["util"] ];
|
||||
|
||||
const modulesCache = {};
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ RED.editor.colorPicker = RED.colorPicker = (function() {
|
||||
var focusTarget = colorInput;
|
||||
colorInput.on("change", function (e) {
|
||||
var color = colorInput.val();
|
||||
if (options.defaultValue && !color.match(/^([a-z]+|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3})$/)) {
|
||||
color = options.defaultValue;
|
||||
}
|
||||
colorHiddenInput.val(color).trigger('change');
|
||||
refreshDisplay(color);
|
||||
});
|
||||
|
||||
@@ -255,6 +255,9 @@
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var usesEnv = false;
|
||||
var usesMoment = false;
|
||||
var usesClone = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
@@ -267,6 +270,18 @@
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("env", function(name) {
|
||||
usesEnv = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("moment", function(name) {
|
||||
usesMoment = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("clone", function(name) {
|
||||
usesClone = true;
|
||||
return null;
|
||||
});
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
|
||||
return;
|
||||
@@ -284,6 +299,18 @@
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesEnv) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.env-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesMoment) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.moment-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesClone) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.clone-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
|
||||
var formattedResult;
|
||||
if (result !== undefined) {
|
||||
|
||||
@@ -235,6 +235,7 @@
|
||||
RED.editor.colorPicker.create({
|
||||
id: "red-ui-editor-node-color",
|
||||
value: color,
|
||||
defaultValue: "#DDAA99",
|
||||
palette: recommendedColors,
|
||||
sortPalette: function (a, b) {return a.l - b.l;}
|
||||
}).appendTo(colorRow);
|
||||
|
||||
@@ -101,6 +101,7 @@ RED.group = (function() {
|
||||
RED.editor.colorPicker.create({
|
||||
id:"node-input-style-stroke",
|
||||
value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
|
||||
defaultValue: "#a4a4a4",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
@@ -112,6 +113,7 @@ RED.group = (function() {
|
||||
RED.editor.colorPicker.create({
|
||||
id:"node-input-style-fill",
|
||||
value: style.fill || defaultGroupStyle.fill ||"none",
|
||||
defaultValue: "none",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
@@ -129,6 +131,7 @@ RED.group = (function() {
|
||||
RED.editor.colorPicker.create({
|
||||
id:"node-input-style-color",
|
||||
value: style.color || defaultGroupStyle.color ||"#a4a4a4",
|
||||
defaultValue: "#a4a4a4",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
|
||||
@@ -175,9 +175,19 @@ RED.palette = (function() {
|
||||
$('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent)
|
||||
}
|
||||
|
||||
var safeType = type.replace(/'/g,"\\'");
|
||||
const safeType = type.replace(/'/g,"\\'");
|
||||
const wrapStr = function (str) {
|
||||
if(str.indexOf(' ') >= 0) {
|
||||
return '"' + str + '"'
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
$('<button type="button" onclick="RED.search.show(\'type:'+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>').appendTo(popOverContent)
|
||||
$('<button type="button"; return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>')
|
||||
.appendTo(popOverContent)
|
||||
.on('click', function() {
|
||||
RED.search.show('type:' + wrapStr(safeType))
|
||||
})
|
||||
$('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
|
||||
|
||||
$('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent);
|
||||
|
||||
@@ -545,7 +545,7 @@ RED.projects = (function() {
|
||||
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
|
||||
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.clone-project.ssh-key-desc")+'</div>').appendTo(sshwarningRow);
|
||||
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
e.preventDefault();
|
||||
dialog.dialog( "close" );
|
||||
RED.userSettings.show('gitconfig');
|
||||
@@ -1171,11 +1171,11 @@ RED.projects = (function() {
|
||||
|
||||
row = $('<div class="form-row button-group"></div>').appendTo(container);
|
||||
|
||||
var openProject = $('<button data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
|
||||
var createAsEmpty = $('<button data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
|
||||
// var createAsCopy = $('<button data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
|
||||
var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
|
||||
// var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
|
||||
var openProject = $('<button type="button" data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
|
||||
var createAsEmpty = $('<button type="button" data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
|
||||
// var createAsCopy = $('<button type="button" data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
|
||||
var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
|
||||
// var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
|
||||
row.find(".red-ui-projects-dialog-screen-create-type").on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
container.find(".red-ui-projects-dialog-screen-create-type").removeClass('selected');
|
||||
@@ -1271,7 +1271,7 @@ RED.projects = (function() {
|
||||
var credentialsLeftBox = $('<div class="red-ui-projects-dialog-credentials-box-left">').appendTo(credentialsBox);
|
||||
|
||||
var credentialsEnabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-enabled"></div>').appendTo(credentialsLeftBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled"> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled" checked> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
|
||||
var credentialsDisabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-disabled disabled"></div>').appendTo(credentialsLeftBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="disabled"> <i class="fa fa-unlock"></i> <span>'+RED._("projects.encryption-config.disable")+'</span></label>').appendTo(credentialsDisabledBox);
|
||||
|
||||
@@ -1397,7 +1397,7 @@ RED.projects = (function() {
|
||||
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
|
||||
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.create.desc2")+'</div>').appendTo(sshwarningRow);
|
||||
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
e.preventDefault();
|
||||
$('#red-ui-projects-dialog-cancel').trigger("click");
|
||||
RED.userSettings.show('gitconfig');
|
||||
@@ -1631,14 +1631,14 @@ RED.projects = (function() {
|
||||
function deleteProject(row,name,done) {
|
||||
var cover = $('<div class="red-ui-projects-dialog-project-list-entry-delete-confirm"></div>').on("click", function(evt) { evt.stopPropagation(); }).appendTo(row);
|
||||
$('<span>').text(RED._("projects.delete.confirm")).appendTo(cover);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
|
||||
.appendTo(cover)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
cover.remove();
|
||||
done(true);
|
||||
});
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
|
||||
.appendTo(cover)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
@@ -1822,7 +1822,7 @@ RED.projects = (function() {
|
||||
header.addClass("selectable");
|
||||
|
||||
var tools = $('<div class="red-ui-projects-dialog-project-list-entry-tools"></div>').appendTo(header);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
|
||||
.appendTo(tools)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -106,38 +106,51 @@ RED.search = (function() {
|
||||
return val;
|
||||
}
|
||||
|
||||
function search(val) {
|
||||
var results = [];
|
||||
var typeFilter;
|
||||
var m = /(?:^| )type:([^ ]+)/.exec(val);
|
||||
if (m) {
|
||||
val = val.replace(/(?:^| )type:[^ ]+/,"");
|
||||
typeFilter = m[1];
|
||||
function extractType(val, flags) {
|
||||
// extracts: type:XYZ & type:"X Y Z"
|
||||
const regEx = /(?:type):\s*(?:"([^"]+)"|([^" ]+))/;
|
||||
let m
|
||||
while ((m = regEx.exec(val)) !== null) {
|
||||
// avoid infinite loops with zero-width matches
|
||||
if (m.index === regEx.lastIndex) {
|
||||
regEx.lastIndex++;
|
||||
}
|
||||
val = val.replace(m[0]," ").trim()
|
||||
const flag = m[2] || m[1] // quoted entries in capture group 1, unquoted in capture group 2
|
||||
flags.type = flags.type || [];
|
||||
flags.type.push(flag);
|
||||
}
|
||||
var flags = {};
|
||||
return val;
|
||||
}
|
||||
|
||||
function search(val) {
|
||||
const results = [];
|
||||
const flags = {};
|
||||
val = extractFlag(val,"invalid",flags);
|
||||
val = extractFlag(val,"unused",flags);
|
||||
val = extractFlag(val,"config",flags);
|
||||
val = extractFlag(val,"subflow",flags);
|
||||
val = extractFlag(val,"hidden",flags);
|
||||
val = extractFlag(val,"modified",flags);
|
||||
val = extractValue(val,"flow",flags);// flow:active or flow:<flow-id>
|
||||
val = extractValue(val,"flow",flags);// flow:current or flow:<flow-id>
|
||||
val = extractValue(val,"uses",flags);// uses:<node-id>
|
||||
val = extractType(val,flags);// type:<node-type>
|
||||
val = val.trim();
|
||||
var hasFlags = Object.keys(flags).length > 0;
|
||||
const hasFlags = Object.keys(flags).length > 0;
|
||||
const hasTypeFilter = flags.type && flags.type.length > 0
|
||||
if (flags.flow && flags.flow.indexOf("current") >= 0) {
|
||||
let idx = flags.flow.indexOf("current");
|
||||
flags.flow[idx] = RED.workspaces.active();//convert active to flow ID
|
||||
flags.flow[idx] = RED.workspaces.active();//convert 'current' to active flow ID
|
||||
}
|
||||
if (flags.flow && flags.flow.length) {
|
||||
flags.flow = [ ...new Set(flags.flow) ]; //deduplicate
|
||||
}
|
||||
if (val.length > 0 || typeFilter || hasFlags) {
|
||||
if (val.length > 0 || hasFlags) {
|
||||
val = val.toLowerCase();
|
||||
var i;
|
||||
var j;
|
||||
var list = [];
|
||||
var nodes = {};
|
||||
let i;
|
||||
let j;
|
||||
let list = [];
|
||||
const nodes = {};
|
||||
let keys = [];
|
||||
if (flags.uses) {
|
||||
keys = flags.uses;
|
||||
@@ -145,10 +158,10 @@ RED.search = (function() {
|
||||
keys = Object.keys(index);
|
||||
}
|
||||
for (i=0;i<keys.length;i++) {
|
||||
var key = keys[i];
|
||||
var kpos = keys[i].indexOf(val);
|
||||
if (kpos > -1) {
|
||||
var ids = Object.keys(index[key]||{});
|
||||
const key = keys[i];
|
||||
const kpos = val ? keys[i].indexOf(val) : -1;
|
||||
if (kpos > -1 || (val === "" && hasFlags)) {
|
||||
const ids = Object.keys(index[key]||{});
|
||||
for (j=0;j<ids.length;j++) {
|
||||
var node = index[key][ids[j]];
|
||||
var isConfigNode = node.node._def.category === "config" && node.node.type !== 'group';
|
||||
@@ -156,7 +169,7 @@ RED.search = (function() {
|
||||
continue;
|
||||
}
|
||||
if (flags.hasOwnProperty("invalid")) {
|
||||
var nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid;
|
||||
const nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid;
|
||||
if (flags.invalid === nodeIsValid) {
|
||||
continue;
|
||||
}
|
||||
@@ -186,7 +199,7 @@ RED.search = (function() {
|
||||
}
|
||||
}
|
||||
if (flags.hasOwnProperty("unused")) {
|
||||
var isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
|
||||
const isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
|
||||
(isConfigNode && node.node.users.length === 0 && node.node._def.hasUsers !== false)
|
||||
if (flags.unused !== isUnused) {
|
||||
continue;
|
||||
@@ -197,12 +210,16 @@ RED.search = (function() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!typeFilter || node.node.type === typeFilter) {
|
||||
nodes[node.node.id] = nodes[node.node.id] = {
|
||||
let typeIndex = -1
|
||||
if(hasTypeFilter) {
|
||||
typeIndex = flags.type.indexOf(node.node.type)
|
||||
}
|
||||
if (!hasTypeFilter || typeIndex > -1) {
|
||||
nodes[node.node.id] = nodes[node.node.id] || {
|
||||
node: node.node,
|
||||
label: node.label
|
||||
};
|
||||
nodes[node.node.id].index = Math.min(nodes[node.node.id].index||Infinity,kpos);
|
||||
nodes[node.node.id].index = Math.min(nodes[node.node.id].index || Infinity, typeIndex > -1 ? typeIndex : kpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,6 +506,13 @@ RED.subflow = (function() {
|
||||
RED.nodes.groups(id).forEach(function(n) {
|
||||
removedGroups.push(n);
|
||||
})
|
||||
|
||||
var removedJunctions = RED.nodes.junctions(id)
|
||||
for (var i=0;i<removedJunctions.length;i++) {
|
||||
var removedEntities = RED.nodes.removeJunction(removedJunctions[i])
|
||||
removedLinks = removedLinks.concat(removedEntities.links)
|
||||
}
|
||||
|
||||
var removedConfigNodes = [];
|
||||
for (var i=0;i<removedNodes.length;i++) {
|
||||
var removedEntities = RED.nodes.remove(removedNodes[i].id);
|
||||
@@ -536,6 +543,7 @@ RED.subflow = (function() {
|
||||
nodes:removedNodes,
|
||||
links:removedLinks,
|
||||
groups: removedGroups,
|
||||
junctions: removedJunctions,
|
||||
subflows: [activeSubflow]
|
||||
}
|
||||
}
|
||||
@@ -932,7 +940,6 @@ RED.subflow = (function() {
|
||||
|
||||
|
||||
function buildEnvUIRow(row, tenv, ui, node) {
|
||||
console.log(tenv, ui)
|
||||
ui.label = ui.label||{};
|
||||
if ((tenv.type === "cred" || (tenv.parent && tenv.parent.type === "cred")) && !ui.type) {
|
||||
ui.type = "cred";
|
||||
|
||||
@@ -50,7 +50,7 @@ RED.sidebar.help = (function() {
|
||||
|
||||
tocPanel = $("<div>", {class: "red-ui-sidebar-help-toc"}).appendTo(stackContainer);
|
||||
var helpPanel = $("<div>").css({
|
||||
"overflow-y": "scroll"
|
||||
"overflow-y": "auto"
|
||||
}).appendTo(stackContainer);
|
||||
|
||||
panels = RED.panels.create({
|
||||
|
||||
@@ -98,7 +98,7 @@ RED.sidebar.info = (function() {
|
||||
|
||||
propertiesPanelContent = $("<div>").css({
|
||||
"flex":"1 1 auto",
|
||||
"overflow-y":"scroll",
|
||||
"overflow-y":"auto",
|
||||
}).appendTo(propertiesPanel);
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
bottom: 0px;
|
||||
left:0px;
|
||||
right: 0px;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.red-ui-debug-filter-box {
|
||||
position:absolute;
|
||||
|
||||
@@ -368,7 +368,7 @@ button.red-ui-button-small
|
||||
border:1px solid var(--red-ui-secondary-border-color);
|
||||
border-radius:5px;
|
||||
height: calc(100% - 21px);
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
background: var(--red-ui-secondary-background);
|
||||
}
|
||||
|
||||
@@ -562,7 +562,7 @@ div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle {
|
||||
.red-ui-icon-list {
|
||||
width: 308px;
|
||||
height: 200px;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
line-height: 0px;
|
||||
position: relative;
|
||||
&.red-ui-icon-list-dark {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
}
|
||||
}
|
||||
#red-ui-project-settings-tab-settings {
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.red-ui-sidebar-vc-shade {
|
||||
background: var(--red-ui-primary-background);
|
||||
@@ -183,7 +183,7 @@
|
||||
}
|
||||
.red-ui-projects-dialog-project-list-inner-container {
|
||||
flex-grow: 1 ;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
position:relative;
|
||||
.red-ui-editableList-border {
|
||||
border: none;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
|
||||
.red-ui-palette-category {
|
||||
&:not(.expanded) button {
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 8px 20px 20px;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.red-ui-settings-row {
|
||||
padding: 5px 10px 2px;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#red-ui-workspace-chart {
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
bottom:25px;
|
||||
bottom:26px;
|
||||
top: 35px;
|
||||
left:0px;
|
||||
right:0px;
|
||||
|
||||
@@ -14,6 +14,9 @@ declare var msg: NodeMessage;
|
||||
/** @type {string} the id of the incoming `msg` (alias of msg._msgid) */
|
||||
declare const __msgid__:string;
|
||||
|
||||
declare const util:typeof import('util')
|
||||
declare const promisify:typeof import('util').promisify
|
||||
|
||||
/**
|
||||
* @typedef NodeStatus
|
||||
* @type {object}
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
'$base64encode':{ args:[ ]},
|
||||
'$boolean':{ args:[ 'arg' ]},
|
||||
'$ceil':{ args:[ 'number' ]},
|
||||
'$clone': { args:[ 'arg' ]},
|
||||
'$contains':{ args:[ 'str', 'pattern' ]},
|
||||
'$count':{ args:[ 'array' ]},
|
||||
'$decodeUrl':{ args:[ 'str' ]},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script type="text/html" data-template-name="complete">
|
||||
<div class="form-row node-input-target-row">
|
||||
<button id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button type="button" id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-complete-target-filter"></div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<label for="node-input-uncaught" style="width: auto" data-i18n="catch.label.uncaught"></label>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row">
|
||||
<button id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button type="button" id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-catch-target-filter"></div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row">
|
||||
<button id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button type="button" id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-status-target-filter"></div>
|
||||
|
||||
@@ -91,21 +91,21 @@
|
||||
<div id="func-tab-init" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-body" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-finalize" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
if (val === "_custom_") {
|
||||
val = $(this).val();
|
||||
}
|
||||
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
|
||||
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/\.].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
|
||||
fvar.val(varName);
|
||||
fvar.trigger("change");
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
var r = node.rules[currentRule];
|
||||
if (r.t === "move") {
|
||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) {
|
||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1) && (r.p !== r.to)) {
|
||||
applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => {
|
||||
applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => {
|
||||
completeApplyingRules(msg,currentRule,done);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<option value="yaml">YAML</option>
|
||||
<option value="text" data-i18n="template.label.none"></option>
|
||||
</select>
|
||||
<button id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
|
||||
<button type="button" id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-certfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" id="node-config-input-certfile">
|
||||
<span id="tls-config-certname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-certname">
|
||||
<input type="hidden" id="node-config-input-certdata">
|
||||
@@ -37,7 +37,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-keyfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" id="node-config-input-keyfile">
|
||||
<span id="tls-config-keyname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-keyname">
|
||||
<input type="hidden" id="node-config-input-keydata">
|
||||
@@ -53,7 +53,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-cafile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" title=" " id="node-config-input-cafile">
|
||||
<span id="tls-config-caname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-caname">
|
||||
<input type="hidden" id="node-config-input-cadata">
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
hostField.val(data.host);
|
||||
}
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
if (this.noproxy) {
|
||||
|
||||
@@ -474,7 +474,6 @@ module.exports = function(RED) {
|
||||
setIfHasProperty(opts, node, "protocolVersion", init);
|
||||
setIfHasProperty(opts, node, "keepalive", init);
|
||||
setIfHasProperty(opts, node, "cleansession", init);
|
||||
setIfHasProperty(opts, node, "sessionExpiry", init);
|
||||
setIfHasProperty(opts, node, "topicAliasMaximum", init);
|
||||
setIfHasProperty(opts, node, "maximumPacketSize", init);
|
||||
setIfHasProperty(opts, node, "receiveMaximum", init);
|
||||
@@ -484,6 +483,11 @@ module.exports = function(RED) {
|
||||
} else if (hasProperty(opts, "userProps")) {
|
||||
node.userProperties = opts.userProps;
|
||||
}
|
||||
if (hasProperty(opts, "sessionExpiry")) {
|
||||
node.sessionExpiryInterval = opts.sessionExpiry;
|
||||
} else if (hasProperty(opts, "sessionExpiryInterval")) {
|
||||
node.sessionExpiryInterval = opts.sessionExpiryInterval
|
||||
}
|
||||
|
||||
function createLWT(topic, payload, qos, retain, v5opts, v5SubPropName) {
|
||||
let message = undefined;
|
||||
@@ -782,7 +786,9 @@ module.exports = function(RED) {
|
||||
|
||||
// Send any birth message
|
||||
if (node.birthMessage) {
|
||||
node.publish(node.birthMessage);
|
||||
setTimeout(() => {
|
||||
node.publish(node.birthMessage);
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
node._clientOn("reconnect", function() {
|
||||
@@ -991,14 +997,21 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
if (topicOK) {
|
||||
node.client.publish(msg.topic, msg.payload, options, function(err) {
|
||||
done && done(err);
|
||||
return
|
||||
});
|
||||
node.client.publish(msg.topic, msg.payload, options, function (err) {
|
||||
if (done) {
|
||||
done(err)
|
||||
} else {
|
||||
node.error(err, msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const error = new Error(RED._("mqtt.errors.invalid-topic"));
|
||||
error.warn = true;
|
||||
done(error);
|
||||
const error = new Error(RED._("mqtt.errors.invalid-topic"))
|
||||
error.warn = true
|
||||
if (done) {
|
||||
done(error)
|
||||
} else {
|
||||
node.warn(error, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,6 +227,7 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
|
||||
|
||||
@@ -91,6 +91,11 @@
|
||||
<label for="node-input-senderr" style="width: auto" data-i18n="httpin.senderr"></label>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<input type="checkbox" id="node-input-insecureHTTPParser" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-insecureHTTPParser", style="width: auto;" data-i18n="httpin.insecureHTTPParser"></label>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label>
|
||||
@@ -227,6 +232,7 @@
|
||||
persist: {value:false},
|
||||
proxy: {type:"http proxy",required: false,
|
||||
label:RED._("node-red:httpin.proxy-config") },
|
||||
insecureHTTPParser: {value: false},
|
||||
authType: {value: ""},
|
||||
senderr: {value: false},
|
||||
headers: { value: [] }
|
||||
@@ -338,6 +344,12 @@
|
||||
} else {
|
||||
$("#node-input-useProxy").prop("checked", false);
|
||||
}
|
||||
|
||||
if (node.insecureHTTPParser) {
|
||||
$("node-intput-insecureHTTPParser").prop("checked", true)
|
||||
} else {
|
||||
$("node-intput-insecureHTTPParser").prop("checked", false)
|
||||
}
|
||||
updateProxyOptions();
|
||||
$("#node-input-useProxy").on("click", function() {
|
||||
updateProxyOptions();
|
||||
@@ -405,6 +417,7 @@
|
||||
});
|
||||
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
if (node.headers) {
|
||||
|
||||
@@ -86,6 +86,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; }
|
||||
else if (n.paytoqs === "body") { paytobody = true; }
|
||||
|
||||
node.insecureHTTPParser = n.insecureHTTPParser
|
||||
|
||||
var prox, noprox;
|
||||
if (process.env.http_proxy) { prox = process.env.http_proxy; }
|
||||
@@ -244,6 +245,10 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
delete options.headers[h];
|
||||
}
|
||||
})
|
||||
|
||||
if (node.insecureHTTPParser) {
|
||||
options.insecureHTTPParser = true
|
||||
}
|
||||
}
|
||||
],
|
||||
beforeRedirect: [
|
||||
|
||||
@@ -52,4 +52,7 @@
|
||||
used to mark the templated sections. For example, to use <code>[[ ]]</code>
|
||||
instead, add the following line to the top of the template:</p>
|
||||
<pre>{{=[[ ]]=}}</pre>
|
||||
<h4>Using environment variables</h4>
|
||||
<p>The template node can access environment variables using the syntax:</p>
|
||||
<pre>My favourite colour is {{env.COLOUR}}.</pre>
|
||||
</script>
|
||||
|
||||
@@ -554,7 +554,8 @@
|
||||
},
|
||||
"status": {
|
||||
"requesting": "requesting"
|
||||
}
|
||||
},
|
||||
"insecureHTTPParser": "Disable strict HTTP parsing"
|
||||
},
|
||||
"websocket": {
|
||||
"label": {
|
||||
|
||||
@@ -48,4 +48,7 @@
|
||||
<p><b>注: </b>デフォルトでは、<i>mustache</i>形式は置換対象のHTML要素をエスケープします。これを抑止するには<code>{{{三重}}}</code>括弧形式を使います。</p>
|
||||
<p>もし、コンテンツの中で<code>{{ }}</code>を出力する必要がある場合は、テンプレートで使われる記号文字を変えることもできます。例えば、<code>[[ ]]</code>を代わりに用いるには、テンプレートの先頭に以下の行を追加します。</p>
|
||||
<pre>{{=[[ ]]=}}</pre>
|
||||
<h4>環境変数の利用</h4>
|
||||
<p>templateノードでは、次の構文を用いると環境変数にアクセスできます:</p>
|
||||
<pre>私の好きな色は{{env.COLOUR}}です。</pre>
|
||||
</script>
|
||||
|
||||
@@ -554,7 +554,8 @@
|
||||
},
|
||||
"status": {
|
||||
"requesting": "要求中"
|
||||
}
|
||||
},
|
||||
"insecureHTTPParser": "厳密なHTTPパース処理を無効化"
|
||||
},
|
||||
"websocket": {
|
||||
"label": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/nodes",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -25,7 +25,7 @@
|
||||
"cookie": "0.5.0",
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.0.1",
|
||||
"denque": "2.1.0",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "10.1.0",
|
||||
"got": "11.8.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/registry",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.0.1",
|
||||
"@node-red/util": "3.0.2",
|
||||
"clone": "2.1.2",
|
||||
"fs-extra": "10.1.0",
|
||||
"semver": "7.3.7",
|
||||
"tar": "6.1.11",
|
||||
"uglify-js": "3.16.2"
|
||||
"uglify-js": "3.16.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,10 +134,12 @@ function createNode(flow,config) {
|
||||
subflowInstanceConfig,
|
||||
instanceConfig
|
||||
);
|
||||
// Register this subflow as an instance node of the parent flow.
|
||||
// This allows nodes inside the subflow to get ahold of each other
|
||||
// such as a node accessing its config node
|
||||
flow.subflowInstanceNodes[config.id] = subflow
|
||||
subflow.start();
|
||||
return subflow.node;
|
||||
|
||||
Log.error(Log._("nodes.flow.unknown-type", {type:type}));
|
||||
}
|
||||
} catch(err) {
|
||||
Log.error(err);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"runtime": {
|
||||
"welcome": "Willkommen bei Node-RED!",
|
||||
"welcome": "Willkommen bei Node-RED",
|
||||
"version": "__component__ Version: __version__",
|
||||
"unsupported_version": "Nicht unterstützte Version von __component__. Erforderlich: __requires__, jedoch gefunden: __version__",
|
||||
"paths": {
|
||||
@@ -8,7 +8,6 @@
|
||||
"httpStatic": "HTTP-Statisch: __path__"
|
||||
}
|
||||
},
|
||||
|
||||
"server": {
|
||||
"loading": "Paletten-Nodes werden geladen",
|
||||
"palette-editor": {
|
||||
@@ -34,17 +33,19 @@
|
||||
"install-failed-not-found": "Das Modul $t(server.install.install-failed-long) wurde nicht gefunden",
|
||||
"install-failed-name": "$t(server.install.install-failed-long). Ungültiger Modulname: __name__",
|
||||
"install-failed-url": "$t(server.install.install-failed-long). Ungültige URL: __url__",
|
||||
"post-install-error": "Fehler bei der Ausführung des 'postInstall'-Hooks:",
|
||||
"upgrading": "Upgrade von Modul __name__ auf Version __version__ gestartet",
|
||||
"upgraded": "Upgrade von Modul __name__ war erfolgreich. Neustart von Node-RED für die Verwendung der neuen Version erforderlich.",
|
||||
"upgrade-failed-not-found": "Upgrade fehlgeschlagen. $t(server.install.install-failed-long). Version nicht gefunden.",
|
||||
"uninstalling": "Das Modul __name__ wird deinstalliert",
|
||||
"uninstall-failed": "Deinstallation fehlgeschlagen",
|
||||
"uninstall-failed-long": "Die Deinstallation des Moduls __name__ ist fehlgeschlagen:",
|
||||
"uninstalled": "Das Modul __name__ ist deinstalliert"
|
||||
"uninstalled": "Das Modul __name__ ist deinstalliert",
|
||||
"old-ext-mod-dir-warning": "\n\n---------------------------------------------------------------------\nNode-RED 1.3 Verzeichnis externer Module erkannt:\n __oldDir__\nDieses Verzeichnis wird nicht mehr verwendet. Die externen Module werden\nin Ihrem Node-RED-Benutzerverzeichnis neu installiert:\n __newDir__\nLöschen Sie das alte externalModules-Verzeichnis, um diese Meldung abzustellen.\n---------------------------------------------------------------------\n"
|
||||
},
|
||||
"deprecatedOption": "Die Verwendung von __old__ ist abgekündigt. Stattdessen __new__ verwenden.",
|
||||
"unable-to-listen": "Überwachen (listen) von __listenpath__ nicht möglich",
|
||||
"port-in-use": "FEHLER: Port wird verwendet",
|
||||
"port-in-use": "Fehler: Port wird verwendet",
|
||||
"uncaught-exception": "Nicht abgefangene Ausnahmebedingung:",
|
||||
"admin-ui-disabled": "Administrator-Benutzeroberfläche deaktiv",
|
||||
"now-running": "Server wird jetzt auf __listenpath__ ausgeführt",
|
||||
@@ -55,11 +56,10 @@
|
||||
"refresh-interval": "Erneuerung der https-Einstellungen erfolgt alle __interval__ Stunden",
|
||||
"settings-refreshed": "https-Einstellungen wurden erneuert",
|
||||
"refresh-failed": "Erneuerung der https-Einstellungen fehlgeschlagen: __message__",
|
||||
"nodejs-version": "httpsRefreshInterval erfordert Node.js 11 or later",
|
||||
"nodejs-version": "httpsRefreshInterval erfordert Node.js 11 oder höher",
|
||||
"function-required": "httpsRefreshInterval erfordert die https-Eigenschaft in Form einer Funktion"
|
||||
}
|
||||
},
|
||||
|
||||
"api": {
|
||||
"flows": {
|
||||
"error-save": "Fehler beim Speichern der Flows: __message__",
|
||||
@@ -77,17 +77,16 @@
|
||||
"error-enable": "Der Node konnte nicht aktiviert werden:"
|
||||
}
|
||||
},
|
||||
|
||||
"comms": {
|
||||
"error": "Kommunikationskanal-Fehler: __message__",
|
||||
"error-server": "Kommunikationsserver-Fehler: __message__",
|
||||
"error-send": "Kommunikationsende-Fehler: __message__"
|
||||
},
|
||||
|
||||
"settings": {
|
||||
"user-not-available": "Einstellungen konnten nicht gespeichert werden: __message__",
|
||||
"not-available": "Einstellungen nicht verfügbar",
|
||||
"property-read-only": "Die Eigenschaft '__prop__ 'ist schreibgeschützt"
|
||||
"property-read-only": "Die Eigenschaft '__prop__' ist schreibgeschützt",
|
||||
"readonly-mode": "Laufzeitumgebung im Nur-Lese-Modus. Änderungen werden nicht gespeichert."
|
||||
},
|
||||
"library": {
|
||||
"unknownLibrary": "Unbekannte Bibliothek (Library): __library__",
|
||||
@@ -98,10 +97,12 @@
|
||||
},
|
||||
"nodes": {
|
||||
"credentials": {
|
||||
"error": "Fehler beim Laden der Berechtigungen: __message__",
|
||||
"error-saving": "Fehler beim Speichern der Berechtigungen: __message__",
|
||||
"not-registered": "Der Berechtigung-Typ '__type__' ist nicht registriert",
|
||||
"system-key-warning": "\n---------------------------------------------------------------------\nDie Datei mit den Flow-Berechtigungen wird mit einem vom System\ngenerierten Schlüssel verschlüsselt.\nWenn der vom System generierte Schlüssel aus irgendeinem Grund\nverloren geht, kann die Datei mit den Berechtigungen nicht\nwiederhergestellt werden. Sie muss dann gelöscht und die\nBerechtigungen müssen erneut eingestellt werden.\nEs sollte ein eigener Schlüssel mit Hilfe der Option\n'credentialSecret' in der Einstellungsdatei vorgegeben werden.\nNode-RED wird dann die Datei mit den Flow-Berechtigungen\nbei der nächsten Übernahme (deploy) einer Änderung erneut\nverschlüsseln.\n---------------------------------------------------------------------"
|
||||
"error": "Fehler beim Laden der Credentials: __message__",
|
||||
"error-saving": "Fehler beim Speichern der Credentials: __message__",
|
||||
"not-registered": "Der Credentials-Typ '__type__' ist nicht registriert",
|
||||
"system-key-warning": "\n---------------------------------------------------------------------\nDie Datei mit den Flow-Credentials wird mit einem vom System\ngenerierten Schlüssel verschlüsselt.\nWenn der vom System generierte Schlüssel aus irgendeinem Grund\nverloren geht, kann die Datei mit den Credentials nicht\nwiederhergestellt werden. Sie muss dann gelöscht und die\nCredentials müssen erneut eingestellt werden.\nEs sollte ein eigener Schlüssel mit Hilfe der Option\n'credentialSecret' in der Einstellungsdatei vorgegeben werden.\nNode-RED wird dann die Datei mit den Flow-Credentials\nbei der nächsten Übernahme (deploy) einer Änderung erneut\nverschlüsseln.\n---------------------------------------------------------------------",
|
||||
"unencrypted": "Verwende unverschlüsselte Credentials",
|
||||
"encryptedNotFound": "Verschlüsselte Credentials nicht gefunden"
|
||||
},
|
||||
"flows": {
|
||||
"safe-mode": "Die Flows sind gestoppt im abgesicherten Modus. Übernahme (deploy) zum Starten.",
|
||||
@@ -121,6 +122,7 @@
|
||||
"stopped-flows": "Flows sind gestoppt",
|
||||
"stopped": "gestoppt",
|
||||
"stopping-error": "Fehler beim Stoppen des Nodes: __message__",
|
||||
"updated-flows": "Flows aktualisiert",
|
||||
"added-flow": "Flow wird hinzugefügt: __label__",
|
||||
"updated-flow": "Aktualisierter Flow: __label__",
|
||||
"removed-flow": "Entfernter Flow: __label__",
|
||||
@@ -145,7 +147,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"storage": {
|
||||
"index": {
|
||||
"forbidden-flow-name": "Unzulässiger Flow-Name"
|
||||
@@ -159,6 +160,7 @@
|
||||
"restore": "Die '__type__'-Dateisicherung wird wiederhergestellt: __path__",
|
||||
"restore-fail": "Die Wiederherstellung der '__type__'-Dateisicherung ist fehlgeschlagen: __message__",
|
||||
"fsync-fail": "Die Übertragung der Datei __path__ auf das Laufwerk ist fehlgeschlagen: __message__",
|
||||
"warn_name": "Name der Flows-Datei nicht festgelegt. Name wird unter Verwendung des Hostnamens generiert.",
|
||||
"projects": {
|
||||
"changing-project": "Aktives Projekt wird festgelegt: __project__",
|
||||
"active-project": "Aktives Projekt: __project__",
|
||||
@@ -174,7 +176,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"context": {
|
||||
"log-store-init": "Kontextspeicher: __name__ [__info__]",
|
||||
"error-loading-module": "Fehler beim Laden des Kontextspeichers: __message__",
|
||||
@@ -189,5 +190,4 @@
|
||||
"error-write": "Fehler beim Schreiben des Kontextes: __message__"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/runtime",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/registry": "3.0.1",
|
||||
"@node-red/util": "3.0.1",
|
||||
"@node-red/registry": "3.0.2",
|
||||
"@node-red/util": "3.0.2",
|
||||
"async-mutex": "0.3.2",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.18.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/util",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -16,7 +16,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"fs-extra": "10.1.0",
|
||||
"i18next": "21.8.14",
|
||||
"i18next": "21.8.16",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.8.6",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
|
||||
10
packages/node_modules/node-red/package.json
vendored
10
packages/node_modules/node-red/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,10 +31,10 @@
|
||||
"flow"
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/editor-api": "3.0.1",
|
||||
"@node-red/runtime": "3.0.1",
|
||||
"@node-red/util": "3.0.1",
|
||||
"@node-red/nodes": "3.0.1",
|
||||
"@node-red/editor-api": "3.0.2",
|
||||
"@node-red/runtime": "3.0.2",
|
||||
"@node-red/util": "3.0.2",
|
||||
"@node-red/nodes": "3.0.2",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.18.1",
|
||||
|
||||
@@ -1717,6 +1717,24 @@ describe('change Node', function() {
|
||||
changeNode1.receive({topic:{foo:{bar:1}}, payload:"String"});
|
||||
});
|
||||
});
|
||||
it('moves the value of a message property object to itself', function(done) {
|
||||
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
helper.load(changeNode, flow, function() {
|
||||
var changeNode1 = helper.getNode("changeNode1");
|
||||
var helperNode1 = helper.getNode("helperNode1");
|
||||
helperNode1.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.equal("bar");
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
changeNode1.receive({payload:"bar"});
|
||||
});
|
||||
});
|
||||
it('moves the value of a message property object to a sub-property', function(done) {
|
||||
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.foo","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
|
||||
@@ -31,6 +31,8 @@ var multer = require("multer");
|
||||
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||
var fs = require('fs-extra');
|
||||
var auth = require('basic-auth');
|
||||
const { version } = require("os");
|
||||
const net = require('net')
|
||||
|
||||
describe('HTTP Request Node', function() {
|
||||
var testApp;
|
||||
@@ -2265,4 +2267,71 @@ describe('HTTP Request Node', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('should parse broken headers', function() {
|
||||
|
||||
const versions = process.versions.node.split('.')
|
||||
|
||||
if (( versions[0] == 14 && versions[1] >= 20 ) ||
|
||||
( versions[0] == 16 && versions[1] >= 16 ) ||
|
||||
( versions[0] == 18 && versions[1] >= 5 ) ||
|
||||
( versions[0] > 18)) {
|
||||
// only test if on new enough NodeJS version
|
||||
|
||||
let port = testPort++
|
||||
|
||||
let server;
|
||||
|
||||
before(function() {
|
||||
server = net.createServer(function (socket) {
|
||||
socket.write("HTTP/1.0 200\nContent-Type: text/plain\n\nHelloWorld")
|
||||
socket.end()
|
||||
})
|
||||
|
||||
server.listen(port,'127.0.0.1', function(err) {
|
||||
})
|
||||
});
|
||||
|
||||
after(function() {
|
||||
server.close()
|
||||
});
|
||||
|
||||
it('should accept broken headers', function (done) {
|
||||
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:`http://localhost:${port}/`, insecureHTTPParser: true},
|
||||
{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.should.equal('HelloWorld')
|
||||
done()
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
n1.receive({payload: 'foo'})
|
||||
});
|
||||
});
|
||||
|
||||
it('should reject broken headers', function (done) {
|
||||
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:`http://localhost:${port}/`},
|
||||
{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.should.equal(`RequestError: Parse Error: Missing expected CR after header value : http://localhost:${port}/`)
|
||||
done()
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
n1.receive({payload: 'foo'})
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('MQTT Nodes', function () {
|
||||
} catch (error) { }
|
||||
});
|
||||
|
||||
it('should be loaded and have default values', function (done) {
|
||||
it('should be loaded and have default values (MQTT V4)', function (done) {
|
||||
this.timeout = 2000;
|
||||
const { flow, nodes } = buildBasicMQTTSendRecvFlow({ id: "mqtt.broker", name: "mqtt_broker", autoConnect: false }, { id: "mqtt.in", topic: "in_topic" }, { id: "mqtt.out", topic: "out_topic" });
|
||||
helper.load(mqttNodes, flow, function () {
|
||||
@@ -61,6 +61,52 @@ describe('MQTT Nodes', function () {
|
||||
mqttBroker.options.clientId.should.containEql('nodered_');
|
||||
mqttBroker.options.should.have.property('keepalive').type("number");
|
||||
mqttBroker.options.should.have.property('reconnectPeriod').type("number");
|
||||
//as this is not a v5 connection, ensure v5 properties are not present
|
||||
mqttBroker.options.should.not.have.property('protocolVersion', 5);
|
||||
mqttBroker.options.should.not.have.property('properties');
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
}
|
||||
});
|
||||
});
|
||||
it('should be loaded and have default values (MQTT V5)', function (done) {
|
||||
this.timeout = 2000;
|
||||
const { flow, nodes } = buildBasicMQTTSendRecvFlow({ id: "mqtt.broker", name: "mqtt_broker", autoConnect: false, cleansession: false, clientid: 'clientid', keepalive: 35, sessionExpiry: '6000', protocolVersion: '5', userProps: {"prop": "val"}}, { id: "mqtt.in", topic: "in_topic" }, { id: "mqtt.out", topic: "out_topic" });
|
||||
helper.load(mqttNodes, flow, function () {
|
||||
try {
|
||||
const mqttIn = helper.getNode("mqtt.in");
|
||||
const mqttOut = helper.getNode("mqtt.out");
|
||||
const mqttBroker = helper.getNode("mqtt.broker");
|
||||
|
||||
should(mqttIn).be.type("object", "mqtt in node should be an object")
|
||||
mqttIn.should.have.property('broker', nodes.mqtt_broker.id); //should be the id of the broker node
|
||||
mqttIn.should.have.property('datatype', 'utf8'); //default: 'utf8'
|
||||
mqttIn.should.have.property('isDynamic', false); //default: false
|
||||
mqttIn.should.have.property('inputs', 0); //default: 0
|
||||
mqttIn.should.have.property('qos', 2); //default: 2
|
||||
mqttIn.should.have.property('topic', "in_topic");
|
||||
mqttIn.should.have.property('wires', [["helper.node"]]);
|
||||
|
||||
should(mqttOut).be.type("object", "mqtt out node should be an object")
|
||||
mqttOut.should.have.property('broker', nodes.mqtt_broker.id); //should be the id of the broker node
|
||||
mqttOut.should.have.property('topic', "out_topic");
|
||||
|
||||
should(mqttBroker).be.type("object", "mqtt broker node should be an object")
|
||||
mqttBroker.should.have.property('broker', BROKER_HOST);
|
||||
mqttBroker.should.have.property('port', BROKER_PORT);
|
||||
mqttBroker.should.have.property('brokerurl');
|
||||
// mqttBroker.should.have.property('autoUnsubscribe', true);//default: true
|
||||
mqttBroker.should.have.property('autoConnect', false);//Set "autoConnect:false" in brokerOptions
|
||||
mqttBroker.should.have.property('options');
|
||||
mqttBroker.options.should.have.property('clean', false);
|
||||
mqttBroker.options.should.have.property('clientId', 'clientid');
|
||||
mqttBroker.options.should.have.property('keepalive').type("number", 35);
|
||||
mqttBroker.options.should.have.property('reconnectPeriod').type("number");
|
||||
//as this IS a v5 connection, ensure v5 properties are not present
|
||||
mqttBroker.options.should.have.property('protocolVersion', 5);
|
||||
mqttBroker.options.should.have.property('properties');
|
||||
mqttBroker.options.properties.should.have.property('sessionExpiryInterval');
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
@@ -173,7 +219,7 @@ describe('MQTT Nodes', function () {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -299,7 +345,7 @@ describe('MQTT Nodes', function () {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', contentType: "application/json", // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -385,7 +431,7 @@ describe('MQTT Nodes', function () {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.beforeLoad = (flow) => { //add a status node pointed at MQTT Out node (to watch for connection status change)
|
||||
flow.push({ "id": "status.node", "type": "status", "name": "status_node", "scope": ["mqtt.out"], "wires": [["helper.node"]] });//add status node to watch mqtt_out
|
||||
}
|
||||
@@ -416,18 +462,31 @@ describe('MQTT Nodes', function () {
|
||||
this.timeout = 2000;
|
||||
const baseTopic = nextTopic();
|
||||
const brokerOptions = {
|
||||
autoConnect: false,
|
||||
protocolVersion: 4,
|
||||
birthTopic: baseTopic + "/birth",
|
||||
birthPayload: "broker connected",
|
||||
birthPayload: "broker birth",
|
||||
birthQos: 2,
|
||||
}
|
||||
const options = {};
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null };
|
||||
options.expectMsg = {
|
||||
const expectMsg = {
|
||||
topic: brokerOptions.birthTopic,
|
||||
payload: brokerOptions.birthPayload,
|
||||
qos: brokerOptions.birthQos
|
||||
};
|
||||
const options = { };
|
||||
const hooks = { };
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
compareMsgToExpected(msg, expectMsg);
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
}
|
||||
})
|
||||
mqttIn.receive({ "action": "connect" }); //now request connect action
|
||||
return true; //handled
|
||||
}
|
||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should publish close message', function (done) {
|
||||
@@ -666,6 +725,7 @@ function buildMQTTBrokerNode(id, name, brokerHost, brokerPort, options) {
|
||||
node.cleansession = String(options.cleansession) == "false" ? false : true;
|
||||
node.autoUnsubscribe = String(options.autoUnsubscribe) == "false" ? false : true;
|
||||
node.autoConnect = String(options.autoConnect) == "false" ? false : true;
|
||||
node.sessionExpiry = options.sessionExpiry ? options.sessionExpiry : undefined;
|
||||
|
||||
if (options.birthTopic) {
|
||||
node.birthTopic = options.birthTopic;
|
||||
@@ -760,8 +820,8 @@ function waitBrokerConnect(broker, timeLimit) {
|
||||
let waitConnected = (broker, timeLimit) => {
|
||||
const brokers = Array.isArray(broker) ? broker : [broker];
|
||||
timeLimit = timeLimit || 1000;
|
||||
let timer, resolved = false;
|
||||
return new Promise( (resolve, reject) => {
|
||||
let timer, resolved = false;
|
||||
timer = wait();
|
||||
function wait() {
|
||||
if (brokers.every(e => e.connected == true)) {
|
||||
|
||||
@@ -61,7 +61,7 @@ describe("api/index", function() {
|
||||
should.not.exist(api.httpAdmin);
|
||||
done();
|
||||
});
|
||||
describe('initalises admin api without adminAuth', function(done) {
|
||||
describe('initalises admin api without adminAuth', function() {
|
||||
before(function() {
|
||||
beforeEach();
|
||||
api.init({},{},{},{});
|
||||
@@ -78,7 +78,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('initalises admin api without editor', function(done) {
|
||||
describe('initalises admin api without editor', function() {
|
||||
before(function() {
|
||||
beforeEach();
|
||||
api.init({ disableEditor: true },{},{},{});
|
||||
@@ -95,7 +95,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('initialises api with admin middleware', function(done) {
|
||||
describe('initialises api with admin middleware', function() {
|
||||
it('ignores non-function values',function(done) {
|
||||
api.init({ httpAdminRoot: true, httpAdminMiddleware: undefined },{},{},{});
|
||||
const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'testMiddleware')
|
||||
@@ -112,7 +112,7 @@ describe("api/index", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('initialises api with authentication enabled', function(done) {
|
||||
describe('initialises api with authentication enabled', function() {
|
||||
|
||||
it('enables an oauth/openID based authentication mechanism',function(done) {
|
||||
const stub = sinon.stub(apiAuth, 'genericStrategy').callsFake(function(){});
|
||||
@@ -135,7 +135,7 @@ describe("api/index", function() {
|
||||
|
||||
});
|
||||
|
||||
describe('initialises api with custom cors config', function (done) {
|
||||
describe('initialises api with custom cors config', function () {
|
||||
const httpAdminCors = {
|
||||
origin: "*",
|
||||
methods: "GET,PUT,POST,DELETE"
|
||||
@@ -156,7 +156,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('editor start', function (done) {
|
||||
describe('editor start', function () {
|
||||
|
||||
it('cannot be started when editor is disabled', function (done) {
|
||||
const stub = sinon.stub(apiEditor, 'start').callsFake(function () {
|
||||
|
||||
Reference in New Issue
Block a user