mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Compare commits
	
		
			63 Commits
		
	
	
		
			3.1.0-beta
			...
			4133-mqtt-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | a790136164 | ||
|  | 32a49a1ef1 | ||
|  | 4b88775183 | ||
|  | 29db82625f | ||
|  | 2b6c9e3439 | ||
|  | 9ea4853c89 | ||
|  | 3b5e21761b | ||
|  | 2d76bf29cf | ||
|  | c21f7abe4e | ||
|  | 8c191263c0 | ||
|  | 2679ff277c | ||
|  | 9e3f148273 | ||
|  | 7e9042e9f7 | ||
|  | 67c5a248ad | ||
|  | e8ddee24a9 | ||
|  | be4eab65f6 | ||
|  | c0650cc0f5 | ||
|  | 02c7d014cb | ||
|  | 67dd7e30fa | ||
|  | e9a08af73b | ||
|  | 08b1ef2766 | ||
|  | 667d8673d4 | ||
|  | d44ea9d558 | ||
|  | 86dfe86813 | ||
|  | 246409970d | ||
|  | 841f1849c8 | ||
|  | 00e7e4d43c | ||
|  | ee43a845aa | ||
|  | a7cc66af93 | ||
|  | f8701cfed0 | ||
|  | 6b205bf303 | ||
|  | 6fbcec8b98 | ||
|  | c30e57c31d | ||
|  | df3dc36874 | ||
|  | 7b71d8d212 | ||
|  | 2eaae4b83f | ||
|  | 3c66af9506 | ||
|  | e5d579c1bb | ||
|  | ee811ca89b | ||
|  | 8e4933041d | ||
|  | 1f3559e14f | ||
|  | f1fa1bbe4e | ||
|  | 5eb46c570d | ||
|  | 24178beafc | ||
|  | e30df544db | ||
|  | 6044871438 | ||
|  | e612bb6a38 | ||
|  | 81ea67d6da | ||
|  | 06e35baeaa | ||
|  | c9d72d7a1d | ||
|  | 62e9572070 | ||
|  | fea68c8acc | ||
|  | 929f0e90ac | ||
|  | 81331e68d2 | ||
|  | 4fda59a585 | ||
|  | ede3ac4282 | ||
|  | 16f8b78b39 | ||
|  | 892d21fb77 | ||
|  | 95a7980ada | ||
|  | 281e9d1357 | ||
|  | 742f05f59d | ||
|  | 79db4f8aa1 | ||
|  | f4d7b71984 | 
							
								
								
									
										14
									
								
								.github/workflows/tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/tests.yml
									
									
									
									
										vendored
									
									
								
							| @@ -19,9 +19,9 @@ jobs: | ||||
