diff --git a/CHANGELOG.md b/CHANGELOG.md index 618c3d8b5..68ea56f85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +#### 3.1.7: Maintenance Release + + - Add Japanese translation for v3.1.6 (#4603) @kazuhitoyokoi + - Update jsonata version (#4593) @hardillb + +#### 3.1.6: Maintenance Release + +Editor + + - Do not flag env var in num typedInput as error (#4582) @knolleary + - Fix example flow name in import dialog (#4578) @kazuhitoyokoi + - Fix missing node icons in workspace (#4570) @knolleary + +Runtime + + - Handle undefined env vars (#4581) @knolleary + - fix: Removed offending MD5 crypto hash and replaced with SHA1 and SHA256 … (#4568) @JaysonHurst + - chore: remove never use import code (#4580) @giscafer + +Nodes + + - fix: template node zh-CN translation (#4575) @giscafer + #### 3.1.5: Maintenance Release Runtime diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/settings.js b/packages/node_modules/@node-red/editor-api/lib/admin/settings.js index d72f9e094..425d42415 100644 --- a/packages/node_modules/@node-red/editor-api/lib/admin/settings.js +++ b/packages/node_modules/@node-red/editor-api/lib/admin/settings.js @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var apiUtils = require("../util"); var runtimeAPI; var settings; var theme = require("../editor/theme"); 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 e18925c19..b071a9caf 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 @@ -18,7 +18,6 @@ var BearerStrategy = require('passport-http-bearer').Strategy; var ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy; var passport = require("passport"); -var crypto = require("crypto"); var util = require("util"); var Tokens = require("./tokens"); diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/index.js b/packages/node_modules/@node-red/editor-api/lib/editor/index.js index 648daa09b..54cf17f12 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/index.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/index.js @@ -14,11 +14,9 @@ * limitations under the License. **/ -var express = require("express"); var path = require('path'); var comms = require("./comms"); -var library = require("./library"); var info = require("./settings"); var auth = require("../auth"); diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/library.js b/packages/node_modules/@node-red/editor-api/lib/editor/library.js index cd564b3f8..7853227ea 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/library.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/library.js @@ -15,8 +15,6 @@ **/ var apiUtils = require("../util"); -var fs = require('fs'); -var fspath = require('path'); var runtimeAPI; diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/locales.js b/packages/node_modules/@node-red/editor-api/lib/editor/locales.js index 568f5837b..6109d8741 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/locales.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/locales.js @@ -13,9 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var fs = require('fs'); -var path = require('path'); -// var apiUtil = require('../util'); var i18n = require("@node-red/util").i18n; // TODO: separate module diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/sshkeys.js b/packages/node_modules/@node-red/editor-api/lib/editor/sshkeys.js index 08097571f..885967b91 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/sshkeys.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/sshkeys.js @@ -15,7 +15,6 @@ **/ var apiUtils = require("../util"); -var express = require("express"); var runtimeAPI; var settings; diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/theme.js b/packages/node_modules/@node-red/editor-api/lib/editor/theme.js index e5c3904c7..c3808a751 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/theme.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/theme.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var express = require("express"); var util = require("util"); var path = require("path"); var fs = require("fs"); diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/ui.js b/packages/node_modules/@node-red/editor-api/lib/editor/ui.js index e7bf15069..37c79d415 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/ui.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/ui.js @@ -99,7 +99,7 @@ module.exports = { // settings.instanceId is set asynchronously to the editor-api // being initiaised. So we defer calculating the cacheBuster hash // until the first load of the editor - cacheBuster = crypto.createHash('md5').update(`${settings.version || 'version'}-${settings.instanceId || 'instanceId'}`).digest("hex").substring(0,12) + cacheBuster = crypto.createHash('sha1').update(`${settings.version || 'version'}-${settings.instanceId || 'instanceId'}`).digest("hex").substring(0,12) } let sessionMessages; diff --git a/packages/node_modules/@node-red/editor-api/lib/index.js b/packages/node_modules/@node-red/editor-api/lib/index.js index d9f34eafd..9264550b3 100644 --- a/packages/node_modules/@node-red/editor-api/lib/index.js +++ b/packages/node_modules/@node-red/editor-api/lib/index.js @@ -24,11 +24,8 @@ * @namespace @node-red/editor-api */ -var express = require("express"); var bodyParser = require("body-parser"); -var util = require('util'); var passport = require('passport'); -var cors = require('cors'); var auth = require("./auth"); var apiUtil = require("./util"); 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 5d988c68a..53c8616fd 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 @@ -303,7 +303,8 @@ "missingType": "不正なフロー - __index__ 番目の要素に'type'プロパティがありません" }, "conflictNotification1": "読み込もうとしているノードのいくつかは、既にワークスペース内に存在しています。", - "conflictNotification2": "読み込むノードを選択し、また既存のノードを置き換えるか、もしくはそれらのコピーを読み込むかも選択してください。" + "conflictNotification2": "読み込むノードを選択し、また既存のノードを置き換えるか、もしくはそれらのコピーを読み込むかも選択してください。", + "alreadyExists": "本ノードは既に存在" }, "copyMessagePath": "パスをコピーしました", "copyMessageValue": "値をコピーしました", diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js index d0e2c4256..94bf19718 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js @@ -919,7 +919,10 @@ RED.utils = (function() { * @returns true if valid, String if invalid */ function validateTypedProperty(propertyValue, propertyType, opt) { - + if (propertyValue && /^\${[^}]+}$/.test(propertyValue)) { + // Allow ${ENV_VAR} value + return true + } let error if (propertyType === 'json') { try { diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index 23385940c..b3ed6a6cc 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -4156,7 +4156,7 @@ RED.view = (function() { } var width = img.width * scaleFactor; if (width > 20) { - scalefactor *= 20/width; + scaleFactor *= 20/width; width = 20; } var height = img.height * scaleFactor; diff --git a/packages/node_modules/@node-red/editor-client/src/js/validators.js b/packages/node_modules/@node-red/editor-client/src/js/validators.js index 1673495aa..c17955ce1 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/validators.js +++ b/packages/node_modules/@node-red/editor-client/src/js/validators.js @@ -16,8 +16,20 @@ RED.validators = { number: function(blankAllowed,mopt){ return function(v, opt) { - if ((blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v))) { - return true; + if (blankAllowed && (v === '' || v === undefined)) { + return true + } + if (v !== '') { + if (/^NaN$|^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$|^[+-]?(0b|0B)[01]+$|^[+-]?(0o|0O)[0-7]+$|^[+-]?(0x|0X)[0-9a-fA-F]+$/.test(v)) { + return true + } + if (/^\${[^}]+}$/.test(v)) { + // Allow ${ENV_VAR} value + return true + } + } + if (!isNaN(v)) { + return true } if (opt && opt.label) { return RED._("validator.errors.invalid-num-prop", { diff --git a/packages/node_modules/@node-red/nodes/core/common/20-inject.html b/packages/node_modules/@node-red/nodes/core/common/20-inject.html index d50725d51..5895220d3 100644 --- a/packages/node_modules/@node-red/nodes/core/common/20-inject.html +++ b/packages/node_modules/@node-red/nodes/core/common/20-inject.html @@ -227,34 +227,42 @@ name: {value:""}, props:{value:[{p:"payload"},{p:"topic",vt:"str"}], validate:function(v, opt) { if (!v || v.length === 0) { return true } + const errors = [] for (var i=0;i 0) { + return errors + } return true; } }, repeat: { value:"", validate: function(v, opt) { if ((v === "") || - (RED.validators.number(v) && + (RED.validators.number()(v) && (v >= 0) && (v <= 2147483))) { return true; } @@ -263,7 +271,7 @@ }, crontab: {value:""}, once: {value:false}, - onceDelay: {value:0.1}, + onceDelay: {value:0.1, validate: RED.validators.number(true)}, topic: {value:""}, payload: {value:"", validate: RED.validators.typedInput("payloadType", false) }, payloadType: {value:"date"}, diff --git a/packages/node_modules/@node-red/nodes/locales/zh-CN/function/80-template.html b/packages/node_modules/@node-red/nodes/locales/zh-CN/function/80-template.html index 938a77818..31b43c764 100644 --- a/packages/node_modules/@node-red/nodes/locales/zh-CN/function/80-template.html +++ b/packages/node_modules/@node-red/nodes/locales/zh-CN/function/80-template.html @@ -23,7 +23,7 @@
template string
msg.payload填充的模板。如果未在编辑面板中配置,则可以将设为msg的属性。
-

