diff --git a/CHANGELOG.md b/CHANGELOG.md index b297e93ab..9b8eff388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,39 @@ +#### 2.1.4: Maintenance Release + +Runtime + + - fix env var access using $parent for groups (#3278) @HiroyasuNishiyama + - Add proper error handling for 404 errors when serving debug files (#3277) @knolleary + - Add Japanese translations for Node-RED v2.1.0-beta.1 (#3179) @kazuhitoyokoi + - Include full user object on login audit events (#3269) @knolleary + - Remove styling from de locale files (#3237) @knolleary + +Editor + + - Change tab hide button icon to an eye and add search option (#3282) @knolleary + - Fix i18n handling of namespaces with spaces in (#3281) @knolleary + - Trigger change event when autoComplete fills in input (#3280) @knolleary + - Apply CN i18n fix (#3279) @knolleary + - fix select menu label of config node to use paletteLabel (#3273) @HiroyasuNishiyama + - fix removed tab not to cause node conflict (#3275) @HiroyasuNishiyama + - Group diff fix (#3239) @knolleary + - Only toggle disabled workspace flag if on activeWorkspace (#3252) @knolleary + - Do not show status for disabled nodes (#3253) @knolleary + - Set dimension value for tour guide (#3265) @kazuhitoyokoi + - Avoid redundant initialisation of TypedInput type (#3263) @knolleary + - Don't let themes change flow port label color (#3270) @bonanitech + - Fix treeList gutter calculation to handle floating gutters (#3238) @knolleary + +Nodes + +- Debug: Handle RegExp types in Debug sidebar (#3251) @knolleary +- Delay: fix 2nd output when in rate limit per topic modes (#3261) @dceejay +- Link: fix to show link target when selected (#3267) @HiroyasuNishiyama +- Inject: Do not modify inject node props in oneditprepare (#3242) @knolleary +- HTTP Request: HTTP Basic Auth should always add : between username and password even if empty (#3236) @hardillb #### 2.1.3: Maintenance Release diff --git a/package.json b/package.json index b23e52876..15ce9148c 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,9 @@ } ], "dependencies": { - "acorn": "8.5.0", + "acorn": "8.6.0", "acorn-walk": "8.2.0", - "ajv": "8.6.3", + "ajv": "8.8.2", "async-mutex": "0.3.2", "basic-auth": "2.0.1", "bcryptjs": "2.4.3", @@ -37,7 +37,7 @@ "clone": "2.1.2", "content-type": "1.0.4", "cookie": "0.4.1", - "cookie-parser": "1.4.5", + "cookie-parser": "1.4.6", "cors": "2.8.5", "cronosjs": "1.7.1", "denque": "2.0.1", @@ -46,11 +46,11 @@ "form-data": "4.0.0", "fs-extra": "10.0.0", "fs.notify": "0.0.4", - "got": "11.8.2", + "got": "11.8.3", "hash-sum": "2.0.0", "hpagent": "0.1.2", "https-proxy-agent": "5.0.0", - "i18next": "21.3.1", + "i18next": "21.5.4", "iconv-lite": "0.6.3", "is-utf8": "0.2.1", "js-yaml": "3.14.1", @@ -60,22 +60,22 @@ "media-typer": "1.1.0", "memorystore": "1.6.6", "mime": "2.5.2", - "moment-timezone": "0.5.33", + "moment-timezone": "0.5.34", "mqtt": "4.2.8", "multer": "1.4.3", "mustache": "4.2.0", "node-red-admin": "^2.2.1", "nopt": "5.0.0", - "oauth2orize": "1.11.0", + "oauth2orize": "1.11.1", "on-headers": "1.0.2", "passport": "0.5.0", "passport-http-bearer": "1.0.1", "passport-oauth2-client-password": "0.1.2", - "raw-body": "2.4.1", + "raw-body": "2.4.2", "semver": "7.3.5", "tar": "6.1.11", "tough-cookie": "4.0.0", - "uglify-js": "3.14.2", + "uglify-js": "3.14.4", "uuid": "8.3.2", "ws": "7.5.1", "xml2js": "0.4.23" @@ -109,11 +109,11 @@ "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "marked": "3.0.7", "minami": "1.2.3", - "mocha": "9.1.2", + "mocha": "9.1.3", "node-red-node-test-helper": "^0.2.7", - "nodemon": "2.0.13", + "nodemon": "2.0.15", "proxy": "^1.0.2", - "sass": "1.43.2", + "sass": "1.44.0", "should": "13.2.3", "sinon": "11.1.2", "stoppable": "^1.1.0", diff --git a/packages/node_modules/@node-red/editor-api/lib/auth/index.js b/packages/node_modules/@node-red/editor-api/lib/auth/index.js index f32f6d0d6..41d96b3f6 100644 --- a/packages/node_modules/@node-red/editor-api/lib/auth/index.js +++ b/packages/node_modules/@node-red/editor-api/lib/auth/index.js @@ -141,7 +141,7 @@ function completeVerify(profile,done) { Users.authenticate(profile).then(function(user) { if (user) { Tokens.create(user.username,"node-red-editor",user.permissions).then(function(tokens) { - log.audit({event: "auth.login",username:user.username,scope:user.permissions}); + log.audit({event: "auth.login",user,username:user.username,scope:user.permissions}); user.tokens = tokens; done(null,user); }); diff --git a/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js b/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js index bae4df5c3..7a77354fa 100644 --- a/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js +++ b/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js @@ -93,7 +93,7 @@ var passwordTokenExchange = function(client, username, password, scope, done) { return logEntry.user !== username; }); Tokens.create(username,client.id,scope).then(function(tokens) { - log.audit({event: "auth.login",username:username,client:client.id,scope:scope}); + log.audit({event: "auth.login",user,username:username,client:client.id,scope:scope}); done(null,tokens.accessToken,null,{expires_in:tokens.expires_in}); }); } else { diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json index 19d488b52..aebb7454e 100644 --- a/packages/node_modules/@node-red/editor-api/package.json +++ b/packages/node_modules/@node-red/editor-api/package.json @@ -28,7 +28,7 @@ "mime": "2.5.2", "multer": "1.4.3", "mustache": "4.2.0", - "oauth2orize": "1.11.0", + "oauth2orize": "1.11.1", "passport-http-bearer": "1.0.1", "passport-oauth2-client-password": "0.1.2", "passport": "0.5.0", diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json index 0e60d17e3..cac66dd7a 100755 --- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json @@ -59,6 +59,8 @@ "hideOtherFlows": "Hide other flows", "showAllFlows": "Show all flows", "hideAllFlows": "Hide all flows", + "hiddenFlows": "List __count__ hidden flow", + "hiddenFlows_plural": "List __count__ hidden flows", "showLastHiddenFlow": "Show last hidden flow", "listFlows": "List flows", "listSubflows": "List subflows", @@ -90,6 +92,7 @@ "palette": { "show": "Show palette" }, + "edit": "Edit", "settings": "Settings", "userSettings": "User Settings", "nodes": "Nodes", @@ -668,7 +671,8 @@ "unusedConfigNodes": "Unused configuration nodes", "invalidNodes": "Invalid nodes", "uknownNodes": "Unknown nodes", - "unusedSubflows": "Unused subflows" + "unusedSubflows": "Unused subflows", + "hiddenFlows": "Hidden flows" } }, "help": { @@ -1135,6 +1139,7 @@ "defaultValue": "Default value" }, "tourGuide": { + "takeATour": "Take a tour", "start": "Start", "next": "Next" }, diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json index 83a6468a4..6436c0518 100644 --- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json @@ -54,7 +54,14 @@ "delete": "本当に '__label__' を削除しますか?", "dropFlowHere": "ここにフローをドロップしてください", "addFlow": "フローの追加", + "addFlowToRight": "右側にフローを追加", + "hideFlow": "フローを非表示", + "hideOtherFlows": "他のフローを非表示", + "showAllFlows": "全てのフローを表示", + "hideAllFlows": "全てのフローを非表示", + "showLastHiddenFlow": "最後に非表示にしたフローを表示", "listFlows": "フロー一覧", + "listSubflows": "サブフロー一覧", "status": "状態", "enabled": "有効", "disabled": "無効", @@ -83,6 +90,7 @@ "palette": { "show": "パレットを表示" }, + "edit": "編集", "settings": "設定", "userSettings": "ユーザ設定", "nodes": "ノード", @@ -105,6 +113,7 @@ "editPalette": "パレットの管理", "other": "その他", "showTips": "ヒントを表示", + "showWelcomeTours": "新バージョンのガイドツアーを表示", "help": "Node-REDウェブサイト", "projects": "プロジェクト", "projects-new": "新規", @@ -116,7 +125,20 @@ "groupSelection": "選択部分をグループ化", "ungroupSelection": "選択部分をグループ解除", "groupMergeSelection": "選択部分をマージ", - "groupRemoveSelection": "グループから削除" + "groupRemoveSelection": "グループから削除", + "arrange": "配置", + "alignLeft": "左揃え", + "alignCenter": "左右中央揃え", + "alignRight": "右揃え", + "alignTop": "上揃え", + "alignMiddle": "上下中央揃え", + "alignBottom": "下揃え", + "distributeHorizontally": "左右に整列", + "distributeVertically": "上下に整列", + "moveToBack": "最背面へ移動", + "moveToFront": "最前面へ移動", + "moveBackwards": "背面へ移動", + "moveForwards": "前面へ移動" } }, "actions": { @@ -451,7 +473,8 @@ "global": "グローバル", "workspace": "ワークスペース", "selectAll": "全てのノードを選択", - "selectAllConnected": "接続された全てのノードを選択", + "selectNone": "選択を外す", + "selectAllConnected": "接続されたノードを選択", "addRemoveNode": "ノードの選択、選択解除", "editSelected": "選択したノードを編集", "deleteSelected": "選択したノードや接続を削除", @@ -461,10 +484,13 @@ "moveNode": "選択したノードを移動(移動量大)", "toggleSidebar": "サイドバーの表示/非表示", "togglePalette": "パレットの表示/非表示", - "copyNode": "選択したノードをコピー", - "cutNode": "選択したノードを切り取り", + "copyNode": "ノードをコピー", + "cutNode": "ノードを切り取り", "pasteNode": "ノードを貼り付け", + "copyGroupStyle": "グループ様式をコピー", + "pasteGroupStyle": "グループ様式を貼り付け", "undoChange": "変更操作を戻す", + "redoChange": "変更操作をやり直し", "searchBox": "ノードを検索", "managePalette": "パレットの管理", "actionList": "動作一覧" @@ -519,7 +545,8 @@ "nodeEnabled_plural": "ノードを有効化しました:", "nodeDisabled": "ノードを無効化しました:", "nodeDisabled_plural": "ノードを無効化しました:", - "nodeUpgraded": "ノードモジュール __module__ をバージョン __version__ へ更新しました" + "nodeUpgraded": "ノードモジュール __module__ をバージョン __version__ へ更新しました", + "unknownNodeRegistered": "ノードの読み込みエラー:
\"__file__\"已存在
是否要替换它?
" diff --git a/packages/node_modules/@node-red/editor-client/src/js/i18n.js b/packages/node_modules/@node-red/editor-client/src/js/i18n.js index 028321ce9..b8c03b85b 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/i18n.js +++ b/packages/node_modules/@node-red/editor-client/src/js/i18n.js @@ -38,6 +38,8 @@ RED.i18n = (function() { defaultNS: "editor", fallbackLng: ['en-US'], returnObjects: true, + keySeparator: ".", + nsSeparator: ":", interpolation: { unescapeSuffix: 'HTML', escapeValue: false, diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index 76f544396..b17387a52 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -805,7 +805,6 @@ RED.nodes = (function() { var removedGroups = []; if (ws) { delete workspaces[id]; - allNodes.removeTab(id); delete linkTabMap[id]; workspacesOrder.splice(workspacesOrder.indexOf(id),1); var i; @@ -843,6 +842,7 @@ RED.nodes = (function() { for (i=removedGroups.length-1; i>=0; i--) { removeGroup(removedGroups[i]); } + allNodes.removeTab(id); RED.events.emit('flows:remove',ws); } return {nodes:removedNodes,links:removedLinks, groups: removedGroups}; @@ -1097,6 +1097,11 @@ RED.nodes = (function() { // Until we know how that can happen, add a filter here to remove them node.nodes = node.nodes.filter(function(n) { return !!n }).map(function(n) { return n.id }); } + if (n.type === "tab" || n.type === "group") { + if (node.env && node.env.length === 0) { + delete node.env; + } + } if (n._def.category != "config") { node.x = n.x; node.y = n.y; diff --git a/packages/node_modules/@node-red/editor-client/src/js/red.js b/packages/node_modules/@node-red/editor-client/src/js/red.js index 517cbf316..36e45e570 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/red.js +++ b/packages/node_modules/@node-red/editor-client/src/js/red.js @@ -590,7 +590,7 @@ var RED = (function() { {id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"} ]}); } - menuOptions.push({id:"menu-item-edit-menu", label:"Edit", options: [ + menuOptions.push({id:"menu-item-edit-menu", label:RED._("menu.label.edit"), options: [ {id: "menu-item-edit-undo", label:RED._("keyboard.undoChange"), disabled: true, onselect: "core:undo"}, {id: "menu-item-edit-redo", label:RED._("keyboard.redoChange"), disabled: true, onselect: "core:redo"}, null, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.js index 6f1ac1aa1..192ccda7a 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.js @@ -21,7 +21,7 @@ * value: String : the value to insert if selected * label: String|DOM Element : the label to display in the dropdown. * } - * + * */ $.widget( "nodered.autoComplete", { @@ -62,7 +62,7 @@ maxHeight: 200, class: "red-ui-autoComplete-container", options: completions, - onselect: (opt) => { this.element.val(opt.value); this.element.focus() }, + onselect: (opt) => { this.element.val(opt.value); this.element.focus(); this.element.trigger("change") }, onclose: () => { this.completionMenuShown = false; delete this.menu; this.element.focus()} }); this.menu.show({ diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js index f3327c2e6..d1e6a39d2 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js @@ -117,6 +117,8 @@ RED.tabs = (function() { menuOptions = options.menu() } else if (Array.isArray(options.menu)) { menuOptions = options.menu; + } else if (typeof options.menu === 'function') { + menuOptions = options.menu(); } menu = RED.menu.init({options: menuOptions}); menu.attr("id",options.id+"-menu"); @@ -809,15 +811,18 @@ RED.tabs = (function() { event.preventDefault(); removeTab(tab.id); }); + RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); } if (tab.hideable) { li.addClass("red-ui-tabs-closeable") - var closeLink = $("",{href:"#",class:"red-ui-tab-close"}).appendTo(li); - closeLink.append(''); + var closeLink = $("",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li); + closeLink.append(''); + closeLink.append(''); closeLink.on("click",function(event) { event.preventDefault(); hideTab(tab.id); }); + RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); } var badges = $('').appendTo(li); @@ -826,7 +831,8 @@ RED.tabs = (function() { $('').appendTo(badges); } - link.attr("title",tab.label); + // link.attr("title",tab.label); + RED.popover.tooltip(link,function() { return tab.label}) if (options.onadd) { options.onadd(tab); @@ -945,7 +951,6 @@ RED.tabs = (function() { renameTab: function(id,label) { tabs[id].label = label; var tab = ul.find("a[href='#"+id+"']"); - tab.attr("title",label); tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label)); updateTabWidths(); }, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js index 9092d4dcf..2d628769e 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js @@ -556,7 +556,7 @@ this.optionExpandButton = $('').appendTo(this.uiSelect); this.optionExpandButtonIcon = $('').appendTo(this.optionExpandButton); - this.type(this.options.default||this.typeList[0].value); + this.type(this.typeField.val() || this.options.default||this.typeList[0].value); this.typeChanged = !!this.options.default; }catch(err) { console.log(err.stack); @@ -805,6 +805,7 @@ var that = this; var currentType = this.type(); this.typeMap = {}; + var firstCall = (this.typeList === undefined); this.typeList = types.map(function(opt) { var result; if (typeof opt === 'string') { @@ -829,10 +830,14 @@ } this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) }); if (currentType && !this.typeMap.hasOwnProperty(currentType)) { - this.type(this.typeList[0].value); + if (!firstCall) { + this.type(this.typeList[0].value); + } } else { this.propertyType = null; - this.type(currentType); + if (!firstCall) { + this.type(currentType); + } } if (this.typeList.length === 1 && !this.typeList[0].icon && (!this.typeList[0].label || this.typeList[0].showLabel === false)) { this.selectTrigger.hide() diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js b/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js index 646fe326e..b6a069ab5 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/diff.js @@ -554,6 +554,8 @@ RED.diff = (function() { color: "#DDAA99", defaults:{name:{value:""}} } + } else if (node.type === "group") { + def = RED.group.def; } else { def = {}; } @@ -763,16 +765,15 @@ RED.diff = (function() { } } - if (node.hasOwnProperty('x')) { if (localNode) { - if (localNode.x !== node.x || localNode.y !== node.y) { + if (localNode.x !== node.x || localNode.y !== node.y || localNode.w !== node.w || localNode.h !== node.h ) { localChanged = true; localChanges++; } } if (remoteNode) { - if (remoteNode.x !== node.x || remoteNode.y !== node.y) { + if (remoteNode.x !== node.x || remoteNode.y !== node.y|| remoteNode.w !== node.w || remoteNode.h !== node.h) { remoteChanged = true; remoteChanges++; } @@ -790,7 +791,12 @@ RED.diff = (function() { localCell.addClass("red-ui-diff-status-"+(localChanged?"changed":"unchanged")); $(''+(localChanged?'':'')+'').appendTo(localCell); element = $('').appendTo(localCell); - propertyElements['local.position'] = RED.utils.createObjectElement({x:localNode.x,y:localNode.y}, + var localPosition = {x:localNode.x,y:localNode.y}; + if (localNode.hasOwnProperty('w')) { + localPosition.w = localNode.w; + localPosition.h = localNode.h; + } + propertyElements['local.position'] = RED.utils.createObjectElement(localPosition, { path: "position", exposeApi: true, @@ -811,7 +817,12 @@ RED.diff = (function() { if (remoteNode) { $(''+(remoteChanged?'':'')+'').appendTo(remoteCell); element = $('').appendTo(remoteCell); - propertyElements['remote.position'] = RED.utils.createObjectElement({x:remoteNode.x,y:remoteNode.y}, + var remotePosition = {x:remoteNode.x,y:remoteNode.y}; + if (remoteNode.hasOwnProperty('w')) { + remotePosition.w = remoteNode.w; + remotePosition.h = remoteNode.h; + } + propertyElements['remote.position'] = RED.utils.createObjectElement(remotePosition, { path: "position", exposeApi: true, @@ -883,11 +894,11 @@ RED.diff = (function() { } } } - var properties = Object.keys(node).filter(function(p) { return p!='inputLabels'&&p!='outputLabels'&&p!='z'&&p!='wires'&&p!=='x'&&p!=='y'&&p!=='id'&&p!=='type'&&(!def.defaults||!def.defaults.hasOwnProperty(p))}); + var properties = Object.keys(node).filter(function(p) { return p!='inputLabels'&&p!='outputLabels'&&p!='z'&&p!='wires'&&p!=='x'&&p!=='y'&&p!=='w'&&p!=='h'&&p!=='id'&&p!=='type'&&(!def.defaults||!def.defaults.hasOwnProperty(p))}); if (def.defaults) { properties = properties.concat(Object.keys(def.defaults)); } - if (node.type !== 'tab') { + if (node.type !== 'tab' && node.type !== "group") { properties = properties.concat(['inputLabels','outputLabels']); } if ( ((localNode && localNode.hasOwnProperty('icon')) || (remoteNode && remoteNode.hasOwnProperty('icon'))) && diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js index 643110d10..6017fb687 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js @@ -744,7 +744,16 @@ RED.editor = (function() { delete cn.__label__; }); - select.append(''); + var label = type; + if (typeof node_def.paletteLabel !== "undefined") { + try { + label = RED.utils.sanitize((typeof node_def.paletteLabel === "function" ? node_def.paletteLabel.call(node_def) : node_def.paletteLabel)||type); + } catch(err) { + console.log("Definition error: "+type+".paletteLabel",err); + } + } + + select.append(''); window.setTimeout(function() { select.trigger("change");},50); } } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/envVarProperties.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/envVarProperties.js index 10425f18a..fb1d89b3f 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/envVarProperties.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/envVarProperties.js @@ -56,8 +56,12 @@ }); } if (!isSameObj(old_env, new_env)) { - node.env = new_env; editState.changes.env = node.env; + if (new_env.length === 0) { + delete node.env; + } else { + node.env = new_env; + } editState.changed = true; } } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js index 02c7735a7..045588310 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js @@ -105,6 +105,7 @@ RED.search = (function() { val = extractFlag(val,"unused",flags); val = extractFlag(val,"config",flags); val = extractFlag(val,"subflow",flags); + val = extractFlag(val,"hidden",flags); // uses:First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.
"+ - "You can choose not to see this tour in the future by disabling it under the View tab of User Settings.
" } + title: { + "en-US": "A new Tour Guide", + "ja": "新しいツアーガイド" + }, + description: { + "en-US": "First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.
" + + "You can choose not to see this tour in the future by disabling it under the View tab of User Settings.
", + "ja": "最初に、既に見つけている様に、新機能の本ツアーがあります。本ツアーは、新バージョンのNode-REDフローエディタを初めて開いた時のみ表示されます。
" + + "ユーザ設定の表示タブの中で、この機能を無効化することで、本ツアーを表示しないようにすることもできます。
" + } }, { - title: { "en-US": "New Edit menu" }, + title: { + "en-US": "New Edit menu", + "ja": "新しい編集メニュー" + }, prepare() { $("#red-ui-header-button-sidemenu").trigger("click"); - $("#menu-item-edit-menu").parent().addClass("open") + $("#menu-item-edit-menu").parent().addClass("open"); }, complete() { - $("#menu-item-edit-menu").parent().removeClass("open") + $("#menu-item-edit-menu").parent().removeClass("open"); }, element: "#menu-item-edit-menu-submenu", interactive: false, direction: "left", - description: { "en-US": "The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.
"+ - "The menu now displays keyboard shortcuts for the options.
" } - + description: { + "en-US": "The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.
" + + "The menu now displays keyboard shortcuts for the options.
", + "ja": "メインメニューに「編集」セクションが追加されました。本セクションには、切り取り/貼り付けや、変更操作を戻す/やり直しの様な使い慣れたオプションが含まれています。
" + + "本メニューには、オプションのためのキーボードショートカットも表示されるようになりました。
" + } }, { - title: { "en-US": "Arranging nodes" }, + title: { + "en-US": "Arranging nodes", + "ja": "ノードの配置" + }, prepare() { $("#red-ui-header-button-sidemenu").trigger("click"); - $("#menu-item-arrange-menu").parent().addClass("open") + $("#menu-item-arrange-menu").parent().addClass("open"); }, complete() { - $("#menu-item-arrange-menu").parent().removeClass("open") + $("#menu-item-arrange-menu").parent().removeClass("open"); }, element: "#menu-item-arrange-menu-submenu", interactive: false, direction: "left", - description: { "en-US": "The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.
" }, + description: { + "en-US": "The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.
", + "ja": "メニューの新しい「配置」セクションには、ノードの配置を助ける新しいオプションが提供されています。ノードの端を揃えたり、均等に配置したり、表示順序を変更したりできます。
" + } }, { - title: { "en-US": "Hiding tabs" }, + title: { + "en-US": "Hiding tabs", + "ja": "タブの非表示" + }, element: "#red-ui-workspace-tabs > li.active", - description: { "en-US": 'Tabs can now be hidden by clicking their icon.
The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.' }, + description: { + "en-US": '
Tabs can now be hidden by clicking their icon.
The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.', + "ja": '
アイコンをクリックすることで、タブを非表示にできます。
情報サイドバーには、全てのタブが一覧表示されており、現在非表示になっているタブを確認できます。' + }, interactive: false, prepare() { $("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","block"); @@ -54,9 +85,15 @@ export default { } }, { - title: { "en-US": "Tab menu" }, + title: { + "en-US": "Tab menu", + "ja": "タブメニュー" + }, element: "#red-ui-workspace-tabs-menu", - description: { "en-US": '
The new tab menu also provides lots of new options for your tabs.
' }, + description: { + "en-US": "The new tab menu also provides lots of new options for your tabs.
", + "ja": "新しいタブメニューには、タブに関する沢山の新しいオプションが提供されています。
" + }, interactive: false, direction: "left", prepare() { @@ -67,10 +104,16 @@ export default { } }, { - title: { "en-US": "Flow and Group level environment variables" }, + title: { + "en-US": "Flow and Group level environment variables", + "ja": "フローとグループの環境変数" + }, element: "#red-ui-workspace-tabs > li.active", interactive: false, - description: { "en-US": "Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.
" }, + description: { + "en-US": "Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.
", + "ja": "フローとグループには、内部のノードから参照できる環境変数を設定できるようになりました。
" + } }, { prepare(done) { @@ -78,20 +121,28 @@ export default { setTimeout(done,700); }, element: "#red-ui-tab-editor-tab-envProperties-link-button", - description: { "en-US": "Their edit dialogs have a new Environment Variables section.
" }, + description: { + "en-US": "Their edit dialogs have a new Environment Variables section.
", + "ja": "編集ダイアログに環境変数セクションが追加されました。
" + } }, { element: ".node-input-env-container-row", direction: "left", - description: { "en-US": 'The environment variables are listed in this table and new ones can be added by clicking the button.
' }, + description: { + "en-US": 'The environment variables are listed in this table and new ones can be added by clicking the button.
', + "ja": 'この表に環境変数が一覧表示されており、ボタンをクリックすることで新しい変数を追加できます。
' + }, complete(done) { $("#node-dialog-cancel").trigger("click"); setTimeout(done,500); } }, - { - title: {"en-US":"Link Call node added"}, + title: { + "en-US": "Link Call node added", + "ja": "Link Callノードを追加" + }, prepare(done) { this.paletteWasClosed = $("#red-ui-main-container").hasClass("red-ui-palette-closed"); RED.actions.invoke("core:toggle-palette",true) @@ -100,22 +151,34 @@ export default { }, element: '[data-palette-type="link call"]', direction: "right", - description: { "en-US": 'The Link Call
node lets you call another flow that begins with a Link In
node and get the result back when the message reaches a Link Out
node.
The Link Call
node lets you call another flow that begins with a Link In
node and get the result back when the message reaches a Link Out
node.
Link Call
ノードを用いることで、Link In
ノードから始まるフローを呼び出し、Link Out
ノードに到達した時に、結果を取得できます。
The MQTT
nodes now support creating their connections and subscriptions dynamically.
The MQTT
nodes now support creating their connections and subscriptions dynamically.
MQTT
ノードは、動的な接続や購読ができるようになりました。
The file nodes have been renamed to make it clearer which node does what.
' }, + description: { + "en-US": "The file nodes have been renamed to make it clearer which node does what.
", + "ja": "fileノードの名前が変更され、どのノードが何を行うかが明確になりました。
" + } }, { - title: {"en-US":"Deep copy option on Change node"}, + title: { + "en-US": "Deep copy option on Change node", + "ja": "Changeノードのディープコピーオプション" + }, prepare(done) { - var def = RED.nodes.getType('change') - RED.editor.edit({id:"test",type:"change",rules:[{t:'set',p:'payload',pt:'msg', tot:'msg',to:"anotherProperty"}],_def:def, _:def._}) + var def = RED.nodes.getType('change'); + RED.editor.edit({id:"test",type:"change",rules:[{t:"set",p:"payload",pt:"msg", tot:"msg",to:"anotherProperty"}],_def:def, _:def._}); setTimeout(done,700); }, complete(done) { @@ -139,13 +208,22 @@ export default { setTimeout(done,500); }, element: function() { - return $(".node-input-rule-property-deepCopy").next() + return $(".node-input-rule-property-deepCopy").next(); }, - description: { "en-US": 'The Set rule has a new option to create a deep copy of the value. This ensures a complete copy is made, rather than using a reference.
' }, + description: { + "en-US": "The Set rule has a new option to create a deep copy of the value. This ensures a complete copy is made, rather than using a reference.
", + "ja": "値を代入に、値のディープコピーを作成するオプションが追加されました。これによって参照ではなく、完全なコピーが作成されます。
" + } }, { - title: { "en-US": "And that's not all..." }, - description: { "en-US": "There are many more smaller changes, including:
msg
TypedInput.msg.resetTimeout
in the Join
node.Delay
node's rate limiting mode.Delay
node for rate limited messages.There are many more smaller changes, including:
msg
TypedInput.msg.resetTimeout
in the Join
node.Delay
node's rate limiting mode.Delay
node for rate limited messages.以下の様な小さな変更が沢山あります:
msg
TypedInputの自動補完提案Join
ノードでmsg.resetTimeout
のサポートDelay
ノードの流量制御モードにおいて先頭メッセージをキューに追加Delay
ノードで流量制限されたメッセージ向けの任意の2つ目の出力linkノード間のリンクはlinkノードを選択した場合にのみ表示されます。他のタブへのリンクがある場合には、仮想的なノードを表示します。この仮想的ノードをクリックすると、対応するタブに移動できます。
注: サブフローの外から中、もしくは、中から外へのリンクを作成することはできません。
+ + diff --git a/packages/node_modules/@node-red/nodes/locales/ja/messages.json b/packages/node_modules/@node-red/nodes/locales/ja/messages.json index bcbf2e8d4..4fdd6bb09 100644 --- a/packages/node_modules/@node-red/nodes/locales/ja/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/ja/messages.json @@ -144,11 +144,16 @@ "filterCurrent": "現在のフロー", "debugNodes": "debugノード", "clearLog": "ログを削除", + "clearFilteredLog": "選択したメッセージを削除", "filterLog": "ログのフィルタリング", "openWindow": "新しいウィンドウで開く", "copyPath": "パスをコピー", "copyPayload": "値をコピー", - "pinPath": "展開を固定" + "pinPath": "展開を固定", + "selectAll": "全てを選択", + "selectNone": "選択を外す", + "all": "全て", + "filtered": "選択したメッセージ" }, "messageMenu": { "collapseAll": "全パスを折りたたむ", @@ -159,7 +164,15 @@ }, "link": { "linkIn": "link in", - "linkOut": "link out" + "linkOut": "link out", + "linkCall": "link call", + "linkOutReturn": "link return", + "outMode": "モード", + "sendToAll": "接続された全てのlinkノードへ送信", + "returnToCaller": "link callノードへ返却", + "error": { + "missingReturn": "返却するノードの情報が存在しません" + } }, "tls": { "tls": "TLS設定", @@ -282,7 +295,9 @@ "and": "回/", "rate": "流量", "msgper": "メッセージ/", + "queuemsg": "中間メッセージをキューに追加", "dropmsg": "中間メッセージを削除", + "sendmsg": "2番目の出力で中間メッセージを送信", "allowrate": "msg.rate(ミリ秒単位)で流量値を上書き", "label": { "delay": "delay", @@ -401,7 +416,11 @@ "maximumPacketSize": "最大パケット長", "receiveMaximum": "最大受信数", "session": "セッション", - "delay": "遅延" + "delay": "遅延", + "action": "動作", + "staticTopic": "1つのトピックを購読", + "dynamicTopic": "動的な購読", + "auto-connect": "自動接続" }, "sections-label": { "birth-message": "接続時の送信メッセージ(Birthメッセージ)", @@ -442,7 +461,10 @@ "invalid-topic": "不正なトピックが設定されています", "nonclean-missingclientid": "「セッションの初期化」使用時に、クライアントIDが設定されていません", "invalid-json-string": "不正なJSON文字列", - "invalid-json-parse": "JSON文字列のパースに失敗しました" + "invalid-json-parse": "JSON文字列のパースに失敗しました", + "invalid-action-action": "指定された動作が不正です", + "invalid-action-alreadyconnected": "接続する前にブローカから切断してください", + "invalid-action-badsubscription": "msg.topicが存在しないか不正です" } }, "httpin": { @@ -478,6 +500,7 @@ "proxy-config": "プロキシ設定", "use-proxyauth": "プロキシ認証を使用", "noproxy-hosts": "例外ホスト", + "senderr": "2xx以外の応答をcatchノードへ送信", "utf8": "UTF8文字列", "binary": "バイナリバッファ", "json": "JSONオブジェクト", @@ -703,13 +726,15 @@ "delete": "delete __property__", "move": "move __property__", "changeCount": "change: __count__ rules", - "regex": "正規表現を使用" + "regex": "正規表現を使用", + "deepCopy": "値のディープコピー" }, "action": { "set": "値の代入", "change": "値の置換", "delete": "値の削除", "move": "値の移動", + "toValue": "対象の値", "to": "対象の値", "search": "検索する文字列", "replace": "置換後の文字列" @@ -851,6 +876,8 @@ }, "file": { "label": { + "write": "write file", + "read": "read file", "filename": "ファイル名", "action": "動作", "addnewline": "メッセージの入力のたびに改行を追加", @@ -858,7 +885,6 @@ "outputas": "出力形式", "breakchunks": "チャンクへ分割", "breaklines": "行へ分割", - "filelabel": "file", "sendError": "エラーメッセージを送信(互換モード)", "encoding": "文字コード", "deletelabel": "delete __file__", diff --git a/packages/node_modules/@node-red/nodes/locales/ko/messages.json b/packages/node_modules/@node-red/nodes/locales/ko/messages.json index 442e0ef65..328edb2c5 100755 --- a/packages/node_modules/@node-red/nodes/locales/ko/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/ko/messages.json @@ -771,7 +771,6 @@ "outputas": "출력형식", "breakchunks": "청크로 분할", "breaklines": "행으로 분할", - "filelabel": "file", "sendError": "에러메세지를 송신(호환모드)", "deletelabel": "delete __file__", "utf8String": "UTF8문자열", diff --git a/packages/node_modules/@node-red/nodes/locales/ru/messages.json b/packages/node_modules/@node-red/nodes/locales/ru/messages.json index f32160bf1..075efe5b2 100755 --- a/packages/node_modules/@node-red/nodes/locales/ru/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/ru/messages.json @@ -816,7 +816,6 @@ "outputas": "Выход", "breakchunks": "Разбить файл на части", "breaklines": "Разбить на строки", - "filelabel": "файл", "sendError": "Отправлять сообщение при ошибке (устаревший режим)", "encoding": "Кодировка", "deletelabel": "удалить __file__", diff --git a/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json b/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json index 7f928f733..090af502f 100644 --- a/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/zh-CN/messages.json @@ -804,7 +804,6 @@ "outputas": "输出", "breakchunks": "分拆成块", "breaklines": "分拆成行", - "filelabel": "文件", "sendError": "发生错误时发送消息(传统模式)", "encoding": "编码", "deletelabel": "删除 __file__", diff --git a/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json b/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json index 1335e9ff2..15b45892e 100644 --- a/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/zh-TW/messages.json @@ -809,7 +809,6 @@ "outputas": "輸出", "breakchunks": "分拆成塊", "breaklines": "分拆成行", - "filelabel": "文件", "sendError": "發生錯誤時發送消息(傳統模式)", "encoding": "編碼", "deletelabel": "刪除 __file__", diff --git a/packages/node_modules/@node-red/nodes/package.json b/packages/node_modules/@node-red/nodes/package.json index 03b101969..e11c27a9b 100644 --- a/packages/node_modules/@node-red/nodes/package.json +++ b/packages/node_modules/@node-red/nodes/package.json @@ -15,13 +15,13 @@ } ], "dependencies": { - "acorn": "8.5.0", + "acorn": "8.6.0", "acorn-walk": "8.2.0", - "ajv": "8.6.3", + "ajv": "8.8.2", "body-parser": "1.19.0", "cheerio": "1.0.0-rc.10", "content-type": "1.0.4", - "cookie-parser": "1.4.5", + "cookie-parser": "1.4.6", "cookie": "0.4.1", "cors": "2.8.5", "cronosjs": "1.7.1", @@ -29,7 +29,7 @@ "form-data": "4.0.0", "fs-extra": "10.0.0", "fs.notify": "0.0.4", - "got": "11.8.2", + "got": "11.8.3", "hash-sum": "2.0.0", "hpagent": "0.1.2", "https-proxy-agent": "5.0.0", @@ -40,7 +40,7 @@ "multer": "1.4.3", "mustache": "4.2.0", "on-headers": "1.0.2", - "raw-body": "2.4.1", + "raw-body": "2.4.2", "tough-cookie": "4.0.0", "uuid": "8.3.2", "ws": "7.5.1", diff --git a/packages/node_modules/@node-red/registry/package.json b/packages/node_modules/@node-red/registry/package.json index c40176645..4bba38fab 100644 --- a/packages/node_modules/@node-red/registry/package.json +++ b/packages/node_modules/@node-red/registry/package.json @@ -21,6 +21,6 @@ "fs-extra": "10.0.0", "semver": "7.3.5", "tar": "6.1.11", - "uglify-js": "3.14.2" + "uglify-js": "3.14.4" } } diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js index 23f41e0ed..5fb21157e 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js @@ -439,8 +439,6 @@ class Flow { } } return [env.name, env]; - - return [env.name, env]; }); group._env = Object.fromEntries(entries); } @@ -457,24 +455,24 @@ class Flow { const val = ((value === "true") || (value === true)); - return { + return [{ val: val - }; + }, null]; } if (type === "cred") { - return { + return [{ val: value - }; + }, null]; } try { var val = redUtil.evaluateNodeProperty(value, type, node, null, null); - return { + return [{ val: val - }; + }, null]; } catch (e) { this.error(e); - return null; + return [null, null]; } } } @@ -488,7 +486,7 @@ class Flow { return this.getGroupEnvSetting(node, parent, name); } } - return null; + return [null, name]; } @@ -545,6 +543,9 @@ class Flow { } } } + else { + key = key.substring(8); + } } return this.parent.getSetting(key); } diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js index 0f3aefe26..3d2bc3afe 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js @@ -373,10 +373,11 @@ class Subflow extends Flow { const node = this.subflowInstance; if (node.g) { const group = this.getGroupNode(node.g); - const result = this.getGroupEnvSetting(node, group, name); + const [result, newName] = this.getGroupEnvSetting(node, group, name); if (result) { return result.val; } + name = newName; } diff --git a/packages/node_modules/@node-red/util/lib/i18n.js b/packages/node_modules/@node-red/util/lib/i18n.js index cddcb764f..4f1cf110f 100644 --- a/packages/node_modules/@node-red/util/lib/i18n.js +++ b/packages/node_modules/@node-red/util/lib/i18n.js @@ -136,8 +136,6 @@ function getCurrentLocale() { function init(settings) { if (!initPromise) { - // Keep this as a 'when' promise as top-level red.js uses 'otherwise' - // and embedded users of NR may have copied that. initPromise = new Promise((resolve,reject) => { i18n.use(MessageFileLoader); var opt = { @@ -146,6 +144,8 @@ function init(settings) { defaultNS: "runtime", ns: [], fallbackLng: defaultLang, + keySeparator: ".", + nsSeparator: ":", interpolation: { unescapeSuffix: 'HTML', escapeValue: false, diff --git a/packages/node_modules/@node-red/util/lib/util.js b/packages/node_modules/@node-red/util/lib/util.js index 8f123cf25..bfea58f0f 100644 --- a/packages/node_modules/@node-red/util/lib/util.js +++ b/packages/node_modules/@node-red/util/lib/util.js @@ -526,10 +526,11 @@ function getSetting(node, name, flow_) { if (flow) { if (node && node.g) { const group = flow.getGroupNode(node.g); - const result = flow.getGroupEnvSetting(node, group, name); + const [result, newName] = flow.getGroupEnvSetting(node, group, name); if (result) { return result.val; } + name = newName; } return flow.getSetting(name); } @@ -842,6 +843,9 @@ function encodeObject(msg,opts) { length: msg.msg.size } needsStringify = true; + } else if (msg.msg && msg.msg.constructor.name === "RegExp") { + msg.format = 'regexp'; + msg.msg = msg.msg.toString(); } if (needsStringify || (msg.format === "Object")) { msg.msg = safeJSONStringify(msg.msg, function(key, value) { @@ -907,6 +911,12 @@ function encodeObject(msg,opts) { data: Object.fromEntries(Array.from(value.entries()).slice(0,debuglength)), length: value.size } + } else if (value.constructor.name === "RegExp") { + value = { + __enc__: true, + type: "regexp", + data: value.toString() + } } } else if (value === undefined) { value = { diff --git a/packages/node_modules/@node-red/util/package.json b/packages/node_modules/@node-red/util/package.json index 0005ed292..ef65c8c67 100644 --- a/packages/node_modules/@node-red/util/package.json +++ b/packages/node_modules/@node-red/util/package.json @@ -16,10 +16,10 @@ ], "dependencies": { "fs-extra": "10.0.0", - "i18next": "21.3.1", + "i18next": "21.5.4", "json-stringify-safe": "5.0.1", "jsonata": "1.8.5", "lodash.clonedeep": "^4.5.0", - "moment-timezone": "0.5.33" + "moment-timezone": "0.5.34" } } diff --git a/test/unit/@node-red/runtime/lib/flows/Flow_spec.js b/test/unit/@node-red/runtime/lib/flows/Flow_spec.js index 95086c296..eed4810c4 100644 --- a/test/unit/@node-red/runtime/lib/flows/Flow_spec.js +++ b/test/unit/@node-red/runtime/lib/flows/Flow_spec.js @@ -1275,6 +1275,52 @@ describe('Flow', function() { } }); + it("can access environment variable property using $parent", function (done) { + try { + after(function() { + delete process.env.V0; + delete process.env.V1; + }) + process.env.V0 = "gv0"; + process.env.V1 = "gv1"; + var config = flowUtils.parseConfig([ + {id:"t1",type:"tab",env:[ + {"name": "V0", value: "v0", type: "str"} + ]}, + {id:"g1",type:"group",z:"t1",env:[ + {"name": "V0", value: "v1", type: "str"}, + {"name": "V1", value: "v2", type: "str"} + ]}, + {id:"g2",type:"group",z:"t1",g:"g1",env:[ + {"name": "V1", value: "v3", type: "str"} + ]}, + {id:"1",x:10,y:10,z:"t1",type:"test",foo:"${$parent.V0}",wires:[]}, + {id:"2",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"${$parent.V0}",wires:[]}, + {id:"3",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"${$parent.V1}",wires:[]}, + {id:"4",x:10,y:10,z:"t1",g:"g2",type:"test",foo:"${$parent.V1}",wires:[]}, + {id:"5",x:10,y:10,z:"t1",type:"test",foo:"${$parent.V1}",wires:[]}, + ]); + var flow = Flow.create({getSetting:v=>process.env[v]},config,config.flows["t1"]); + flow.start(); + + var activeNodes = flow.getActiveNodes(); + + activeNodes["1"].foo.should.equal("gv0"); + activeNodes["2"].foo.should.equal("v0"); + activeNodes["3"].foo.should.equal("gv1"); + activeNodes["4"].foo.should.equal("v2"); + activeNodes["5"].foo.should.equal("gv1"); + + flow.stop().then(function() { + done(); + }); + } + catch (e) { + console.log(e.stack); + done(e); + } + + }); });