node-red-contrib-prib-functions 0.18.0 → 0.19.2

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.
@@ -30,7 +30,8 @@
30
30
  schemaType: {value:"json"},
31
31
  skipLeading: {value:0},
32
32
  skipTrailing: {value:0},
33
- delimiter: {value:",",required:true}
33
+ delimiter: {value:",",required:true},
34
+ compressionType: {value:"gzip"}
34
35
  },
35
36
  inputs: 1,
36
37
  outputs: 2,
@@ -43,11 +44,49 @@
43
44
  return this.name ||this.actionSource+"=>"+this.actionTarget|| "Transform";
44
45
  },
45
46
  oneditprepare: function() {
46
- const actionTarget=this.actionTarget
47
+ const actionTarget=this.actionTarget;
48
+ $("#node-input-actionSource").typedInput({type:"actionSource", types:[{
49
+ value: "actionSource",
50
+ options: [
51
+ { value: "Array", label: "Array"},
52
+ { value: "AVRO", label: "AVRO"},
53
+ { value: "Buffer", label: "Buffer"},
54
+ { value: "Compressed", label: "Compressed"},
55
+ { value: "Confluence", label: "Confluence"},
56
+ { value: "CSVWithHeader", label: "CSV with header"},
57
+ { value: "CSV", label: "CSV"},
58
+ { value: "ISO8385", label: "ISO 8583"},
59
+ { value: "JSON", label: "JSON"},
60
+ { value: "String", label: "String"},
61
+ { value: "snappy", label: "Snappy"},
62
+ { value: "path", label: "Path"},
63
+ { value: "XLSX", label: "XLSX (excel)"},
64
+ { value: "XLSXObject", label: "XLSX object (excel)"},
65
+ { value: "XML", label: "XML"}
66
+ ]
67
+ }]});
68
+ $("#node-input-compressionType").typedInput({type:"compression", types:[{
69
+ value: "compression",
70
+ options: [
71
+ { value: "setGzip", label: "gzip"},
72
+ { value: "setGzipSpeed", label: "gzip speed"},
73
+ { value: "setGzipCompression", label: "gzip compression"},
74
+ { value: "setZlib", label: "zip"},
75
+ { value: "setZlibSpeed", label: "zip speed"},
76
+ { value: "setZlibCompression", label: "zip compression"},
77
+ { value: "setLzma", label: "Lempel-Ziv-Markov speed"},
78
+ { value: "setLzmaCompression", label: "Lempel-Ziv-Markov compression"},
79
+ { value: "setBrotli", label: "Brotli"},
80
+ { value: "setSnappy", label: "Snappy"},
81
+ { value: "setFlate", label: "Deflate/Inflate"}
82
+ ]
83
+ }]});
84
+
47
85
  $("#node-input-actionSource").change(function() {
48
86
  const actionSource=$(this).val();
49
87
  $(".form-row-http-in-skip").hide();
50
88
  $(".form-row-http-in-schema").hide();
89
+ $(".form-row-http-in-compressionType").hide();
51
90
  if(!['CSV','CSVWithHeader'].includes(actionSource)) {
52
91
  $(".form-row-http-in-csv").hide();
53
92
  }
@@ -62,10 +101,19 @@
62
101
  options["XLSXObject"]="XLSX object (excel)";
63
102
  break;
64
103
  case 'AVRO':
104
+ case 'Buffer':
105
+ options["Compressed"]="Compressed";
106
+ break;
65
107
  case 'Confluence':
66
108
  options["JSON"]="JSON";
67
109
  $(".form-row-http-in-schema").show();
68
110
  break;
111
+ case 'Compressed':
112
+ options["JSON"]="JSON";
113
+ options["String"]="String";
114
+ options["Buffer"]="Buffer";
115
+ $(".form-row-http-in-compressionType").show();
116
+ break;
69
117
  case 'CSVWithHeader':
70
118
  options["JSON"]="JSON";
71
119
  case 'CSV':
@@ -82,8 +130,8 @@
82
130
  case 'JSON':
83
131
  options["Array"]="Array";
84
132
  options["AVRO"]="AVRO";
133
+ options["Compressed"]="Compressed";
85
134
  options["Confluence"]="Confluence";
86
- options["CSVWithHeader"]="CSV with header";
87
135
  options["CSV"]="CSV";
88
136
  options["ISO8385"]="ISO 8583";
89
137
  options["HTML"]="HTML";
@@ -108,6 +156,7 @@
108
156
  options["Compress"]="Compress";
109
157
  break;
110
158
  case 'String':
159
+ options["Compressed"]="Compressed";
111
160
  options["JSON"]="JSON";
112
161
  break;
113
162
  case 'XLSX':
@@ -145,11 +194,15 @@
145
194
  if(!['CSV','CSVWithHeader'].includes(actionTarget)) {
146
195
  $(".form-row-http-in-csv").hide();
147
196
  }
197
+ $(".form-row-http-in-compressionType").hide();
148
198
  switch (actionTarget) {
149
199
  case 'AVRO':
150
200
  case 'Confluence':
151
201
  $(".form-row-http-in-schema").show();
152
202
  break;
203
+ case 'Compressed':
204
+ $(".form-row-http-in-compressionType").show();
205
+ break;
153
206
  case 'CSV':
154
207
  $(".form-row-http-in-csv").show();
155
208
  break;
@@ -187,21 +240,7 @@
187
240
  </div>
188
241
  <div class="form-row">
189
242
  <label for="node-input-actionSource"><i class="fa fa-list-ul"></i> Source Type </label>
190
- <select id="node-input-actionSource" placeholder="actionSource">
191
- <option value="Array">Array</option>
192
- <option value="AVRO">AVRO</option>
193
- <option value="Confluence">Confluence</option>
194
- <option value="CSVWithHeader">CSV with header</option>
195
- <option value="CSV">CSV</option>
196
- <option value="ISO8385">ISO 8583</option>
197
- <option value="JSON">JSON</option>
198
- <option value="String">String</option>
199
- <option value="snappy">snappy</option>
200
- <option value="path">Path</option>
201
- <option value="XLSX">XLSX (excel)</option>
202
- <option value="XLSXObject">XLSX object (excel)</option>
203
- <option value="XML">XML</option>
204
- </select>
243
+ <input type="text" id="node-input-actionSource">
205
244
  </div>
206
245
  <div class="form-row">
207
246
  <label for="node-input-actionTarget"><i class="fa fa-list-ul"></i> Target Type </label>
@@ -227,7 +266,10 @@
227
266
  <input type="text" id="node-input-schema" style="width:70%">
228
267
  <input type="hidden" id="node-input-schemaType">
229
268
  </div>
230
-
269
+ <div class="form-row form-row-http-in-compressionType hide">
270
+ <label for="node-input-compressionType"><i class="fa fa-envelope"></i> <span data-i18n="common.label.compressionType"> Type </span></label>
271
+ <input type="text" id="node-input-compressionType">
272
+ </div>
231
273
 
232
274
  </script>
233
275
 
@@ -1,12 +1,13 @@
1
1
  const logger = new (require("node-red-contrib-logger"))("transform");
2
2
  logger.sendInfo("Copyright 2020 Jaroslav Peter Prib");
3
+ const CompressionTool = require('compressiontool');
3
4
 
4
5
  const regexCSV=/,(?=(?:(?:[^"]*"){2})*[^"]*$)/,
5
6
  Buffer=require('buffer').Buffer,
6
7
  os=require('os'),
7
8
  path=require('path'),
8
9
  process=require('process');
9
- let avsc,snappy,xmlParser,json2xmlParser,XLSX;
10
+ let avsc,snappy,xmlParser,json2xmlParser,XLSX,compressor;
10
11
  const {ISO8583BitMapId,ISO8583BitMapName}=require("./ISO8583BitMap");
11
12
  let ISO8583,ISO8583message;
12
13
  const XMLoptions = {
@@ -170,6 +171,35 @@ function array2tag(a,t,tf){
170
171
  const ts="<"+t+">",te="</"+t+">"
171
172
  return a.reduce((a,c)=>a+=ts+tf(c)+te,"");
172
173
  }
174
+ function Array2csv(node,data){
175
+ if(!(data instanceof Array)) return JSON.stringify(data);
176
+ if(data.length==0) return;
177
+ if(data[0] instanceof Array) {
178
+ return data.map(r=>
179
+ r instanceof Array?r.map(c=>JSON.stringify(c)).join(node.delimiter):JSON.stringify(r)
180
+ ).join("\n");
181
+ } else if(data[0] instanceof Object) {
182
+ const properties=[];
183
+ data.forEach(r=>{
184
+ if(typeof r == "object" && ! (r instanceof Array)){
185
+ Object.keys(r).forEach(p=>{
186
+ if(properties.includes(p)) return
187
+ properties.push(p)
188
+ })
189
+ }
190
+ })
191
+ properties.sort();
192
+ const rows=data.map(r=>{
193
+ if(typeof r == "object" && ! (r instanceof Array)) {
194
+ return properties.map(c=>r[c]||"").join(node.delimiter)
195
+ } else {
196
+ return node.delimiter.repeat(properties.length)+JSON.stringify(r)
197
+ }
198
+ })
199
+ return properties.join(node.delimiter)+"\n"+rows.join("\n");
200
+ }
201
+ return data .map(r=>JSON.stringify(r)).join("/n");
202
+ }
173
203
  const functions={
174
204
  ArrayToCSV: (RED,node,msg,data)=>data.map(c=>JSON.stringify(c)).join("\n"),
175
205
  ArrayToHTML: (RED,node,msg,data)=>
@@ -198,6 +228,52 @@ const functions={
198
228
  ArrayToXLSX:ArrayToXLSX,
199
229
  ArrayToXLSXObject:ArrayToXLSXObject,
200
230
  AVROToJSON: (RED,node,msg,data)=>node.avroTransformer.fromBuffer(data), // = {kind: 'CAT', name: 'Albert'}
231
+ BufferToCompressed: (RED,node,msg,data)=>compressor.compress(data,
232
+ (compressed)=>{
233
+ node.setData(RED,node,msg,compressed);
234
+ node.send(msg);
235
+ },
236
+ (err)=>{
237
+ error(node,Error(err));
238
+ }
239
+ ),
240
+ CompressedToBuffer:(RED,node,msg,data)=>compressor.decompress(data,
241
+ (uncompressed)=>{
242
+ node.setData(RED,node,msg,uncompressed);
243
+ node.send(msg);
244
+ },
245
+ (err)=>{
246
+ error(node,Error(err));
247
+ }
248
+ ),
249
+ CompressedToJSON:(RED,node,msg,data)=>compressor.decompress(data,
250
+ (uncompressed)=>{
251
+ try{
252
+ node.setData(RED,node,msg,JSON.parse(uncompressed));
253
+ node.send(msg);
254
+ } catch(ex){
255
+ msg.error=ex.message
256
+ node.setData(RED,node,msg,uncompressed);
257
+ }
258
+ },
259
+ (err)=>{
260
+ error(node,Error(err));
261
+ }
262
+ ),
263
+ CompressedToString:(RED,node,msg,data)=>compressor.decompress(data,
264
+ (uncompressed)=>{
265
+ try{
266
+ node.setData(RED,node,msg,uncompressed.toString());
267
+ node.send(msg);
268
+ } catch(ex){
269
+ msg.error=ex.message;
270
+ node.setData(RED,node,msg,uncompressed);
271
+ }
272
+ },
273
+ (err)=>{
274
+ error(node,Error(err));
275
+ }
276
+ ),
201
277
  ConfluenceToJSON: ConfluenceToJSON,
202
278
  CSVToArray: (RED,node,msg,data)=>{
203
279
  let lines=csvLines(data,node.skipLeading,node.skipTrailing);
@@ -256,8 +332,17 @@ const functions={
256
332
  }
257
333
  return data;
258
334
  },
335
+ JSONToCompressed: (RED,node,msg,data)=>compressor.compress(JSON.stringify(data),
336
+ (compressed)=>{
337
+ node.setData(RED,node,msg,compressed);
338
+ node.send(msg);
339
+ },
340
+ (err)=>{
341
+ error(node,Error(err));
342
+ }
343
+ ),
259
344
  JSONToConfluence:JSONToConfluence,
260
- JSONToCSV: (RED,node,msg,data)=>functions.ArrayToCSV(RED,node,msg,functions.JSONToArray(RED,node,msg,data)),
345
+ JSONToCSV: (RED,node,msg,data)=>Array2csv(node,data),
261
346
  JSONToAVRO: (RED,node,msg,data)=>node.avroTransformer.toBuffer(data), // Encoded buffer.
262
347
  JSONToHTML: (RED,node,msg,data,level=0)=>{
263
348
  if(Array.isArray(data)) {
@@ -294,6 +379,15 @@ const functions={
294
379
  JSONToXLSX:JSONToXLSX,
295
380
  JSONToXLSXObject:JSONToXLSXObject,
296
381
  JSONToXML: (RED,node,msg,data)=>json2xmlParser.parse(data),
382
+ StringToCompressed: (RED,node,msg,data)=>compressor.compress(data,
383
+ (compressed)=>{
384
+ node.setData(RED,node,msg,compressed);
385
+ node.send(msg);
386
+ },
387
+ (err)=>{
388
+ error(node,Error(err));
389
+ }
390
+ ),
297
391
  StringToJSON: (RED,node,msg,data)=>JSON.parse(data),
298
392
  pathToBasename: (RED,node,msg,data)=>path.basename(data),
299
393
  pathToDirname: (RED,node,msg,data)=>path.dirname(data),
@@ -373,11 +467,11 @@ module.exports = function (RED) {
373
467
  }
374
468
  if(logger.active) logger.send({label:"load xml",xmlParserKeys:Object.keys(xmlParser),json2xmlParser:Object.keys(json2xmlParser)});
375
469
  }
376
- node.sendInFunction=["snappy"].includes(node.actionSource)||["Messages"].includes(node.actionTarget);
470
+ node.sendInFunction=["snappy","Compressed"].includes(node.actionSource)||["Messages","Compressed"].includes(node.actionTarget);
377
471
  node.hasNewTopic=![null,""].includes(node.topicProperty);
378
472
  const sourceMap="(RED,node,msg)=>"+(node.sourceProperty||"msg.payload"),
379
473
  sourceDelete="(RED,node,msg)=>{delete "+(node.sourceProperty||"msg.payload")+";}",
380
- targetMap="(RED,node,msg,data,index)=>{"+(node.targetProperty||"msg.payload")+"=data;"+
474
+ targetMap="(RED,node,msg,data,index)=>{"+(node.targetProperty||"msg.payload")+"=data;"+
381
475
  (node.sendInFunction && node.hasNewTopic? "msg.topic=node.topicFunction(RED,node,msg,data,index);":"")+
382
476
  (node.sendInFunction ? "" : "node.send(msg);" )+
383
477
  "}",
@@ -389,13 +483,21 @@ module.exports = function (RED) {
389
483
  node.topicFunction=evalFunction("topic",topicMap);
390
484
  if(is(node,"AVRO")) {
391
485
  node.avroTransformer=avsc.Type.forSchema(node.schemaValid);
486
+ } else if(is(node,"Compressed")) {
487
+ compressor=new CompressionTool();
488
+ compressor[node.compressionType]();
392
489
  } else if(is(node,"Confluence")) {
393
490
  node.schemas={};
394
491
  for(const schema in node.schemaValid )
395
492
  node.schemas[schema]=avsc.Type.forSchema(node.schemaValid[schema]);
396
493
  logger.info({label:"confluence",schemas:Object.keys(node.schemas)});
397
494
  }
495
+ if(node.actionTarget=="Compressed"){
496
+ compressor=new CompressionTool();
497
+ compressor[node.compressionType]();
498
+ }
398
499
  } catch(ex) {
500
+ logger.error(n);
399
501
  error(node,ex,"Invalid setup "+ex.message);
400
502
  return;
401
503
  }
@@ -420,15 +522,17 @@ module.exports = function (RED) {
420
522
  error(node,ex,node.actionSource+"\nto "+node.actionTarget + " not implemented")
421
523
  return;
422
524
  }
423
-
525
+ node.processMsg=node.sendInFunction?this.transform
526
+ :(RED,node,msg,data)=>node.setData(RED,node,msg,node.transform(RED,node,msg,data));
424
527
  this.status({fill:"green",shape:"ring",text:"Ready"});
425
528
  node.on("input", function(msg) {
426
529
  if(logger.active) logger.send({label:"input",msgid:msg._msgid,topic:msg.topic});
427
530
  try{
428
531
  const data=node.getData(RED,node,msg);
429
532
  if(node.invalidSourceType(data)) throw Error("expected source data type "+node.actionSource);
430
- node.setData(RED,node,msg,node.transform(RED,node,msg,data));
533
+ node.processMsg(RED,node,msg,data);
431
534
  } catch (ex) {
535
+ if(logger.active) logger.sendErrorAndDump("on input error",ex)
432
536
  msg.error=node.actionSource+" to "+node.actionTarget + " " +ex.message;
433
537
  error(node,Error(msg.error),"Error(s)");
434
538
  node.send([null,msg]);
Binary file