Outputs

+

输出

msg object
由来自传入msg的属性来填充已配置的模板后输出的带有属性的msg。
@@ -32,7 +32,7 @@

默认情况下使用mustache格式。如有需要也可以切换其他格式。

例如:

Hello {{payload.name}}. Today is {{date}}
-

receives a message containing: +

接收一条消息,其中包含:

{
   date: "Monday",
   payload: {
diff --git a/packages/node_modules/@node-red/registry/lib/library.js b/packages/node_modules/@node-red/registry/lib/library.js
index 0b242b270..07cb54318 100644
--- a/packages/node_modules/@node-red/registry/lib/library.js
+++ b/packages/node_modules/@node-red/registry/lib/library.js
@@ -36,7 +36,7 @@ async function getFlowsFromPath(path) {
                     promises.push(getFlowsFromPath(fullPath));
                 } else if (/\.json$/.test(file)){
                     validFiles.push(file);
-                    promises.push(Promise.resolve(file.split(".")[0]))
+                    promises.push(Promise.resolve(file.replace(/\.json$/, '')))
                 }
             })
         }
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 b541a9d95..dd3d335a2 100644
--- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js
+++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js
@@ -485,7 +485,7 @@ class Flow {
         }
         if (!key.startsWith("$parent.")) {
             if (this._env.hasOwnProperty(key)) {
-                return (Object.hasOwn(this._env[key], 'value') && this._env[key].__clone__) ? clone(this._env[key].value) : this._env[key]
+                return (this._env[key] && Object.hasOwn(this._env[key], 'value') && this._env[key].__clone__) ? clone(this._env[key].value) : this._env[key]
             }
         } else {
                 key = key.substring(8);
diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Group.js b/packages/node_modules/@node-red/runtime/lib/flows/Group.js
index 521b6ceda..90d93cf45 100644
--- a/packages/node_modules/@node-red/runtime/lib/flows/Group.js
+++ b/packages/node_modules/@node-red/runtime/lib/flows/Group.js
@@ -41,7 +41,7 @@ class Group {
         }
         if (!key.startsWith("$parent.")) {
             if (this._env.hasOwnProperty(key)) {
-                return (Object.hasOwn(this._env[key], 'value') && this._env[key].__clone__) ? clone(this._env[key].value) : this._env[key]
+                return (this._env[key] && Object.hasOwn(this._env[key], 'value') && this._env[key].__clone__) ? clone(this._env[key].value) : this._env[key]
             }
         } else {
             key = key.substring(8);
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 62948d203..c3a47e1f7 100644
--- a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js
+++ b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js
@@ -376,7 +376,7 @@ class Subflow extends Flow {
         }
         if (!key.startsWith("$parent.")) {
             if (this._env.hasOwnProperty(key)) {
-                return (Object.hasOwn(this._env[key], 'value') && this._env[key].__clone__) ? clone(this._env[key].value) : this._env[key]
+                return (this._env[key] && Object.hasOwn(this._env[key], 'value') && this._env[key].__clone__) ? clone(this._env[key].value) : this._env[key]
             }
         } else {
             key = key.substring(8);
diff --git a/packages/node_modules/@node-red/runtime/lib/storage/index.js b/packages/node_modules/@node-red/runtime/lib/storage/index.js
index f5e07e254..989989e1d 100644
--- a/packages/node_modules/@node-red/runtime/lib/storage/index.js
+++ b/packages/node_modules/@node-red/runtime/lib/storage/index.js
@@ -77,7 +77,7 @@ var storageModuleInterface = {
                         flows: flows,
                         credentials: creds
                     };
-                    result.rev = crypto.createHash('md5').update(JSON.stringify(result.flows)).digest("hex");
+                    result.rev = crypto.createHash('sha256').update(JSON.stringify(result.flows)).digest("hex");
                     return result;
                 })
             });
