Compare commits

..

19 Commits

Author SHA1 Message Date
Nick O'Leary
6179d1eef2 Bump for beta.2 2023-03-06 17:30:34 +00:00
Nick O'Leary
9f121f4c72 Merge pull request #4094 from node-red/increase-workspace
Increase workspace size to 8000x8000
2023-03-06 17:13:24 +00:00
Nick O'Leary
4deca552fa Merge pull request #4093 from node-red/subflow-nested-context
Generate stable ids for subflow instance internal nodes
2023-03-06 17:13:10 +00:00
Nick O'Leary
2d066307f4 Merge branch 'master' into dev 2023-03-06 16:17:02 +00:00
Nick O'Leary
e47698bfd4 Handle null subflow object when clearing context 2023-03-03 20:02:46 +00:00
Nick O'Leary
e91981207f Generate stable ids for subflow instance internal nodes
Fixes #3996 #3889
2023-03-03 18:46:49 +00:00
Nick O'Leary
f1fa1bbe4e Merge pull request #4073 from kazuhitoyokoi/master-flowname
Change default file name to flows.json in project feature
2023-03-02 15:11:13 +00:00
Nick O'Leary
5eb46c570d Merge pull request #4075 from node-red/fix-link-to-monaco-options-4074
Update monaco docs link in settings.js
2023-03-02 15:08:33 +00:00
Stephen McLaughlin
24178beafc update monaco docs link in settings.js
closes #4074
2023-02-26 15:17:45 +00:00
Kazuhito Yokoi
e30df544db Change default file name to flows.json in project feature 2023-02-26 00:27:13 +09:00
Nick O'Leary
6044871438 Merge pull request #3911 from node-red/protect-hooks
Ensure errors in preDeliver callback are handled
2023-02-21 14:26:39 +00:00
Nick O'Leary
e612bb6a38 Merge pull request #3915 from node-red/Fix-file-write-last-line-newline-append
Fix extra newline append for multipart file write
2023-02-21 14:26:20 +00:00
Nick O'Leary
81ea67d6da Merge pull request #4046 from bggbr/master
Fix "EADDRINUSE" error
2023-02-21 14:25:06 +00:00
bggbr
892d21fb77 Fix "EADDRINUSE" error 2023-02-03 22:23:09 +09:00
Dave Conway-Jones
95a7980ada Update tests.yml 2022-11-30 22:28:52 +00:00
Dave Conway-Jones
281e9d1357 Fix extra newline append for multipart file write
ref Issue #3913
2022-11-30 22:28:46 +00:00
Nick O'Leary
742f05f59d Update packages/node_modules/@node-red/runtime/lib/flows/Flow.js 2022-11-30 22:23:04 +00:00
Nick O'Leary
79db4f8aa1 Update packages/node_modules/@node-red/runtime/lib/flows/Flow.js
Co-authored-by: Stephen McLaughlin <44235289+Steve-Mcl@users.noreply.github.com>
2022-11-30 22:22:44 +00:00
Nick O'Leary
f4d7b71984 Ensure errors in preDeliver callback are handled
Fixes #3848
2022-10-04 15:20:06 +01:00
21 changed files with 219 additions and 48 deletions

View File

@@ -19,9 +19,9 @@ jobs:
matrix:
node-version: [16, 18]
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

View File

