@node-red/nodes 3.1.0-beta.3 → 3.1.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/common/25-catch.html +3 -1
- package/core/common/25-status.html +9 -1
- package/core/common/60-link.html +1 -1
- package/core/function/10-function.html +27 -1
- package/core/function/10-function.js +21 -3
- package/core/function/10-switch.html +1 -0
- package/core/function/89-delay.js +1 -0
- package/core/network/21-httprequest.html +1 -1
- package/core/network/21-httprequest.js +26 -11
- package/core/sequence/17-split.js +3 -0
- package/core/storage/10-file.js +10 -3
- package/locales/de/messages.json +2 -1
- package/locales/en-US/common/20-inject.html +1 -1
- package/locales/en-US/messages.json +4 -1
- package/locales/fr/messages.json +3 -0
- package/locales/ja/common/20-inject.html +1 -1
- package/locales/ja/messages.json +6 -1
- package/locales/ru/messages.json +2 -1
- package/package.json +1 -1
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
if (this.name) {
|
|
42
42
|
return this.name;
|
|
43
43
|
}
|
|
44
|
-
if (this.scope) {
|
|
44
|
+
if (this.scope === "group") {
|
|
45
|
+
return this._("catch.catchGroup");
|
|
46
|
+
} else if (Array.isArray(this.scope)) {
|
|
45
47
|
return this._("catch.catchNodes",{number:this.scope.length});
|
|
46
48
|
}
|
|
47
49
|
return this.uncaught?this._("catch.catchUncaught"):this._("catch.catch")
|
|
@@ -33,7 +33,15 @@
|
|
|
33
33
|
outputs:1,
|
|
34
34
|
icon: "status.svg",
|
|
35
35
|
label: function() {
|
|
36
|
-
|
|
36
|
+
if (this.name) {
|
|
37
|
+
return this.name;
|
|
38
|
+
}
|
|
39
|
+
if (this.scope === "group") {
|
|
40
|
+
return this._("status.statusGroup");
|
|
41
|
+
} else if (Array.isArray(this.scope)) {
|
|
42
|
+
return this._("status.statusNodes",{number:this.scope.length});
|
|
43
|
+
}
|
|
44
|
+
return this._("status.status")
|
|
37
45
|
},
|
|
38
46
|
labelStyle: function() {
|
|
39
47
|
return this.name?"node_label_italic":"";
|
package/core/common/60-link.html
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
|
29
29
|
</div>
|
|
30
30
|
<div class="form-row">
|
|
31
|
-
<label for="node-input-timeout"><span data-i18n="exec.label.timeout"></span></label>
|
|
31
|
+
<label for="node-input-timeout"><i class="fa fa-clock-o"></i> <span data-i18n="exec.label.timeout"></span></label>
|
|
32
32
|
<input type="text" id="node-input-timeout" placeholder="30" style="width: 70px; margin-right: 5px;"><span data-i18n="inject.seconds"></span>
|
|
33
33
|
</div>
|
|
34
34
|
<div class="form-row">
|
|
@@ -82,6 +82,11 @@
|
|
|
82
82
|
<input id="node-input-outputs" style="width: 60px;" value="1">
|
|
83
83
|
</div>
|
|
84
84
|
|
|
85
|
+
<div class="form-row">
|
|
86
|
+
<label for="node-input-timeout"><i class="fa fa-clock-o"></i> <span data-i18n="function.label.timeout"></span></label>
|
|
87
|
+
<input id="node-input-timeout" style="width: 60px;" data-i18n="[placeholder]join.seconds">
|
|
88
|
+
</div>
|
|
89
|
+
|
|
85
90
|
<div class="form-row node-input-libs-row hide" style="margin-bottom: 0px;">
|
|
86
91
|
<label><i class="fa fa-cubes"></i> <span data-i18n="function.label.modules"></span></label>
|
|
87
92
|
</div>
|
|
@@ -360,6 +365,7 @@
|
|
|
360
365
|
name: {value:"_DEFAULT_"},
|
|
361
366
|
func: {value:"\nreturn msg;"},
|
|
362
367
|
outputs: {value:1},
|
|
368
|
+
timeout:{value:0},
|
|
363
369
|
noerr: {value:0,required:true,
|
|
364
370
|
validate: function(v, opt) {
|
|
365
371
|
if (!v) {
|
|
@@ -464,6 +470,26 @@
|
|
|
464
470
|
}
|
|
465
471
|
});
|
|
466
472
|
|
|
473
|
+
// 4294967 is max in node.js timeout.
|
|
474
|
+
$( "#node-input-timeout" ).spinner({
|
|
475
|
+
min: 0,
|
|
476
|
+
max: 4294967,
|
|
477
|
+
change: function(event, ui) {
|
|
478
|
+
var value = this.value;
|
|
479
|
+
if(value == ""){
|
|
480
|
+
value = 0;
|
|
481
|
+
}
|
|
482
|
+
else
|
|
483
|
+
{
|
|
484
|
+
value = parseInt(value);
|
|
485
|
+
}
|
|
486
|
+
value = isNaN(value) ? 1 : value;
|
|
487
|
+
value = Math.max(value, parseInt($(this).attr("aria-valuemin")));
|
|
488
|
+
value = Math.min(value, parseInt($(this).attr("aria-valuemax")));
|
|
489
|
+
if (value !== this.value) { $(this).spinner("value", value); }
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
|
|
467
493
|
var buildEditor = function(id, stateId, focus, value, defaultValue, extraLibs, offset) {
|
|
468
494
|
var editor = RED.editor.createEditor({
|
|
469
495
|
id: id,
|
|
@@ -503,7 +529,7 @@
|
|
|
503
529
|
editor:this.editor, // the field name the main text body goes to
|
|
504
530
|
mode:"ace/mode/nrjavascript",
|
|
505
531
|
fields:[
|
|
506
|
-
'name', 'outputs',
|
|
532
|
+
'name', 'outputs', 'timeout',
|
|
507
533
|
{
|
|
508
534
|
name: 'initialize',
|
|
509
535
|
get: function() {
|
|
@@ -96,6 +96,13 @@ module.exports = function(RED) {
|
|
|
96
96
|
node.name = n.name;
|
|
97
97
|
node.func = n.func;
|
|
98
98
|
node.outputs = n.outputs;
|
|
99
|
+
node.timeout = n.timeout*1000;
|
|
100
|
+
if(node.timeout>0){
|
|
101
|
+
node.timeoutOptions = {
|
|
102
|
+
timeout:node.timeout,
|
|
103
|
+
breakOnSigint:true
|
|
104
|
+
}
|
|
105
|
+
}
|
|
99
106
|
node.ini = n.initialize ? n.initialize.trim() : "";
|
|
100
107
|
node.fin = n.finalize ? n.finalize.trim() : "";
|
|
101
108
|
node.libs = n.libs || [];
|
|
@@ -362,6 +369,10 @@ module.exports = function(RED) {
|
|
|
362
369
|
})(__initSend__);`;
|
|
363
370
|
iniOpt = createVMOpt(node, " setup");
|
|
364
371
|
iniScript = new vm.Script(iniText, iniOpt);
|
|
372
|
+
if(node.timeout>0){
|
|
373
|
+
iniOpt.timeout = node.timeout;
|
|
374
|
+
iniOpt.breakOnSigint = true;
|
|
375
|
+
}
|
|
365
376
|
}
|
|
366
377
|
node.script = vm.createScript(functionText, createVMOpt(node, ""));
|
|
367
378
|
if (node.fin && (node.fin !== "")) {
|
|
@@ -385,6 +396,10 @@ module.exports = function(RED) {
|
|
|
385
396
|
})();`;
|
|
386
397
|
finOpt = createVMOpt(node, " cleanup");
|
|
387
398
|
finScript = new vm.Script(finText, finOpt);
|
|
399
|
+
if(node.timeout>0){
|
|
400
|
+
finOpt.timeout = node.timeout;
|
|
401
|
+
finOpt.breakOnSigint = true;
|
|
402
|
+
}
|
|
388
403
|
}
|
|
389
404
|
var promise = Promise.resolve();
|
|
390
405
|
if (iniScript) {
|
|
@@ -396,9 +411,12 @@ module.exports = function(RED) {
|
|
|
396
411
|
var start = process.hrtime();
|
|
397
412
|
context.msg = msg;
|
|
398
413
|
context.__send__ = send;
|
|
399
|
-
context.__done__ = done;
|
|
400
|
-
|
|
401
|
-
node.
|
|
414
|
+
context.__done__ = done;
|
|
415
|
+
var opts = {};
|
|
416
|
+
if (node.timeout>0){
|
|
417
|
+
opts = node.timeoutOptions;
|
|
418
|
+
}
|
|
419
|
+
node.script.runInContext(context,opts);
|
|
402
420
|
context.results.then(function(results) {
|
|
403
421
|
sendResults(node,send,msg._msgid,results,false);
|
|
404
422
|
if (handleNodeDoneCall) {
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
} else if (type === "istype") {
|
|
104
104
|
r.v = rule.find(".node-input-rule-type-value").typedInput('type');
|
|
105
105
|
r.vt = rule.find(".node-input-rule-type-value").typedInput('type');
|
|
106
|
+
r.vt = (r.vt === "number") ? "num" : "str";
|
|
106
107
|
} else if (type === "jsonata_exp") {
|
|
107
108
|
r.v = rule.find(".node-input-rule-exp-value").typedInput('value');
|
|
108
109
|
r.vt = rule.find(".node-input-rule-exp-value").typedInput('type');
|
|
@@ -229,6 +229,7 @@ module.exports = function(RED) {
|
|
|
229
229
|
node.on("input", function(msg, send, done) {
|
|
230
230
|
if (!node.drop) {
|
|
231
231
|
var m = RED.util.cloneMessage(msg);
|
|
232
|
+
delete m.flush;
|
|
232
233
|
if (Object.keys(m).length > 1) {
|
|
233
234
|
if (node.intervalID !== -1) {
|
|
234
235
|
if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(m.rate)) && node.rate !== m.rate) {
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
|
|
94
94
|
<div class="form-row">
|
|
95
95
|
<input type="checkbox" id="node-input-insecureHTTPParser" style="display: inline-block; width: auto; vertical-align: top;">
|
|
96
|
-
<label for="node-input-insecureHTTPParser"
|
|
96
|
+
<label for="node-input-insecureHTTPParser" style="width: auto;" data-i18n="httpin.insecureHTTPParser"></label>
|
|
97
97
|
</div>
|
|
98
98
|
|
|
99
99
|
|
|
@@ -23,6 +23,8 @@ module.exports = async function(RED) {
|
|
|
23
23
|
const { v4: uuid } = require('uuid');
|
|
24
24
|
const crypto = require('crypto');
|
|
25
25
|
const URL = require("url").URL
|
|
26
|
+
const http = require("http")
|
|
27
|
+
const https = require("https")
|
|
26
28
|
var mustache = require("mustache");
|
|
27
29
|
var querystring = require("querystring");
|
|
28
30
|
var cookie = require("cookie");
|
|
@@ -65,16 +67,27 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
65
67
|
function HTTPRequest(n) {
|
|
66
68
|
RED.nodes.createNode(this,n);
|
|
67
69
|
checkNodeAgentPatch();
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
const node = this;
|
|
71
|
+
const nodeUrl = n.url;
|
|
72
|
+
const isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1;
|
|
73
|
+
const nodeMethod = n.method || "GET";
|
|
74
|
+
let paytoqs = false;
|
|
75
|
+
let paytobody = false;
|
|
76
|
+
let redirectList = [];
|
|
77
|
+
const sendErrorsToCatch = n.senderr;
|
|
76
78
|
node.headers = n.headers || [];
|
|
77
|
-
|
|
79
|
+
const useKeepAlive = n["persist"];
|
|
80
|
+
let agents = null
|
|
81
|
+
if (useKeepAlive) {
|
|
82
|
+
agents = {
|
|
83
|
+
http: new http.Agent({ keepAlive: true }),
|
|
84
|
+
https: new https.Agent({ keepAlive: true })
|
|
85
|
+
}
|
|
86
|
+
node.on('close', function () {
|
|
87
|
+
agents.http.destroy()
|
|
88
|
+
agents.https.destroy()
|
|
89
|
+
})
|
|
90
|
+
}
|
|
78
91
|
if (n.tls) {
|
|
79
92
|
var tlsNode = RED.nodes.getNode(n.tls);
|
|
80
93
|
}
|
|
@@ -560,12 +573,14 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|
|
560
573
|
opts.agent = {
|
|
561
574
|
http: new HttpProxyAgent(proxyOptions),
|
|
562
575
|
https: new HttpsProxyAgent(proxyOptions)
|
|
563
|
-
}
|
|
564
|
-
|
|
576
|
+
}
|
|
565
577
|
} else {
|
|
566
578
|
node.warn("Bad proxy url: "+ prox);
|
|
567
579
|
}
|
|
568
580
|
}
|
|
581
|
+
if (useKeepAlive && !opts.agent) {
|
|
582
|
+
opts.agent = agents
|
|
583
|
+
}
|
|
569
584
|
if (tlsNode) {
|
|
570
585
|
opts.https = {};
|
|
571
586
|
tlsNode.addTLSOptions(opts.https);
|
|
@@ -629,6 +629,9 @@ module.exports = function(RED) {
|
|
|
629
629
|
joinChar = node.joiner;
|
|
630
630
|
if (n.count === "" && msg.hasOwnProperty('parts')) {
|
|
631
631
|
targetCount = msg.parts.count || 0;
|
|
632
|
+
if (msg.parts.hasOwnProperty('id')) {
|
|
633
|
+
partId = msg.parts.id;
|
|
634
|
+
}
|
|
632
635
|
}
|
|
633
636
|
if (node.build === 'object') {
|
|
634
637
|
propertyKey = RED.util.getMessageProperty(msg,node.key);
|
package/core/storage/10-file.js
CHANGED
|
@@ -68,9 +68,12 @@ module.exports = function(RED) {
|
|
|
68
68
|
node.error(err,msg);
|
|
69
69
|
return done();
|
|
70
70
|
} else {
|
|
71
|
-
|
|
71
|
+
processMsg2(msg,nodeSend,value,done);
|
|
72
72
|
}
|
|
73
73
|
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function processMsg2(msg,nodeSend,filename,done) {
|
|
74
77
|
filename = filename || "";
|
|
75
78
|
msg.filename = filename;
|
|
76
79
|
var fullFilename = filename;
|
|
@@ -311,9 +314,12 @@ module.exports = function(RED) {
|
|
|
311
314
|
node.error(err,msg);
|
|
312
315
|
return done();
|
|
313
316
|
} else {
|
|
314
|
-
|
|
317
|
+
processMsg2(msg, nodeSend, (value || "").replace(/\t|\r|\n/g,''), nodeDone);
|
|
315
318
|
}
|
|
316
319
|
});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
function processMsg2(msg, nodeSend, filename, nodeDone) {
|
|
317
323
|
filename = filename || "";
|
|
318
324
|
var fullFilename = filename;
|
|
319
325
|
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
|
@@ -434,7 +440,8 @@ module.exports = function(RED) {
|
|
|
434
440
|
nodeDone();
|
|
435
441
|
});
|
|
436
442
|
}
|
|
437
|
-
}
|
|
443
|
+
}
|
|
444
|
+
|
|
438
445
|
this.on('close', function() {
|
|
439
446
|
node.status({});
|
|
440
447
|
});
|
package/locales/de/messages.json
CHANGED
|
@@ -216,7 +216,8 @@
|
|
|
216
216
|
"initialize": "Start",
|
|
217
217
|
"finalize": "Stopp",
|
|
218
218
|
"outputs": "Ausgänge",
|
|
219
|
-
"modules": "Module"
|
|
219
|
+
"modules": "Module",
|
|
220
|
+
"timeout": "Timeout"
|
|
220
221
|
},
|
|
221
222
|
"text": {
|
|
222
223
|
"initialize": "// Der Code hier wird ausgeführt,\n// wenn der Node gestartet wird\n",
|
|
@@ -36,5 +36,5 @@ greater than one day you should consider using a scheduler node that can cope wi
|
|
|
36
36
|
<p><b>Note</b>: The <i>"Interval between times"</i> and <i>"at a specific time"</i> options use the standard cron system.
|
|
37
37
|
This means that 20 minutes will be at the next hour, 20 minutes past and 40 minutes past - not in 20 minutes time.
|
|
38
38
|
If you want every 20 minutes from now - use the <i>"interval"</i> option.</p>
|
|
39
|
-
<p><b>Note</b>: To include a newline in a string you must use
|
|
39
|
+
<p><b>Note</b>: To include a newline in a string you must use the Function or Template node to create the payload.</p>
|
|
40
40
|
</script>
|
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
},
|
|
95
95
|
"catch": {
|
|
96
96
|
"catch": "catch: all",
|
|
97
|
+
"catchGroup": "catch: group",
|
|
97
98
|
"catchNodes": "catch: __number__",
|
|
98
99
|
"catchUncaught": "catch: uncaught",
|
|
99
100
|
"label": {
|
|
@@ -109,6 +110,7 @@
|
|
|
109
110
|
},
|
|
110
111
|
"status": {
|
|
111
112
|
"status": "status: all",
|
|
113
|
+
"statusGroup": "status: group",
|
|
112
114
|
"statusNodes": "status: __number__",
|
|
113
115
|
"label": {
|
|
114
116
|
"source": "Report status from",
|
|
@@ -250,7 +252,8 @@
|
|
|
250
252
|
"initialize": "On Start",
|
|
251
253
|
"finalize": "On Stop",
|
|
252
254
|
"outputs": "Outputs",
|
|
253
|
-
"modules": "Modules"
|
|
255
|
+
"modules": "Modules",
|
|
256
|
+
"timeout": "Timeout"
|
|
254
257
|
},
|
|
255
258
|
"text": {
|
|
256
259
|
"initialize": "// Code added here will be run once\n// whenever the node is started.\n",
|
package/locales/fr/messages.json
CHANGED
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
},
|
|
104
104
|
"scope": {
|
|
105
105
|
"all": "tous les noeuds",
|
|
106
|
+
"group": "dans le même groupe",
|
|
106
107
|
"selected": "noeuds sélectionnés"
|
|
107
108
|
}
|
|
108
109
|
},
|
|
@@ -115,6 +116,7 @@
|
|
|
115
116
|
},
|
|
116
117
|
"scope": {
|
|
117
118
|
"all": "tous les noeuds",
|
|
119
|
+
"group": "dans le même groupe",
|
|
118
120
|
"selected": "noeuds sélectionnés"
|
|
119
121
|
}
|
|
120
122
|
},
|
|
@@ -414,6 +416,7 @@
|
|
|
414
416
|
"port": "Port",
|
|
415
417
|
"keepalive": "Rester en vie",
|
|
416
418
|
"cleansession": "Utiliser une session propre",
|
|
419
|
+
"autoUnsubscribe": "Se désabonner automatiquement lors de la déconnexion",
|
|
417
420
|
"cleanstart": "Utiliser un démarrage propre",
|
|
418
421
|
"use-tls": "Utiliser TLS",
|
|
419
422
|
"tls-config": "Configuration TLS",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
<p>また、フロー開始の際に一度だけメッセージを送出させることもできます。</p>
|
|
31
31
|
<p>「<i>時間間隔</i>」に指定可能な値の最大値は、約596時間(もしくは24日)です。一日より長い間隔を扱いたい場合は、電源停止や再起動にも対応可能なスケジューラノードの利用を検討すると良いでしょう。</p>
|
|
32
32
|
<p><b>注</b>:「<i>指定した時間間隔、日時</i>」と「<i>指定した日時</i>」オプションは標準的なcronシステムを内部で利用します。したがって「20分」という指定は、その時点から20分後ではなく、毎時きっかり、20分、40分を意味します。現時刻から20分毎を指定するには「<i>指定した時間間隔</i>」オプションを用います。</p>
|
|
33
|
-
<p><b>注</b>: 文字列に改行を含めたい場合は、functionノードを使ってペイロードを設定してください。</p>
|
|
33
|
+
<p><b>注</b>: 文字列に改行を含めたい場合は、functionノードまたはtemplateノードを使ってペイロードを設定してください。</p>
|
|
34
34
|
</script>
|
package/locales/ja/messages.json
CHANGED
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
},
|
|
95
95
|
"catch": {
|
|
96
96
|
"catch": "catch: 全て",
|
|
97
|
+
"catchGroup": "catch: グループ",
|
|
97
98
|
"catchNodes": "catch: __number__",
|
|
98
99
|
"catchUncaught": "catch: 未補足",
|
|
99
100
|
"label": {
|
|
@@ -103,11 +104,13 @@
|
|
|
103
104
|
},
|
|
104
105
|
"scope": {
|
|
105
106
|
"all": "全てのノード",
|
|
107
|
+
"group": "同一グループ内",
|
|
106
108
|
"selected": "選択したノード"
|
|
107
109
|
}
|
|
108
110
|
},
|
|
109
111
|
"status": {
|
|
110
112
|
"status": "status: 全て",
|
|
113
|
+
"statusGroup": "status: グループ",
|
|
111
114
|
"statusNodes": "status: __number__",
|
|
112
115
|
"label": {
|
|
113
116
|
"source": "ステータス取得元",
|
|
@@ -115,6 +118,7 @@
|
|
|
115
118
|
},
|
|
116
119
|
"scope": {
|
|
117
120
|
"all": "全てのノード",
|
|
121
|
+
"group": "同一グループ内",
|
|
118
122
|
"selected": "選択したノード"
|
|
119
123
|
}
|
|
120
124
|
},
|
|
@@ -248,7 +252,8 @@
|
|
|
248
252
|
"initialize": "初期化処理",
|
|
249
253
|
"finalize": "終了処理",
|
|
250
254
|
"outputs": "出力数",
|
|
251
|
-
"modules": "モジュール"
|
|
255
|
+
"modules": "モジュール",
|
|
256
|
+
"timeout": "タイムアウト"
|
|
252
257
|
},
|
|
253
258
|
"text": {
|
|
254
259
|
"initialize": "// ここに記述したコードは、ノードをデプロイした時に\n// 一度だけ実行されます。\n",
|
package/locales/ru/messages.json
CHANGED
|
@@ -212,7 +212,8 @@
|
|
|
212
212
|
"function": "Функция",
|
|
213
213
|
"initialize": "Настройка",
|
|
214
214
|
"finalize": "Закрытие",
|
|
215
|
-
"outputs": "Выходы"
|
|
215
|
+
"outputs": "Выходы",
|
|
216
|
+
"timeout":"Время ожидания"
|
|
216
217
|
},
|
|
217
218
|
"text": {
|
|
218
219
|
"initialize": "// Добавленный здесь код будет исполняться\n// однократно при развертывании узла.\n",
|