diff --git a/packages/node_modules/@node-red/editor/src/js/ui/diff.js b/packages/node_modules/@node-red/editor/src/js/ui/diff.js index b5af903a0..457ba5638 100644 --- a/packages/node_modules/@node-red/editor/src/js/ui/diff.js +++ b/packages/node_modules/@node-red/editor/src/js/ui/diff.js @@ -881,7 +881,6 @@ 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))}); if (def.defaults) { properties = properties.concat(Object.keys(def.defaults)); @@ -889,6 +888,13 @@ RED.diff = (function() { if (node.type !== 'tab') { properties = properties.concat(['inputLabels','outputLabels']); } + if ( ((localNode && localNode.hasOwnProperty('icon')) || (remoteNode && remoteNode.hasOwnProperty('icon'))) && + properties.indexOf('icon') === -1 + ) { + properties.unshift('icon'); + } + + properties.forEach(function(d) { localChanged = false; remoteChanged = false; diff --git a/packages/node_modules/@node-red/editor/src/js/ui/editor.js b/packages/node_modules/@node-red/editor/src/js/ui/editor.js index e0445be54..46904131b 100644 --- a/packages/node_modules/@node-red/editor/src/js/ui/editor.js +++ b/packages/node_modules/@node-red/editor/src/js/ui/editor.js @@ -1110,7 +1110,7 @@ RED.editor = (function() { changed = true; } } else { - if (icon !== defaultIcon) { + if (icon !== "" && icon !== defaultIcon) { changes.icon = editing_node.icon; editing_node.icon = icon; changed = true; diff --git a/packages/node_modules/@node-red/nodes/core/logic/15-change.js b/packages/node_modules/@node-red/nodes/core/logic/15-change.js index 2c1443846..2e2332615 100644 --- a/packages/node_modules/@node-red/nodes/core/logic/15-change.js +++ b/packages/node_modules/@node-red/nodes/core/logic/15-change.js @@ -283,6 +283,9 @@ module.exports = function(RED) { } } function applyRules(msg, currentRule) { + if (currentRule >= node.rules.length) { + return Promise.resolve(msg); + } var r = node.rules[currentRule]; var rulePromise; if (r.t === "move") { diff --git a/packages/node_modules/@node-red/runtime/index.js b/packages/node_modules/@node-red/runtime/index.js index 7e6d8af95..20580d2d0 100644 --- a/packages/node_modules/@node-red/runtime/index.js +++ b/packages/node_modules/@node-red/runtime/index.js @@ -166,12 +166,10 @@ function start() { if (settings.httpStatic) { log.info(log._("runtime.paths.httpStatic",{path:path.resolve(settings.httpStatic)})); } - redNodes.loadContextsPlugin().then(function () { + return redNodes.loadContextsPlugin().then(function () { redNodes.loadFlows().then(redNodes.startFlows).catch(function(err) {}); started = true; }); - }).catch(function(err) { - console.log(err); }); }); } diff --git a/packages/node_modules/@node-red/runtime/locales/en-US/runtime.json b/packages/node_modules/@node-red/runtime/locales/en-US/runtime.json index 1bb6d0cae..a38f44d08 100644 --- a/packages/node_modules/@node-red/runtime/locales/en-US/runtime.json +++ b/packages/node_modules/@node-red/runtime/locales/en-US/runtime.json @@ -163,7 +163,12 @@ "error-module-not-defined": "Context store '__storage__' missing 'module' option", "error-invalid-module-name": "Invalid context store name: '__name__'", "error-invalid-default-module": "Default context store unknown: '__storage__'", - "unknown-store": "Unknown context store '__name__' specified. Using default store." + "unknown-store": "Unknown context store '__name__' specified. Using default store.", + "error-loading-module": "Error loading context store: __message__", + "localfilesystem": { + "error-circular": "Context __scope__ contains a circular reference that cannot be persisted", + "error-write": "Error writing context: __message__" + } } } diff --git a/packages/node_modules/@node-red/runtime/nodes/context/index.js b/packages/node_modules/@node-red/runtime/nodes/context/index.js index fc6018956..2f700cf30 100644 --- a/packages/node_modules/@node-red/runtime/nodes/context/index.js +++ b/packages/node_modules/@node-red/runtime/nodes/context/index.js @@ -170,6 +170,8 @@ function load() { defaultStore = "memory"; } return resolve(Promise.all(promises)); + }).catch(function(err) { + throw new Error(log._("context.error-loading-module",{message:err.toString()})); }); } diff --git a/packages/node_modules/@node-red/runtime/nodes/context/localfilesystem.js b/packages/node_modules/@node-red/runtime/nodes/context/localfilesystem.js index 64d0dc0d2..6f5f7d126 100644 --- a/packages/node_modules/@node-red/runtime/nodes/context/localfilesystem.js +++ b/packages/node_modules/@node-red/runtime/nodes/context/localfilesystem.js @@ -104,8 +104,6 @@ function loadFile(storagePath){ }else{ return Promise.resolve(undefined); } - }).catch(function(err){ - throw Promise.reject(err); }); } @@ -113,9 +111,21 @@ function listFiles(storagePath) { var promises = []; return fs.readdir(storagePath).then(function(files) { files.forEach(function(file) { - promises.push(fs.readdir(path.join(storagePath,file)).then(function(subdirFiles) { - return subdirFiles.map(subfile => path.join(file,subfile)); - })) + if (!/^\./.test(file)) { + var fullPath = path.join(storagePath,file); + var stats = fs.statSync(fullPath); + if (stats.isDirectory()) { + promises.push(fs.readdir(fullPath).then(function(subdirFiles) { + var result = []; + subdirFiles.forEach(subfile => { + if (/\.json$/.test(subfile)) { + result.push(path.join(file,subfile)) + } + }); + return result; + })) + } + } }); return Promise.all(promises); }).then(dirs => dirs.reduce((acc, val) => acc.concat(val), [])); @@ -172,7 +182,7 @@ LocalFileSystem.prototype.open = function(){ if(err.code == 'ENOENT') { return fs.ensureDir(self.storageBaseDir); }else{ - return Promise.reject(err); + throw err; } }).then(function() { self._flushPendingWrites = function() { @@ -185,7 +195,7 @@ LocalFileSystem.prototype.open = function(){ var context = newContext[scope]; var stringifiedContext = stringify(context); if (stringifiedContext.circular && !self.knownCircularRefs[scope]) { - log.warn("Context "+scope+" contains a circular reference that cannot be persisted"); + log.warn(log._("error-circular",{scope:scope})); self.knownCircularRefs[scope] = true; } else { delete self.knownCircularRefs[scope]; @@ -249,7 +259,11 @@ LocalFileSystem.prototype.set = function(scope, key, value, callback) { // there's a pending write which will handle this return; } else { - this._pendingWriteTimeout = setTimeout(function() { self._flushPendingWrites.call(self)}, this.flushInterval); + this._pendingWriteTimeout = setTimeout(function() { + self._flushPendingWrites.call(self).catch(function(err) { + log.error(log._("context.localfilesystem.error-write",{message:err.toString()})) + }); + }, this.flushInterval); } } else if (callback && typeof callback !== 'function') { throw new Error("Callback must be a function"); @@ -272,7 +286,7 @@ LocalFileSystem.prototype.set = function(scope, key, value, callback) { } var stringifiedContext = stringify(obj); if (stringifiedContext.circular && !self.knownCircularRefs[scope]) { - log.warn("Context "+scope+" contains a circular reference that cannot be persisted"); + log.warn(log._("error-circular",{scope:scope})); self.knownCircularRefs[scope] = true; } else { delete self.knownCircularRefs[scope]; diff --git a/test/nodes/core/logic/15-change_spec.js b/test/nodes/core/logic/15-change_spec.js index 8a7d123de..eda82a685 100644 --- a/test/nodes/core/logic/15-change_spec.js +++ b/test/nodes/core/logic/15-change_spec.js @@ -78,6 +78,24 @@ describe('change Node', function() { done(); }); }); + it('should no-op if there are no rules', function(done) { + var flow = [{"id":"changeNode1","type":"change","rules":[],"action":"","property":"","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.should.eql(sentMsg); + done(); + } catch(err) { + done(err); + } + }); + var sentMsg = {payload:"leaveMeAlong"}; + changeNode1.receive(sentMsg); + }); + }); describe('#set' , function() {