@@ -1,5 +1,54 @@
#### 3.1.0-beta.1: Beta Release
#### 3.1.0-beta.2: Beta Release
Editor
- NEW: Add change icon to tabs (#4068) @knolleary
- NEW: Complete overhaul of Group UX (#4079) @knolleary
- NEW: Add link to node help in node edit dialog footer (#4065) @knolleary
- NEW: Added editor feature for connecting multiple nodes to single node (#4051) @sonntam
- NEW: Increase workspace size to 8000x8000 (#4094) @knolleary
- Ensure node buttons are redrawn when flow lock state is changed (#4091) @knolleary
- Prevent loops being created with junction nodes (#4087) @knolleary
- Prevent opening locked node's edit dialog (#4069) @knolleary
- Reverse direction of tab scroll to expected direction (#4064) @knolleary
- Add cancel operation to editableList (#4077) @HiroyasuNishiyama
- Apply Mermaid diagram for project settings UI (#4054) @kazuhitoyokoi
- Add tooltip for show/hide button on info sidebar (#4050) @kazuhitoyokoi
- Fix align nodes on locked tab (#4072) @HiroyasuNishiyama
- Fix importing connected link nodes into a subflow (#4082) @knolleary
- Fix to add empty marker to empty group (#4060) @HiroyasuNishiyama
- Fix image URLs for v3.0 tour (#4053) @kazuhitoyokoi
- Show scrollbar in notification dialog only when needed (#4048) @kazuhitoyokoi
- Update-monaco-and-typings (#4089) @Steve-Mcl
- Update jquery UI (#4088) @knolleary
- Support i18n of lock/unlock buttons in flow property UI (#4049) @kazuhitoyokoi
- Translation kr (#3895) @hae-iotplatform
- Translation zhcn (请懂中文的帮忙review) (#3952) @cliyr
- Add French translation of nodes (#3964) @GogoVega
- Add French translation (#3962) @GogoVega
- Portuguese Brazilian (pt-BR) translation (#3804) @FabsMuller
Runtime
- NEW: Generate stable ids for subflow instance internal nodes (#4093) @knolleary
- NEW: Change default file name to flows.json in project feature (#4073) @kazuhitoyokoi
- NEW: Deprecate synchronous access to jsonata (#4090) @knolleary
- Add Node 18 to test matrix (#4084) @knolleary
- Bump minimum nodejs version supported to match documented value (#4086) @knolleary
- Update monaco docs link in settings.js (#4075) @Steve-Mcl
- Remove duplicated messages in the message catalog (#4066) @kazuhitoyokoi
- Ensure errors in preDeliver callback are handled (#3911) @knolleary
- Fix "EADDRINUSE" error (#4046) @bggbr
Nodes
- Link Call: Clear link-call timeouts when node is closed (#4085) @knolleary
- Join: ensure inflight status is cleared when in auto mode (#4083) @knolleary
- File Out: Fix extra newline append for multipart file write (#3915) @dceejay
- Add validators for complete and link call nodes (#4056) @kazuhitoyokoi
#### 3.1.0-beta.1: Beta Release
Editor

View File

@@ -1,6 +1,6 @@
{
"name": "node-red",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"license": "Apache-2.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,8 +16,8 @@
}
],
"dependencies": {
"@node-red/util": "3.1.0-beta.1",
"@node-red/editor-client": "3.1.0-beta.1",
"@node-red/util": "3.1.0-beta.2",
"@node-red/editor-client": "3.1.0-beta.2",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"clone": "2.1.2",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-client",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,15 +1,71 @@
export default {
version: "3.1.0-beta.1",
version: "3.1.0-beta.2",
steps: [
{
titleIcon: "fa fa-map-o",
title: {
"en-US": "Welcome to Node-RED 3.1 Beta 1!",
"en-US": "Welcome to Node-RED 3.1 Beta 2!",
"ja": "Node-RED 3.1 ベータ1へようこそ!"
},
description: {
"en-US": "<p>This is the first beta release for 3.1.0 and we have a few new features to tell you about.</p>",
"ja": "<p>これは3.1.0の最初のベータリリースです。いくつかの新機能について説明します。</p>"
"en-US": "<p>This is the second beta release for 3.1.0 and we have a few new features to tell you about.</p>",
// "ja": "<p>これは3.1.0の最初のベータリリースです。いくつかの新機能について説明します。</p>"
}
},
{
title: {
"en-US": "New ways to work with groups",
},
description: {
"en-US": `<p>We have changed how you interact with groups in the editor.</p>
<ul>
<li>They don't get in the way when clicking on a node</li>
<li>They can be reordered using the Moving Forwards and Move Backwards actions</li>
<li>Multiple nodes can be dragged into a group in one go</li>
<li>Holding <code>Alt</code> when dragging a node will *remove* it from its group</li>
</ul>`
}
},
{
title: {
"en-US": "Change notification on tabs",
},
image: 'images/tab-changes.png',
description: {
"en-US": `<p>When a tab contains undeployed changes it now shows the
same style of change icon used by nodes.</p>
<p>This will make it much easier to track down changes when you're
working across multiple flows.</p>`
}
},
{
title: {
"en-US": "A bigger canvas to work with",
},
description: {
"en-US": `<p>The default canvas size has been increased so you can fit more
into one flow.</p>
<p>We still recommend using tools such as subflows and Link Nodes to help
keep things organised, but now you have more room to work in.</p>`
}
},
{
title: {
"en-US": "Finding help",
},
image: 'images/node-help.png',
description: {
"en-US": `<p>All node edit dialogs now include a link to that node's help
in the footer.</p>
<p>Clicking it will open up the Help sidebar showing the help for that node.</p>`
}
},
{
title: {
"en-US": "And lots more...",
},
description: {
"en-US": `<p>Of course we have everything from 3.1.0-beta.1 as well....</p>`
}
},
{

View File

@@ -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));
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/nodes",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/registry",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,7 +16,7 @@
}
],
"dependencies": {
"@node-red/util": "3.1.0-beta.1",
"@node-red/util": "3.1.0-beta.2",
"clone": "2.1.2",
"fs-extra": "10.1.0",
"semver": "7.3.8",

View File

@@ -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) {

View File

@@ -474,7 +474,7 @@ class Subflow extends Flow {
*/
function createNodeInSubflow(subflowInstanceId, def) {
let node = clone(def);
let nid = redUtil.generateId();
let nid = `${subflowInstanceId}-${node.id}` //redUtil.generateId();
// console.log("Create Node In subflow",node._alias, "--->",nid, "(",node.type,")")
// node_map[node.id] = node;
node._alias = node.id;

View File

@@ -589,17 +589,28 @@ function deleteContext(id,flowId) {
* If flowConfig is undefined, all flow/node contexts will be removed
**/
function clean(flowConfig) {
flowConfig = flowConfig || { allNodes: {} };
var promises = [];
for(var plugin in stores){
if(stores.hasOwnProperty(plugin)){
promises.push(stores[plugin].clean(Object.keys(flowConfig.allNodes)));
}
flowConfig = flowConfig || { allNodes: {}, subflows: {} };
const knownNodes = new Set(Object.keys(flowConfig.allNodes))
// We need to alias all of the subflow instance contents
for (const subflow of Object.values(flowConfig.subflows || {})) {
subflow.instances.forEach(instance => {
for (const nodeId of Object.keys(subflow.nodes || {})) {
knownNodes.add(`${instance.id}-${nodeId}`)
}
for (const nodeId of Object.keys(subflow.configs || {})) {
knownNodes.add(`${instance.id}-${nodeId}`)
}
})
}
for (var id in contexts) {
if (contexts.hasOwnProperty(id) && id !== "global") {
var promises = [];
for (const store of Object.values(stores)){
promises.push(store.clean(Array.from(knownNodes)));
}
for (const id of Object.keys(contexts)) {
if (id !== "global") {
var idParts = id.split(":");
if (!flowConfig.allNodes.hasOwnProperty(idParts[0])) {
if (!knownNodes.has(idParts[0])) {
delete contexts[id];
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/runtime",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,8 +16,8 @@
}
],
"dependencies": {
"@node-red/registry": "3.1.0-beta.1",
"@node-red/util": "3.1.0-beta.1",
"@node-red/registry": "3.1.0-beta.2",
"@node-red/util": "3.1.0-beta.2",
"async-mutex": "0.4.0",
"clone": "2.1.2",
"express": "4.18.2",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/util",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -1,6 +1,6 @@
{
"name": "node-red",
"version": "3.1.0-beta.1",
"version": "3.1.0-beta.2",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"license": "Apache-2.0",
@@ -31,10 +31,10 @@
"flow"
],
"dependencies": {
"@node-red/editor-api": "3.1.0-beta.1",
"@node-red/runtime": "3.1.0-beta.1",
"@node-red/util": "3.1.0-beta.1",
"@node-red/nodes": "3.1.0-beta.1",
"@node-red/editor-api": "3.1.0-beta.2",
"@node-red/runtime": "3.1.0-beta.2",
"@node-red/util": "3.1.0-beta.2",
"@node-red/nodes": "3.1.0-beta.2",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
"express": "4.18.2",

View File

@@ -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 {

View File

@@ -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",

View File

@@ -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"}];