@@ -95,7 +95,7 @@ var storageModuleInterface = {
 
             return credentialSavePromise.then(function() {
                 return storageModule.saveFlows(flows, user).then(function() {
-                    return crypto.createHash('md5').update(JSON.stringify(config.flows)).digest("hex");
+                    return crypto.createHash('sha256').update(JSON.stringify(config.flows)).digest("hex");
                 })
             });
         },
diff --git a/test/unit/@node-red/registry/lib/library_spec.js b/test/unit/@node-red/registry/lib/library_spec.js
index 2e0e7e99a..75c444f67 100644
--- a/test/unit/@node-red/registry/lib/library_spec.js
+++ b/test/unit/@node-red/registry/lib/library_spec.js
@@ -33,16 +33,15 @@ describe("library api", function() {
         should.not.exist(library.getExampleFlowPath('foo','bar'));
     });
 
-    it('returns a valid example path', function(done) {
+    it('returns valid example paths', function(done) {
         library.init();
         library.addExamplesDir("test-module",path.resolve(__dirname+'/resources/examples')).then(function() {
             try {
                 var flows = library.getExampleFlows();
-                flows.should.deepEqual({"test-module":{"f":["one"]}});
+                flows.should.deepEqual({"test-module":{"f":["1.2.3","one"]}});
 
                 var examplePath = library.getExampleFlowPath('test-module','one');
-                examplePath.should.eql(path.resolve(__dirname+'/resources/examples/one.json'))
-
+                examplePath.should.eql(path.resolve(__dirname+'/resources/examples/one.json'));
 
                 library.removeExamplesDir('test-module');
 
@@ -57,6 +56,5 @@ describe("library api", function() {
                 done(err);
             }
         });
-
-    })
+    });
 });
diff --git a/test/unit/@node-red/registry/lib/resources/examples/1.2.3.json b/test/unit/@node-red/registry/lib/resources/examples/1.2.3.json
new file mode 100644
index 000000000..e69de29bb