@node-red/nodes 2.2.2 → 3.0.0-beta.1
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/05-junction.html +5 -0
- package/core/common/05-junction.js +12 -0
- package/core/common/20-inject.html +25 -13
- package/core/common/21-debug.html +60 -6
- package/core/common/21-debug.js +57 -27
- package/core/common/60-link.html +66 -29
- package/core/common/60-link.js +169 -20
- package/core/common/lib/debug/debug-utils.js +34 -1
- package/core/function/10-function.html +57 -21
- package/core/function/10-switch.html +3 -1
- package/core/function/10-switch.js +1 -0
- package/core/function/15-change.html +40 -12
- package/core/function/16-range.html +14 -5
- package/core/function/80-template.html +16 -12
- package/core/function/89-delay.html +46 -6
- package/core/function/89-trigger.html +12 -4
- package/core/function/rbe.html +7 -3
- package/core/network/05-tls.html +10 -4
- package/core/network/06-httpproxy.html +10 -1
- package/core/network/10-mqtt.html +73 -17
- package/core/network/10-mqtt.js +191 -80
- package/core/network/21-httpin.html +6 -2
- package/core/network/21-httprequest.html +217 -12
- package/core/network/21-httprequest.js +98 -17
- package/core/network/22-websocket.html +19 -5
- package/core/network/22-websocket.js +16 -13
- package/core/network/31-tcpin.html +47 -10
- package/core/network/31-tcpin.js +8 -3
- package/core/network/32-udp.html +14 -2
- package/core/parsers/70-CSV.html +4 -1
- package/core/parsers/70-JSON.html +3 -2
- package/core/parsers/70-XML.html +2 -1
- package/core/parsers/70-YAML.html +2 -1
- package/core/sequence/17-split.html +5 -1
- package/core/sequence/19-batch.html +28 -4
- package/core/storage/10-file.html +68 -8
- package/core/storage/10-file.js +46 -3
- package/core/storage/23-watch.html +2 -1
- package/core/storage/23-watch.js +21 -43
- package/locales/de/messages.json +1 -0
- package/locales/en-US/common/60-link.html +18 -3
- package/locales/en-US/messages.json +68 -17
- package/locales/en-US/network/21-httprequest.html +1 -1
- package/locales/en-US/storage/10-file.html +6 -2
- package/locales/ja/common/60-link.html +12 -0
- package/locales/ja/messages.json +63 -16
- package/locales/ko/messages.json +1 -0
- package/locales/ru/messages.json +1 -0
- package/locales/zh-CN/messages.json +1 -0
- package/locales/zh-TW/messages.json +1 -0
- package/package.json +12 -12
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
<div id="node-row-newline" class="form-row hidden" style="padding-left:110px;">
|
|
53
|
-
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"
|
|
53
|
+
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"><br/>
|
|
54
|
+
<input type="checkbox" id="node-input-trim" style="display:inline-block; width:auto; vertical-align:top;"> <span data-i18n="tcpin.label.reattach"></span>
|
|
54
55
|
</div>
|
|
55
56
|
|
|
56
57
|
<div class="form-row">
|
|
@@ -70,14 +71,27 @@
|
|
|
70
71
|
defaults: {
|
|
71
72
|
name: {value:""},
|
|
72
73
|
server: {value:"server", required:true},
|
|
73
|
-
host: {
|
|
74
|
-
|
|
74
|
+
host: {
|
|
75
|
+
value:"",
|
|
76
|
+
validate:function(v, opt) {
|
|
77
|
+
if ((this.server == "server")||v.length > 0) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return RED._("node-red:tcpin.errors.invalid-host");
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
port: {
|
|
84
|
+
value:"", required:true,
|
|
85
|
+
label:RED._("node-red:tcpin.label.port"),
|
|
86
|
+
validate:RED.validators.number(false)},
|
|
75
87
|
datamode:{value:"stream"},
|
|
76
88
|
datatype:{value:"buffer"},
|
|
77
89
|
newline:{value:""},
|
|
78
90
|
topic: {value:""},
|
|
91
|
+
trim: {value:false},
|
|
79
92
|
base64: {/*deprecated*/ value:false, required:true},
|
|
80
|
-
tls: {type:"tls-config", value:'', required:false
|
|
93
|
+
tls: {type:"tls-config", value:'', required:false,
|
|
94
|
+
label:RED._("node-red:httpin.tls-config") }
|
|
81
95
|
},
|
|
82
96
|
inputs:0,
|
|
83
97
|
outputs:1,
|
|
@@ -186,12 +200,29 @@
|
|
|
186
200
|
color: "Silver",
|
|
187
201
|
defaults: {
|
|
188
202
|
name: {value:""},
|
|
189
|
-
host: {
|
|
190
|
-
|
|
203
|
+
host: {
|
|
204
|
+
value:"",
|
|
205
|
+
validate:function(v, opt) {
|
|
206
|
+
if ((this.beserver != "client")||v.length > 0) {
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
return RED._("node-red:tcpin.errors.invalid-host");
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
port: {
|
|
213
|
+
value:"",
|
|
214
|
+
validate:function(v) {
|
|
215
|
+
if ((this.beserver == "reply")||RED.validators.number()(v)) {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
return RED._("node-red:tcpin.errors.invalid-port");
|
|
219
|
+
}
|
|
220
|
+
},
|
|
191
221
|
beserver: {value:"client", required:true},
|
|
192
222
|
base64: {value:false, required:true},
|
|
193
223
|
end: {value:false, required:true},
|
|
194
|
-
tls: {type:"tls-config", value:'', required:false
|
|
224
|
+
tls: {type:"tls-config", value:'', required:false,
|
|
225
|
+
label:RED._("node-red:httpin.tls-config") }
|
|
195
226
|
},
|
|
196
227
|
inputs:1,
|
|
197
228
|
outputs:0,
|
|
@@ -286,7 +317,8 @@
|
|
|
286
317
|
<span id="node-units"></span>
|
|
287
318
|
</div>
|
|
288
319
|
<div id="node-row-newline" class="form-row hidden" style="padding-left:162px;">
|
|
289
|
-
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"
|
|
320
|
+
<span data-i18n="tcpin.label.delimited"></span> <input type="text" id="node-input-newline" style="width:110px;" data-i18n="[placeholder]tcpin.label.optional"><br/>
|
|
321
|
+
<input type="checkbox" id="node-input-trim" style="display:inline-block; width:auto; vertical-align:top;"> <span data-i18n="tcpin.label.reattach"></span>
|
|
290
322
|
</div>
|
|
291
323
|
<div class="form-row">
|
|
292
324
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
|
@@ -301,12 +333,17 @@
|
|
|
301
333
|
defaults: {
|
|
302
334
|
name: {value:""},
|
|
303
335
|
server: {value:""},
|
|
304
|
-
port: {
|
|
336
|
+
port: {
|
|
337
|
+
value:"",
|
|
338
|
+
label: RED._("node-red:tcpin.label.port"),
|
|
339
|
+
validate:RED.validators.regex(/^(\d*|)$/)
|
|
340
|
+
},
|
|
305
341
|
out: {value:"time", required:true},
|
|
306
342
|
ret: {value:"buffer"},
|
|
307
343
|
splitc: {value:"0", required:true},
|
|
308
344
|
newline: {value:""},
|
|
309
|
-
|
|
345
|
+
trim: {value:false},
|
|
346
|
+
tls: {type:"tls-config", value:'', required:false, label:RED._("node-red:httpin.tls-config")}
|
|
310
347
|
},
|
|
311
348
|
inputs:1,
|
|
312
349
|
outputs:1,
|
package/core/network/31-tcpin.js
CHANGED
|
@@ -88,6 +88,7 @@ module.exports = function(RED) {
|
|
|
88
88
|
this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */
|
|
89
89
|
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
|
|
90
90
|
this.base64 = n.base64;
|
|
91
|
+
this.trim = n.trim || false;
|
|
91
92
|
this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
|
|
92
93
|
this.closing = false;
|
|
93
94
|
this.connected = false;
|
|
@@ -135,7 +136,8 @@ module.exports = function(RED) {
|
|
|
135
136
|
buffer = buffer+data;
|
|
136
137
|
var parts = buffer.split(node.newline);
|
|
137
138
|
for (var i = 0; i<parts.length-1; i+=1) {
|
|
138
|
-
msg = {topic:node.topic, payload:parts[i]
|
|
139
|
+
msg = {topic:node.topic, payload:parts[i]};
|
|
140
|
+
if (node.trim == true) { msg.payload += node.newline; }
|
|
139
141
|
msg._session = {type:"tcp",id:id};
|
|
140
142
|
node.send(msg);
|
|
141
143
|
}
|
|
@@ -229,7 +231,8 @@ module.exports = function(RED) {
|
|
|
229
231
|
buffer = buffer+data;
|
|
230
232
|
var parts = buffer.split(node.newline);
|
|
231
233
|
for (var i = 0; i<parts.length-1; i+=1) {
|
|
232
|
-
msg = {topic:node.topic, payload:parts[i]
|
|
234
|
+
msg = {topic:node.topic, payload:parts[i], ip:socket.remoteAddress, port:socket.remotePort};
|
|
235
|
+
if (node.trim == true) { msg.payload += node.newline; }
|
|
233
236
|
msg._session = {type:"tcp",id:id};
|
|
234
237
|
node.send(msg);
|
|
235
238
|
}
|
|
@@ -518,6 +521,7 @@ module.exports = function(RED) {
|
|
|
518
521
|
this.out = n.out;
|
|
519
522
|
this.ret = n.ret || "buffer";
|
|
520
523
|
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
|
|
524
|
+
this.trim = n.trim || false;
|
|
521
525
|
this.splitc = n.splitc;
|
|
522
526
|
if (n.tls) {
|
|
523
527
|
var tlsNode = RED.nodes.getNode(n.tls);
|
|
@@ -653,7 +657,8 @@ module.exports = function(RED) {
|
|
|
653
657
|
let parts = chunk.split(node.newline);
|
|
654
658
|
for (var p=0; p<parts.length-1; p+=1) {
|
|
655
659
|
let m = RED.util.cloneMessage(msg);
|
|
656
|
-
m.payload = parts[p]
|
|
660
|
+
m.payload = parts[p];
|
|
661
|
+
if (node.trim == true) { m.payload += node.newline; }
|
|
657
662
|
nodeSend(m);
|
|
658
663
|
}
|
|
659
664
|
chunk = parts[parts.length-1];
|
package/core/network/32-udp.html
CHANGED
|
@@ -62,10 +62,22 @@
|
|
|
62
62
|
defaults: {
|
|
63
63
|
name: {value:""},
|
|
64
64
|
iface: {value:""},
|
|
65
|
-
port: {
|
|
65
|
+
port: {
|
|
66
|
+
value:"", required:true,
|
|
67
|
+
label:RED._("node-red:udp.label.port"),
|
|
68
|
+
validate:RED.validators.number(false)
|
|
69
|
+
},
|
|
66
70
|
ipv: {value:"udp4"},
|
|
67
71
|
multicast: {value:"false"},
|
|
68
|
-
group: {
|
|
72
|
+
group: {
|
|
73
|
+
value:"",
|
|
74
|
+
validate:function(v,opt) {
|
|
75
|
+
if ((this.multicast !== "true")||v.length > 0) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return RED._("node-red:udp.errors.invalid-group");
|
|
79
|
+
}
|
|
80
|
+
},
|
|
69
81
|
datatype: {value:"buffer",required:true}
|
|
70
82
|
},
|
|
71
83
|
inputs:0,
|
package/core/parsers/70-CSV.html
CHANGED
|
@@ -75,7 +75,10 @@
|
|
|
75
75
|
color:"#DEBD5C",
|
|
76
76
|
defaults: {
|
|
77
77
|
name: {value:""},
|
|
78
|
-
sep: {
|
|
78
|
+
sep: {
|
|
79
|
+
value:',', required:true,
|
|
80
|
+
label:RED._("node-red:csv.label.separator"),
|
|
81
|
+
validate:RED.validators.regex(/^.{1,2}$/)},
|
|
79
82
|
//quo: {value:'"',required:true},
|
|
80
83
|
hdrin: {value:""},
|
|
81
84
|
hdrout: {value:"none"},
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<label style="width:100%;"><span data-i18n="json.label.o2j"></span></label>
|
|
22
22
|
</div>
|
|
23
23
|
<div class="form-row node-json-to-json-options" style="padding-left: 20px;">
|
|
24
|
-
<input style="width:20px; vertical-align:top; margin-right: 5px;" type="checkbox" id="node-input-pretty"><label style="width: auto;" for="node-input-pretty" data-i18n="json.label.pretty"></
|
|
24
|
+
<input style="width:20px; vertical-align:top; margin-right: 5px;" type="checkbox" id="node-input-pretty"><label style="width: auto;" for="node-input-pretty" data-i18n="json.label.pretty"></label>
|
|
25
25
|
</div>
|
|
26
26
|
</script>
|
|
27
27
|
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
color:"#DEBD5C",
|
|
32
32
|
defaults: {
|
|
33
33
|
name: {value:""},
|
|
34
|
-
property: {value:"payload",required:true
|
|
34
|
+
property: {value:"payload",required:true,
|
|
35
|
+
label:RED._("node-red:json.label.property")},
|
|
35
36
|
action: {value:""},
|
|
36
37
|
pretty: {value:false}
|
|
37
38
|
},
|
package/core/parsers/70-XML.html
CHANGED
|
@@ -202,7 +202,11 @@
|
|
|
202
202
|
name: {value:""},
|
|
203
203
|
mode: {value:"auto"},
|
|
204
204
|
build: { value:"object"},
|
|
205
|
-
property: {
|
|
205
|
+
property: {
|
|
206
|
+
value:"payload",
|
|
207
|
+
label: RED._("node-red:join.message-prop"),
|
|
208
|
+
validate:RED.validators.typedInput("propertyType", false)
|
|
209
|
+
},
|
|
206
210
|
propertyType: { value:"msg"},
|
|
207
211
|
key: {value:"topic"},
|
|
208
212
|
joiner: { value:"\\n"},
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
<div class="form-row">
|
|
48
48
|
<input type="checkbox" id="node-input-allowEmptySequence" style="margin-left:20px; margin-right: 10px; vertical-align:top; width:auto;">
|
|
49
49
|
<label for="node-input-allowEmptySequence" style="width:auto;" data-i18n="batch.interval.empty"></label>
|
|
50
|
-
|
|
50
|
+
</div>
|
|
51
51
|
</div>
|
|
52
52
|
|
|
53
53
|
<div class="node-row-msg-concat">
|
|
@@ -73,9 +73,33 @@
|
|
|
73
73
|
defaults: {
|
|
74
74
|
name: {value:""},
|
|
75
75
|
mode: {value:"count"},
|
|
76
|
-
count: {
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
count: {
|
|
77
|
+
value:10,
|
|
78
|
+
validate:function(v, opt) {
|
|
79
|
+
if (RED.validators.number(v) && (v >= 1)) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
return RED._("node-red:batch.error.invalid-count");
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
overlap: {
|
|
86
|
+
value:0,
|
|
87
|
+
validate:function(v, opt) {
|
|
88
|
+
if (RED.validators.number(v) && (v >= 0)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
return RED._("node-red:batch.error.invalid-overlap");
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
interval: {
|
|
95
|
+
value:10,
|
|
96
|
+
validate:function(v, opt) {
|
|
97
|
+
if (RED.validators.number(v) && (v >= 1)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return RED._("node-red:batch.error.invalid-interval");
|
|
101
|
+
}
|
|
102
|
+
},
|
|
79
103
|
allowEmptySequence: {value:false},
|
|
80
104
|
topics: {value:[{topic:""}]}
|
|
81
105
|
},
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<div class="form-row node-input-filename">
|
|
4
4
|
<label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
|
|
5
5
|
<input id="node-input-filename" type="text">
|
|
6
|
+
<input type="hidden" id="node-input-filenameType">
|
|
6
7
|
</div>
|
|
7
8
|
<div class="form-row">
|
|
8
9
|
<label for="node-input-overwriteFile"><i class="fa fa-random"></i> <span data-i18n="file.label.action"></span></label>
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
</div>
|
|
30
31
|
<div class="form-row">
|
|
31
32
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
|
32
|
-
<input type="text" id="node-input-name"
|
|
33
|
+
<input type="text" id="node-input-name">
|
|
33
34
|
</div>
|
|
34
35
|
<div class="form-tips"><span data-i18n="file.tip"></span></div>
|
|
35
36
|
</script>
|
|
@@ -37,7 +38,8 @@
|
|
|
37
38
|
<script type="text/html" data-template-name="file in">
|
|
38
39
|
<div class="form-row">
|
|
39
40
|
<label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="file.label.filename"></span></label>
|
|
40
|
-
<input id="node-input-filename" type="text"
|
|
41
|
+
<input id="node-input-filename" type="text">
|
|
42
|
+
<input type="hidden" id="node-input-filenameType">
|
|
41
43
|
</div>
|
|
42
44
|
<div class="form-row">
|
|
43
45
|
<label for="node-input-format"><i class="fa fa-sign-out"></i> <span data-i18n="file.label.outputas"></span></label>
|
|
@@ -60,7 +62,7 @@
|
|
|
60
62
|
</div>
|
|
61
63
|
<div class="form-row">
|
|
62
64
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
|
63
|
-
<input type="text" id="node-input-name"
|
|
65
|
+
<input type="text" id="node-input-name">
|
|
64
66
|
</div>
|
|
65
67
|
<div class="form-tips"><span data-i18n="file.tip"></span></div>
|
|
66
68
|
</script>
|
|
@@ -196,7 +198,8 @@
|
|
|
196
198
|
category: 'storage',
|
|
197
199
|
defaults: {
|
|
198
200
|
name: {value:""},
|
|
199
|
-
filename: {value:""},
|
|
201
|
+
filename: {value:"filename"},
|
|
202
|
+
filenameType: {value:"msg"},
|
|
200
203
|
appendNewline: {value:true},
|
|
201
204
|
createDir: {value:false},
|
|
202
205
|
overwriteFile: {value:"false"},
|
|
@@ -207,10 +210,13 @@
|
|
|
207
210
|
outputs:1,
|
|
208
211
|
icon: "file-out.svg",
|
|
209
212
|
label: function() {
|
|
213
|
+
var fn = this.filename;
|
|
214
|
+
if(this.filenameType != "str" && this.filenameType != "env" ) { fn = ""; }
|
|
215
|
+
if(this.filenameType === "env") { fn = "env."+fn; }
|
|
210
216
|
if (this.overwriteFile === "delete") {
|
|
211
|
-
return this.name||this._("file.label.deletelabel",{file:
|
|
217
|
+
return this.name||this._("file.label.deletelabel",{file:fn});
|
|
212
218
|
} else {
|
|
213
|
-
return this.name||
|
|
219
|
+
return this.name||fn||this._("file.label.write");
|
|
214
220
|
}
|
|
215
221
|
},
|
|
216
222
|
paletteLabel: RED._("node-red:file.label.write"),
|
|
@@ -229,6 +235,31 @@
|
|
|
229
235
|
value: "setbymsg",
|
|
230
236
|
label: node._("file.encoding.setbymsg")
|
|
231
237
|
}).text(label).appendTo(encSel);
|
|
238
|
+
$("#node-input-filename").typedInput({
|
|
239
|
+
default: "msg",
|
|
240
|
+
types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"],
|
|
241
|
+
typeField: $("#node-input-filenameType")
|
|
242
|
+
});
|
|
243
|
+
if(typeof node.filenameType == 'undefined') {
|
|
244
|
+
//existing node AND filenameType is not set - inplace (compatible) upgrade to new typedInput
|
|
245
|
+
if(node.filename == "") { //was using empty value to denote msg.filename - set typedInput to match
|
|
246
|
+
node.filename = "filename";
|
|
247
|
+
node.filenameType = "msg";
|
|
248
|
+
$("#node-input-filename").typedInput("type", node.filenameType);
|
|
249
|
+
$("#node-input-filename").typedInput("value", node.filename);
|
|
250
|
+
} else if(/^\${[^}]+}$/.test(node.filename)) { //was using an ${ENV_VAR}
|
|
251
|
+
node.filenameType = "env";
|
|
252
|
+
node.filename = node.filename.replace(/\${([^}]+)}/g, function(match, name) {
|
|
253
|
+
return (name === undefined)?"":name;
|
|
254
|
+
});
|
|
255
|
+
$("#node-input-filename").typedInput("type", node.filenameType);
|
|
256
|
+
$("#node-input-filename").typedInput("value", node.filename);
|
|
257
|
+
} else { //was using a static filename - set typedInput type to str
|
|
258
|
+
node.filenameType = "str";
|
|
259
|
+
$("#node-input-filename").typedInput("type", node.filenameType);
|
|
260
|
+
$("#node-input-filename").typedInput("value", node.filename);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
232
263
|
encodings.forEach(function(item) {
|
|
233
264
|
if(Array.isArray(item)) {
|
|
234
265
|
var group = $("<optgroup/>", {
|
|
@@ -266,7 +297,8 @@
|
|
|
266
297
|
category: 'storage',
|
|
267
298
|
defaults: {
|
|
268
299
|
name: {value:""},
|
|
269
|
-
filename: {value:""},
|
|
300
|
+
filename: {value:"filename"},
|
|
301
|
+
filenameType: {value:"msg"},
|
|
270
302
|
format: {value:"utf8"},
|
|
271
303
|
chunk: {value:false},
|
|
272
304
|
sendError: {value: false},
|
|
@@ -291,7 +323,10 @@
|
|
|
291
323
|
},
|
|
292
324
|
icon: "file-in.svg",
|
|
293
325
|
label: function() {
|
|
294
|
-
|
|
326
|
+
var fn = this.filename;
|
|
327
|
+
if(this.filenameType != "str" && this.filenameType != "env" ) { fn = ""; }
|
|
328
|
+
if(this.filenameType === "env") { fn = "env."+fn; }
|
|
329
|
+
return this.name||fn||this._("file.label.read");
|
|
295
330
|
},
|
|
296
331
|
paletteLabel: RED._("node-red:file.label.read"),
|
|
297
332
|
labelStyle: function() {
|
|
@@ -305,6 +340,31 @@
|
|
|
305
340
|
value: "none",
|
|
306
341
|
label: label
|
|
307
342
|
}).text(label).appendTo(encSel);
|
|
343
|
+
$("#node-input-filename").typedInput({
|
|
344
|
+
default: "msg",
|
|
345
|
+
types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"],
|
|
346
|
+
typeField: $("#node-input-filenameType")
|
|
347
|
+
});
|
|
348
|
+
if(typeof node.filenameType == 'undefined') {
|
|
349
|
+
//existing node AND filenameType is not set - inplace (compatible) upgrade to new typedInput
|
|
350
|
+
if(node.filename == "") { //was using empty value to denote msg.filename - set typedInput to match
|
|
351
|
+
node.filename = "filename";
|
|
352
|
+
node.filenameType = "msg";
|
|
353
|
+
$("#node-input-filename").typedInput("type", node.filenameType);
|
|
354
|
+
$("#node-input-filename").typedInput("value", node.filename);
|
|
355
|
+
} else if(/^\${[^}]+}$/.test(node.filename)) { //was using an ${ENV_VAR}
|
|
356
|
+
node.filenameType = "env";
|
|
357
|
+
node.filename = node.filename.replace(/\${([^}]+)}/g, function(match, name) {
|
|
358
|
+
return (name === undefined)?"":name;
|
|
359
|
+
});
|
|
360
|
+
$("#node-input-filename").typedInput("type", node.filenameType);
|
|
361
|
+
$("#node-input-filename").typedInput("value", node.filename);
|
|
362
|
+
} else { //was using a static filename - set typedInput type to str
|
|
363
|
+
node.filenameType = "str";
|
|
364
|
+
$("#node-input-filename").typedInput("type", node.filenameType);
|
|
365
|
+
$("#node-input-filename").typedInput("value", node.filename);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
308
368
|
encodings.forEach(function(item) {
|
|
309
369
|
if(Array.isArray(item)) {
|
|
310
370
|
var group = $("<optgroup/>", {
|
package/core/storage/10-file.js
CHANGED
|
@@ -39,6 +39,7 @@ module.exports = function(RED) {
|
|
|
39
39
|
// Write/delete a file
|
|
40
40
|
RED.nodes.createNode(this,n);
|
|
41
41
|
this.filename = n.filename;
|
|
42
|
+
this.filenameType = n.filenameType;
|
|
42
43
|
this.appendNewline = n.appendNewline;
|
|
43
44
|
this.overwriteFile = n.overwriteFile.toString();
|
|
44
45
|
this.createDir = n.createDir || false;
|
|
@@ -50,7 +51,28 @@ module.exports = function(RED) {
|
|
|
50
51
|
node.closeCallback = null;
|
|
51
52
|
|
|
52
53
|
function processMsg(msg,nodeSend, done) {
|
|
53
|
-
var filename = node.filename ||
|
|
54
|
+
var filename = node.filename || "";
|
|
55
|
+
//Pre V3 compatibility - if filenameType is empty, do in place upgrade
|
|
56
|
+
if(typeof node.filenameType == 'undefined' || node.filenameType == "") {
|
|
57
|
+
//existing node AND filenameType is not set - inplace (compatible) upgrade
|
|
58
|
+
if(filename == "") { //was using empty value to denote msg.filename
|
|
59
|
+
node.filename = "filename";
|
|
60
|
+
node.filenameType = "msg";
|
|
61
|
+
} else { //was using a static filename - set typedInput type to str
|
|
62
|
+
node.filenameType = "str";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
RED.util.evaluateNodeProperty(node.filename,node.filenameType,node,msg,(err,value) => {
|
|
67
|
+
if (err) {
|
|
68
|
+
node.error(err,msg);
|
|
69
|
+
return done();
|
|
70
|
+
} else {
|
|
71
|
+
filename = value;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
filename = filename || "";
|
|
75
|
+
msg.filename = filename;
|
|
54
76
|
var fullFilename = filename;
|
|
55
77
|
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
|
56
78
|
fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
|
|
@@ -158,7 +180,7 @@ module.exports = function(RED) {
|
|
|
158
180
|
done();
|
|
159
181
|
});
|
|
160
182
|
}
|
|
161
|
-
if (node.
|
|
183
|
+
if (node.filenameType === "str" || node.filenameType === "env") {
|
|
162
184
|
// Static filename - write and reuse the stream next time
|
|
163
185
|
node.wstream.write(buf, function() {
|
|
164
186
|
nodeSend(msg);
|
|
@@ -256,6 +278,7 @@ module.exports = function(RED) {
|
|
|
256
278
|
// Read a file
|
|
257
279
|
RED.nodes.createNode(this,n);
|
|
258
280
|
this.filename = n.filename;
|
|
281
|
+
this.filenameType = n.filenameType;
|
|
259
282
|
this.format = n.format;
|
|
260
283
|
this.chunk = false;
|
|
261
284
|
this.encoding = n.encoding || "none";
|
|
@@ -270,8 +293,28 @@ module.exports = function(RED) {
|
|
|
270
293
|
var node = this;
|
|
271
294
|
|
|
272
295
|
this.on("input",function(msg, nodeSend, nodeDone) {
|
|
273
|
-
var filename =
|
|
296
|
+
var filename = node.filename || "";
|
|
297
|
+
//Pre V3 compatibility - if filenameType is empty, do in place upgrade
|
|
298
|
+
if(typeof node.filenameType == 'undefined' || node.filenameType == "") {
|
|
299
|
+
//existing node AND filenameType is not set - inplace (compatible) upgrade
|
|
300
|
+
if(filename == "") { //was using empty value to denote msg.filename
|
|
301
|
+
node.filename = "filename";
|
|
302
|
+
node.filenameType = "msg";
|
|
303
|
+
} else { //was using a static filename - set typedInput type to str
|
|
304
|
+
node.filenameType = "str";
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
RED.util.evaluateNodeProperty(node.filename,node.filenameType,node,msg,(err,value) => {
|
|
308
|
+
if (err) {
|
|
309
|
+
node.error(err,msg);
|
|
310
|
+
return done();
|
|
311
|
+
} else {
|
|
312
|
+
filename = (value || "").replace(/\t|\r|\n/g,'');
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
filename = filename || "";
|
|
274
316
|
var fullFilename = filename;
|
|
317
|
+
var filePath = "";
|
|
275
318
|
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
|
276
319
|
fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
|
|
277
320
|
}
|
package/core/storage/23-watch.js
CHANGED
|
@@ -16,24 +16,9 @@
|
|
|
16
16
|
|
|
17
17
|
module.exports = function(RED) {
|
|
18
18
|
"use strict";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
var getAllDirs = function (dir, filelist) {
|
|
24
|
-
filelist = filelist || [];
|
|
25
|
-
fs.readdirSync(dir).forEach(file => {
|
|
26
|
-
try {
|
|
27
|
-
if (fs.statSync(path.join(dir, file)).isDirectory() ) {
|
|
28
|
-
filelist.push(path.join(dir, file));
|
|
29
|
-
getAllDirs(path.join(dir, file), filelist);
|
|
30
|
-
}
|
|
31
|
-
} catch (error) {
|
|
32
|
-
//should we raise an error?
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
return filelist;
|
|
36
|
-
}
|
|
19
|
+
const watch = require('node-watch')
|
|
20
|
+
const fs = require("fs")
|
|
21
|
+
const path = require("path")
|
|
37
22
|
|
|
38
23
|
function WatchNode(n) {
|
|
39
24
|
RED.nodes.createNode(this,n);
|
|
@@ -44,52 +29,45 @@ module.exports = function(RED) {
|
|
|
44
29
|
this.files[f] = this.files[f].trim();
|
|
45
30
|
}
|
|
46
31
|
this.p = (this.files.length === 1) ? this.files[0] : JSON.stringify(this.files);
|
|
47
|
-
|
|
32
|
+
const node = this;
|
|
48
33
|
|
|
49
|
-
|
|
50
|
-
for (var fi in node.files) {
|
|
51
|
-
if (node.files.hasOwnProperty(fi)) {
|
|
52
|
-
node.files = node.files.concat(getAllDirs( node.files[fi]));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
34
|
+
const watcher = watch(this.files, { recursive: this.recursive });
|
|
56
35
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
36
|
+
watcher.on('change', function (event, fpath) {
|
|
37
|
+
const file = path.basename(fpath)
|
|
38
|
+
let stat;
|
|
60
39
|
try {
|
|
61
|
-
if (fs.statSync(fpath).isDirectory()) { fpath = path.join(fpath,file); }
|
|
62
40
|
stat = fs.statSync(fpath);
|
|
63
41
|
} catch(e) { }
|
|
64
|
-
|
|
65
|
-
|
|
42
|
+
let type = "none";
|
|
43
|
+
const msg = {
|
|
44
|
+
payload:fpath,
|
|
45
|
+
topic:node.p,
|
|
46
|
+
file:file,
|
|
47
|
+
filename:fpath,
|
|
48
|
+
event: event
|
|
49
|
+
};
|
|
66
50
|
if (stat) {
|
|
67
51
|
if (stat.isFile()) { type = "file"; msg.size = stat.size; }
|
|
68
52
|
else if (stat.isBlockDevice()) { type = "blockdevice"; }
|
|
69
53
|
else if (stat.isCharacterDevice()) { type = "characterdevice"; }
|
|
70
54
|
else if (stat.isSocket()) { type = "socket"; }
|
|
71
55
|
else if (stat.isFIFO()) { type = "fifo"; }
|
|
72
|
-
else if (stat.isDirectory()) {
|
|
73
|
-
type = "directory";
|
|
74
|
-
if (node.recursive) {
|
|
75
|
-
notifications.add([fpath]);
|
|
76
|
-
notifications.add(getAllDirs(fpath));
|
|
77
|
-
}
|
|
78
|
-
}
|
|
56
|
+
else if (stat.isDirectory()) { type = "directory"; }
|
|
79
57
|
else { type = "n/a"; }
|
|
80
58
|
}
|
|
81
59
|
msg.type = type;
|
|
82
60
|
node.send(msg);
|
|
83
61
|
});
|
|
84
62
|
|
|
85
|
-
|
|
86
|
-
|
|
63
|
+
watcher.on('error', function (error) {
|
|
64
|
+
const msg = { payload: "" };
|
|
87
65
|
node.error(error,msg);
|
|
88
66
|
});
|
|
89
67
|
|
|
90
68
|
this.close = function() {
|
|
91
|
-
|
|
69
|
+
watcher.close();
|
|
92
70
|
}
|
|
93
71
|
}
|
|
94
|
-
RED.nodes.registerType("watch",WatchNode);
|
|
72
|
+
RED.nodes.registerType("watch", WatchNode);
|
|
95
73
|
}
|
package/locales/de/messages.json
CHANGED
|
@@ -423,6 +423,7 @@
|
|
|
423
423
|
"string": "Ein String",
|
|
424
424
|
"base64": "Ein Base64-kodierter String",
|
|
425
425
|
"auto": "Auto-Erkennung (string oder buffer)",
|
|
426
|
+
"auto-detect": "Auto-Erkennung (parsed JSON-Objekt, string oder buffer)",
|
|
426
427
|
"json": "Ein analysiertes (parsed) JSON-Objekt"
|
|
427
428
|
},
|
|
428
429
|
"true": "wahr",
|