|       matrix: | ||||
|         node-version: [14, 16] | ||||
|     steps: | ||||
|     - uses: actions/checkout@v2 | ||||
|     - uses: actions/checkout@v3 | ||||
|     - name: Use Node.js ${{ matrix.node-version }} | ||||
|       uses: actions/setup-node@v2 | ||||
|       uses: actions/setup-node@v3 | ||||
|       with: | ||||
|         node-version: ${{ matrix.node-version }} | ||||
|     - name: Install Dependencies | ||||
| @@ -29,8 +29,8 @@ jobs: | ||||
|     - name: Run tests | ||||
|       run: | | ||||
|         npm run test | ||||
|     - name: Publish to coveralls.io | ||||
|       if: ${{ matrix.node-version == 14 }} | ||||
|       uses: coverallsapp/github-action@v1.1.2 | ||||
|       with: | ||||
|         github-token: ${{ github.token }} | ||||
|     # - name: Publish to coveralls.io | ||||
|     #   if: ${{ matrix.node-version == 14 }} | ||||
|     #   uses: coverallsapp/github-action@v1.1.2 | ||||
|     #   with: | ||||
|     #     github-token: ${{ github.token }} | ||||
|   | ||||
| @@ -2,8 +2,7 @@ | ||||
|  | ||||
| http://nodered.org | ||||
|  | ||||
| [](https://travis-ci.org/node-red/node-red) | ||||
| [](https://coveralls.io/r/node-red/node-red?branch=master) | ||||
| [](https://github.com/node-red/node-red/actions?query=branch%3Amaster) | ||||
|  | ||||
| Low-code programming for event-driven applications. | ||||
|  | ||||
|   | ||||
| @@ -491,6 +491,7 @@ | ||||
|         "unassigned": "Unassigned", | ||||
|         "global": "global", | ||||
|         "workspace": "workspace", | ||||
|         "editor": "edit dialog", | ||||
|         "selectAll": "Select all", | ||||
|         "selectNone": "Select none", | ||||
|         "selectAllConnected": "Select connected", | ||||
| @@ -683,6 +684,8 @@ | ||||
|             "empty": "empty", | ||||
|             "globalConfig": "Global Configuration Nodes", | ||||
|             "triggerAction": "Trigger action", | ||||
|             "showFlow": "Show", | ||||
|             "hideFlow": "Hide", | ||||
|             "find": "Find in workspace" | ||||
|         }, | ||||
|         "help": { | ||||
|   | ||||
| @@ -491,6 +491,7 @@ | ||||
|         "unassigned": "未割当", | ||||
|         "global": "グローバル", | ||||
|         "workspace": "ワークスペース", | ||||
|         "editor": "編集ダイアログ", | ||||
|         "selectAll": "全てのノードを選択", | ||||
|         "selectNone": "選択を外す", | ||||
|         "selectAllConnected": "接続されたノードを選択", | ||||
| @@ -683,6 +684,8 @@ | ||||
|             "empty": "空", | ||||
|             "globalConfig": "グローバル設定ノード", | ||||
|             "triggerAction": "アクションを実行", | ||||
|             "showFlow": "表示", | ||||
|             "hideFlow": "非表示", | ||||
|             "find": "ワークスペース内を検索" | ||||
|         }, | ||||
|         "help": { | ||||
|   | ||||
| @@ -2095,16 +2095,27 @@ RED.nodes = (function() { | ||||
|                     } else if (n.type.substring(0,7) === "subflow") { | ||||
|                         var parentId = n.type.split(":")[1]; | ||||
|                         var subflow = subflow_denylist[parentId]||subflow_map[parentId]||getSubflow(parentId); | ||||
|                         if (createNewIds || options.importMap[n.id] === "copy") { | ||||
|                             parentId = subflow.id; | ||||
|                             node.type = "subflow:"+parentId; | ||||
|                             node._def = registry.getNodeType(node.type); | ||||
|                             delete node.i; | ||||
|                         if (!subflow){ | ||||
|                             node._def = { | ||||
|                                 color:"#fee", | ||||
|                                 defaults: {}, | ||||
|                                 label: "unknown: "+n.type, | ||||
|                                 labelStyle: "red-ui-flow-node-label-italic", | ||||
|                                 outputs: n.outputs|| (n.wires && n.wires.length) || 0, | ||||
|                                 set: registry.getNodeSet("node-red/unknown") | ||||
|                             } | ||||
|                         } else { | ||||
|                             if (createNewIds || options.importMap[n.id] === "copy") { | ||||
|                                 parentId = subflow.id; | ||||
|                                 node.type = "subflow:"+parentId; | ||||
|                                 node._def = registry.getNodeType(node.type); | ||||
|                                 delete node.i; | ||||
|                             } | ||||
|                             node.name = n.name; | ||||
|                             node.outputs = subflow.out.length; | ||||
|                             node.inputs = subflow.in.length; | ||||
|                             node.env = n.env; | ||||
|                         } | ||||
|                         node.name = n.name; | ||||
|                         node.outputs = subflow.out.length; | ||||
|                         node.inputs = subflow.in.length; | ||||
|                         node.env = n.env; | ||||
|                     } else if (n.type === 'junction') { | ||||
|                          node._def = {defaults:{}} | ||||
|                          node._config.x = node.x | ||||
|   | ||||
| @@ -47,7 +47,7 @@ RED.actionList = (function() { | ||||
|         var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog); | ||||
|         searchInput = $('<input type="text" data-i18n="[placeholder]keyboard.filterActions">').appendTo(searchDiv).searchBox({ | ||||
|             change: function() { | ||||
|                 filterTerm = $(this).val().trim(); | ||||
|                 filterTerm = $(this).val().trim().toLowerCase(); | ||||
|                 filterTerms = filterTerm.split(" "); | ||||
|                 searchResults.editableList('filter'); | ||||
|                 searchResults.find("li.selected").removeClass("selected"); | ||||
|   | ||||
| @@ -37,13 +37,13 @@ RED.clipboard = (function() { | ||||
|             // IE11 workaround | ||||
|             // IE does not support data uri scheme for downloading data | ||||
|             var blob = new Blob([data], { | ||||
|                 type: "data:text/plain;charset=utf-8" | ||||
|                 type: "data:application/json;charset=utf-8" | ||||
|             }); | ||||
|             navigator.msSaveBlob(blob, file); | ||||
|         } | ||||
|         else { | ||||
|             var element = document.createElement('a'); | ||||
|             element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data)); | ||||
|             element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(data)); | ||||
|             element.setAttribute('download', file); | ||||
|             element.style.display = 'none'; | ||||
|             document.body.appendChild(element); | ||||
|   | ||||
| @@ -45,11 +45,13 @@ RED.editor = (function() { | ||||
|         var hasChanged; | ||||
|         if (node.type.indexOf("subflow:")===0) { | ||||
|             subflow = RED.nodes.subflow(node.type.substring(8)); | ||||
|             isValid = subflow.valid; | ||||
|             hasChanged = subflow.changed; | ||||
|             if (isValid === undefined) { | ||||
|                 isValid = validateNode(subflow); | ||||
|             if (subflow){ | ||||
|                 isValid = subflow.valid; | ||||
|                 hasChanged = subflow.changed; | ||||
|                 if (isValid === undefined) { | ||||
|                     isValid = validateNode(subflow); | ||||
|                     hasChanged = subflow.changed; | ||||
|                 } | ||||
|             } | ||||
|             validationErrors = validateNodeProperties(node, node._def.defaults, node); | ||||
|             node.valid = isValid && validationErrors.length === 0; | ||||
|   | ||||
| @@ -491,7 +491,11 @@ RED.keyboard = (function() { | ||||
|                 okButton.attr("disabled",!valid); | ||||
|             }); | ||||
|  | ||||
|             var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="red-ui-workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope); | ||||
|             var scopeSelect = $('<select>'+ | ||||
|                 '<option value="*" data-i18n="keyboard.global"></option>'+ | ||||
|                 '<option value="red-ui-workspace" data-i18n="keyboard.workspace"></option>'+ | ||||
|                 '<option value="red-ui-editor-stack" data-i18n="keyboard.editor"></option>'+ | ||||
|                 '</select>').appendTo(scope); | ||||
|             scopeSelect.i18n(); | ||||
|             if (object.scope === "workspace") { | ||||
|                 object.scope = "red-ui-workspace"; | ||||
|   | ||||
| @@ -747,14 +747,14 @@ RED.projects = (function() { | ||||
|                         var row = $('<div class="form-row"></div>').appendTo(body); | ||||
|                         $('<label for="red-ui-projects-dialog-screen-create-project-file">'+RED._("projects.default-files.flow-file")+'</label>').appendTo(row); | ||||
|                         var subrow = $('<div style="position:relative;"></div>').appendTo(row); | ||||
|                         var defaultFlowFile = (createProjectOptions.files &&createProjectOptions.files.flow) || (RED.settings.files && RED.settings.files.flow)||"flow.json"; | ||||
|                         var defaultFlowFile = (createProjectOptions.files &&createProjectOptions.files.flow) || (RED.settings.files && RED.settings.files.flow) || "flows.json"; | ||||
|                         projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val(defaultFlowFile) | ||||
|                             .on("change keyup paste",validateForm) | ||||
|                             .appendTo(subrow); | ||||
|                         $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow); | ||||
|                         $('<label class="red-ui-projects-edit-form-sublabel"><small>*.json</small></label>').appendTo(row); | ||||
|  | ||||
|                         var defaultCredentialsFile = (createProjectOptions.files &&createProjectOptions.files.credentials) || (RED.settings.files && RED.settings.files.credentials)||"flow_cred.json"; | ||||
|                         var defaultCredentialsFile = (createProjectOptions.files &&createProjectOptions.files.credentials) || (RED.settings.files && RED.settings.files.credentials) || "flows_cred.json"; | ||||
|                         row = $('<div class="form-row"></div>').appendTo(body); | ||||
|                         $('<label for="red-ui-projects-dialog-screen-create-project-credfile">'+RED._("projects.default-files.credentials-file")+'</label>').appendTo(row); | ||||
|                         subrow = $('<div style="position:relative;"></div>').appendTo(row); | ||||
| @@ -1257,7 +1257,7 @@ RED.projects = (function() { | ||||
|                         row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty"></div>').appendTo(container); | ||||
|                         $('<label for="red-ui-projects-dialog-screen-create-project-file">'+RED._("projects.create.flow-file")+'</label>').appendTo(row); | ||||
|                         subrow = $('<div style="position:relative;"></div>').appendTo(row); | ||||
|                         projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val("flow.json") | ||||
|                         projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val("flows.json") | ||||
|                             .on("change keyup paste",validateForm) | ||||
|                             .appendTo(subrow); | ||||
|                         $('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow); | ||||
|   | ||||
| @@ -663,24 +663,23 @@ RED.subflow = (function() { | ||||
|         var candidateOutputs = []; | ||||
|         var candidateInputNodes = {}; | ||||
|  | ||||
|         var boundingBox = [nodeList[0].x, | ||||
|             nodeList[0].y, | ||||
|             nodeList[0].x, | ||||
|             nodeList[0].y]; | ||||
|         var boundingBox = [nodeList[0].x-(nodeList[0].w/2), | ||||
|             nodeList[0].y-(nodeList[0].h/2), | ||||
|             nodeList[0].x+(nodeList[0].w/2), | ||||
|             nodeList[0].y+(nodeList[0].h/2)]; | ||||
|  | ||||
|         for (i=0;i<nodeList.length;i++) { | ||||
|             n = nodeList[i]; | ||||
|             nodes[n.id] = {n:n,outputs:{}}; | ||||
|             boundingBox = [ | ||||
|                 Math.min(boundingBox[0],n.x), | ||||
|                 Math.min(boundingBox[1],n.y), | ||||
|                 Math.max(boundingBox[2],n.x), | ||||
|                 Math.max(boundingBox[3],n.y) | ||||
|                 Math.min(boundingBox[0],n.x-(n.w/2)), | ||||
|                 Math.min(boundingBox[1],n.y-(n.h/2)), | ||||
|                 Math.max(boundingBox[2],n.x+(n.w/2)), | ||||
|                 Math.max(boundingBox[3],n.y+(n.h/2)) | ||||
|             ] | ||||
|         } | ||||
|         var offsetX = snapToGrid(boundingBox[0] - 200); | ||||
|         var offsetY = snapToGrid(boundingBox[1] - 80); | ||||
|  | ||||
|         var offsetX = snapToGrid(boundingBox[0] - 140); | ||||
|         var offsetY = snapToGrid(boundingBox[1] - 60); | ||||
|  | ||||
|         var center = [ | ||||
|             snapToGrid((boundingBox[2]+boundingBox[0]) / 2), | ||||
|   | ||||
| @@ -135,6 +135,10 @@ RED.sidebar.info.outliner = (function() { | ||||
|                     RED.workspaces.show(n.id, null, true); | ||||
|                 } | ||||
|             }); | ||||
|             RED.popover.tooltip(toggleVisibleButton, function () { | ||||
|                 var isHidden = !div.hasClass("red-ui-info-outline-item-hidden"); | ||||
|                 return RED._("sidebar.info." + (isHidden ? "hideFlow" : "showFlow")); | ||||
|             }); | ||||
|         } | ||||
|         if (n.type !== 'subflow') { | ||||
|             var toggleButton = $('<button type="button" class="red-ui-info-outline-item-control-disable red-ui-button red-ui-button-small"><i class="fa fa-circle-thin"></i><i class="fa fa-ban"></i></button>').appendTo(controls).on("click",function(evt) { | ||||
| @@ -613,6 +617,9 @@ RED.sidebar.info.outliner = (function() { | ||||
|                 objects[n.id].children = missingParents[n.id]; | ||||
|                 delete missingParents[n.id] | ||||
|             } | ||||
|             if (objects[n.id].children.length === 0) { | ||||
|                 objects[n.id].children.push(getEmptyItem(n.id)); | ||||
|             } | ||||
|         } | ||||
|         var parent = n.g||n.z||"__global__"; | ||||
|  | ||||
|   | ||||
| @@ -2646,6 +2646,16 @@ RED.view = (function() { | ||||
|                         var result = RED.nodes.removeJunction(node) | ||||
|                         removedJunctions.push(node); | ||||
|                         removedLinks = removedLinks.concat(result.links); | ||||
|                         if (node.g) { | ||||
|                             var group = RED.nodes.group(node.g); | ||||
|                             if (selectedGroups.indexOf(group) === -1) { | ||||
|                                 // Don't use RED.group.removeFromGroup as that emits | ||||
|                                 // a change event on the node - but we're deleting it | ||||
|                                 var index = group.nodes.indexOf(node); | ||||
|                                 group.nodes.splice(index,1); | ||||
|                                 RED.group.markDirty(group); | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                         if (node.direction === "out") { | ||||
|                             removedSubflowOutputs.push(node); | ||||
|   | ||||
| @@ -124,7 +124,7 @@ | ||||
|     list-style-type: none; | ||||
|     margin: 0; | ||||
|     padding:0; | ||||
|  | ||||
|     overflow-wrap: anywhere; | ||||
|     li { | ||||
|         display: inline-block; | ||||
|         padding:0; | ||||
|   | ||||
| @@ -32,7 +32,7 @@ | ||||
|     color: var(--red-ui-primary-text-color); | ||||
|     border: 1px solid var(--red-ui-notification-border-default); | ||||
|     border-left-width: 16px; | ||||
|     overflow: scroll; | ||||
|     overflow: auto; | ||||
|     max-height: 80vh; | ||||
|     .ui-dialog-buttonset { | ||||
|         margin-top: 20px; | ||||
|   | ||||
| @@ -55,7 +55,7 @@ | ||||
| .red-ui-palette-search { | ||||
|     position: relative; | ||||
|     overflow: hidden; | ||||
|     background: var(--red-ui-secondary-background); | ||||
|     background: var(--red-ui-form-input-background); | ||||
|     text-align: center; | ||||
|     height: 35px; | ||||
|     padding: 3px; | ||||
|   | ||||
| @@ -35,6 +35,7 @@ | ||||
|     padding: 8px; | ||||
|     border-radius: 2px; | ||||
|     background: var(--red-ui-popover-background); | ||||
|     overflow-wrap: anywhere; | ||||
| } | ||||
| .red-ui-popover:after, .red-ui-popover:before { | ||||
|     border: solid transparent; | ||||
|   | ||||
| @@ -108,6 +108,8 @@ | ||||
|     } | ||||
|     .red-ui-search-result-node-label { | ||||
|         color: var(--red-ui-secondary-text-color); | ||||
|         width: 240px; | ||||
|         overflow-wrap: anywhere; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -31,6 +31,7 @@ | ||||
|     > span { | ||||
|         display: inline-block; | ||||
|         margin-left: 5px; | ||||
|         overflow-wrap: anywhere; | ||||
|     } | ||||
|     border-bottom: 1px solid var(--red-ui-secondary-border-color); | ||||
| } | ||||
|   | ||||
| @@ -18,7 +18,16 @@ | ||||
|         color:"#c0edc0", | ||||
|         defaults: { | ||||
|             name: {value:""}, | ||||
|             scope: {value:[], type:"*[]"}, | ||||
|             scope: { | ||||
|                 value: [], | ||||
|                 type: "*[]", | ||||
|                 validate: function (v, opt) { | ||||
|                     if (v.length > 0) { | ||||
|                         return true; | ||||
|                     } | ||||
|                     return RED._("node-red:complete.errors.scopeUndefined"); | ||||
|                 } | ||||
|             }, | ||||
|             uncaught: {value:false} | ||||
|         }, | ||||
|         inputs:0, | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
|  | ||||
| <script type="text/html" data-template-name="link in"> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label> | ||||
| @@ -272,7 +271,17 @@ | ||||
|         color:"#ddd",//"#87D8CF", | ||||
|         defaults: { | ||||
|             name: { value: "" }, | ||||
|             links: { value: [], type:"link in[]" }, | ||||
|             links: { | ||||
|                 value: [], | ||||
|                 type: "link in[]", | ||||
|                 validate: function (v, opt) { | ||||
|                     if ((this.linkType === "static" && v.length > 0) | ||||
|                       || this.linkType === "dynamic") { | ||||
|                         return true; | ||||
|                     } | ||||
|                     return RED._("node-red:link.errors.linkUndefined"); | ||||
|                 } | ||||
|             }, | ||||
|             linkType: { value:"static" }, | ||||
|             timeout: { | ||||
|                 value: "30", | ||||
|   | ||||
| @@ -164,10 +164,10 @@ module.exports = function(RED) { | ||||
|                     if (returnNode && returnNode.returnLinkMessage) { | ||||
|                         returnNode.returnLinkMessage(messageEvent.id, msg); | ||||
|                     } else { | ||||
|                         node.warn(RED._("link.error.missingReturn")) | ||||
|                         node.warn(RED._("link.errors.missingReturn")); | ||||
|                     } | ||||
|                 } else { | ||||
|                     node.warn(RED._("link.error.missingReturn")) | ||||
|                     node.warn(RED._("link.errors.missingReturn")); | ||||
|                 } | ||||
|                 done(); | ||||
|             } else if (mode === "link") { | ||||
|   | ||||
| @@ -35,7 +35,11 @@ module.exports = function(RED) { | ||||
|                 } | ||||
|                 else { node.previous = {}; } | ||||
|             } | ||||
|             var value = RED.util.getMessageProperty(msg,node.property); | ||||
|             var value; | ||||
|             try { | ||||
|                 value = RED.util.getMessageProperty(msg,node.property); | ||||
|             } | ||||
|             catch(e) { } | ||||
|             if (value !== undefined) { | ||||
|                 var t = "_no_topic"; | ||||
|                 if (node.septopics) { t = topic || t; } | ||||
|   | ||||
| @@ -697,7 +697,8 @@ module.exports = function(RED) { | ||||
|                 node.options.rejectUnauthorized = (node.verifyservercert == "true" || node.verifyservercert === true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         node.v5 = () => node.options && node.options.protocolVersion == 5 | ||||
|         node.subscriptionIdentifiersAvailable = () => node.v5() && node.serverProperties && node.serverProperties.subscriptionIdentifiersAvailable | ||||
|         n.autoConnect = n.autoConnect === "false" || n.autoConnect === false ? false : true; | ||||
|         node.setOptions(n, true); | ||||
|  | ||||
| @@ -920,7 +921,12 @@ module.exports = function(RED) { | ||||
|             }; | ||||
|             node.subscriptions[topic][ref] = sub; | ||||
|             if (node.connected) { | ||||
|                 const subIdsAvailable = node.subscriptionIdentifiersAvailable() | ||||
|                 node._clientOn('message',sub.handler); | ||||
|                 // if the broker doesn't support subscription identifiers (e.g. AWS core), then don't send them | ||||
|                 if (options.properties && options.properties.subscriptionIdentifier && subIdsAvailable !== true) { | ||||
|                     delete options.properties.subscriptionIdentifier | ||||
|                 } | ||||
|                 node.client.subscribe(topic, options); | ||||
|             } | ||||
|         }; | ||||
|   | ||||
| @@ -117,7 +117,9 @@ module.exports = function(RED) { | ||||
|                 } | ||||
|                 if (typeof data === "boolean") { data = data.toString(); } | ||||
|                 if (typeof data === "number") { data = data.toString(); } | ||||
|                 if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; } | ||||
|                 var aflg = true; | ||||
|                 if (msg.hasOwnProperty("parts") && msg.parts.type === "string" && (msg.parts.count === msg.parts.index + 1)) { aflg = false; } | ||||
|                 if ((node.appendNewline) && (!Buffer.isBuffer(data)) && aflg) { data += os.EOL; } | ||||
|                 var buf; | ||||
|                 if (node.encoding === "setbymsg") { | ||||
|                     buf = encode(data, msg.encoding || "none"); | ||||
| @@ -314,7 +316,6 @@ module.exports = function(RED) { | ||||
|             }); | ||||
|             filename = filename || ""; | ||||
|             var fullFilename = filename; | ||||
|             var filePath = ""; | ||||
|             if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) { | ||||
|                 fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename)); | ||||
|             } | ||||
|   | ||||
| @@ -119,7 +119,10 @@ | ||||
|         } | ||||
|     }, | ||||
|     "complete": { | ||||
|         "completeNodes": "complete: __number__" | ||||
|         "completeNodes": "complete: __number__", | ||||
|         "errors": { | ||||
|             "scopeUndefined": "scope undefined" | ||||
|         } | ||||
|     }, | ||||
|     "debug": { | ||||
|         "output": "Output", | ||||
| @@ -181,8 +184,9 @@ | ||||
|         "staticLinkCall": "Fixed target", | ||||
|         "dynamicLinkCall": "Dynamic target (msg.target)", | ||||
|         "dynamicLinkLabel": "Dynamic", | ||||
|         "error": { | ||||
|             "missingReturn": "Missing return node information" | ||||
|         "errors": { | ||||
|             "missingReturn": "Missing return node information", | ||||
|             "linkUndefined": "link undefined" | ||||
|         } | ||||
|     }, | ||||
|     "tls": { | ||||
|   | ||||
| @@ -119,7 +119,10 @@ | ||||
|         } | ||||
|     }, | ||||
|     "complete": { | ||||
|         "completeNodes": "complete: __number__" | ||||
|         "completeNodes": "complete: __number__", | ||||
|         "errors": { | ||||
|             "scopeUndefined": "スコープが未定義" | ||||
|         } | ||||
|     }, | ||||
|     "debug": { | ||||
|         "output": "対象", | ||||
| @@ -181,8 +184,9 @@ | ||||
|         "staticLinkCall": "対象を固定で指定", | ||||
|         "dynamicLinkCall": "対象を動的に指定 (msg.target)", | ||||
|         "dynamicLinkLabel": "動的", | ||||
|         "error": { | ||||
|             "missingReturn": "返却するノードの情報が存在しません" | ||||
|         "errors": { | ||||
|             "missingReturn": "返却するノードの情報が存在しません", | ||||
|             "linkUndefined": "リンクが未定義" | ||||
|         } | ||||
|     }, | ||||
|     "tls": { | ||||
|   | ||||
| @@ -818,6 +818,16 @@ function handlePreRoute(flow, sendEvent, reportError) { | ||||
|     }) | ||||
| } | ||||
|  | ||||
| function deliverMessageToDestination(sendEvent) { | ||||
|     if (sendEvent?.destination?.node) { | ||||
|         try { | ||||
|             sendEvent.destination.node.receive(sendEvent.msg); | ||||
|         } catch(err) { | ||||
|             Log.error(`Error delivering message to node:${sendEvent.destination.node._path} [${sendEvent.destination.node.type}]`) | ||||
|             Log.error(err.stack) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| function handlePreDeliver(flow,sendEvent, reportError) { | ||||
|     // preDeliver - the local router has identified the node it is going to send to. At this point, the message has been cloned if needed. | ||||
|     hooks.trigger("preDeliver",sendEvent,(err) => { | ||||
| @@ -827,15 +837,10 @@ function handlePreDeliver(flow,sendEvent, reportError) { | ||||
|         } else if (err !== false) { | ||||
|             if (asyncMessageDelivery) { | ||||
|                 setImmediate(function() { | ||||
|                     if (sendEvent.destination.node) { | ||||
|                         sendEvent.destination.node.receive(sendEvent.msg); | ||||
|                     } | ||||
|                     deliverMessageToDestination(sendEvent) | ||||
|                 }) | ||||
|             } else { | ||||
|                 if (sendEvent.destination.node) { | ||||
|                     sendEvent.destination.node.receive(sendEvent.msg); | ||||
|  | ||||
|                 } | ||||
|                 deliverMessageToDestination(sendEvent) | ||||
|             } | ||||
|             // postDeliver - the message has been dispatched to be delivered asynchronously (unless the sync delivery flag is set, in which case it would be continue as synchronous delivery) | ||||
|             hooks.trigger("postDeliver", sendEvent, function(err) { | ||||
|   | ||||
| @@ -199,7 +199,9 @@ function parseConfig(config) { | ||||
|                if (subflowDetails) { | ||||
|                    var subflowType = subflowDetails[1] | ||||
|                    n.subflow = subflowType; | ||||
|                    flow.subflows[subflowType].instances.push(n) | ||||
|                    if (flow.subflows[subflowType]) { | ||||
|                        flow.subflows[subflowType].instances.push(n) | ||||
|                    } | ||||
|                } | ||||
|                if (container) { | ||||
|                    container.nodes[n.id] = n; | ||||
|   | ||||
							
								
								
									
										2
									
								
								packages/node_modules/node-red/red.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								packages/node_modules/node-red/red.js
									
									
									
									
										vendored
									
									
								
							| @@ -458,7 +458,7 @@ httpsPromise.then(function(startupHttps) { | ||||
|     RED.start().then(function() { | ||||
|         if (settings.httpAdminRoot !== false || settings.httpNodeRoot !== false || settings.httpStatic) { | ||||
|             server.on('error', function(err) { | ||||
|                 if (err.errno === "EADDRINUSE") { | ||||
|                 if (err.code === "EADDRINUSE") { | ||||
|                     RED.log.error(RED.log._("server.unable-to-listen", {listenpath:getListenPath()})); | ||||
|                     RED.log.error(RED.log._("server.port-in-use")); | ||||
|                 } else { | ||||
|   | ||||
							
								
								
									
										2
									
								
								packages/node_modules/node-red/settings.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								packages/node_modules/node-red/settings.js
									
									
									
									
										vendored
									
									
								
							| @@ -416,7 +416,7 @@ module.exports = { | ||||
|                  */ | ||||
|                 // theme: "vs", | ||||
|                 /** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc. | ||||
|                  * for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html | ||||
|                  * for the full list, see https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneEditorConstructionOptions.html | ||||
|                  */ | ||||
|                 //fontSize: 14, | ||||
|                 //fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace", | ||||
|   | ||||
| @@ -854,7 +854,7 @@ describe('inject node', function() { | ||||
|             }); | ||||
|             n1.on("call:error", function(err) { | ||||
|                 count++; | ||||
|                 if (count == 2) { | ||||
|                 if (count == 1) { | ||||
|                     done(); | ||||
|                 } | ||||
|             }); | ||||
|   | ||||
| @@ -194,6 +194,55 @@ describe('file Nodes', function() { | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should append to a file and add newline, except last line of multipart input', function(done) { | ||||
|             var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false, wires: [["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper"}]; | ||||
|             try { | ||||
|                 fs.unlinkSync(fileToTest); | ||||
|             } catch(err) { | ||||
|             } | ||||
|             helper.load(fileNode, flow, function() { | ||||
|                 var n1 = helper.getNode("fileNode1"); | ||||
|                 var n2 = helper.getNode("helperNode1"); | ||||
|                 var count = 0; | ||||
|                 //var data = ["Line1", "Line2"]; | ||||
|  | ||||
|                 n2.on("input", function (msg) { | ||||
|                     try { | ||||
|                         msg.should.have.property("payload"); | ||||
|                         //data.should.containDeep([msg.payload]); | ||||
|                         if (count === 3) { | ||||
|                             var f = fs.readFileSync(fileToTest).toString(); | ||||
|                             if (os.type() !== "Windows_NT") { | ||||
|                                 f.should.have.length(23); | ||||
|                                 f.should.equal("Line1\nLine2\nLine3\nLine4"); | ||||
|                             } | ||||
|                             else { | ||||
|                                 f.should.have.length(23); | ||||
|                                 f.should.equal("Line1\r\nLine2\r\nLine3\r\nLine4"); | ||||
|                             } | ||||
|                             done(); | ||||
|                         } | ||||
|                         count++; | ||||
|                     } | ||||
|                     catch (e) { | ||||
|                         done(e); | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 n1.receive({payload:"Line1",parts:{index:0,type:"string"}});    // string | ||||
|                 setTimeout(function() { | ||||
|                     n1.receive({payload:"Line2",parts:{index:1,type:"string"}});    // string | ||||
|                 },30); | ||||
|                 setTimeout(function() { | ||||
|                     n1.receive({payload:"Line3",parts:{index:2,type:"string"}});    // string | ||||
|                 },60); | ||||
|                 setTimeout(function() { | ||||
|                     n1.receive({payload:"Line4",parts:{index:3,type:"string",count:4}});    // string | ||||
|                 },90); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should append to a file after it has been deleted ', function(done) { | ||||
|             var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper"}]; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user