@node-red/nodes 3.1.0 → 3.1.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.
@@ -104,6 +104,7 @@ module.exports = function(RED) {
104
104
  * @returns `true` if it is a valid topic
105
105
  */
106
106
  function isValidPublishTopic(topic) {
107
+ if (topic.length === 0) return false;
107
108
  return !/[\+#\b\f\n\r\t\v\0]/.test(topic);
108
109
  }
109
110
 
@@ -219,8 +220,8 @@ module.exports = function(RED) {
219
220
  */
220
221
  function subscriptionHandler(node, datatype ,topic, payload, packet) {
221
222
  const msg = {topic:topic, payload:null, qos:packet.qos, retain:packet.retain};
222
- const v5 = (node && node.brokerConn)
223
- ? node.brokerConn.v5()
223
+ const v5 = (node && node.brokerConn)
224
+ ? node.brokerConn.v5()
224
225
  : Object.prototype.hasOwnProperty.call(packet, "properties");
225
226
  if(v5 && packet.properties) {
226
227
  setStrProp(packet.properties, msg, "responseTopic");
@@ -451,7 +452,7 @@ module.exports = function(RED) {
451
452
 
452
453
  /**
453
454
  * Perform the disconnect action
454
- * @param {MQTTInNode|MQTTOutNode} node
455
+ * @param {MQTTInNode|MQTTOutNode} node
455
456
  * @param {Function} done
456
457
  */
457
458
  function handleDisconnectAction(node, done) {
@@ -611,7 +612,7 @@ module.exports = function(RED) {
611
612
  node.brokerurl = node.url;
612
613
  } else {
613
614
  // if the broker is ws:// or wss:// or tcp://
614
- if (node.broker.indexOf("://") > -1) {
615
+ if ((typeof node.broker === 'string') && node.broker.indexOf("://") > -1) {
615
616
  node.brokerurl = node.broker;
616
617
  // Only for ws or wss, check if proxy env var for additional configuration
617
618
  if (node.brokerurl.indexOf("wss://") > -1 || node.brokerurl.indexOf("ws://") > -1) {
@@ -865,7 +866,7 @@ module.exports = function(RED) {
865
866
  * Call end and wait for the client to end (or timeout)
866
867
  * @param {mqtt.MqttClient} client The broker client
867
868
  * @param {number} ms The time to wait for the client to end
868
- * @returns
869
+ * @returns
869
870
  */
870
871
  let waitEnd = (client, ms) => {
871
872
  return new Promise( (resolve, reject) => {
@@ -905,7 +906,7 @@ module.exports = function(RED) {
905
906
  node.subid = 1;
906
907
 
907
908
  //typedef for subscription object:
908
- /**
909
+ /**
909
910
  * @typedef {Object} Subscription
910
911
  * @property {String} topic - topic to subscribe to
911
912
  * @property {Object} [options] - options object
@@ -933,7 +934,7 @@ module.exports = function(RED) {
933
934
  const ref = _ref || 0;
934
935
  let options
935
936
  let qos = 1 // default to QoS 1 (AWS and several other brokers don't support QoS 2)
936
-
937
+
937
938
  // if options is an object, then clone it
938
939
  if (typeof _options == "object") {
939
940
  options = RED.util.cloneMessage(_options || {})
@@ -947,7 +948,7 @@ module.exports = function(RED) {
947
948
  if (typeof qos === "number" && qos >= 0 && qos <= 2) {
948
949
  options.qos = qos;
949
950
  }
950
-
951
+
951
952
  subscription.topic = _topic;
952
953
  subscription.qos = qos;
953
954
  subscription.options = RED.util.cloneMessage(options);
@@ -957,16 +958,16 @@ module.exports = function(RED) {
957
958
  }
958
959
 
959
960
  /**
960
- * If topic is a subscription object, then use that, otherwise look up the topic in
961
+ * If topic is a subscription object, then use that, otherwise look up the topic in
961
962
  * the subscriptions object. If the topic is not found, then create a new subscription
962
963
  * object and add it to the subscriptions object.
963
- * @param {Subscription|String} topic
964
- * @param {*} options
965
- * @param {*} callback
966
- * @param {*} ref
964
+ * @param {Subscription|String} topic
965
+ * @param {*} options
966
+ * @param {*} callback
967
+ * @param {*} ref
967
968
  */
968
969
  node.subscribe = function (topic, options, callback, ref) {
969
- /** @type {Subscription} */
970
+ /** @type {Subscription} */
970
971
  let subscription
971
972
  let doCompare = false
972
973
  let changesFound = false
@@ -1004,7 +1005,7 @@ module.exports = function(RED) {
1004
1005
  _brokerConn.unsubscribe(sub.topic, sub.ref, true)
1005
1006
  }
1006
1007
  })
1007
-
1008
+
1008
1009
  // if subscription is found (or sent in as a parameter), then check for changes.
1009
1010
  // if there are any changes requested, tidy up the old subscription
1010
1011
  if (subscription) {
@@ -1091,7 +1092,7 @@ module.exports = function(RED) {
1091
1092
  delete sub[ref]
1092
1093
  }
1093
1094
  }
1094
- // if instructed to remove the actual MQTT client subscription
1095
+ // if instructed to remove the actual MQTT client subscription
1095
1096
  if (unsub) {
1096
1097
  // if there are no more subscriptions for the topic, then remove the topic
1097
1098
  if (Object.keys(sub).length === 0) {
@@ -63,7 +63,7 @@ module.exports = function(RED) {
63
63
  if (!(notemplate && (msg.hasOwnProperty("parts") && msg.parts.hasOwnProperty("index") && msg.parts.index > 0))) {
64
64
  template = clean(node.template);
65
65
  }
66
- var ou = "";
66
+ const ou = [];
67
67
  if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
68
68
  if (node.hdrout !== "none" && node.hdrSent === false) {
69
69
  if ((template.length === 1) && (template[0] === '')) {
@@ -74,7 +74,7 @@ module.exports = function(RED) {
74
74
  template = Object.keys(msg.payload[0]);
75
75
  }
76
76
  }
77
- ou += template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep) + node.ret;
77
+ ou.push(template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep));
78
78
  if (node.hdrout === "once") { node.hdrSent = true; }
79
79
  }
80
80
  for (var s = 0; s < msg.payload.length; s++) {
@@ -93,7 +93,7 @@ module.exports = function(RED) {
93
93
  msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
94
94
  }
95
95
  }
96
- ou += msg.payload[s].join(node.sep) + node.ret;
96
+ ou.push(msg.payload[s].join(node.sep));
97
97
  }
98
98
  else {
99
99
  if ((template.length === 1) && (template[0] === '') && (msg.hasOwnProperty("columns"))) {
@@ -105,6 +105,7 @@ module.exports = function(RED) {
105
105
  node.warn(RED._("csv.errors.obj_csv"));
106
106
  tmpwarn = false;
107
107
  }
108
+ const row = [];
108
109
  for (var p in msg.payload[0]) {
109
110
  /* istanbul ignore else */
110
111
  if (msg.payload[s].hasOwnProperty(p)) {
@@ -118,21 +119,22 @@ module.exports = function(RED) {
118
119
  }
119
120
  if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
120
121
  q = q.replace(/"/g, '""');
121
- ou += node.quo + q + node.quo + node.sep;
122
+ row.push(node.quo + q + node.quo);
122
123
  }
123
124
  else if (q.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
124
- ou += node.quo + q + node.quo + node.sep;
125
+ row.push(node.quo + q + node.quo);
125
126
  }
126
- else { ou += q + node.sep; } // otherwise just add
127
+ else { row.push(q); } // otherwise just add
127
128
  }
128
129
  }
129
130
  }
130
- ou = ou.slice(0,-1) + node.ret;
131
+ ou.push(row.join(node.sep)); // add separator
131
132
  }
132
133
  else {
134
+ const row = [];
133
135
  for (var t=0; t < template.length; t++) {
134
136
  if (template[t] === '') {
135
- ou += node.sep;
137
+ row.push('');
136
138
  }
137
139
  else {
138
140
  var tt = template[t];
@@ -146,19 +148,20 @@ module.exports = function(RED) {
146
148
  p = RED.util.ensureString(p);
147
149
  if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
148
150
  p = p.replace(/"/g, '""');
149
- ou += node.quo + p + node.quo + node.sep;
151
+ row.push(node.quo + p + node.quo);
150
152
  }
151
153
  else if (p.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
152
- ou += node.quo + p + node.quo + node.sep;
154
+ row.push(node.quo + p + node.quo);
153
155
  }
154
- else { ou += p + node.sep; } // otherwise just add
156
+ else { row.push(p); } // otherwise just add
155
157
  }
156
158
  }
157
- ou = ou.slice(0,-1) + node.ret; // remove final "comma" and add "newline"
159
+ ou.push(row.join(node.sep)); // add separator
158
160
  }
159
161
  }
160
162
  }
161
- msg.payload = ou;
163
+ // join lines, don't forget to add the last new line
164
+ msg.payload = ou.join(node.ret) + node.ret;
162
165
  msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
163
166
  if (msg.payload !== '') { send(msg); }
164
167
  done();
@@ -41,8 +41,8 @@
41
41
  color:"#DEBD5C",
42
42
  defaults: {
43
43
  name: {value:""},
44
- property: {value:"payload"},
45
- outproperty: {value:"payload"},
44
+ property: {value:"payload", validate: RED.validators.typedInput({ type: 'msg' }) },
45
+ outproperty: {value:"payload", validate: RED.validators.typedInput({ type: 'msg' }) },
46
46
  tag: {value:""},
47
47
  ret: {value:"html"},
48
48
  as: {value:"single"}
@@ -32,6 +32,7 @@
32
32
  defaults: {
33
33
  name: {value:""},
34
34
  property: {value:"payload",required:true,
35
+ validate: RED.validators.typedInput({ type: 'msg' }),
35
36
  label:RED._("node-red:json.label.property")},
36
37
  action: {value:""},
37
38
  pretty: {value:false}
@@ -27,7 +27,8 @@
27
27
  defaults: {
28
28
  name: {value:""},
29
29
  property: {value:"payload",required:true,
30
- label:RED._("node-red:common.label.property")},
30
+ label:RED._("node-red:common.label.property"),
31
+ validate: RED.validators.typedInput({ type: 'msg' })},
31
32
  attr: {value:""},
32
33
  chr: {value:""}
33
34
  },
@@ -16,6 +16,7 @@
16
16
  color:"#DEBD5C",
17
17
  defaults: {
18
18
  property: {value:"payload",required:true,
19
+ validate: RED.validators.typedInput({ type: 'msg' }),
19
20
  label:RED._("node-red:common.label.property")},
20
21
  name: {value:""}
21
22
  },
@@ -57,7 +57,7 @@
57
57
  arraySplt: {value:1},
58
58
  arraySpltType: {value:"len"},
59
59
  stream: {value:false},
60
- addname: {value:""}
60
+ addname: {value:"", validate: RED.validators.typedInput({ type: 'msg', allowBlank: true })}
61
61
  },
62
62
  inputs:1,
63
63
  outputs:1,
@@ -208,7 +208,22 @@
208
208
  validate:RED.validators.typedInput("propertyType", false)
209
209
  },
210
210
  propertyType: { value:"msg"},
211
- key: {value:"topic"},
211
+ key: {value:"topic", validate: (function () {
212
+ const typeValidator = RED.validators.typedInput({ type: 'msg' })
213
+ return function(v, opt) {
214
+ const joinMode = $("#node-input-mode").val() || this.mode
215
+ if (joinMode !== 'custom') {
216
+ return true
217
+ }
218
+ const buildType = $("#node-input-build").val() || this.build
219
+ if (buildType !== 'object') {
220
+ return true
221
+ } else {
222
+ return typeValidator(v, opt)
223
+ }
224
+ }
225
+ })()
226
+ },
212
227
  joiner: { value:"\\n"},
213
228
  joinerType: { value:"str"},
214
229
  accumulate: { value:"false" },
@@ -198,7 +198,7 @@
198
198
  category: 'storage',
199
199
  defaults: {
200
200
  name: {value:""},
201
- filename: {value:""},
201
+ filename: {value:"", validate: RED.validators.typedInput({ typeField: 'filenameType' })},
202
202
  filenameType: {value:"str"},
203
203
  appendNewline: {value:true},
204
204
  createDir: {value:false},
@@ -297,7 +297,7 @@
297
297
  category: 'storage',
298
298
  defaults: {
299
299
  name: {value:""},
300
- filename: {value:""},
300
+ filename: {value:"", validate: RED.validators.typedInput({ typeField: 'filenameType' }) },
301
301
  filenameType: {value:"str"},
302
302
  format: {value:"utf8"},
303
303
  chunk: {value:false},
@@ -36,5 +36,5 @@
36
36
  <p><b>Remarque</b> : Les options <i>"Intervalle entre les heures"</i> et <i>"à une heure précise"</i> utilisent le système cron standard.
37
37
  Cela signifie que pour la première option, vous pouvez envoyer un message à intervalle régulier entre les heures voulues.
38
38
  Si vous voulez envoyer un message toutes les minutes à partir de maintenant, utiliser l'option <i>"intervalle"</i>.</p>
39
- <p><b>Remarque</b> : Pour inclure une nouvelle ligne dans une chaîne, vous devez utiliser un noeud de fonction pour créer la charge utile.</p>
39
+ <p><b>Remarque</b> : Pour inclure une nouvelle ligne dans une chaîne, vous devez utiliser soit un noeud de fonction soit le noeud template pour créer la charge utile.</p>
40
40
  </script>