node-red-contrib-prib-functions 0.22.0 → 0.23.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.
- package/README.md +87 -35
- package/lib/common.js +128 -0
- package/lib/objectExtensions.js +190 -80
- package/lib/typedInput.js +77 -0
- package/matrix/matrixNode.html +2 -1
- package/package.json +12 -11
- package/test/00-objectExtensions.js +192 -1
- package/test/data/.config.nodes.json +3 -3
- package/test/data/.config.nodes.json.backup +3 -3
- package/test/data/.config.users.json +3 -2
- package/test/data/.config.users.json.backup +3 -2
- package/test/data/.flow.json.backup +3208 -425
- package/test/data/flow.json +3187 -402
- package/test/data/package-lock.json +4 -4
- package/testing/test.js +59 -26
- package/transform/transform.html +163 -19
- package/transform/transform.js +106 -55
- package/visual/shapes/base..js +1 -0
- package/visual/visual.js +0 -0
- package/visual/visualNode.js +45 -0
package/transform/transform.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
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');
|
|
4
3
|
const NumPy = require("./NumPy.js")
|
|
4
|
+
const typedInput = require("../lib/typedInput.js")
|
|
5
|
+
const {coalesce,nullif,toDateTypeZulu}=require("../lib/objectExtensions")
|
|
5
6
|
const regexCSV=/,(?=(?:(?:[^"]*"){2})*[^"]*$)/,
|
|
6
7
|
Buffer=require('buffer').Buffer,
|
|
7
8
|
os=require('os'),
|
|
@@ -28,12 +29,13 @@ const XMLoptions = {
|
|
|
28
29
|
// stopNodes: ["parse-me-as-string"]
|
|
29
30
|
trimValues: false
|
|
30
31
|
};
|
|
31
|
-
|
|
32
|
+
const makeDateType=data=>(data instanceof Date? data:new Date(data))
|
|
33
|
+
const error=(node,ex,shortMessage)=>{
|
|
32
34
|
if(logger.active) logger.send({label:"transformNode catch",shortMessage:shortMessage,error:ex.message,stack:ex.stack});
|
|
33
35
|
node.error(ex.message);
|
|
34
36
|
node.status({fill:"red",shape:"ring",text:(shortMessage||ex.message).substr(0,50)});
|
|
35
37
|
}
|
|
36
|
-
|
|
38
|
+
const getAvroTransformer=(node,schema)=>{
|
|
37
39
|
try{
|
|
38
40
|
return avsc.Type.forSchema(node.schemas[schema]);
|
|
39
41
|
} catch(ex){
|
|
@@ -42,32 +44,19 @@ function getAvroTransformer(node,schema) {
|
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
const addWorksheet2JSON=(object,worksheet,workbook,options)=>{
|
|
46
48
|
object[worksheet]=XLSX.utils.sheet_to_json(workbook.Sheets[worksheet],options);
|
|
47
49
|
if(options.header) object[worksheet].shift();
|
|
48
50
|
if(logger.active) logger.send({label:"addWorksheet2JSON",object:object,worksheet:worksheet})
|
|
49
51
|
return object;
|
|
50
52
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return XLSXObjectToJSON(RED,node,msg,XLSXToXLSXObject(RED,node,msg,data));
|
|
59
|
-
}
|
|
60
|
-
function XLSXToXLSXObject(RED,node,msg,data){
|
|
61
|
-
return XLSX.read(data, {raw:true,type: 'buffer' });
|
|
62
|
-
}
|
|
63
|
-
function XLSXObjectToArray(RED,node,msg,data){
|
|
64
|
-
return data.SheetNames.reduce((a,worksheet)=>addWorksheet2JSON(a,worksheet,data,{header:1,raw:true}),{})
|
|
65
|
-
}
|
|
66
|
-
function JSONToXLSX(RED,node,msg,data){
|
|
67
|
-
const workbook=JSONToXLSXObject(RED,node,msg,data);
|
|
68
|
-
return XLSX.write(workbook, {bookType:"xlsx", type:'buffer'});
|
|
69
|
-
}
|
|
70
|
-
function JSONToXLSXObject(RED,node,msg,data){
|
|
53
|
+
const XLSXObjectToJSON=(RED,node,msg,data)=>data.SheetNames.reduce((a,worksheet)=>addWorksheet2JSON(a,worksheet,data),{})
|
|
54
|
+
const XLSXToArray=(RED,node,msg,data)=>XLSXObjectToArray(RED,node,msg,XLSXToXLSXObject(RED,node,msg,data))
|
|
55
|
+
const XLSXToJSON=(RED,node,msg,data)=>XLSXObjectToJSON(RED,node,msg,XLSXToXLSXObject(RED,node,msg,data))
|
|
56
|
+
const XLSXToXLSXObject=(RED,node,msg,data)=>XLSX.read(data, {raw:true,type: 'buffer' })
|
|
57
|
+
const XLSXObjectToArray=(RED,node,msg,data)=>data.SheetNames.reduce((a,worksheet)=>addWorksheet2JSON(a,worksheet,data,{header:1,raw:true}),{})
|
|
58
|
+
const JSONToXLSX=(RED,node,msg,data)=>XLSX.write(JSONToXLSXObject(RED,node,msg,data), {bookType:"xlsx", type:'buffer'})
|
|
59
|
+
const JSONToXLSXObject=(RED,node,msg,data)=>{
|
|
71
60
|
const workbook = XLSX.utils.book_new();
|
|
72
61
|
for(const worksheet in data) {
|
|
73
62
|
const ws=XLSX.utils.json_to_sheet(data[worksheet]);
|
|
@@ -75,11 +64,8 @@ function JSONToXLSXObject(RED,node,msg,data){
|
|
|
75
64
|
}
|
|
76
65
|
return workbook;
|
|
77
66
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return XLSX.write(workbook, {bookType:"xlsx", type:'buffer'});
|
|
81
|
-
}
|
|
82
|
-
function ArrayToXLSXObject(RED,node,msg,data){
|
|
67
|
+
const ArrayToXLSX=(RED,node,msg,data)=>XLSX.write(ArrayToXLSXObject(RED,node,msg,data), {bookType:"xlsx", type:'buffer'})
|
|
68
|
+
const ArrayToXLSXObject=(RED,node,msg,data)=>{
|
|
83
69
|
const workbook = XLSX.utils.book_new();
|
|
84
70
|
if(Array.isArray(data)) {
|
|
85
71
|
const ws=XLSX.utils.aoa_to_sheet(data);
|
|
@@ -92,7 +78,7 @@ function ArrayToXLSXObject(RED,node,msg,data){
|
|
|
92
78
|
}
|
|
93
79
|
return workbook;
|
|
94
80
|
}
|
|
95
|
-
|
|
81
|
+
const ConfluenceToJSON=(RED,node,msg,data)=>{
|
|
96
82
|
if(!Buffer.isBuffer(data)) data=Buffer.from(data);
|
|
97
83
|
const magicByte=data.readUInt8();
|
|
98
84
|
if(magicByte!==0) throw Error("expected magic byte and not found, found "+magicByte);
|
|
@@ -101,8 +87,7 @@ function ConfluenceToJSON(RED,node,msg,data){
|
|
|
101
87
|
const avroTransformer=getAvroTransformer(node,schema);
|
|
102
88
|
return {schema:schema,data:avroTransformer.fromBuffer(data.subarray(5))};
|
|
103
89
|
}
|
|
104
|
-
|
|
105
|
-
function JSONToConfluence(RED,node,msg,data){
|
|
90
|
+
const JSONToConfluence=(RED,node,msg,data)=>{
|
|
106
91
|
if(!data.schema) throw Error("property schema not defined");
|
|
107
92
|
if(!data.data) throw Error("property data not defined");
|
|
108
93
|
const header=Buffer.alloc(5);
|
|
@@ -112,7 +97,6 @@ function JSONToConfluence(RED,node,msg,data){
|
|
|
112
97
|
const avro=transformer.toBuffer(data.data);
|
|
113
98
|
return Buffer.concat([header,avro]);
|
|
114
99
|
}
|
|
115
|
-
|
|
116
100
|
function SendArray(RED,node,msg,array){
|
|
117
101
|
if(logger.active) logger.send({label:"SendArray",size:array.length});
|
|
118
102
|
this.index=0;
|
|
@@ -120,7 +104,6 @@ function SendArray(RED,node,msg,array){
|
|
|
120
104
|
this.node=node;
|
|
121
105
|
this.msg=msg;
|
|
122
106
|
this.array=array;
|
|
123
|
-
node.deleteSourceProperty(RED,node,msg);
|
|
124
107
|
this.next();
|
|
125
108
|
}
|
|
126
109
|
SendArray.prototype.next=function() {
|
|
@@ -135,6 +118,7 @@ SendArray.prototype.next=function() {
|
|
|
135
118
|
this.lastTouchTime=currentTime;
|
|
136
119
|
|
|
137
120
|
let i=cpuUsedRatio>0.9 || memoryUsedRatio>0.9 || heapUsedRatio>0.99?1:100;
|
|
121
|
+
const newMsgs=[]
|
|
138
122
|
while(--i) {
|
|
139
123
|
if(this.index>=this.array.length) {
|
|
140
124
|
delete this;
|
|
@@ -144,12 +128,13 @@ SendArray.prototype.next=function() {
|
|
|
144
128
|
newMsg._msgid=newMsg._msgid+":"+index;
|
|
145
129
|
this.node.setData(this.RED,this.node,newMsg,this.array[index],index)
|
|
146
130
|
this.index++;
|
|
147
|
-
|
|
131
|
+
newMsgs.push(newMsg);
|
|
148
132
|
}
|
|
133
|
+
this.node.send([newMsgs]);
|
|
149
134
|
const call=this.next.bind(this);
|
|
150
135
|
this.timeoutID=setTimeout(call, 100);
|
|
151
136
|
};
|
|
152
|
-
|
|
137
|
+
const removeQuotes=(data)=>{
|
|
153
138
|
try{
|
|
154
139
|
const d=data.trim();
|
|
155
140
|
if(d.length>1 && d.startsWith('"') && d.endsWith('"')) return d.slice(1,-1);
|
|
@@ -159,7 +144,7 @@ function removeQuotes(data){
|
|
|
159
144
|
return data;
|
|
160
145
|
}
|
|
161
146
|
}
|
|
162
|
-
|
|
147
|
+
const csvLines=(data,skipLeading=0,skipTrailing=0)=>{
|
|
163
148
|
if(logger.active) logger.send({label:"csvLines",skipLeading:skipLeading,skipTrailing:skipTrailing});
|
|
164
149
|
let lines=data.split(/[\r\n]+/g),skip=skipLeading;
|
|
165
150
|
while(skip--) lines.shift();
|
|
@@ -167,11 +152,11 @@ function csvLines(data,skipLeading=0,skipTrailing=0) {
|
|
|
167
152
|
while(skip--) lines.pop();
|
|
168
153
|
return lines;
|
|
169
154
|
}
|
|
170
|
-
|
|
155
|
+
const array2tag=(a,t,tf)=>{
|
|
171
156
|
const ts="<"+t+">",te="</"+t+">"
|
|
172
157
|
return a.reduce((a,c)=>a+=ts+tf(c)+te,"");
|
|
173
158
|
}
|
|
174
|
-
|
|
159
|
+
const Array2csv=(node,data)=>{
|
|
175
160
|
if(!(data instanceof Array)) return JSON.stringify(data);
|
|
176
161
|
if(data.length==0) return;
|
|
177
162
|
if(data[0] instanceof Array) {
|
|
@@ -217,17 +202,20 @@ const functions={
|
|
|
217
202
|
ArrayToMessages: (RED,node,msg,data)=>{
|
|
218
203
|
if(logger.active) logger.send({label:"ArrayToMessages",arraySize:data.length});
|
|
219
204
|
if(data.length>node.maxMessages) throw Error("messages to be created "+data.length +"> max: "+node.maxMessages);
|
|
205
|
+
const newMsgs=[]
|
|
220
206
|
data.map((row,i)=>{
|
|
221
207
|
const newMsg=RED.util.cloneMessage(msg);
|
|
222
208
|
newMsg._msgid=newMsg._msgid+":"+i;
|
|
223
209
|
if(logger.active) logger.send({label:"ArrayToMessages",row:row,index:i});
|
|
224
210
|
node.setData(RED,node,newMsg,row,i)
|
|
225
|
-
|
|
211
|
+
newMsgs.push(newMsg);
|
|
226
212
|
});
|
|
213
|
+
node.send([newMsgs])
|
|
227
214
|
},
|
|
228
215
|
ArrayToXLSX:ArrayToXLSX,
|
|
229
216
|
ArrayToXLSXObject:ArrayToXLSXObject,
|
|
230
217
|
AVROToJSON: (RED,node,msg,data)=>node.avroTransformer.fromBuffer(data), // = {kind: 'CAT', name: 'Albert'}
|
|
218
|
+
BigIntToRangeLimit: (RED,node,msg,data)=> data?data.rangeLimit(node.minBigIntTyped,node.maxBigIntTyped):node.minBigInt,
|
|
231
219
|
BufferToCompressed: (RED,node,msg,data)=>compressor.compress(data,
|
|
232
220
|
(compressed)=>{
|
|
233
221
|
node.setData(RED,node,msg,compressed);
|
|
@@ -314,6 +302,10 @@ const functions={
|
|
|
314
302
|
});
|
|
315
303
|
return lines;
|
|
316
304
|
},
|
|
305
|
+
DateToisBetween: (RED,node,msg,data)=> toDateTypeZulu(data).isBetween(node.minDateTyped,node.maxDateTyped),
|
|
306
|
+
DateToISODate: (RED,node,msg,data)=> toDateTypeZulu(data).toISOString().slice(0,10),
|
|
307
|
+
DateToLocalDate: (RED,node,msg,data)=> toDateTypeZulu(data).toLocaleDateString().slice(0,10),
|
|
308
|
+
DateToRangeLimit: (RED,node,msg,data)=> (data? toDateTypeZulu(data).rangeLimit(node.minDateTyped,node.maxDateTyped):node.minDateTyped),
|
|
317
309
|
ISO8385ToArray: (RED,node,msg,data)=>ISO8583message.unpackSync(data, data.length),
|
|
318
310
|
ISO8385ToJSON: (RED,node,msg,data)=>{
|
|
319
311
|
let j={},d=ISO8583message.unpackSync(data, data.length);
|
|
@@ -325,7 +317,8 @@ const functions={
|
|
|
325
317
|
JSONToArray: (RED,node,msg,data)=>{
|
|
326
318
|
if(data instanceof Object){
|
|
327
319
|
let a=[];
|
|
328
|
-
|
|
320
|
+
properties=Object.keys(data)
|
|
321
|
+
for(const p of properties) {
|
|
329
322
|
a.push([p,functions.JSONToArray(RED,node,msg,data[p])]);
|
|
330
323
|
}
|
|
331
324
|
return a;
|
|
@@ -367,7 +360,6 @@ const functions={
|
|
|
367
360
|
if(logger.active) logger.send({label:"JSONToMessages",messages:data.length});
|
|
368
361
|
if(Array.isArray(data)) {
|
|
369
362
|
new node.SendArray(RED,node,msg,data);
|
|
370
|
-
// functions.ArrayToMessages(RED,node,msg,data);
|
|
371
363
|
} else {
|
|
372
364
|
const newMsg=RED.util.cloneMessage(msg);
|
|
373
365
|
newMsg._msgid=newMsg._msgid+":0";
|
|
@@ -384,6 +376,23 @@ const functions={
|
|
|
384
376
|
npyToJSON: (RED,node,msg,data)=>new NumPy(data).toSerializable(),
|
|
385
377
|
npyToNumPyObject: (RED,node,msg,data)=>new NumPy(data),
|
|
386
378
|
NumPyObjectToJSON: (RED,node,msg,data)=> data.toSerializable(),
|
|
379
|
+
NumberToAbbreviated: (RED,node,msg,data)=> data?data.isAbbreviated():data,
|
|
380
|
+
NumberToisBetween: (RED,node,msg,data)=> data.isBetween(node.minNumber,node.maxNumber),
|
|
381
|
+
NumberToRangeLimit: (RED,node,msg,data)=> data?data.rangeLimit(node.minNumber,node.maxNumber):node.minNumber,
|
|
382
|
+
ObjectToCoalesce: (RED,node,msg,data)=>coalesce(data,node.value),
|
|
383
|
+
ObjectToDeepClone: (RED,node,msg,data)=>daat.deepClone(),
|
|
384
|
+
ObjectToNullif: (RED,node,msg,data)=>nullif(data,node.value),
|
|
385
|
+
StringToAppend: (RED,node,msg,data)=>data.concat(node.getString(msg)),
|
|
386
|
+
StringToArrayByDelimiter: (RED,node,msg,data)=>data
|
|
387
|
+
.split(node.delimiter??',')
|
|
388
|
+
.map(entry => entry.trim())
|
|
389
|
+
.filter(entry => entry),
|
|
390
|
+
StringToAt: (RED,node,msg,data)=>data.At(node.index),
|
|
391
|
+
StringToCapitalize: (RED,node,msg,data)=> data.capitalize(),
|
|
392
|
+
StringToCamelize: (RED,node,msg,data)=>data.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase()),
|
|
393
|
+
StringToCharAt: (RED,node,msg,data)=>data.charAt(node.index),
|
|
394
|
+
StringToCharCodeAt: (RED,node,msg,data)=>data.charCodeAt(node.index),
|
|
395
|
+
StringToCodePointAt: (RED,node,msg,data)=>data.codePointAt(node.index),
|
|
387
396
|
StringToCompressed: (RED,node,msg,data)=>compressor.compress(data,
|
|
388
397
|
(compressed)=>{
|
|
389
398
|
node.setData(RED,node,msg,compressed);
|
|
@@ -393,7 +402,39 @@ const functions={
|
|
|
393
402
|
error(node,Error(err));
|
|
394
403
|
}
|
|
395
404
|
),
|
|
396
|
-
|
|
405
|
+
StringToConcat: (RED,node,msg,data)=>data.concat(node.getString(msg)),
|
|
406
|
+
StringToDate: (RED,node,msg,data)=>toDateTypeZulu(data),
|
|
407
|
+
StringToDateLocal: (RED,node,msg,data)=>new Date(data),
|
|
408
|
+
StringToTimestamp: (RED,node,msg,data)=>Date.parse(data),
|
|
409
|
+
StringToDelimiterOnCase:(RED,node,msg,data)=>data.replace(/[A-Z]/g, (letter, index) => {
|
|
410
|
+
const lcLet = letter.toLowerCase();
|
|
411
|
+
const separator= node.delimiter??"-"
|
|
412
|
+
return index ? separator + lcLet : lcLet;
|
|
413
|
+
})
|
|
414
|
+
.replace(/([-_ ]){1,}/g,node.delimiter??"-"),
|
|
415
|
+
StringToDeunderscore: (RED,node,msg,data)=> data.deunderscore(),
|
|
416
|
+
StringToDeunderscoreCapitilize: (RED,node,msg,data)=> data.deunderscoreCapitilize(),
|
|
417
|
+
StringToDropSquareBracketPrefix: (RED,node,msg,data)=> data.dropSquareBracketPrefix(),
|
|
418
|
+
StringToEndsWith: (RED,node,msg,data)=> data.endsWith(node.getString(msg)),
|
|
419
|
+
StringToFloat: (RED,node,msg,data)=>parseFloat(data),
|
|
420
|
+
StringToGetWord: (RED,node,msg,data)=> data.getWord(node.index),
|
|
421
|
+
StringToInteger: (RED,node,msg,data)=>parseInt(data, node.radix??10),
|
|
422
|
+
StringToisBetween: (RED,node,msg,data)=> data.isBetween(node.minString,node.maxString),
|
|
423
|
+
StringToJSON: (RED,node,msg,data)=>JSON.parse(data),
|
|
424
|
+
StringToLowerCase: (RED,node,msg,data)=> data.toLowerCase(),
|
|
425
|
+
StringToNumber: (RED,node,msg,data)=>Number(data),
|
|
426
|
+
StringToPrepend: (RED,node,msg,data)=>node.getString(msg).concat(data),
|
|
427
|
+
StringToRangeLimit: (RED,node,msg,data)=> data?data.rangeLimit(node.minString,node.maxString):node.minString,
|
|
428
|
+
StringToReal: (RED,node,msg,data)=> data.toReal(),
|
|
429
|
+
StringToSplit: (RED,node,msg,data)=>data.split(node.getString(msg)),
|
|
430
|
+
StringToStartsWith: (RED,node,msg,data)=> data.startsWith(node.getString(msg)),
|
|
431
|
+
StringToTitle: (RED,node,msg,data)=>data.toTitle(),
|
|
432
|
+
StringTotTitleGrammatical: (RED,node,msg,data)=>data.toTitleGrammatical(),
|
|
433
|
+
StringToTrim: (RED,node,msg,data)=>data.trim(),
|
|
434
|
+
StringToTrimEnd: (RED,node,msg,data)=>data.trimEnd(),
|
|
435
|
+
StringToTrimStart: (RED,node,msg,data)=>data.trimStart(),
|
|
436
|
+
StringToUpperCase: (RED,node,msg,data)=> data.toUpperCase(),
|
|
437
|
+
StringToXmlStringEncode: (RED,node,msg,data)=> data.xmlStringEncode(),
|
|
397
438
|
pathToBasename: (RED,node,msg,data)=>path.basename(data),
|
|
398
439
|
pathToDirname: (RED,node,msg,data)=>path.dirname(data),
|
|
399
440
|
pathToExtname: (RED,node,msg,data)=>path.extname(data),
|
|
@@ -443,7 +484,7 @@ function evalFunction(id,mapping){
|
|
|
443
484
|
throw Error(id+" "+ex.message);
|
|
444
485
|
}
|
|
445
486
|
}
|
|
446
|
-
|
|
487
|
+
const is=(node,value)=>{
|
|
447
488
|
return node.actionSource==value||node.actionTarget==value;
|
|
448
489
|
}
|
|
449
490
|
let jsonata;
|
|
@@ -454,7 +495,7 @@ function JSONataTransform(data,ok,error){
|
|
|
454
495
|
})()
|
|
455
496
|
*/
|
|
456
497
|
|
|
457
|
-
this.
|
|
498
|
+
this.transformFunctionCompiled.evalFunction(data,{},(error, result) => {
|
|
458
499
|
if(error) {
|
|
459
500
|
console.error(error);
|
|
460
501
|
return;
|
|
@@ -489,32 +530,42 @@ module.exports = function (RED) {
|
|
|
489
530
|
}
|
|
490
531
|
if(logger.active) logger.send({label:"load xml",xmlParserKeys:Object.keys(xmlParser),json2xmlParser:Object.keys(json2xmlParser)});
|
|
491
532
|
}
|
|
533
|
+
if(['Append','Concat','EndsWith','Prepend','Split','StartsWith'].includes(node.actionTarget)) {
|
|
534
|
+
typedInput.setGetFunction(RED,node,"string")
|
|
535
|
+
}
|
|
492
536
|
node.sendInFunction=["snappy","Compressed"].includes(node.actionSource)||["Messages","Compressed"].includes(node.actionTarget);
|
|
493
537
|
node.hasNewTopic=![null,""].includes(node.topicProperty);
|
|
494
|
-
const
|
|
495
|
-
|
|
496
|
-
|
|
538
|
+
const source=(node.sourceProperty||"msg.payload")
|
|
539
|
+
const target=(node.targetProperty||"msg.payload")
|
|
540
|
+
const sourceMap="(RED,node,msg)=>"+source,
|
|
541
|
+
deleteSource=typedInput.getValue(RED,node,"deleteSource",true)
|
|
542
|
+
targetMap="(RED,node,msg,data,index)=>{"+target+"=data;"+
|
|
497
543
|
(node.sendInFunction && node.hasNewTopic? "msg.topic=node.topicFunction(RED,node,msg,data,index);":"")+
|
|
544
|
+
(deleteSource&&source!==target?"delete "+source+";"+"delete "+source+";":"")+
|
|
498
545
|
(node.sendInFunction ? "" : "node.send(msg);" )+
|
|
499
546
|
"}",
|
|
500
547
|
topicMap="(RED,node,msg,data,index)=>"+(node.topicProperty||"msg.topic");
|
|
501
|
-
logger.sendInfo({label:"mappings",source:sourceMap,target:targetMap,topicMap:topicMap});
|
|
548
|
+
logger.sendInfo({label:"mappings",source:sourceMap,deleteSource:deleteSource,target:targetMap,topicMap:topicMap});
|
|
502
549
|
node.getData=evalFunction("source",sourceMap);
|
|
503
|
-
node.deleteSourceProperty=evalFunction("source delete",sourceDelete);
|
|
504
550
|
node.setData=evalFunction("target",targetMap);
|
|
505
551
|
node.topicFunction=evalFunction("topic",topicMap);
|
|
506
552
|
if(is(node,"AVRO")) {
|
|
507
553
|
node.avroTransformer=avsc.Type.forSchema(node.schemaValid);
|
|
508
|
-
} else
|
|
554
|
+
} else if(is(node,"Compressed")) {
|
|
555
|
+
const CompressionTool = require('compressiontool')
|
|
509
556
|
compressor=new CompressionTool();
|
|
510
557
|
compressor[node.compressionType]();
|
|
511
|
-
} else
|
|
558
|
+
} else if(is(node,"Confluence")) {
|
|
512
559
|
node.schemas={};
|
|
513
560
|
for(const schema in node.schemaValid )
|
|
514
561
|
node.schemas[schema]=avsc.Type.forSchema(node.schemaValid[schema]);
|
|
515
562
|
logger.info({label:"confluence",schemas:Object.keys(node.schemas)});
|
|
563
|
+
} else if(node.actionSource=="Date") {
|
|
564
|
+
if(node.maxDate) node.maxDateTyped=toDateTypeZulu(node.maxDate)
|
|
565
|
+
if(node.minDate) node.minDateTyped=toDateTypeZulu(node.minDate)
|
|
516
566
|
}
|
|
517
567
|
if(node.actionTarget=="Compressed"){
|
|
568
|
+
const CompressionTool = require('compressiontool')
|
|
518
569
|
compressor=new CompressionTool();
|
|
519
570
|
compressor[node.compressionType]();
|
|
520
571
|
}
|
|
@@ -523,7 +574,7 @@ module.exports = function (RED) {
|
|
|
523
574
|
error(node,ex,"Invalid setup "+ex.message);
|
|
524
575
|
return;
|
|
525
576
|
}
|
|
526
|
-
if(node
|
|
577
|
+
if(is(node,"ISO8583")) {
|
|
527
578
|
if(!ISO8583) {
|
|
528
579
|
try{
|
|
529
580
|
ISO8583=require('iso-8583');
|
|
@@ -535,10 +586,10 @@ module.exports = function (RED) {
|
|
|
535
586
|
}
|
|
536
587
|
}
|
|
537
588
|
}
|
|
538
|
-
if(node.
|
|
589
|
+
if(node.transformFunction && is(node,"JSON")) {
|
|
539
590
|
try{
|
|
540
591
|
if(!jsonata) jsonata=require('jsonata')
|
|
541
|
-
node.
|
|
592
|
+
node.transformFunctionCompiled = jsonata(node.transformFunction);
|
|
542
593
|
} catch (ex) {
|
|
543
594
|
error(node,ex,"Transform function error");
|
|
544
595
|
return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const square=[[0,0],[1,0],[1,1],[0,1]]
|
package/visual/visual.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const logger = new (require("node-red-contrib-logger"))("visual");
|
|
2
|
+
logger.sendInfo("Copyright 2025 Jaroslav Peter Prib");
|
|
3
|
+
const levenshteinDistance = require("./levenshteinDistance");
|
|
4
|
+
function error(node,message,shortMessage){
|
|
5
|
+
if(logger.active) logger.send({label:"error",node:node.id,error:error,shortMessage});
|
|
6
|
+
node.error(message);
|
|
7
|
+
node.status({fill:"red",shape:"ring",text:shortMessage});
|
|
8
|
+
}
|
|
9
|
+
function evalFunction(id,mapping){
|
|
10
|
+
try{
|
|
11
|
+
return eval(mapping);
|
|
12
|
+
} catch(ex) {
|
|
13
|
+
throw Error(id+" "+ex.message);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
module.exports = function (RED) {
|
|
17
|
+
function loggerNode (n) {
|
|
18
|
+
RED.nodes.createNode(this, n);
|
|
19
|
+
const node = Object.assign(this, n);
|
|
20
|
+
|
|
21
|
+
const source1Map="(RED,node,msg)=>"+(node.source1Property||"msg.payload"),
|
|
22
|
+
source2Map="(RED,node,msg)=>"+(node.source2Property||"msg.payload"),
|
|
23
|
+
targetMap="(RED,node,msg,data)=>{"+(node.targetProperty||"msg.payload")+"=data;}";
|
|
24
|
+
logger.sendInfo({label:"mappings",source1:source1Map,source2:source2Map,target:targetMap});
|
|
25
|
+
try{
|
|
26
|
+
node.getData1=evalFunction("source1",source1Map);
|
|
27
|
+
node.getData2=evalFunction("source2",source2Map);
|
|
28
|
+
node.setData=evalFunction("target",targetMap);
|
|
29
|
+
} catch(ex) {
|
|
30
|
+
error(node,ex,"Invalid setup "+ex.message);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
node.on('input', function (msg) {
|
|
34
|
+
try{
|
|
35
|
+
node.setData(RED,node,msg,levenshteinDistance(node.getData1(RED,node,msg),node.getData2(RED,node,msg)));
|
|
36
|
+
node.send(msg);
|
|
37
|
+
} catch(ex) {
|
|
38
|
+
msg.error=ex.message;
|
|
39
|
+
error(node,ex,"Error(s), check log");
|
|
40
|
+
node.send([null,msg]);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
RED.nodes.registerType(logger.label, loggerNode);
|
|
45
|
+
};
|