mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge branch 'dev' into continuous-search
This commit is contained in:
commit
5233bc501c
32
CHANGELOG.md
32
CHANGELOG.md
@ -1,3 +1,35 @@
|
|||||||
|
#### 2.2.2: Maintenance Release
|
||||||
|
|
||||||
|
Nodes
|
||||||
|
|
||||||
|
- Fix "close timed out" error when performing full deploy or modifying broker node. (#3451) @Steve-Mcl
|
||||||
|
|
||||||
|
|
||||||
|
#### 2.2.1: Maintenance Release
|
||||||
|
|
||||||
|
Editor
|
||||||
|
|
||||||
|
- Handle mixed-cased filter terms in keyboard shortcut dialog (#3444) @knolleary
|
||||||
|
- Prevent duplicate links being added between nodes (#3442) @knolleary
|
||||||
|
- Fix to hide tooltip after removing subflow tab (#3391) @HiroyasuNishiyama
|
||||||
|
- Fix node validation to be applied to config node (#3397) @HiroyasuNishiyama
|
||||||
|
- Fix: Dont add wires to undo buffer twice (#3437) @Steve-Mcl
|
||||||
|
|
||||||
|
Runtime
|
||||||
|
|
||||||
|
- Improve module location parsing (of stack info) when adding hook (#3447) @Steve-Mcl
|
||||||
|
- Fix substitution of NR_NODE_PATH (#3445) @HiroyasuNishiyama
|
||||||
|
- Remove console.log when ignoring disabled module (#3439) @knolleary
|
||||||
|
- Improve "Unexpected Node Error" logging (#3446) @Steve-Mcl
|
||||||
|
|
||||||
|
Nodes
|
||||||
|
|
||||||
|
- Debug: Fix no-prototype-builtins bug in debug node and utils (#3394) @Alkarex
|
||||||
|
- Delay: Fix Japanese message of delay node (#3434)
|
||||||
|
- Allow nbRateUnits to be undefined when validating (#3443) @knolleary
|
||||||
|
- Coding help for recently added node-red Predefined Environment Variables (#3440) @Steve-Mcl
|
||||||
|
|
||||||
|
|
||||||
#### 2.2.0: Milestone Release
|
#### 2.2.0: Milestone Release
|
||||||
|
|
||||||
Editor
|
Editor
|
||||||
|
26
package.json
26
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red",
|
"name": "node-red",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"description": "Low-code programming for event-driven applications",
|
"description": "Low-code programming for event-driven applications",
|
||||||
"homepage": "http://nodered.org",
|
"homepage": "http://nodered.org",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@ -28,7 +28,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "8.7.0",
|
"acorn": "8.7.0",
|
||||||
"acorn-walk": "8.2.0",
|
"acorn-walk": "8.2.0",
|
||||||
"ajv": "8.9.0",
|
"ajv": "8.10.0",
|
||||||
"async-mutex": "0.3.2",
|
"async-mutex": "0.3.2",
|
||||||
"basic-auth": "2.0.1",
|
"basic-auth": "2.0.1",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"cheerio": "1.0.0-rc.10",
|
"cheerio": "1.0.0-rc.10",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"content-type": "1.0.4",
|
"content-type": "1.0.4",
|
||||||
"cookie": "0.4.1",
|
"cookie": "0.4.2",
|
||||||
"cookie-parser": "1.4.6",
|
"cookie-parser": "1.4.6",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"cronosjs": "1.7.1",
|
"cronosjs": "1.7.1",
|
||||||
@ -50,32 +50,32 @@
|
|||||||
"hash-sum": "2.0.0",
|
"hash-sum": "2.0.0",
|
||||||
"hpagent": "0.1.2",
|
"hpagent": "0.1.2",
|
||||||
"https-proxy-agent": "5.0.0",
|
"https-proxy-agent": "5.0.0",
|
||||||
"i18next": "21.6.10",
|
"i18next": "21.6.11",
|
||||||
"iconv-lite": "0.6.3",
|
"iconv-lite": "0.6.3",
|
||||||
"is-utf8": "0.2.1",
|
"is-utf8": "0.2.1",
|
||||||
"js-yaml": "3.14.1",
|
"js-yaml": "3.14.1",
|
||||||
"json-stringify-safe": "5.0.1",
|
"json-stringify-safe": "5.0.1",
|
||||||
"jsonata": "1.8.5",
|
"jsonata": "1.8.6",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"media-typer": "1.1.0",
|
"media-typer": "1.1.0",
|
||||||
"memorystore": "1.6.6",
|
"memorystore": "1.6.7",
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"moment-timezone": "0.5.34",
|
"moment-timezone": "0.5.34",
|
||||||
"mqtt": "4.3.4",
|
"mqtt": "4.3.5",
|
||||||
"multer": "1.4.4",
|
"multer": "1.4.4",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
"node-red-admin": "^2.2.2",
|
"node-red-admin": "^2.2.3",
|
||||||
"nopt": "5.0.0",
|
"nopt": "5.0.0",
|
||||||
"oauth2orize": "1.11.1",
|
"oauth2orize": "1.11.1",
|
||||||
"on-headers": "1.0.2",
|
"on-headers": "1.0.2",
|
||||||
"passport": "0.5.2",
|
"passport": "0.5.2",
|
||||||
"passport-http-bearer": "1.0.1",
|
"passport-http-bearer": "1.0.1",
|
||||||
"passport-oauth2-client-password": "0.1.2",
|
"passport-oauth2-client-password": "0.1.2",
|
||||||
"raw-body": "2.4.2",
|
"raw-body": "2.4.3",
|
||||||
"semver": "7.3.5",
|
"semver": "7.3.5",
|
||||||
"tar": "6.1.11",
|
"tar": "6.1.11",
|
||||||
"tough-cookie": "4.0.0",
|
"tough-cookie": "4.0.0",
|
||||||
"uglify-js": "3.15.0",
|
"uglify-js": "3.15.1",
|
||||||
"uuid": "8.3.2",
|
"uuid": "8.3.2",
|
||||||
"ws": "7.5.6",
|
"ws": "7.5.6",
|
||||||
"xml2js": "0.4.23"
|
"xml2js": "0.4.23"
|
||||||
@ -84,7 +84,7 @@
|
|||||||
"bcrypt": "5.0.1"
|
"bcrypt": "5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"dompurify": "2.3.4",
|
"dompurify": "2.3.5",
|
||||||
"grunt": "1.4.1",
|
"grunt": "1.4.1",
|
||||||
"grunt-chmod": "~1.1.1",
|
"grunt-chmod": "~1.1.1",
|
||||||
"grunt-cli": "~1.4.3",
|
"grunt-cli": "~1.4.3",
|
||||||
@ -113,11 +113,11 @@
|
|||||||
"node-red-node-test-helper": "^0.2.7",
|
"node-red-node-test-helper": "^0.2.7",
|
||||||
"nodemon": "2.0.15",
|
"nodemon": "2.0.15",
|
||||||
"proxy": "^1.0.2",
|
"proxy": "^1.0.2",
|
||||||
"sass": "1.49.0",
|
"sass": "1.49.7",
|
||||||
"should": "13.2.3",
|
"should": "13.2.3",
|
||||||
"sinon": "11.1.2",
|
"sinon": "11.1.2",
|
||||||
"stoppable": "^1.1.0",
|
"stoppable": "^1.1.0",
|
||||||
"supertest": "6.2.1"
|
"supertest": "6.2.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/editor-api",
|
"name": "@node-red/editor-api",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,15 +16,15 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/util": "2.2.0",
|
"@node-red/util": "2.2.2",
|
||||||
"@node-red/editor-client": "2.2.0",
|
"@node-red/editor-client": "2.2.2",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"body-parser": "1.19.1",
|
"body-parser": "1.19.1",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"express-session": "1.17.2",
|
"express-session": "1.17.2",
|
||||||
"express": "4.17.2",
|
"express": "4.17.2",
|
||||||
"memorystore": "1.6.6",
|
"memorystore": "1.6.7",
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"multer": "1.4.4",
|
"multer": "1.4.4",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
|
@ -634,14 +634,7 @@
|
|||||||
"empty": "leer",
|
"empty": "leer",
|
||||||
"globalConfig": "Globale Konfigurations-Nodes",
|
"globalConfig": "Globale Konfigurations-Nodes",
|
||||||
"triggerAction": "Auslösen",
|
"triggerAction": "Auslösen",
|
||||||
"find": "Suche im Arbeitsbereich",
|
"find": "Suche im Arbeitsbereich"
|
||||||
"search": {
|
|
||||||
"configNodes": "Konfigurations-Nodes",
|
|
||||||
"unusedConfigNodes": "Unbenutzte Konfigurations-Nodes",
|
|
||||||
"invalidNodes": "Ungültige Nodes",
|
|
||||||
"uknownNodes": "Unbekannte Nodes",
|
|
||||||
"unusedSubflows": "Unbenutzte Subflows"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"name": "Hilfe",
|
"name": "Hilfe",
|
||||||
@ -863,7 +856,14 @@
|
|||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"empty": "Keine Übereinstimmungen gefunden",
|
"empty": "Keine Übereinstimmungen gefunden",
|
||||||
"addNode": "Node hinzufügen ..."
|
"addNode": "Node hinzufügen ...",
|
||||||
|
"options": {
|
||||||
|
"configNodes": "Konfigurations-Nodes",
|
||||||
|
"unusedConfigNodes": "Unbenutzte Konfigurations-Nodes",
|
||||||
|
"invalidNodes": "Ungültige Nodes",
|
||||||
|
"uknownNodes": "Unbekannte Nodes",
|
||||||
|
"unusedSubflows": "Unbenutzte Subflows"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"expressionEditor": {
|
"expressionEditor": {
|
||||||
"functions": "Funktionen",
|
"functions": "Funktionen",
|
||||||
|
@ -501,7 +501,8 @@
|
|||||||
"redoChange": "Redo",
|
"redoChange": "Redo",
|
||||||
"searchBox": "Open search box",
|
"searchBox": "Open search box",
|
||||||
"managePalette": "Manage palette",
|
"managePalette": "Manage palette",
|
||||||
"actionList":"Action list"
|
"actionList": "Action list",
|
||||||
|
"splitWiresWithLinks": "Split selection with Link nodes"
|
||||||
},
|
},
|
||||||
"library": {
|
"library": {
|
||||||
"library": "Library",
|
"library": "Library",
|
||||||
@ -671,15 +672,7 @@
|
|||||||
"empty": "empty",
|
"empty": "empty",
|
||||||
"globalConfig": "Global Configuration Nodes",
|
"globalConfig": "Global Configuration Nodes",
|
||||||
"triggerAction": "Trigger action",
|
"triggerAction": "Trigger action",
|
||||||
"find": "Find in workspace",
|
"find": "Find in workspace"
|
||||||
"search": {
|
|
||||||
"configNodes": "Configuration nodes",
|
|
||||||
"unusedConfigNodes": "Unused configuration nodes",
|
|
||||||
"invalidNodes": "Invalid nodes",
|
|
||||||
"uknownNodes": "Unknown nodes",
|
|
||||||
"unusedSubflows": "Unused subflows",
|
|
||||||
"hiddenFlows": "Hidden flows"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"name": "Help",
|
"name": "Help",
|
||||||
@ -903,7 +896,16 @@
|
|||||||
"history": "Search history",
|
"history": "Search history",
|
||||||
"clear": "clear all",
|
"clear": "clear all",
|
||||||
"empty": "No matches found",
|
"empty": "No matches found",
|
||||||
"addNode": "add a node..."
|
"addNode": "add a node...",
|
||||||
|
"options": {
|
||||||
|
"configNodes": "Configuration nodes",
|
||||||
|
"unusedConfigNodes": "Unused configuration nodes",
|
||||||
|
"invalidNodes": "Invalid nodes",
|
||||||
|
"uknownNodes": "Unknown nodes",
|
||||||
|
"unusedSubflows": "Unused subflows",
|
||||||
|
"hiddenFlows": "Hidden flows",
|
||||||
|
"modifiedNodes": "Modified nodes and flows"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"expressionEditor": {
|
"expressionEditor": {
|
||||||
"functions": "Functions",
|
"functions": "Functions",
|
||||||
|
@ -667,15 +667,7 @@
|
|||||||
"empty": "空",
|
"empty": "空",
|
||||||
"globalConfig": "グローバル設定ノード",
|
"globalConfig": "グローバル設定ノード",
|
||||||
"triggerAction": "アクションを実行",
|
"triggerAction": "アクションを実行",
|
||||||
"find": "ワークスペース内を検索",
|
"find": "ワークスペース内を検索"
|
||||||
"search": {
|
|
||||||
"configNodes": "設定ノード",
|
|
||||||
"unusedConfigNodes": "未使用の設定ノード",
|
|
||||||
"invalidNodes": "不正なノード",
|
|
||||||
"uknownNodes": "未知のノード",
|
|
||||||
"unusedSubflows": "未使用のサブフロー",
|
|
||||||
"hiddenFlows": "非表示のフロー"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"name": "ヘルプ",
|
"name": "ヘルプ",
|
||||||
@ -899,7 +891,15 @@
|
|||||||
"history": "検索履歴",
|
"history": "検索履歴",
|
||||||
"clear": "全て削除",
|
"clear": "全て削除",
|
||||||
"empty": "一致したものが見つかりませんでした",
|
"empty": "一致したものが見つかりませんでした",
|
||||||
"addNode": "ノードを追加..."
|
"addNode": "ノードを追加...",
|
||||||
|
"options": {
|
||||||
|
"configNodes": "設定ノード",
|
||||||
|
"unusedConfigNodes": "未使用の設定ノード",
|
||||||
|
"invalidNodes": "不正なノード",
|
||||||
|
"uknownNodes": "未知のノード",
|
||||||
|
"unusedSubflows": "未使用のサブフロー",
|
||||||
|
"hiddenFlows": "非表示のフロー"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"expressionEditor": {
|
"expressionEditor": {
|
||||||
"functions": "関数",
|
"functions": "関数",
|
||||||
|
@ -650,14 +650,7 @@
|
|||||||
"empty": "пусто",
|
"empty": "пусто",
|
||||||
"globalConfig": "Глобальные конфиг узлы",
|
"globalConfig": "Глобальные конфиг узлы",
|
||||||
"triggerAction": "Вызвать действие",
|
"triggerAction": "Вызвать действие",
|
||||||
"find": "Найти в рабочей области",
|
"find": "Найти в рабочей области"
|
||||||
"search": {
|
|
||||||
"configNodes": "Узлы конфигурации",
|
|
||||||
"unusedConfigNodes": "Неиспользуемые узлы конфигурации",
|
|
||||||
"invalidNodes": "Недействительные узлы",
|
|
||||||
"uknownNodes": "Неизвестные узлы",
|
|
||||||
"unusedSubflows": "Неиспользуемые подпотоки"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"name": "Справка",
|
"name": "Справка",
|
||||||
@ -888,7 +881,14 @@
|
|||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"empty": "Ничего не найдено",
|
"empty": "Ничего не найдено",
|
||||||
"addNode": "добавить узел..."
|
"addNode": "добавить узел...",
|
||||||
|
"options": {
|
||||||
|
"configNodes": "Узлы конфигурации",
|
||||||
|
"unusedConfigNodes": "Неиспользуемые узлы конфигурации",
|
||||||
|
"invalidNodes": "Недействительные узлы",
|
||||||
|
"uknownNodes": "Неизвестные узлы",
|
||||||
|
"unusedSubflows": "Неиспользуемые подпотоки"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"expressionEditor": {
|
"expressionEditor": {
|
||||||
"functions": "Функции",
|
"functions": "Функции",
|
||||||
|
@ -614,14 +614,7 @@
|
|||||||
"empty": "空的",
|
"empty": "空的",
|
||||||
"globalConfig": "全局配置节点",
|
"globalConfig": "全局配置节点",
|
||||||
"triggerAction": "触发动作",
|
"triggerAction": "触发动作",
|
||||||
"find": "在工作区中查找",
|
"find": "在工作区中查找"
|
||||||
"search": {
|
|
||||||
"configNodes": "配置节点",
|
|
||||||
"unusedConfigNodes": "未使用的配置节点",
|
|
||||||
"invalidNodes": "无效的节点",
|
|
||||||
"uknownNodes": "未知的节点",
|
|
||||||
"unusedSubflows": "未使用的子流程"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"name": "帮助",
|
"name": "帮助",
|
||||||
@ -842,7 +835,14 @@
|
|||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"empty": "找不到匹配",
|
"empty": "找不到匹配",
|
||||||
"addNode": "添加一个节点..."
|
"addNode": "添加一个节点...",
|
||||||
|
"options": {
|
||||||
|
"configNodes": "配置节点",
|
||||||
|
"unusedConfigNodes": "未使用的配置节点",
|
||||||
|
"invalidNodes": "无效的节点",
|
||||||
|
"uknownNodes": "未知的节点",
|
||||||
|
"unusedSubflows": "未使用的子流程"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"expressionEditor": {
|
"expressionEditor": {
|
||||||
"functions": "功能",
|
"functions": "功能",
|
||||||
|
@ -614,14 +614,7 @@
|
|||||||
"empty": "空的",
|
"empty": "空的",
|
||||||
"globalConfig": "全局配置節點",
|
"globalConfig": "全局配置節點",
|
||||||
"triggerAction": "觸發動作",
|
"triggerAction": "觸發動作",
|
||||||
"find": "在工作區中查找",
|
"find": "在工作區中查找"
|
||||||
"search": {
|
|
||||||
"configNodes": "配置節點",
|
|
||||||
"unusedConfigNodes": "未使用的配置節點",
|
|
||||||
"invalidNodes": "無效的節點",
|
|
||||||
"uknownNodes": "未知的節點",
|
|
||||||
"unusedSubflows": "未使用的子流程"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"name": "幫助",
|
"name": "幫助",
|
||||||
@ -842,7 +835,14 @@
|
|||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"empty": "找不到匹配",
|
"empty": "找不到匹配",
|
||||||
"addNode": "添加一個節點..."
|
"addNode": "添加一個節點...",
|
||||||
|
"options": {
|
||||||
|
"configNodes": "配置節點",
|
||||||
|
"unusedConfigNodes": "未使用的配置節點",
|
||||||
|
"invalidNodes": "無效的節點",
|
||||||
|
"uknownNodes": "未知的節點",
|
||||||
|
"unusedSubflows": "未使用的子流程"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"expressionEditor": {
|
"expressionEditor": {
|
||||||
"functions": "功能",
|
"functions": "功能",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/editor-client",
|
"name": "@node-red/editor-client",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -13,6 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An API for undo / redo history buffer
|
||||||
|
* @namespace RED.history
|
||||||
|
*/
|
||||||
RED.history = (function() {
|
RED.history = (function() {
|
||||||
var undoHistory = [];
|
var undoHistory = [];
|
||||||
var redoHistory = [];
|
var redoHistory = [];
|
||||||
|
@ -92,6 +92,8 @@
|
|||||||
"alt-a h": "core:distribute-selection-horizontally",
|
"alt-a h": "core:distribute-selection-horizontally",
|
||||||
"alt-a v": "core:distribute-selection-vertically",
|
"alt-a v": "core:distribute-selection-vertically",
|
||||||
"shift-f": "core:search-previous",
|
"shift-f": "core:search-previous",
|
||||||
"f": "core:search-next"
|
"f": "core:search-next",
|
||||||
|
"alt-l l": "core:split-wire-with-link-nodes"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Interface to nodes and utility functions for creating/adding/deleting nodes and links
|
||||||
|
* @namespace RED.nodes
|
||||||
|
*/
|
||||||
RED.nodes = (function() {
|
RED.nodes = (function() {
|
||||||
|
|
||||||
var PORT_TYPE_INPUT = 1;
|
var PORT_TYPE_INPUT = 1;
|
||||||
@ -600,6 +605,14 @@ RED.nodes = (function() {
|
|||||||
RED.events.emit('nodes:add',n);
|
RED.events.emit('nodes:add',n);
|
||||||
}
|
}
|
||||||
function addLink(l) {
|
function addLink(l) {
|
||||||
|
if (nodeLinks[l.source.id]) {
|
||||||
|
const isUnique = nodeLinks[l.source.id].out.every(function(link) {
|
||||||
|
return link.sourcePort !== l.sourcePort || link.target.id !== l.target.id
|
||||||
|
})
|
||||||
|
if (!isUnique) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
links.push(l);
|
links.push(l);
|
||||||
if (l.source) {
|
if (l.source) {
|
||||||
// Possible the node hasn't been added yet
|
// Possible the node hasn't been added yet
|
||||||
@ -2676,7 +2689,6 @@ RED.nodes = (function() {
|
|||||||
getType: registry.getNodeType,
|
getType: registry.getNodeType,
|
||||||
getNodeHelp: getNodeHelp,
|
getNodeHelp: getNodeHelp,
|
||||||
convertNode: convertNode,
|
convertNode: convertNode,
|
||||||
|
|
||||||
add: addNode,
|
add: addNode,
|
||||||
remove: removeNode,
|
remove: removeNode,
|
||||||
clear: clear,
|
clear: clear,
|
||||||
|
@ -602,7 +602,10 @@ var RED = (function() {
|
|||||||
null,
|
null,
|
||||||
{id: "menu-item-edit-select-all", label:RED._("keyboard.selectAll"), onselect: "core:select-all-nodes"},
|
{id: "menu-item-edit-select-all", label:RED._("keyboard.selectAll"), onselect: "core:select-all-nodes"},
|
||||||
{id: "menu-item-edit-select-connected", label:RED._("keyboard.selectAllConnected"), onselect: "core:select-connected-nodes"},
|
{id: "menu-item-edit-select-connected", label:RED._("keyboard.selectAllConnected"), onselect: "core:select-connected-nodes"},
|
||||||
{id: "menu-item-edit-select-none", label:RED._("keyboard.selectNone"), onselect: "core:select-none"}
|
{id: "menu-item-edit-select-none", label:RED._("keyboard.selectNone"), onselect: "core:select-none"},
|
||||||
|
null,
|
||||||
|
{id: "menu-item-edit-split-wire-with-links", label:RED._("keyboard.splitWireWithLinks"), onselect: "core:split-wire-with-link-nodes"},
|
||||||
|
|
||||||
]});
|
]});
|
||||||
|
|
||||||
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
|
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
|
||||||
|
@ -350,6 +350,15 @@ RED.popover = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target.on("remove", function (ev) {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
if (active) {
|
||||||
|
active = false;
|
||||||
|
setTimeout(closePopup,delay.hide);
|
||||||
|
}
|
||||||
|
});
|
||||||
if (trigger === 'hover') {
|
if (trigger === 'hover') {
|
||||||
target.on('mouseenter',function(e) {
|
target.on('mouseenter',function(e) {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
|
@ -334,6 +334,9 @@ RED.deploy = (function() {
|
|||||||
var invalidNodes = [];
|
var invalidNodes = [];
|
||||||
|
|
||||||
RED.nodes.eachConfig(function(node) {
|
RED.nodes.eachConfig(function(node) {
|
||||||
|
if (node.valid === undefined) {
|
||||||
|
RED.editor.validateNode(node);
|
||||||
|
}
|
||||||
if (!node.valid && !node.d) {
|
if (!node.valid && !node.d) {
|
||||||
invalidNodes.push(getNodeInfo(node));
|
invalidNodes.push(getNodeInfo(node));
|
||||||
}
|
}
|
||||||
|
@ -577,7 +577,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|||||||
createMonacoCompletionItem("set (flow context)", 'flow.set("${1:name}", ${1:value});','Set a value in flow context',range),
|
createMonacoCompletionItem("set (flow context)", 'flow.set("${1:name}", ${1:value});','Set a value in flow context',range),
|
||||||
createMonacoCompletionItem("get (global context)", 'global.get("${1:name}");','Get a value from global context',range),
|
createMonacoCompletionItem("get (global context)", 'global.get("${1:name}");','Get a value from global context',range),
|
||||||
createMonacoCompletionItem("set (global context)", 'global.set("${1:name}", ${1:value});','Set a value in global context',range),
|
createMonacoCompletionItem("set (global context)", 'global.set("${1:name}", ${1:value});','Set a value in global context',range),
|
||||||
createMonacoCompletionItem("get (env)", 'env.get("${1:name}");','Get env variable value',range),
|
createMonacoCompletionItem("get (env)", 'env.get("${1|NR_NODE_ID,NR_NODE_NAME,NR_NODE_PATH,NR_GROUP_ID,NR_GROUP_NAME,NR_FLOW_ID,NR_FLOW_NAME|}");','Get env variable value',range),
|
||||||
createMonacoCompletionItem("cloneMessage (RED.util)", 'RED.util.cloneMessage(${1:msg});',
|
createMonacoCompletionItem("cloneMessage (RED.util)", 'RED.util.cloneMessage(${1:msg});',
|
||||||
["```typescript",
|
["```typescript",
|
||||||
"RED.util.cloneMessage<T extends registry.NodeMessage>(msg: T): T",
|
"RED.util.cloneMessage<T extends registry.NodeMessage>(msg: T): T",
|
||||||
|
@ -625,7 +625,7 @@ RED.keyboard = (function() {
|
|||||||
pane.find("#red-ui-settings-tab-keyboard-filter").searchBox({
|
pane.find("#red-ui-settings-tab-keyboard-filter").searchBox({
|
||||||
delay: 100,
|
delay: 100,
|
||||||
change: function() {
|
change: function() {
|
||||||
var filterValue = $(this).val().trim();
|
var filterValue = $(this).val().trim().toLowerCase();
|
||||||
if (filterValue === "") {
|
if (filterValue === "") {
|
||||||
shortcutList.editableList('filter', null);
|
shortcutList.editableList('filter', null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,6 +121,7 @@ RED.search = (function() {
|
|||||||
val = extractFlag(val,"config",flags);
|
val = extractFlag(val,"config",flags);
|
||||||
val = extractFlag(val,"subflow",flags);
|
val = extractFlag(val,"subflow",flags);
|
||||||
val = extractFlag(val,"hidden",flags);
|
val = extractFlag(val,"hidden",flags);
|
||||||
|
val = extractFlag(val,"modified",flags);
|
||||||
// uses:<node-id>
|
// uses:<node-id>
|
||||||
val = extractValue(val,"uses",flags);
|
val = extractValue(val,"uses",flags);
|
||||||
|
|
||||||
@ -166,6 +167,11 @@ RED.search = (function() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (flags.hasOwnProperty("modified")) {
|
||||||
|
if (!node.node.changed && !node.node.moved) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (flags.hasOwnProperty("hidden")) {
|
if (flags.hasOwnProperty("hidden")) {
|
||||||
// Only tabs can be hidden
|
// Only tabs can be hidden
|
||||||
if (node.node.type !== 'tab') {
|
if (node.node.type !== 'tab') {
|
||||||
@ -263,9 +269,8 @@ RED.search = (function() {
|
|||||||
} else {
|
} else {
|
||||||
searchResults.editableList('addItem',{});
|
searchResults.editableList('addItem',{});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
options: getSearchOptions()
|
||||||
}
|
|
||||||
});
|
});
|
||||||
var copySearchContainer = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-caret-right"></button>').appendTo(searchDiv).on('click', function(evt) {
|
var copySearchContainer = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-caret-right"></button>').appendTo(searchDiv).on('click', function(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
@ -564,6 +569,17 @@ RED.search = (function() {
|
|||||||
addItemToIndex(item);
|
addItemToIndex(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSearchOptions() {
|
||||||
|
return [
|
||||||
|
{label:RED._("search.options.configNodes"), value:"is:config"},
|
||||||
|
{label:RED._("search.options.unusedConfigNodes"), value:"is:config is:unused"},
|
||||||
|
{label:RED._("search.options.modifiedNodes"), value:"is:modified"},
|
||||||
|
{label:RED._("search.options.invalidNodes"), value: "is:invalid"},
|
||||||
|
{label:RED._("search.options.uknownNodes"), value: "type:unknown"},
|
||||||
|
{label:RED._("search.options.unusedSubflows"), value:"is:subflow is:unused"},
|
||||||
|
{label:RED._("search.options.hiddenFlows"), value:"is:hidden"},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
RED.actions.add("core:search",show);
|
RED.actions.add("core:search",show);
|
||||||
@ -615,7 +631,8 @@ RED.search = (function() {
|
|||||||
init: init,
|
init: init,
|
||||||
show: show,
|
show: show,
|
||||||
hide: hide,
|
hide: hide,
|
||||||
search: search
|
search: search,
|
||||||
|
getSearchOptions: getSearchOptions
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -268,14 +268,7 @@ RED.sidebar.info.outliner = (function() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
options: [
|
options: RED.search.getSearchOptions()
|
||||||
{label:RED._("sidebar.info.search.configNodes"), value:"is:config"},
|
|
||||||
{label:RED._("sidebar.info.search.unusedConfigNodes"), value:"is:config is:unused"},
|
|
||||||
{label:RED._("sidebar.info.search.invalidNodes"), value: "is:invalid"},
|
|
||||||
{label:RED._("sidebar.info.search.uknownNodes"), value: "type:unknown"},
|
|
||||||
{label:RED._("sidebar.info.search.unusedSubflows"), value:"is:subflow is:unused"},
|
|
||||||
{label:RED._("sidebar.info.search.hiddenFlows"), value:"is:hidden"},
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
projectInfo = $('<div class="red-ui-treeList-label red-ui-info-outline-project"><span class="red-ui-treeList-icon"><i class="fa fa-archive"></i></span></div>').hide().appendTo(container)
|
projectInfo = $('<div class="red-ui-treeList-label red-ui-info-outline-project"><span class="red-ui-treeList-icon"><i class="fa fa-archive"></i></span></div>').hide().appendTo(container)
|
||||||
@ -287,15 +280,18 @@ RED.sidebar.info.outliner = (function() {
|
|||||||
data:getFlowData()
|
data:getFlowData()
|
||||||
})
|
})
|
||||||
treeList.on('treelistselect', function(e,item) {
|
treeList.on('treelistselect', function(e,item) {
|
||||||
var node = RED.nodes.node(item.id) || RED.nodes.group(item.id);
|
var node = RED.nodes.node(item.id) || RED.nodes.group(item.id) || RED.nodes.workspace(item.id) || RED.nodes.subflow(item.id);
|
||||||
if (node) {
|
if (node) {
|
||||||
if (node.type === 'group' || node._def.category !== "config") {
|
|
||||||
// RED.view.select({nodes:[node]})
|
|
||||||
} else if (node._def.category === "config") {
|
|
||||||
RED.sidebar.info.refresh(node);
|
RED.sidebar.info.refresh(node);
|
||||||
|
// if (node.type === 'group' || node._def.category !== "config") {
|
||||||
|
// // RED.view.select({nodes:[node]})
|
||||||
|
// } else if (node._def.category === "config") {
|
||||||
|
// RED.sidebar.info.refresh(node);
|
||||||
|
// } else {
|
||||||
|
// // RED.view.select({nodes:[]})
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
// RED.view.select({nodes:[]})
|
RED.sidebar.info.refresh(null);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
treeList.on('treelistconfirm', function(e,item) {
|
treeList.on('treelistconfirm', function(e,item) {
|
||||||
|
@ -163,6 +163,7 @@ RED.sidebar.info = (function() {
|
|||||||
});
|
});
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
function refresh(node) {
|
function refresh(node) {
|
||||||
if (node === undefined) {
|
if (node === undefined) {
|
||||||
refreshSelection();
|
refreshSelection();
|
||||||
@ -271,7 +272,7 @@ RED.sidebar.info = (function() {
|
|||||||
objectType = "group";
|
objectType = "group";
|
||||||
}
|
}
|
||||||
$(propRow.children()[0]).text(RED._("sidebar.info."+objectType))
|
$(propRow.children()[0]).text(RED._("sidebar.info."+objectType))
|
||||||
RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
|
RED.utils.createObjectElement(node.id,{sourceId: node.id}).appendTo(propRow.children()[1]);
|
||||||
|
|
||||||
if (node.type === "tab" || node.type === "subflow") {
|
if (node.type === "tab" || node.type === "subflow") {
|
||||||
// If nothing is selected, but we're on a flow or subflow tab.
|
// If nothing is selected, but we're on a flow or subflow tab.
|
||||||
@ -365,7 +366,7 @@ RED.sidebar.info = (function() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RED.utils.createObjectElement(val).appendTo(propRow.children()[1]);
|
RED.utils.createObjectElement(val,{sourceId: node.id}).appendTo(propRow.children()[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,6 +432,7 @@ RED.sidebar.info = (function() {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setInfoText(infoText,target) {
|
function setInfoText(infoText,target) {
|
||||||
var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(target);
|
var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(target);
|
||||||
info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
||||||
@ -447,6 +449,7 @@ RED.sidebar.info = (function() {
|
|||||||
$(this).toggleClass('expanded',!isExpanded);
|
$(this).toggleClass('expanded',!isExpanded);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var tips = (function() {
|
var tips = (function() {
|
||||||
var enabled = true;
|
var enabled = true;
|
||||||
var startDelay = 1000;
|
var startDelay = 1000;
|
||||||
|
@ -365,7 +365,16 @@ RED.utils = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMessageElement(obj,options) {
|
/**
|
||||||
|
* Create a DOM element representation of obj - as used by Debug sidebar etc
|
||||||
|
*
|
||||||
|
* @params obj - the data to display
|
||||||
|
* @params options - a bag of options
|
||||||
|
*
|
||||||
|
* - If you want the Copy Value button, then set `sourceId`
|
||||||
|
* - If you want the Copy Path button, also set `path` to the value to be copied
|
||||||
|
*/
|
||||||
|
function createObjectElement(obj,options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var key = options.key;
|
var key = options.key;
|
||||||
var typeHint = options.typeHint;
|
var typeHint = options.typeHint;
|
||||||
@ -555,7 +564,7 @@ RED.utils = (function() {
|
|||||||
if (fullLength <= 10) {
|
if (fullLength <= 10) {
|
||||||
for (i=0;i<fullLength;i++) {
|
for (i=0;i<fullLength;i++) {
|
||||||
row = $('<div class="red-ui-debug-msg-object-entry collapsed"></div>').appendTo(arrayRows);
|
row = $('<div class="red-ui-debug-msg-object-entry collapsed"></div>').appendTo(arrayRows);
|
||||||
subElements[path+"["+i+"]"] = buildMessageElement(
|
subElements[path+"["+i+"]"] = createObjectElement(
|
||||||
data[i],
|
data[i],
|
||||||
{
|
{
|
||||||
key: ""+i,
|
key: ""+i,
|
||||||
@ -585,7 +594,7 @@ RED.utils = (function() {
|
|||||||
return function() {
|
return function() {
|
||||||
for (var i=min;i<=max;i++) {
|
for (var i=min;i<=max;i++) {
|
||||||
var row = $('<div class="red-ui-debug-msg-object-entry collapsed"></div>').appendTo(parent);
|
var row = $('<div class="red-ui-debug-msg-object-entry collapsed"></div>').appendTo(parent);
|
||||||
subElements[path+"["+i+"]"] = buildMessageElement(
|
subElements[path+"["+i+"]"] = createObjectElement(
|
||||||
data[i],
|
data[i],
|
||||||
{
|
{
|
||||||
key: ""+i,
|
key: ""+i,
|
||||||
@ -641,7 +650,7 @@ RED.utils = (function() {
|
|||||||
newPath += "[\""+keys[i].replace(/"/,"\\\"")+"\"]"
|
newPath += "[\""+keys[i].replace(/"/,"\\\"")+"\"]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subElements[newPath] = buildMessageElement(
|
subElements[newPath] = createObjectElement(
|
||||||
data[keys[i]],
|
data[keys[i]],
|
||||||
{
|
{
|
||||||
key: keys[i],
|
key: keys[i],
|
||||||
@ -1369,7 +1378,7 @@ RED.utils = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createObjectElement: buildMessageElement,
|
createObjectElement: createObjectElement,
|
||||||
getMessageProperty: getMessageProperty,
|
getMessageProperty: getMessageProperty,
|
||||||
setMessageProperty: setMessageProperty,
|
setMessageProperty: setMessageProperty,
|
||||||
normalisePropertyExpression: normalisePropertyExpression,
|
normalisePropertyExpression: normalisePropertyExpression,
|
||||||
|
@ -809,6 +809,167 @@ RED.view.tools = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits selected wires and re-joins them with link-out+link-in
|
||||||
|
* @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes.
|
||||||
|
*/
|
||||||
|
function splitWiresWithLinkNodes(wires) {
|
||||||
|
let wiresToSplit = wires || RED.view.selection().links;
|
||||||
|
if (!Array.isArray(wiresToSplit)) {
|
||||||
|
wiresToSplit = [wiresToSplit];
|
||||||
|
}
|
||||||
|
if (wiresToSplit.length < 1) {
|
||||||
|
return; //nothing selected
|
||||||
|
}
|
||||||
|
|
||||||
|
const history = {
|
||||||
|
t: 'multi',
|
||||||
|
events: [],
|
||||||
|
dirty: RED.nodes.dirty()
|
||||||
|
}
|
||||||
|
const nodeSrcMap = {};
|
||||||
|
const nodeTrgMap = {};
|
||||||
|
const _gridSize = RED.view.gridSize();
|
||||||
|
|
||||||
|
for (let wireIdx = 0; wireIdx < wiresToSplit.length; wireIdx++) {
|
||||||
|
const wire = wiresToSplit[wireIdx];
|
||||||
|
|
||||||
|
//get source and target nodes of this wire link
|
||||||
|
const nSrc = wire.source;
|
||||||
|
const nTrg = wire.target;
|
||||||
|
|
||||||
|
var updateNewNodePosXY = function (origNode, newNode, alignLeft, snap, yOffset) {
|
||||||
|
const nnSize = RED.view.calculateNodeDimensions(newNode);
|
||||||
|
newNode.w = nnSize[0];
|
||||||
|
newNode.h = nnSize[1];
|
||||||
|
const coords = { x: origNode.x || 0, y: origNode.y || 0, w: origNode.w || RED.view.node_width, h: origNode.h || RED.view.node_height };
|
||||||
|
const x = coords.x - (coords.w/2.0);
|
||||||
|
if (alignLeft) {
|
||||||
|
coords.x = x - _gridSize - (newNode.w/2.0);
|
||||||
|
} else {
|
||||||
|
coords.x = x + coords.w + _gridSize + (newNode.w/2.0);
|
||||||
|
}
|
||||||
|
newNode.x = coords.x;
|
||||||
|
newNode.y = coords.y;
|
||||||
|
if (snap !== false) {
|
||||||
|
const offsets = RED.view.tools.calculateGridSnapOffsets(newNode);
|
||||||
|
newNode.x -= offsets.x;
|
||||||
|
newNode.y -= offsets.y;
|
||||||
|
}
|
||||||
|
newNode.y += (yOffset || 0);
|
||||||
|
}
|
||||||
|
const srcPort = (wire.sourcePort || 0);
|
||||||
|
let linkOutMapId = nSrc.id + ':' + srcPort;
|
||||||
|
let nnLinkOut = nodeSrcMap[linkOutMapId];
|
||||||
|
//Create a Link Out if one is not already present
|
||||||
|
if(!nnLinkOut) {
|
||||||
|
const nLinkOut = RED.view.createNode("link out"); //create link node
|
||||||
|
nnLinkOut = nLinkOut.node;
|
||||||
|
nodeSrcMap[linkOutMapId] = nnLinkOut;
|
||||||
|
let yOffset = 0;
|
||||||
|
if(nSrc.outputs > 1) {
|
||||||
|
|
||||||
|
const CENTER_PORT = (((nSrc.outputs-1) / 2) + 1);
|
||||||
|
const offsetCount = Math.abs(CENTER_PORT - (srcPort + 1));
|
||||||
|
yOffset = (_gridSize * 2 * offsetCount);
|
||||||
|
if((srcPort + 1) < CENTER_PORT) {
|
||||||
|
yOffset = -yOffset;
|
||||||
|
}
|
||||||
|
updateNewNodePosXY(nSrc, nnLinkOut, false, false, yOffset);
|
||||||
|
} else {
|
||||||
|
updateNewNodePosXY(nSrc, nnLinkOut, false, RED.view.snapGrid, yOffset);
|
||||||
|
}
|
||||||
|
//add created node
|
||||||
|
RED.nodes.add(nnLinkOut);
|
||||||
|
RED.editor.validateNode(nnLinkOut);
|
||||||
|
history.events.push(nLinkOut.historyEvent);
|
||||||
|
//connect node to link node
|
||||||
|
const link = {
|
||||||
|
source: nSrc,
|
||||||
|
sourcePort: wire.sourcePort || 0,
|
||||||
|
target: nnLinkOut
|
||||||
|
};
|
||||||
|
RED.nodes.addLink(link);
|
||||||
|
history.events.push({
|
||||||
|
t: 'add',
|
||||||
|
links: [link],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let nnLinkIn = nodeTrgMap[nTrg.id];
|
||||||
|
//Create a Link In if one is not already present
|
||||||
|
if(!nnLinkIn) {
|
||||||
|
const nLinkIn = RED.view.createNode("link in"); //create link node
|
||||||
|
nnLinkIn = nLinkIn.node;
|
||||||
|
nodeTrgMap[nTrg.id] = nnLinkIn;
|
||||||
|
updateNewNodePosXY(nTrg, nnLinkIn, true, RED.view.snapGrid, 0);
|
||||||
|
//add created node
|
||||||
|
RED.nodes.add(nnLinkIn);
|
||||||
|
RED.editor.validateNode(nnLinkIn);
|
||||||
|
history.events.push(nLinkIn.historyEvent);
|
||||||
|
//connect node to link node
|
||||||
|
const link = {
|
||||||
|
source: nnLinkIn,
|
||||||
|
sourcePort: 0,
|
||||||
|
target: nTrg
|
||||||
|
};
|
||||||
|
RED.nodes.addLink(link);
|
||||||
|
history.events.push({
|
||||||
|
t: 'add',
|
||||||
|
links: [link],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//connect the link out/link in virtual wires
|
||||||
|
if(nnLinkIn.links.indexOf(nnLinkOut.id) == -1) {
|
||||||
|
nnLinkIn.links.push(nnLinkOut.id);
|
||||||
|
}
|
||||||
|
if(nnLinkOut.links.indexOf(nnLinkIn.id) == -1) {
|
||||||
|
nnLinkOut.links.push(nnLinkIn.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete the original wire
|
||||||
|
RED.nodes.removeLink(wire);
|
||||||
|
history.events.push({
|
||||||
|
t: "delete",
|
||||||
|
links: [wire]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//add all history events to stack
|
||||||
|
RED.history.push(history);
|
||||||
|
|
||||||
|
//select all downstream of new link-in nodes so user can drag to new location
|
||||||
|
RED.view.clearSelection();
|
||||||
|
RED.view.select({nodes: Object.values(nodeTrgMap) });
|
||||||
|
selectConnected("down");
|
||||||
|
|
||||||
|
//update the view
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the required offsets to snap a node
|
||||||
|
* @param {Object} node The node to calculate grid snap offsets for
|
||||||
|
* @param {Object} [options] Options: `align` can be "nearest", "left" or "right"
|
||||||
|
* @returns `{x:number, y:number}` as the offsets to deduct from `x` and `y`
|
||||||
|
*/
|
||||||
|
function calculateGridSnapOffsets(node, options) {
|
||||||
|
options = options || { align: "nearest" };
|
||||||
|
const gridOffset = { x: 0, y: 0 };
|
||||||
|
const gridSize = RED.view.gridSize();
|
||||||
|
const offsetLeft = node.x - (gridSize * Math.round((node.x - node.w / 2) / gridSize) + node.w / 2);
|
||||||
|
const offsetRight = node.x - (gridSize * Math.round((node.x + node.w / 2) / gridSize) - node.w / 2);
|
||||||
|
gridOffset.x = offsetRight;
|
||||||
|
if (options.align === "right") {
|
||||||
|
//skip - already set to right
|
||||||
|
} else if (options.align === "left" || Math.abs(offsetLeft) < Math.abs(offsetRight)) {
|
||||||
|
gridOffset.x = offsetLeft;
|
||||||
|
}
|
||||||
|
gridOffset.y = node.y - (gridSize * Math.round(node.y / gridSize));
|
||||||
|
return gridOffset;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
||||||
@ -870,6 +1031,8 @@ RED.view.tools = (function() {
|
|||||||
RED.actions.add("core:wire-series-of-nodes", function() { wireSeriesOfNodes() })
|
RED.actions.add("core:wire-series-of-nodes", function() { wireSeriesOfNodes() })
|
||||||
RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
|
RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
|
||||||
|
|
||||||
|
RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
|
||||||
|
|
||||||
// RED.actions.add("core:add-node", function() { addNode() })
|
// RED.actions.add("core:add-node", function() { addNode() })
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@ -881,7 +1044,8 @@ RED.view.tools = (function() {
|
|||||||
* @param {Number} dx
|
* @param {Number} dx
|
||||||
* @param {Number} dy
|
* @param {Number} dy
|
||||||
*/
|
*/
|
||||||
moveSelection: moveSelection
|
moveSelection: moveSelection,
|
||||||
|
calculateGridSnapOffsets: calculateGridSnapOffsets
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -479,7 +479,7 @@ RED.view = (function() {
|
|||||||
drop: function( event, ui ) {
|
drop: function( event, ui ) {
|
||||||
d3.event = event;
|
d3.event = event;
|
||||||
var selected_tool = $(ui.draggable[0]).attr("data-palette-type");
|
var selected_tool = $(ui.draggable[0]).attr("data-palette-type");
|
||||||
var result = addNode(selected_tool);
|
var result = createNode(selected_tool);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -523,15 +523,7 @@ RED.view = (function() {
|
|||||||
nn.y = mousePos[1];
|
nn.y = mousePos[1];
|
||||||
|
|
||||||
if (snapGrid) {
|
if (snapGrid) {
|
||||||
var gridOffset = [0,0];
|
var gridOffset = calculateGridSnapOffsets(nn);
|
||||||
var offsetLeft = nn.x-(gridSize*Math.round((nn.x-nn.w/2)/gridSize)+nn.w/2);
|
|
||||||
var offsetRight = nn.x-(gridSize*Math.round((nn.x+nn.w/2)/gridSize)-nn.w/2);
|
|
||||||
if (Math.abs(offsetLeft) < Math.abs(offsetRight)) {
|
|
||||||
gridOffset[0] = offsetLeft
|
|
||||||
} else {
|
|
||||||
gridOffset[0] = offsetRight
|
|
||||||
}
|
|
||||||
gridOffset[1] = nn.y-(gridSize*Math.round(nn.y/gridSize));
|
|
||||||
nn.x -= gridOffset[0];
|
nn.x -= gridOffset[0];
|
||||||
nn.y -= gridOffset[1];
|
nn.y -= gridOffset[1];
|
||||||
}
|
}
|
||||||
@ -957,81 +949,6 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNode(type,x,y) {
|
|
||||||
var m = /^subflow:(.+)$/.exec(type);
|
|
||||||
|
|
||||||
if (activeSubflow && m) {
|
|
||||||
var subflowId = m[1];
|
|
||||||
if (subflowId === activeSubflow.id) {
|
|
||||||
RED.notify(RED._("notification.error",{message: RED._("notification.errors.cannotAddSubflowToItself")}),"error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (RED.nodes.subflowContains(m[1],activeSubflow.id)) {
|
|
||||||
RED.notify(RED._("notification.error",{message: RED._("notification.errors.cannotAddCircularReference")}),"error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var nn = { id:RED.nodes.id(),z:RED.workspaces.active()};
|
|
||||||
|
|
||||||
nn.type = type;
|
|
||||||
nn._def = RED.nodes.getType(nn.type);
|
|
||||||
|
|
||||||
if (!m) {
|
|
||||||
nn.inputs = nn._def.inputs || 0;
|
|
||||||
nn.outputs = nn._def.outputs;
|
|
||||||
|
|
||||||
for (var d in nn._def.defaults) {
|
|
||||||
if (nn._def.defaults.hasOwnProperty(d)) {
|
|
||||||
if (nn._def.defaults[d].value !== undefined) {
|
|
||||||
nn[d] = JSON.parse(JSON.stringify(nn._def.defaults[d].value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nn._def.onadd) {
|
|
||||||
try {
|
|
||||||
nn._def.onadd.call(nn);
|
|
||||||
} catch(err) {
|
|
||||||
console.log("Definition error: "+nn.type+".onadd:",err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var subflow = RED.nodes.subflow(m[1]);
|
|
||||||
nn.name = "";
|
|
||||||
nn.inputs = subflow.in.length;
|
|
||||||
nn.outputs = subflow.out.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
nn.changed = true;
|
|
||||||
nn.moved = true;
|
|
||||||
|
|
||||||
nn.w = node_width;
|
|
||||||
nn.h = Math.max(node_height,(nn.outputs||0) * 15);
|
|
||||||
nn.resize = true;
|
|
||||||
|
|
||||||
var historyEvent = {
|
|
||||||
t:"add",
|
|
||||||
nodes:[nn.id],
|
|
||||||
dirty:RED.nodes.dirty()
|
|
||||||
}
|
|
||||||
if (activeSubflow) {
|
|
||||||
var subflowRefresh = RED.subflow.refresh(true);
|
|
||||||
if (subflowRefresh) {
|
|
||||||
historyEvent.subflow = {
|
|
||||||
id:activeSubflow.id,
|
|
||||||
changed: activeSubflow.changed,
|
|
||||||
instances: subflowRefresh.instances
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
node: nn,
|
|
||||||
historyEvent: historyEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function canvasMouseDown() {
|
function canvasMouseDown() {
|
||||||
if (RED.view.DEBUG) { console.warn("canvasMouseDown", mouse_mode); }
|
if (RED.view.DEBUG) { console.warn("canvasMouseDown", mouse_mode); }
|
||||||
var point;
|
var point;
|
||||||
@ -1220,7 +1137,7 @@ RED.view = (function() {
|
|||||||
keepAdding = false;
|
keepAdding = false;
|
||||||
resetMouseVars();
|
resetMouseVars();
|
||||||
}
|
}
|
||||||
var result = addNode(type);
|
var result = createNode(type);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1673,16 +1590,9 @@ RED.view = (function() {
|
|||||||
gridOffset[0] = node.n.x-(gridSize*Math.floor(node.n.x/gridSize))-gridSize/2;
|
gridOffset[0] = node.n.x-(gridSize*Math.floor(node.n.x/gridSize))-gridSize/2;
|
||||||
gridOffset[1] = node.n.y-(gridSize*Math.floor(node.n.y/gridSize))-gridSize/2;
|
gridOffset[1] = node.n.y-(gridSize*Math.floor(node.n.y/gridSize))-gridSize/2;
|
||||||
} else {
|
} else {
|
||||||
var offsetLeft = node.n.x-(gridSize*Math.round((node.n.x-node.n.w/2)/gridSize)+node.n.w/2);
|
const snapOffsets = RED.view.tools.calculateGridSnapOffsets(node.n);
|
||||||
var offsetRight = node.n.x-(gridSize*Math.round((node.n.x+node.n.w/2)/gridSize)-node.n.w/2);
|
gridOffset[0] = snapOffsets.x;
|
||||||
// gridOffset[0] = node.n.x-(gridSize*Math.floor((node.n.x-node.n.w/2)/gridSize)+node.n.w/2);
|
gridOffset[1] = snapOffsets.y;
|
||||||
if (Math.abs(offsetLeft) < Math.abs(offsetRight)) {
|
|
||||||
gridOffset[0] = offsetLeft
|
|
||||||
} else {
|
|
||||||
gridOffset[0] = offsetRight
|
|
||||||
}
|
|
||||||
gridOffset[1] = node.n.y-(gridSize*Math.round(node.n.y/gridSize));
|
|
||||||
// console.log(offsetLeft, offsetRight);
|
|
||||||
}
|
}
|
||||||
if (gridOffset[0] !== 0 || gridOffset[1] !== 0) {
|
if (gridOffset[0] !== 0 || gridOffset[1] !== 0) {
|
||||||
for (i = 0; i<movingSet.length(); i++) {
|
for (i = 0; i<movingSet.length(); i++) {
|
||||||
@ -2371,14 +2281,21 @@ RED.view = (function() {
|
|||||||
var removedSubflowStatus;
|
var removedSubflowStatus;
|
||||||
var subflowInstances = [];
|
var subflowInstances = [];
|
||||||
var historyEvents = [];
|
var historyEvents = [];
|
||||||
|
var addToRemovedLinks = function(links) {
|
||||||
|
if(!links) { return; }
|
||||||
|
var _links = Array.isArray(links) ? links : [links];
|
||||||
|
_links.forEach(function(l) {
|
||||||
|
removedLinks.push(l);
|
||||||
|
selectedLinks.remove(l);
|
||||||
|
})
|
||||||
|
}
|
||||||
if (reconnectWires) {
|
if (reconnectWires) {
|
||||||
var reconnectResult = RED.nodes.detachNodes(movingSet.nodes())
|
var reconnectResult = RED.nodes.detachNodes(movingSet.nodes())
|
||||||
var addedLinks = reconnectResult.newLinks;
|
var addedLinks = reconnectResult.newLinks;
|
||||||
if (addedLinks.length > 0) {
|
if (addedLinks.length > 0) {
|
||||||
historyEvents.push({ t:'add', links: addedLinks })
|
historyEvents.push({ t:'add', links: addedLinks })
|
||||||
}
|
}
|
||||||
removedLinks = removedLinks.concat(reconnectResult.removedLinks)
|
addToRemovedLinks(reconnectResult.removedLinks)
|
||||||
}
|
}
|
||||||
|
|
||||||
var startDirty = RED.nodes.dirty();
|
var startDirty = RED.nodes.dirty();
|
||||||
@ -2410,7 +2327,7 @@ RED.view = (function() {
|
|||||||
var removedEntities = RED.nodes.remove(node.id);
|
var removedEntities = RED.nodes.remove(node.id);
|
||||||
removedNodes.push(node);
|
removedNodes.push(node);
|
||||||
removedNodes = removedNodes.concat(removedEntities.nodes);
|
removedNodes = removedNodes.concat(removedEntities.nodes);
|
||||||
removedLinks = removedLinks.concat(removedEntities.links);
|
addToRemovedLinks(removedNodes.removedLinks);
|
||||||
if (node.g) {
|
if (node.g) {
|
||||||
var group = RED.nodes.group(node.g);
|
var group = RED.nodes.group(node.g);
|
||||||
if (selectedGroups.indexOf(group) === -1) {
|
if (selectedGroups.indexOf(group) === -1) {
|
||||||
@ -2443,20 +2360,20 @@ RED.view = (function() {
|
|||||||
if (removedSubflowOutputs.length > 0) {
|
if (removedSubflowOutputs.length > 0) {
|
||||||
result = RED.subflow.removeOutput(removedSubflowOutputs);
|
result = RED.subflow.removeOutput(removedSubflowOutputs);
|
||||||
if (result) {
|
if (result) {
|
||||||
removedLinks = removedLinks.concat(result.links);
|
addToRemovedLinks(result.links);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Assume 0/1 inputs
|
// Assume 0/1 inputs
|
||||||
if (removedSubflowInputs.length == 1) {
|
if (removedSubflowInputs.length == 1) {
|
||||||
result = RED.subflow.removeInput();
|
result = RED.subflow.removeInput();
|
||||||
if (result) {
|
if (result) {
|
||||||
removedLinks = removedLinks.concat(result.links);
|
addToRemovedLinks(result.links);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (removedSubflowStatus) {
|
if (removedSubflowStatus) {
|
||||||
result = RED.subflow.removeStatus();
|
result = RED.subflow.removeStatus();
|
||||||
if (result) {
|
if (result) {
|
||||||
removedLinks = removedLinks.concat(result.links);
|
addToRemovedLinks(result.links);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5534,6 +5451,93 @@ RED.view = (function() {
|
|||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node from a type string.
|
||||||
|
* **NOTE:** Can throw on error - use `try` `catch` block when calling
|
||||||
|
* @param {string} type The node type to create
|
||||||
|
* @param {number} [x] (optional) The horizontal position on the workspace
|
||||||
|
* @param {number} [y] (optional)The vertical on the workspace
|
||||||
|
* @param {string} [z] (optional) The flow tab this node will belong to. Defaults to active workspace.
|
||||||
|
* @returns An object containing the `node` and a `historyEvent`
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function createNode(type, x, y, z) {
|
||||||
|
var m = /^subflow:(.+)$/.exec(type);
|
||||||
|
var activeSubflow = z ? RED.nodes.subflow(z) : null;
|
||||||
|
if (activeSubflow && m) {
|
||||||
|
var subflowId = m[1];
|
||||||
|
if (subflowId === activeSubflow.id) {
|
||||||
|
throw new Error(RED._("notification.error", { message: RED._("notification.errors.cannotAddSubflowToItself") }))
|
||||||
|
}
|
||||||
|
if (RED.nodes.subflowContains(m[1], activeSubflow.id)) {
|
||||||
|
throw new Error(RED._("notification.error", { message: RED._("notification.errors.cannotAddCircularReference") }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var nn = { id: RED.nodes.id(), z: z || RED.workspaces.active() };
|
||||||
|
|
||||||
|
nn.type = type;
|
||||||
|
nn._def = RED.nodes.getType(nn.type);
|
||||||
|
|
||||||
|
if (!m) {
|
||||||
|
nn.inputs = nn._def.inputs || 0;
|
||||||
|
nn.outputs = nn._def.outputs;
|
||||||
|
|
||||||
|
for (var d in nn._def.defaults) {
|
||||||
|
if (nn._def.defaults.hasOwnProperty(d)) {
|
||||||
|
if (nn._def.defaults[d].value !== undefined) {
|
||||||
|
nn[d] = JSON.parse(JSON.stringify(nn._def.defaults[d].value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nn._def.onadd) {
|
||||||
|
try {
|
||||||
|
nn._def.onadd.call(nn);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("Definition error: " + nn.type + ".onadd:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var subflow = RED.nodes.subflow(m[1]);
|
||||||
|
nn.name = "";
|
||||||
|
nn.inputs = subflow.in.length;
|
||||||
|
nn.outputs = subflow.out.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn.changed = true;
|
||||||
|
nn.moved = true;
|
||||||
|
|
||||||
|
nn.w = RED.view.node_width;
|
||||||
|
nn.h = Math.max(RED.view.node_height, (nn.outputs || 0) * 15);
|
||||||
|
nn.resize = true;
|
||||||
|
if (x != null && typeof x == "number" && x >= 0) {
|
||||||
|
nn.x = x;
|
||||||
|
}
|
||||||
|
if (y != null && typeof y == "number" && y >= 0) {
|
||||||
|
nn.y = y;
|
||||||
|
}
|
||||||
|
var historyEvent = {
|
||||||
|
t: "add",
|
||||||
|
nodes: [nn.id],
|
||||||
|
dirty: RED.nodes.dirty()
|
||||||
|
}
|
||||||
|
if (activeSubflow) {
|
||||||
|
var subflowRefresh = RED.subflow.refresh(true);
|
||||||
|
if (subflowRefresh) {
|
||||||
|
historyEvent.subflow = {
|
||||||
|
id: activeSubflow.id,
|
||||||
|
changed: activeSubflow.changed,
|
||||||
|
instances: subflowRefresh.instances
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
node: nn,
|
||||||
|
historyEvent: historyEvent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function calculateNodeDimensions(node) {
|
function calculateNodeDimensions(node) {
|
||||||
var result = [node_width,node_height];
|
var result = [node_width,node_height];
|
||||||
try {
|
try {
|
||||||
@ -5648,7 +5652,21 @@ RED.view = (function() {
|
|||||||
redraw(true);
|
redraw(true);
|
||||||
},
|
},
|
||||||
selection: getSelection,
|
selection: getSelection,
|
||||||
|
clearSelection: clearSelection,
|
||||||
|
createNode: createNode,
|
||||||
|
/** default node width */
|
||||||
|
get node_width() {
|
||||||
|
return node_width;
|
||||||
|
},
|
||||||
|
/** default node height */
|
||||||
|
get node_height() {
|
||||||
|
return node_height;
|
||||||
|
},
|
||||||
|
/** snap to grid option state */
|
||||||
|
get snapGrid() {
|
||||||
|
return snapGrid;
|
||||||
|
},
|
||||||
|
/** gets the current scale factor */
|
||||||
scale: function() {
|
scale: function() {
|
||||||
return scaleFactor;
|
return scaleFactor;
|
||||||
},
|
},
|
||||||
|
@ -431,6 +431,9 @@ RED.workspaces = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
RED.actions.add("core:list-modified-nodes",function() {
|
||||||
|
RED.actions.invoke("core:search","is:modified ");
|
||||||
|
})
|
||||||
RED.actions.add("core:list-hidden-flows",function() {
|
RED.actions.add("core:list-hidden-flows",function() {
|
||||||
RED.actions.invoke("core:search","is:hidden ");
|
RED.actions.invoke("core:search","is:hidden ");
|
||||||
})
|
})
|
||||||
|
@ -263,6 +263,20 @@ declare class global {
|
|||||||
static keys(store: string, callback: Function);
|
static keys(store: string, callback: Function);
|
||||||
}
|
}
|
||||||
declare class env {
|
declare class env {
|
||||||
/** Get an environment variable value */
|
/**
|
||||||
static get(name:string);
|
* Get an environment variable value
|
||||||
|
*
|
||||||
|
* Predefined node-red variables...
|
||||||
|
* * `NR_NODE_ID` - the ID of the node
|
||||||
|
* * `NR_NODE_NAME` - the Name of the node
|
||||||
|
* * `NR_NODE_PATH` - the Path of the node
|
||||||
|
* * `NR_GROUP_ID` - the ID of the containing group
|
||||||
|
* * `NR_GROUP_NAME` - the Name of the containing group
|
||||||
|
* * `NR_FLOW_ID` - the ID of the flow the node is on
|
||||||
|
* * `NR_FLOW_NAME` - the Name of the flow the node is on
|
||||||
|
* @param name Name of the environment variable to get
|
||||||
|
* @example
|
||||||
|
* ```const flowName = env.get("NR_FLOW_NAME");```
|
||||||
|
*/
|
||||||
|
static get(name:string) :string;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ module.exports = function(RED) {
|
|||||||
catch(e) { return false;}
|
catch(e) { return false;}
|
||||||
}
|
}
|
||||||
else if (b === "null") { return a === null; }
|
else if (b === "null") { return a === null; }
|
||||||
|
else if (b === "number") { return typeof a === b && !isNaN(a) }
|
||||||
else { return typeof a === b && !Array.isArray(a) && !Buffer.isBuffer(a) && a !== null; }
|
else { return typeof a === b && !Array.isArray(a) && !Buffer.isBuffer(a) && a !== null; }
|
||||||
},
|
},
|
||||||
'head': function(a, b, c, d, parts) {
|
'head': function(a, b, c, d, parts) {
|
||||||
|
@ -115,7 +115,7 @@
|
|||||||
timeoutUnits: {value:"seconds"},
|
timeoutUnits: {value:"seconds"},
|
||||||
rate: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
rate: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
nbRateUnits: {value:"1", required:false,
|
nbRateUnits: {value:"1", required:false,
|
||||||
validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
validate:function(v) { return v === undefined || (RED.validators.number(v) && (v >= 0)); }},
|
||||||
rateUnits: {value: "second"},
|
rateUnits: {value: "second"},
|
||||||
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||||
|
@ -637,24 +637,8 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
node.deregister = function(mqttNode,done) {
|
node.deregister = function(mqttNode,done) {
|
||||||
delete node.users[mqttNode.id];
|
delete node.users[mqttNode.id];
|
||||||
if (node.closing) {
|
if (!node.closing && node.connected && Object.keys(node.users).length === 0) {
|
||||||
return done();
|
node.disconnect();
|
||||||
}
|
|
||||||
if (Object.keys(node.users).length === 0) {
|
|
||||||
if (node.client && node.client.connected) {
|
|
||||||
// Send close message
|
|
||||||
if (node.closeMessage) {
|
|
||||||
node.publish(node.closeMessage,function(err) {
|
|
||||||
node.client.end(done);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
node.client.end(done);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (node.client) { node.client.end(); }
|
|
||||||
return done();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
@ -663,6 +647,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
node.connect = function (callback) {
|
node.connect = function (callback) {
|
||||||
if (node.canConnect()) {
|
if (node.canConnect()) {
|
||||||
|
node.closing = false;
|
||||||
node.connecting = true;
|
node.connecting = true;
|
||||||
setStatusConnecting(node, true);
|
setStatusConnecting(node, true);
|
||||||
try {
|
try {
|
||||||
@ -672,6 +657,7 @@ module.exports = function(RED) {
|
|||||||
let callbackDone = false; //prevent re-connects causing node.client.on('connect' firing callback multiple times
|
let callbackDone = false; //prevent re-connects causing node.client.on('connect' firing callback multiple times
|
||||||
// Register successful connect or reconnect handler
|
// Register successful connect or reconnect handler
|
||||||
node.client.on('connect', function (connack) {
|
node.client.on('connect', function (connack) {
|
||||||
|
node.closing = false;
|
||||||
node.connecting = false;
|
node.connecting = false;
|
||||||
node.connected = true;
|
node.connected = true;
|
||||||
if(!callbackDone && typeof callback == "function") {
|
if(!callbackDone && typeof callback == "function") {
|
||||||
@ -740,6 +726,7 @@ module.exports = function(RED) {
|
|||||||
reasonCode: rc,
|
reasonCode: rc,
|
||||||
reasonString: rs
|
reasonString: rs
|
||||||
}
|
}
|
||||||
|
node.connected = false;
|
||||||
node.log(RED._("mqtt.state.broker-disconnected", details));
|
node.log(RED._("mqtt.state.broker-disconnected", details));
|
||||||
setStatusDisconnected(node, true);
|
setStatusDisconnected(node, true);
|
||||||
});
|
});
|
||||||
@ -764,25 +751,31 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
node.disconnect = function (callback) {
|
node.disconnect = function (callback) {
|
||||||
const _callback = function () {
|
const _callback = function (resetNodeConnectedState) {
|
||||||
setStatusDisconnected(node, true);
|
setStatusDisconnected(node, true);
|
||||||
|
if(resetNodeConnectedState) {
|
||||||
|
node.closing = true;
|
||||||
node.connecting = false;
|
node.connecting = false;
|
||||||
node.connected = false;
|
node.connected = false;
|
||||||
|
}
|
||||||
callback && typeof callback == "function" && callback();
|
callback && typeof callback == "function" && callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
if(node.client) {
|
if(node.closing) {
|
||||||
if(node.client.connected && node.closeMessage) {
|
return _callback(false);
|
||||||
node.publish(node.closeMessage, function (err) {
|
|
||||||
node.client.end(_callback);
|
|
||||||
});
|
|
||||||
} else if(node.client.connected || node.client.reconnecting) {
|
|
||||||
node.client.end(_callback);
|
|
||||||
} else if(node.client.disconnecting || node.client.connected === false) {
|
|
||||||
_callback();
|
|
||||||
}
|
}
|
||||||
|
var endCallBack = function endCallBack() {
|
||||||
|
}
|
||||||
|
if(node.connected && node.closeMessage) {
|
||||||
|
node.publish(node.closeMessage, function (err) {
|
||||||
|
node.client.end(endCallBack);
|
||||||
|
_callback(true);
|
||||||
|
});
|
||||||
|
} else if(node.connected) {
|
||||||
|
node.client.end(endCallBack);
|
||||||
|
_callback(true);
|
||||||
} else {
|
} else {
|
||||||
_callback();
|
_callback(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.subscriptionIds = {};
|
node.subscriptionIds = {};
|
||||||
@ -1074,6 +1067,8 @@ module.exports = function(RED) {
|
|||||||
node.brokerConn.unsubscribe(node.topic,node.id, removed);
|
node.brokerConn.unsubscribe(node.topic,node.id, removed);
|
||||||
}
|
}
|
||||||
node.brokerConn.deregister(node, done);
|
node.brokerConn.deregister(node, done);
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -1134,7 +1129,11 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
node.brokerConn.register(node);
|
node.brokerConn.register(node);
|
||||||
node.on('close', function(done) {
|
node.on('close', function(done) {
|
||||||
|
if (node.brokerConn) {
|
||||||
node.brokerConn.deregister(node,done);
|
node.brokerConn.deregister(node,done);
|
||||||
|
} else {
|
||||||
|
done();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
node.error(RED._("mqtt.errors.missing-config"));
|
node.error(RED._("mqtt.errors.missing-config"));
|
||||||
|
@ -291,8 +291,8 @@
|
|||||||
"hour": "時間",
|
"hour": "時間",
|
||||||
"days": "日",
|
"days": "日",
|
||||||
"day": "日",
|
"day": "日",
|
||||||
"between": "頻度",
|
"between": "範囲",
|
||||||
"and": "回/",
|
"and": "〜",
|
||||||
"rate": "流量",
|
"rate": "流量",
|
||||||
"msgper": "メッセージ/",
|
"msgper": "メッセージ/",
|
||||||
"queuemsg": "中間メッセージをキューに追加",
|
"queuemsg": "中間メッセージをキューに追加",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/nodes",
|
"name": "@node-red/nodes",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -17,12 +17,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "8.7.0",
|
"acorn": "8.7.0",
|
||||||
"acorn-walk": "8.2.0",
|
"acorn-walk": "8.2.0",
|
||||||
"ajv": "8.9.0",
|
"ajv": "8.10.0",
|
||||||
"body-parser": "1.19.1",
|
"body-parser": "1.19.1",
|
||||||
"cheerio": "1.0.0-rc.10",
|
"cheerio": "1.0.0-rc.10",
|
||||||
"content-type": "1.0.4",
|
"content-type": "1.0.4",
|
||||||
"cookie-parser": "1.4.6",
|
"cookie-parser": "1.4.6",
|
||||||
"cookie": "0.4.1",
|
"cookie": "0.4.2",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"cronosjs": "1.7.1",
|
"cronosjs": "1.7.1",
|
||||||
"denque": "2.0.1",
|
"denque": "2.0.1",
|
||||||
@ -36,11 +36,11 @@
|
|||||||
"is-utf8": "0.2.1",
|
"is-utf8": "0.2.1",
|
||||||
"js-yaml": "3.14.1",
|
"js-yaml": "3.14.1",
|
||||||
"media-typer": "1.1.0",
|
"media-typer": "1.1.0",
|
||||||
"mqtt": "4.3.4",
|
"mqtt": "4.3.5",
|
||||||
"multer": "1.4.4",
|
"multer": "1.4.4",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
"on-headers": "1.0.2",
|
"on-headers": "1.0.2",
|
||||||
"raw-body": "2.4.2",
|
"raw-body": "2.4.3",
|
||||||
"tough-cookie": "4.0.0",
|
"tough-cookie": "4.0.0",
|
||||||
"uuid": "8.3.2",
|
"uuid": "8.3.2",
|
||||||
"ws": "7.5.6",
|
"ws": "7.5.6",
|
||||||
|
@ -353,7 +353,6 @@ async function loadPluginConfig(fileInfo) {
|
|||||||
*/
|
*/
|
||||||
function loadNodeSet(node) {
|
function loadNodeSet(node) {
|
||||||
if (!node.enabled) {
|
if (!node.enabled) {
|
||||||
console.log("BAIL ON",node.id)
|
|
||||||
return Promise.resolve(node);
|
return Promise.resolve(node);
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/registry",
|
"name": "@node-red/registry",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,11 +16,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/util": "2.2.0",
|
"@node-red/util": "2.2.2",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"fs-extra": "10.0.0",
|
"fs-extra": "10.0.0",
|
||||||
"semver": "7.3.5",
|
"semver": "7.3.5",
|
||||||
"tar": "6.1.11",
|
"tar": "6.1.11",
|
||||||
"uglify-js": "3.15.0"
|
"uglify-js": "3.15.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,15 +77,16 @@ function createNode(flow,config) {
|
|||||||
if (typeof nodeTypeConstructor === "function") {
|
if (typeof nodeTypeConstructor === "function") {
|
||||||
var conf = clone(config);
|
var conf = clone(config);
|
||||||
delete conf.credentials;
|
delete conf.credentials;
|
||||||
|
try {
|
||||||
|
Object.defineProperty(conf,'_module', {value: typeRegistry.getNodeInfo(type), enumerable: false, writable: true })
|
||||||
|
Object.defineProperty(conf,'_flow', {value: flow, enumerable: false, writable: true })
|
||||||
|
Object.defineProperty(conf,'_path', {value: `${flow.path}/${config._alias||config.id}`, enumerable: false, writable: true })
|
||||||
|
|
||||||
for (var p in conf) {
|
for (var p in conf) {
|
||||||
if (conf.hasOwnProperty(p)) {
|
if (conf.hasOwnProperty(p)) {
|
||||||
mapEnvVarProperties(conf,p,flow,conf);
|
mapEnvVarProperties(conf,p,flow,conf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
Object.defineProperty(conf,'_module', {value: typeRegistry.getNodeInfo(type), enumerable: false, writable: true })
|
|
||||||
Object.defineProperty(conf,'_flow', {value: flow, enumerable: false, writable: true })
|
|
||||||
Object.defineProperty(conf,'_path', {value: `${flow.path}/${config._alias||config.id}`, enumerable: false, writable: true })
|
|
||||||
newNode = new nodeTypeConstructor(conf);
|
newNode = new nodeTypeConstructor(conf);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Log.log({
|
Log.log({
|
||||||
|
@ -503,10 +503,25 @@ function log_helper(self, level, msg) {
|
|||||||
o.name = self.name;
|
o.name = self.name;
|
||||||
}
|
}
|
||||||
// See https://github.com/node-red/node-red/issues/3327
|
// See https://github.com/node-red/node-red/issues/3327
|
||||||
|
// See https://github.com/node-red/node-red/issues/3389
|
||||||
|
|
||||||
|
let srcError;
|
||||||
|
if (msg instanceof Error) {
|
||||||
|
srcError = msg;//use existing err object for actual stack
|
||||||
|
} else {
|
||||||
|
srcError = new Error(msg);//generate a new error for generate a stack
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
|
if(self instanceof Node && self._flow) {
|
||||||
self._flow.log(o);
|
self._flow.log(o);
|
||||||
|
} else {
|
||||||
|
//if self._flow is not present, this is not a node-red Node
|
||||||
|
//Set info to "Node object is not a node-red Node" to point out the `Node type` problem in log
|
||||||
|
logUnexpectedError(self, srcError, "Node object is not a node-red Node")
|
||||||
|
}
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
logUnexpectedError(self, err)
|
//build an unexpected error report indicating using the original error (for better stack trace)
|
||||||
|
logUnexpectedError(self, srcError, `An error occured attempting to make a log entry: ${err}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -531,7 +546,7 @@ Node.prototype.error = function(logMessage,msg) {
|
|||||||
logMessage = logMessage || "";
|
logMessage = logMessage || "";
|
||||||
}
|
}
|
||||||
var handled = false;
|
var handled = false;
|
||||||
if (msg && typeof msg === 'object') {
|
if (this._flow && msg && typeof msg === 'object') {
|
||||||
handled = this._flow.handleError(this,logMessage,msg);
|
handled = this._flow.handleError(this,logMessage,msg);
|
||||||
}
|
}
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
@ -619,27 +634,34 @@ function inspectObject(flow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function logUnexpectedError(node, error) {
|
function logUnexpectedError(node, error, info) {
|
||||||
let moduleInfo = node._module?`${node._module.module}@${node._module.version}`:"undefined"
|
const header = `
|
||||||
Log.error(`
|
|
||||||
********************************************************************
|
********************************************************************
|
||||||
Unexpected Node Error
|
Unexpected Node Error
|
||||||
${error.stack}
|
********************************************************************`;
|
||||||
Node:
|
|
||||||
Type: ${node.type}
|
|
||||||
Module: ${moduleInfo}
|
|
||||||
ID: ${node._alias||node.id}
|
|
||||||
Properties:
|
|
||||||
${inspectObject(node)}
|
|
||||||
Flow: ${node._flow?node._flow.path:'undefined'}
|
|
||||||
Type: ${node._flow?node._flow.TYPE:'undefined'}
|
|
||||||
Properties:
|
|
||||||
${node._flow?inspectObject(node._flow):'undefined'}
|
|
||||||
|
|
||||||
|
const footer = `
|
||||||
Please report this issue, including the information logged above:
|
Please report this issue, including the information logged above:
|
||||||
https://github.com/node-red/node-red/issues/
|
https://github.com/node-red/node-red/issues/
|
||||||
********************************************************************
|
********************************************************************`;
|
||||||
`)
|
|
||||||
|
let detail = [`Info:\n ${info || 'No additional info'}`];
|
||||||
|
|
||||||
|
//Include Error info?
|
||||||
|
if(error && error.stack){
|
||||||
|
detail.push(`Stack:\n ${error.stack}`)
|
||||||
|
}
|
||||||
|
//Include Node info?
|
||||||
|
if(node && (node._module || node.type)){
|
||||||
|
const moduleInfo = node._module?`${node._module.module}@${node._module.version}`:"undefined";
|
||||||
|
const id = node._alias||node.id||"undefined";
|
||||||
|
detail.push(`Node:\n Type: ${node.type}\n Module: ${moduleInfo}\n ID: ${id}\n Properties:\n ${inspectObject(node)}`)
|
||||||
|
}
|
||||||
|
//Include Flow info?
|
||||||
|
if(node && node._flow){
|
||||||
|
detail.push(`Flow: ${node._flow.path}\n Type: ${node._flow.TYPE}\n Properties:\n ${inspectObject(node._flow)}`)
|
||||||
|
}
|
||||||
|
Log.error(`${header}\n${detail.join("\n")}\n${footer}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Node;
|
module.exports = Node;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/runtime",
|
"name": "@node-red/runtime",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,8 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/registry": "2.2.0",
|
"@node-red/registry": "2.2.2",
|
||||||
"@node-red/util": "2.2.0",
|
"@node-red/util": "2.2.2",
|
||||||
"async-mutex": "0.3.2",
|
"async-mutex": "0.3.2",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"express": "4.17.2",
|
"express": "4.17.2",
|
||||||
|
@ -67,8 +67,25 @@ function add(hookId, callback) {
|
|||||||
throw new Error("Hook "+hookId+" already registered")
|
throw new Error("Hook "+hookId+" already registered")
|
||||||
}
|
}
|
||||||
// Get location of calling code
|
// Get location of calling code
|
||||||
|
let callModule;
|
||||||
const stack = new Error().stack;
|
const stack = new Error().stack;
|
||||||
const callModule = stack.split("\n")[2].split("(")[1].slice(0,-1);
|
const stackEntries = stack.split("\n").slice(1);//drop 1st line (error message)
|
||||||
|
const stackEntry2 = stackEntries[1];//get 2nd stack entry
|
||||||
|
if (stackEntry2) {
|
||||||
|
try {
|
||||||
|
if (stackEntry2.indexOf(" (") >= 0) {
|
||||||
|
callModule = stackEntry2.split("(")[1].slice(0, -1);
|
||||||
|
} else {
|
||||||
|
callModule = stackEntry2.split(" ").slice(-1)[0];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Log.debug(`Unable to determined module when adding hook '${hookId}'. Stack:\n${stackEntries.join("\n")}`);
|
||||||
|
callModule = "unknown:0:0";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.debug(`Unable to determined module when adding hook '${hookId}'. Stack:\n${stackEntries.join("\n")}`);
|
||||||
|
callModule = "unknown:0:0";
|
||||||
|
}
|
||||||
Log.debug(`Adding hook '${hookId}' from ${callModule}`);
|
Log.debug(`Adding hook '${hookId}' from ${callModule}`);
|
||||||
|
|
||||||
const hookItem = {cb:callback, location: callModule, previousHook: null, nextHook: null }
|
const hookItem = {cb:callback, location: callModule, previousHook: null, nextHook: null }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/util",
|
"name": "@node-red/util",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -16,9 +16,9 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "10.0.0",
|
"fs-extra": "10.0.0",
|
||||||
"i18next": "21.6.10",
|
"i18next": "21.6.11",
|
||||||
"json-stringify-safe": "5.0.1",
|
"json-stringify-safe": "5.0.1",
|
||||||
"jsonata": "1.8.5",
|
"jsonata": "1.8.6",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"moment-timezone": "0.5.34"
|
"moment-timezone": "0.5.34"
|
||||||
}
|
}
|
||||||
|
12
packages/node_modules/node-red/package.json
vendored
12
packages/node_modules/node-red/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red",
|
"name": "node-red",
|
||||||
"version": "2.2.0",
|
"version": "2.2.2",
|
||||||
"description": "Low-code programming for event-driven applications",
|
"description": "Low-code programming for event-driven applications",
|
||||||
"homepage": "http://nodered.org",
|
"homepage": "http://nodered.org",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@ -31,15 +31,15 @@
|
|||||||
"flow"
|
"flow"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/editor-api": "2.2.0",
|
"@node-red/editor-api": "2.2.2",
|
||||||
"@node-red/runtime": "2.2.0",
|
"@node-red/runtime": "2.2.2",
|
||||||
"@node-red/util": "2.2.0",
|
"@node-red/util": "2.2.2",
|
||||||
"@node-red/nodes": "2.2.0",
|
"@node-red/nodes": "2.2.2",
|
||||||
"basic-auth": "2.0.1",
|
"basic-auth": "2.0.1",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"express": "4.17.2",
|
"express": "4.17.2",
|
||||||
"fs-extra": "10.0.0",
|
"fs-extra": "10.0.0",
|
||||||
"node-red-admin": "^2.2.2",
|
"node-red-admin": "^2.2.3",
|
||||||
"nopt": "5.0.0",
|
"nopt": "5.0.0",
|
||||||
"semver": "7.3.5"
|
"semver": "7.3.5"
|
||||||
},
|
},
|
||||||
|
@ -242,6 +242,142 @@ describe('inject node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('inject name of node as environment variable by substitution ', function (done) {
|
||||||
|
var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "${NR_NODE_NAME}", payloadType: "str", wires: [["n2"]], z: "flow"},
|
||||||
|
{id: "n2", type: "helper"}];
|
||||||
|
helper.load(injectNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload", "NAME");
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inject id of node as environment variable by substitution ', function (done) {
|
||||||
|
var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "${NR_NODE_ID}", payloadType: "str", wires: [["n2"]], z: "flow"},
|
||||||
|
{id: "n2", type: "helper"}];
|
||||||
|
helper.load(injectNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload", "n1");
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inject path of node as environment variable by substitution ', function (done) {
|
||||||
|
var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "${NR_NODE_PATH}", payloadType: "str", wires: [["n2"]], z: "flow"},
|
||||||
|
{id: "n2", type: "helper"}];
|
||||||
|
helper.load(injectNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload", "flow/n1");
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('inject name of flow as environment variable by substitution ', function (done) {
|
||||||
|
var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "${NR_FLOW_NAME}", payloadType: "str", wires: [["n2"]], z: "flow"},
|
||||||
|
{id: "n2", type: "helper"},
|
||||||
|
{id: "flow", type: "tab", label: "FLOW" },
|
||||||
|
];
|
||||||
|
helper.load(injectNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload", "FLOW");
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inject id of flow as environment variable ', function (done) {
|
||||||
|
var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "${NR_FLOW_ID}", payloadType: "str", wires: [["n2"]], z: "flow"},
|
||||||
|
{id: "n2", type: "helper"},
|
||||||
|
{id: "flow", type: "tab", name: "FLOW" },
|
||||||
|
];
|
||||||
|
helper.load(injectNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload", "flow");
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inject name of group as environment variable by substitution ', function (done) {
|
||||||
|
var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "${NR_GROUP_NAME}", payloadType: "str", wires: [["n2"]], z: "flow", g: "g0"},
|
||||||
|
{id: "n2", type: "helper"},
|
||||||
|
{id: "g0", type: "group", name: "GROUP" },
|
||||||
|
];
|
||||||
|
helper.load(injectNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload", "GROUP");
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inject id of group as environment variable by substitution ', function (done) {
|
||||||
|
var flow = [{id: "n1", type: "inject", name: "NAME", topnic: "t1", payload: "${NR_GROUP_ID}", payloadType: "str", wires: [["n2"]], z: "flow", g: "g0"},
|
||||||
|
{id: "n2", type: "helper"},
|
||||||
|
{id: "g0", type: "group", name: "GROUP" },
|
||||||
|
];
|
||||||
|
helper.load(injectNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload", "g0");
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
n1.receive({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it('sets the value of flow context property', function (done) {
|
it('sets the value of flow context property', function (done) {
|
||||||
var flow = [{id: "n1", type: "inject", topic: "t1", payload: "flowValue", payloadType: "flow", wires: [["n2"]], z: "flow"},
|
var flow = [{id: "n1", type: "inject", topic: "t1", payload: "flowValue", payloadType: "flow", wires: [["n2"]], z: "flow"},
|
||||||
{id: "n2", type: "helper"}];
|
{id: "n2", type: "helper"}];
|
||||||
|
@ -310,6 +310,12 @@ describe('switch Node', function() {
|
|||||||
it('should check if payload if of type number 0', function(done) {
|
it('should check if payload if of type number 0', function(done) {
|
||||||
genericSwitchTest("istype", "number", true, true, 0, done);
|
genericSwitchTest("istype", "number", true, true, 0, done);
|
||||||
});
|
});
|
||||||
|
it('should check if payload if of type number NaN', function(done) {
|
||||||
|
genericSwitchTest("istype", "number", true, false, parseInt("banana"), done);
|
||||||
|
});
|
||||||
|
it('should check if payload if of type number Infinity', function(done) {
|
||||||
|
genericSwitchTest("istype", "number", true, true, 1/0, done);
|
||||||
|
});
|
||||||
it('should check if payload if of type boolean true', function(done) {
|
it('should check if payload if of type boolean true', function(done) {
|
||||||
genericSwitchTest("istype", "boolean", true, true, true, done);
|
genericSwitchTest("istype", "boolean", true, true, true, done);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user