node-red-contrib-prib-functions 0.23.2 → 0.26.0

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.
Files changed (58) hide show
  1. package/.github/copilot-instructions.md +36 -0
  2. package/README.md +153 -140
  3. package/columnar/columnar.html +258 -0
  4. package/columnar/columnar.js +1055 -0
  5. package/columnar/icons/columnar.svg +38 -0
  6. package/fileSystem/filesystem.html +299 -0
  7. package/fileSystem/filesystem.js +170 -0
  8. package/gitlab/gitlab.html +191 -0
  9. package/gitlab/gitlab.js +248 -0
  10. package/gitlab/icons/gitlab.svg +17 -0
  11. package/lib/AlphaBeta.js +32 -0
  12. package/lib/GraphDB.js +40 -9
  13. package/lib/MinMax.js +17 -0
  14. package/lib/Tree.js +64 -0
  15. package/lib/objectExtensions.js +28 -5
  16. package/lib/timeDimension.js +36 -0
  17. package/lib/typedInput.js +18 -2
  18. package/logisticRegression/icons/logisticregression.svg +22 -0
  19. package/logisticRegression/logisticRegression.html +136 -0
  20. package/logisticRegression/logisticRegression.js +83 -0
  21. package/package.json +21 -9
  22. package/test/02-graphdb.js +46 -0
  23. package/test/columnar.js +509 -0
  24. package/test/data/.config.nodes.json +114 -70
  25. package/test/data/.config.nodes.json.backup +104 -71
  26. package/test/data/.config.runtime.json +2 -1
  27. package/test/data/.config.runtime.json.backup +2 -1
  28. package/test/data/.config.users.json +3 -2
  29. package/test/data/.config.users.json.backup +3 -2
  30. package/test/data/.flow.json.backup +1545 -369
  31. package/test/data/flow.json +1457 -270
  32. package/test/data/package-lock.json +11 -11
  33. package/test/data/shares/.config.nodes.json +611 -0
  34. package/test/data/shares/.config.nodes.json.backup +589 -0
  35. package/test/data/shares/.config.runtime.json +5 -0
  36. package/test/data/shares/.config.runtime.json.backup +4 -0
  37. package/test/data/shares/.config.users.json +33 -0
  38. package/test/data/shares/.config.users.json.backup +33 -0
  39. package/test/data/shares/.flow.json.backup +230 -0
  40. package/test/data/shares/.flow_cred.json.backup +3 -0
  41. package/test/data/shares/flow.json +267 -0
  42. package/test/data/shares/flow_cred.json +3 -0
  43. package/test/data/shares/package.json +6 -0
  44. package/test/data/shares/settings.js +544 -0
  45. package/test/dataAnalysisExtensions.js +93 -93
  46. package/test/logisticRegression.js +379 -0
  47. package/test/transform.js +11 -11
  48. package/test/transformConfluence.js +4 -2
  49. package/test/transformNumPy.js +3 -1
  50. package/test/transformXLSX.js +4 -2
  51. package/test/transformXML.js +4 -2
  52. package/test-runner.js +400 -0
  53. package/test.parq +0 -0
  54. package/test_select.js +37 -0
  55. package/testing/test.js +8 -7
  56. package/transform/transform.html +23 -2
  57. package/transform/transform.js +239 -283
  58. package/transform/xlsx2.js +74 -0
@@ -0,0 +1,38 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <defs>
3
+ <linearGradient id="columnarGradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#8BC34A;stop-opacity:1" />
5
+ <stop offset="100%" style="stop-color:#4CAF50;stop-opacity:1" />
6
+ </linearGradient>
7
+ </defs>
8
+
9
+ <!-- Database/storage base -->
10
+ <rect x="2" y="20" width="28" height="8" rx="2" fill="url(#columnarGradient)" opacity="0.8"/>
11
+
12
+ <!-- Column bars representing columnar storage -->
13
+ <rect x="4" y="8" width="3" height="12" fill="url(#columnarGradient)"/>
14
+ <rect x="9" y="6" width="3" height="14" fill="url(#columnarGradient)"/>
15
+ <rect x="14" y="10" width="3" height="10" fill="url(#columnarGradient)"/>
16
+ <rect x="19" y="4" width="3" height="16" fill="url(#columnarGradient)"/>
17
+ <rect x="24" y="12" width="3" height="8" fill="url(#columnarGradient)"/>
18
+
19
+ <!-- Data points on columns -->
20
+ <circle cx="5.5" cy="10" r="1" fill="#FFFFFF"/>
21
+ <circle cx="5.5" cy="14" r="1" fill="#FFFFFF"/>
22
+ <circle cx="5.5" cy="18" r="1" fill="#FFFFFF"/>
23
+
24
+ <circle cx="10.5" cy="8" r="1" fill="#FFFFFF"/>
25
+ <circle cx="10.5" cy="12" r="1" fill="#FFFFFF"/>
26
+ <circle cx="10.5" cy="16" r="1" fill="#FFFFFF"/>
27
+
28
+ <circle cx="15.5" cy="12" r="1" fill="#FFFFFF"/>
29
+ <circle cx="15.5" cy="16" r="1" fill="#FFFFFF"/>
30
+
31
+ <circle cx="20.5" cy="6" r="1" fill="#FFFFFF"/>
32
+ <circle cx="20.5" cy="10" r="1" fill="#FFFFFF"/>
33
+ <circle cx="20.5" cy="14" r="1" fill="#FFFFFF"/>
34
+ <circle cx="20.5" cy="18" r="1" fill="#FFFFFF"/>
35
+
36
+ <circle cx="25.5" cy="14" r="1" fill="#FFFFFF"/>
37
+ <circle cx="25.5" cy="18" r="1" fill="#FFFFFF"/>
38
+ </svg>
@@ -0,0 +1,299 @@
1
+ <script type="text/javascript">
2
+ /*globals RED */
3
+ RED.nodes.registerType('filesystem', {
4
+ category: 'storage',
5
+ color: '#fdeea2',
6
+ defaults: {
7
+ name: {value: ""},
8
+ action: {value:"read",required:true}
9
+ },
10
+ inputs: 1,
11
+ outputs: 2,
12
+ icon: "icons8-one-way-transition-80.png",
13
+ align: 'left',
14
+ paletteLabel: "filesystem",
15
+ inputLabels: "Message In",
16
+ outputLabels: ["Message Out","Error"],
17
+ label: function () {
18
+ return this.name ?? this.action
19
+ },
20
+ actionArgs:{
21
+ "access":["path","mode"],
22
+ "appendFile":["path","data","options"],
23
+ "chmod":["path","mode"],
24
+ "chown":["path","uid","gid"],
25
+ "close":["fd"],
26
+ "copyFile":["src","dest","mode"],
27
+ "cp":["src","dest","options"],
28
+ "createReadStream":["path","options"],
29
+ "createWriteStream":["path","options"],
30
+ "fchmod":["fd","mode"],
31
+ "fchown":["fd","uid","gid"],
32
+ "fdatasync":["fd"],
33
+ "fstat":["fd","options"],
34
+ "fsync":["fd"],
35
+ "ftruncate":["fd","len"],
36
+ "futimes":["fd","atime","mtime"],
37
+ "glob":["pattern","options"],
38
+ "lchmod":["path","mode"],
39
+ "lchown":["path","uid","gid"],
40
+ "lutimes":["path","atime","mtime"],
41
+ "link":["existingPath","newPath"],
42
+ "lstat":["path","options"],
43
+ "mkdir":["path","options"],
44
+ "mkdtemp":["prefix","options"],
45
+ "open":["path","flags","mode"],
46
+ "openAsBlob":["path","options"],
47
+ "opendir":["path","options"],
48
+ "read":["fd","buffer","offset","length","position"],
49
+ "read":["fd","options"],
50
+ "read":["fd","buffer","options"],
51
+ "readdir":["path","options"],
52
+ "readFile":["path","options"],
53
+ "readlink":["path","options"],
54
+ "readv":["fd","buffers","position"],
55
+ "realpath":["path","options"],
56
+ "realpath.native":["path","options"],
57
+ "rename":["oldPath","newPath"],
58
+ "rmdir":["path","options"],
59
+ "rm":["path","options"],
60
+ "stat":["path","options"],
61
+ "statfs":["path","options"],
62
+ "symlink":["target","path","type"],
63
+ "truncate":["path","length"],
64
+ "unlink":["path"],
65
+ "unwatchFile":["filename","listener"],
66
+ "utimes":["path","atime","mtime"],
67
+ "watch":["filename","options","listener"],
68
+ "watchFile":["filename","options","listener"],
69
+ "writeDirect":["fd","buffer","offset","length","position]"],
70
+ "write":["fd","buffer","options"],
71
+ "writeString":["fd","string","position","encoding"],
72
+ "writeFile":["file","data","options"],
73
+ "writev":["fd","buffers","position"]
74
+ },
75
+ argTypes:{
76
+ "atime":{_types:["num","msg"],label:null},
77
+ "buffer":{_types:["msg"],label:null,default:"payload.buffer"},
78
+ "buffers":{_types:['msg'],label:null},
79
+ "encoding":{_types:["str","msg"],label:null},
80
+ "fd":{_types:["msg"],label:null,default:"payload.fd"},
81
+ "flags":{
82
+ typedInput:{
83
+ type:"flags",
84
+ types:[{
85
+ value: "flags",
86
+ multiple: false,
87
+ options: [
88
+ {value: "a", label: "Open for appending, created if missing"},
89
+ {value: "ax", label: "Open for appending"},
90
+ {value: "a+", label: "Open for reading + appending, created if missing"},
91
+ {value: "ax+", label: "Open for reading + appending"},
92
+ {value: "as", label: "Open for synchronous appending, file created if missing"},
93
+ {value: "as+", label: "Open for synchronous reading and appending,created if missing"},
94
+ {value: "r", label: "Open for reading"},
95
+ {value: "rs", label: "Open for synchronous reading"},
96
+ {value: "r+", label: "Open for synchronous reading and writing"},
97
+ {value: "rs+", label: "Open for synchronous reading and writing, bypass system caching"},
98
+ {value: "w", label: "Open for synchronous writing, created if missing or truncated"},
99
+ {value: "wx", label: "Open for synchronous writing, truncated"},
100
+ {value: "w+", label: "Open reading and writing, created if missing or truncated"},
101
+ {value: "wx+", label: "Open reading and writing"}
102
+ ]
103
+ }]
104
+ }
105
+ },
106
+ "uid":{_types:["num","msg"],label:null},
107
+ "gid":{_types:["num","msg"],label:null},
108
+ "length":{_types:["msg","num"],label:null,default:"payload.length"},
109
+ "listener":{_types:["msg"],label:null},
110
+ "mode":{
111
+ label:null,
112
+ typedInput:{
113
+ type:"modes",
114
+ types:[{
115
+ value: "modes",
116
+ multiple: false,
117
+ options: [
118
+ {value: "F_OK", label: "Visible"},
119
+ {value: "R_OK", label: "Read"},
120
+ {value: "W_OK", label: "Write"},
121
+ {value: "X_OK", label: "Execute"},
122
+ ]
123
+ }]
124
+ }
125
+ },
126
+ "mode-file":{
127
+ label:null,
128
+ typedInput:{
129
+ type:"modes",
130
+ types:[{
131
+ value: "modes",
132
+ multiple: false,
133
+ options: [
134
+ {value: "S_IRUSR", label: "read by owner"},
135
+ {value: "S_IWUSR", label: "write by owner"},
136
+ {value: "S_IXUSR", label: "execute/search by owner"},
137
+ {value: "S_IRGRP", label: "read by group"},
138
+ {value: "S_IWGRP", label: "write by group"},
139
+ {value: "S_IXGRP", label: "execute/search by group"},
140
+ {value: "S_IROTH", label: "read by others"},
141
+ {value: "S_IWOTH", label: "write by others"},
142
+ {value: "S_IXOTH", label: "execute/search by others"},
143
+ ]
144
+ }]
145
+ }
146
+ },
147
+ "mtime":{_types:["num","msg"],label:null},
148
+ "newPath":{_types:["str","msg"],label:null},
149
+ "options":{
150
+ appendFile:{
151
+ encoding: {types:['str'],label:null}, //<string> | <null> Default: 'utf8'
152
+ mode: {types:['str'],label:null}, // <integer> Default: 0o666
153
+ flag:"$flag", // <string> See support of file system flags. Default: 'a'.
154
+ flush:{types:['boolean']}
155
+ }
156
+ },
157
+ "path":{_types:['msg','str','flow','global','jsonata','env'],label:null,default:"payload.path"},
158
+ "pattern":{_types:["str","msg"],label:null},
159
+ "offset":{_types:["msg","num"],label:null,default:"payload.offset"},
160
+ "position":{_types:["msg","num"],label:null,default:"payload.position"},
161
+ "prefix":{_types:["str","msg"],label:null},
162
+ "string":{_types:["str","msg"],label:null},
163
+ "type":{_types:["str","msg"],label:null},
164
+ "dest":{_types:['str','msg','flow','global','jsonata','env'],label:"destination"},
165
+ "existingPath":{_types:['str','msg','flow','global','jsonata','env'],label:"existing path"},
166
+ "filename":{_types:['str','msg','flow','global','jsonata','env'],label:"file name"},
167
+ "oldPath":{_types:['str','msg','flow','global','jsonata','env'],label:"old path"},
168
+ "src":{_types:['str','msg','flow','global','jsonata','env'],label:"source"},
169
+ "target":{_types:['msg'],label:"Target",default:"payload.result"}
170
+ },
171
+ addInput: function (baseElement, property, label = property) {
172
+ // console.log("adding field "+property)
173
+ const div=$('<div>', {id:'form-row-http-in-'+property, class: "form-row" })
174
+ const input=$('<input>', { type: 'text', id: 'node-input-' + property, style: "width:70%" })
175
+ const inputType=$('<input>', { type: 'hidden', id: 'node-input-' + property + 'Type' })
176
+ div.append(
177
+ $('<label>', {for:"node-input-" + property}).append(
178
+ $('<i>', {class:"fa fa-bookmark"}),
179
+ $('<span>').attr("data-i18n", "common.label.string").text(" "+(label??property))
180
+ ),
181
+ input,
182
+ inputType
183
+ )
184
+ baseElement.append(div)
185
+ const argType=this.argTypes[property]
186
+ argType.input=input
187
+ argType.inputType=inputType
188
+ if(argType.typedInput)
189
+ return input.typedInput(argType.typedInput)
190
+ const types=argType.types
191
+ input.typedInput({
192
+ default: types[0],
193
+ typeField: inputType,
194
+ types:types,
195
+ validate: ()=>{
196
+ }
197
+ })
198
+ },
199
+ setProperty:function(property,value){
200
+ try{
201
+ // console.log("set "+property)
202
+ if(property.hasOwnProperty("_types")){
203
+ $("#form-row-http-in-"+property).show()
204
+ const argType=this.argTypes[property]
205
+ argType.input.typedInput('value',value??argType.default??"")
206
+ // argType.inputType.val(_this[property+"type"])
207
+ return
208
+ }
209
+ Object.keys(value).forEach(p=>this.setProperty(p,value[p]))
210
+ } catch(ex){
211
+ console.error("setProperty error "+ex.message);
212
+ }
213
+ },
214
+ oneditprepare: function() {
215
+ const _this=this
216
+ const nodeBase=this._def
217
+ const inputBase=$("#input-base")
218
+ for(const property in nodeBase.argTypes) nodeBase.addInput(inputBase,property,nodeBase.argTypes[property].label)
219
+ const action=this.action
220
+ const actions=Object.keys(nodeBase.actionArgs).map(property=>({value:property,label:property}))
221
+ $("#node-input-action").typedInput({type:"action", types:[{
222
+ value: "action",
223
+ options: actions
224
+ }]});
225
+
226
+ $("#node-input-action").change(function() {
227
+ const action=$(this).val();
228
+ Object.keys(nodeBase.argTypes).forEach(property=>{
229
+ try{
230
+ $("#form-row-http-in-"+property).hide()
231
+ } catch(ex){
232
+ console.error("hide in row error "+ex.message);
233
+ }
234
+ })
235
+ nodeBase.actionArgs[action].forEach(property=>nodeBase.setProperty(property,_this[property]))
236
+ if(["open","createWriteStream","exists","fstat","fsync","lstat","mkdir","mkdtemp","open",
237
+ "openAsBlob","opendir","read","readdir","readFile","readlink","readv","realpath","stat","statfs",
238
+ "watch","watchFile","write","writev","existsSync","globSync","lstatSync","mkdirSync","mkdtempSync",
239
+ "mkdtempDisposableSync","opendirSync","openSync","readdirSync","readFileSync","readlinkSync",
240
+ "readSync","readSync"
241
+ ].includes(action)
242
+ )
243
+ nodeBase.setProperty("target",_this.target)
244
+ }).change();
245
+ },
246
+ oneditsave: function() {
247
+ const _this=this
248
+ const nodeBase=this._def
249
+ nodeBase.actionArgs[this.action].forEach(property=>{
250
+ const argType=nodeBase.argTypes[property]
251
+ if(argType.hasOwnProperty("_types")){
252
+ _this[property]=argType.input.typedInput('value');
253
+ _this[property+"type"]=argType.input.typedInput('type')
254
+ return
255
+ }
256
+ for (const p in argType) {
257
+ _this[p]=argType[p].input.typedInput('value')
258
+ _this[p+"type"]=argType[p].input.typedInput('type')
259
+ }
260
+ })
261
+ },
262
+ resizeRule : function(file,newWidth) {
263
+ }
264
+ });
265
+ </script>
266
+
267
+ <script type="text/x-red" data-template-name="filesystem">
268
+ <div class="form-row">
269
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name </label>
270
+ <input type="text" id="node-input-name" placeholder="Name">
271
+ </div>
272
+ <div class="form-row">
273
+ <label for="node-input-action"><i class="fa fa-tag"></i> Action </label>
274
+ <input type="select" id="node-input-action" placeholder="Action">
275
+ </div>
276
+ <div id="input-base">
277
+ </div>
278
+
279
+ </script>
280
+
281
+ <script type="text/x-red" data-help-name="filesystem">
282
+ <p>filesystem</p>
283
+ <p>
284
+ </p>
285
+ <h3>Inputs</h3>
286
+ <dl class="message-properties">
287
+ <dt>msg <span class="property-type">topic</span></dt>
288
+ <dd>incoming message with topic</dd>
289
+ <dt>msg <span class="property-type">payload</span></dt>
290
+ <dd></dd>
291
+ </dl>
292
+ <h3>Ports</h3>
293
+ <dl class="message-properties">
294
+ <dt><span class="property-type">message out</span></dt>
295
+ <dd>Inbound message with </dd>
296
+ <dt><span class="property-type">error</span></dt>
297
+ <dd>a message where msg.error details error</dd>
298
+ </dl>
299
+ </script>
@@ -0,0 +1,170 @@
1
+ const logger = new (require("node-red-contrib-logger"))("filesystem");
2
+ logger.sendInfo("Copyright 2025 Jaroslav Peter Prib");
3
+
4
+ const fs=require('fs')
5
+ const typedInput=require('../lib/typedInput')
6
+
7
+ const actionReturnsValue=["createReadStream","exists","fstat","lstat","mkdir","mkdtemp","open","opendir"]
8
+
9
+ const mode={
10
+ access:{
11
+ "exists":fs.constants.F_OK,
12
+ "readable":fs.constants.R_OK,
13
+ "writable":fs.constants.W_OK,
14
+ "executable":fs.constants.X_OK
15
+ }
16
+ }
17
+
18
+ const OpenErrors={
19
+ "EEXIST":"File already exists",
20
+ "ENOENT":"File does not exist"
21
+ }
22
+ const setAndSend=(msg,value)=>{
23
+ const node=msg._temp.node
24
+ node.setTarget(msg,value)
25
+ delete node._temp
26
+ node.send(msg)
27
+ }
28
+ const setAndSendError=(msg,value)=>{
29
+ const node=msg._temp.node
30
+ node.setTarget(msg,value)
31
+ delete node._temp
32
+ node.send([null,msg])
33
+ }
34
+
35
+ const callbacks={
36
+ default:err=>setAndSendError(this, err==null),
37
+ open:(err,fd)=>{
38
+ if(err){
39
+ try{
40
+ setAndSendError(this,openErrors[err])
41
+ } catch(ex){
42
+ setAndSendError(this,err)
43
+ }
44
+ } else
45
+ setAndSend(this,fd)
46
+ },
47
+ read:(err,data)=>{
48
+ }
49
+ }
50
+ callbacks.stat=callbacks.read
51
+ callbacks.access=callbacks.default
52
+ callbacks.appendFile=callbacks.default
53
+ callbacks.chmod=callbacks.default
54
+ callbacks.chown=callbacks.default
55
+ callbacks.close=callbacks.default
56
+ callbacks.copyFile=callbacks.default
57
+ callbacks.cp=callbacks.default
58
+
59
+ const fsArgs={
60
+ "access":["path","mode","callback"],
61
+ "appendFile":["path","data","options","callback"],
62
+ "chmod":["path","mode","callback"],
63
+ "chown":["path","uid","gid","callback"],
64
+ "close":["fd","callback"],
65
+ "copyFile":["src","dest","mode","callback"],
66
+ "cp":["src","dest","options","callback"],
67
+ "createReadStream":["path","options"],
68
+ "createWriteStream":["path","options"],
69
+ "exists":["path","callback"],
70
+ "fchmod":["fd","mode","callback"],
71
+ "fchown":["fd","uid","gid","callback"],
72
+ "fdatasync":["fd","callback"],
73
+ "fstat":["fd","options","callback"],
74
+ "fsync":["fd","callback"],
75
+ "ftruncate":["fd","len","callback"],
76
+ "futimes":["fd","atime","mtime","callback"],
77
+ "glob":["pattern","options","callback"],
78
+ "lchmod":["path","mode","callback"],
79
+ "lchown":["path","uid","gid","callback"],
80
+ "lutimes":["path","atime","mtime","callback"],
81
+ "link":["existingPath","newPath","callback"],
82
+ "lstat":["path","options","callback"],
83
+ "mkdir":["path","options","callback"],
84
+ "mkdtemp":["prefix","options","callback"],
85
+ "open":["path","flags","mode]","callback"],
86
+ "openAsBlob":["path","options"],
87
+ "opendir":["path","options","callback"],
88
+ "read":["fd","buffer","offset","length","position","callback"],
89
+ "read":["fd","options","callback"],
90
+ "read":["fd","buffer","options","callback"],
91
+ "readdir":["path","options","callback"],
92
+ "readFile":["path","options","callback"],
93
+ "readlink":["path","options","callback"],
94
+ "readv":["fd","buffers","position","callback"],
95
+ "realpath":["path","options","callback"],
96
+ "realpath.native":["path","options","callback"],
97
+ "rename":["oldPath","newPath","callback"],
98
+ "rmdir":["path","options","callback"],
99
+ "rm":["path","options","callback"],
100
+ "stat":["path","options","callback"],
101
+ "statfs":["path","options","callback"],
102
+ "symlink":["target","path","type","callback"],
103
+ "truncate":["path","length","callback"],
104
+ "unlink":["path","callback"],
105
+ "unwatchFile":["filename","listener"],
106
+ "utimes":["path","atime","mtime","callback"],
107
+ "watch":["filename","options","listener"],
108
+ "watchFile":["filename","options","listener"],
109
+ "writeDirect":["fd","buffer","offset","length","position]","callback"],
110
+ "write":["fd","buffer","options","callback"],
111
+ "writeString":["fd","string","position","encoding","callback"],
112
+ "writeFile":["file","data","options","callback"],
113
+ "writev":["fd","buffers","position","callback"]
114
+ }
115
+ /*
116
+ const options={
117
+ append [encoding <string> | <null> Default: 'utf8'
118
+ mode <integer> Default: 0o666
119
+ flag <string> See support of file system flags. Default: 'a'.
120
+ flush <boolean> If true, the underlying file descriptor is flushed prior to closing it. Default: false.
121
+ }
122
+ */
123
+ module.exports = function (RED) {
124
+ function filesystemNode(config) {
125
+ RED.nodes.createNode(this, config);
126
+ const node=Object.assign(this,config)
127
+ try{
128
+ node.actionFunction=fs[node.action]
129
+ node.argList=fsArgs[node.action]
130
+ const argFunctions=getArgFunctions(RED,node,node.argList)
131
+ if(node.argList.includes("callback")){
132
+ node.callback=callbacks[node.action]
133
+ } else {
134
+ node.processFunction=(RED,msg,node)=>{
135
+ node.actionFunction()
136
+ node.send(msg)
137
+ }
138
+ }
139
+ setCallback(node)
140
+ node.status({fill:"green",shape:"ring"})
141
+ if(node.action=="open"){
142
+ this.openedFiles=[]
143
+ node.close = function (removed, done) {
144
+ logger.send({ label: 'close',node:{id:node.id,name:node.name}})
145
+ this.openedFiles.forEach(opened=>{
146
+ try {
147
+ close(open.fdfd,err=>{
148
+ logger({label:"closed",msg:opened_msgid})
149
+ })
150
+ } catch (ex) {
151
+ logger.sendErrorAndStackDump(ex.message, ex)
152
+ }
153
+ })
154
+ done()
155
+ }
156
+ }
157
+ node.on("input", function(msg) {
158
+ try{
159
+ msg._temp={node:node,RED:RED}
160
+ node.processFunction.call(typedInput.getArgsFromFunctions(RED,node,msg,argFunctions))
161
+ } catch(ex) {
162
+ logger.sendErrorAndStackDump(ex.message, ex)
163
+ }
164
+ })
165
+ } catch (ex){
166
+ node.status({fill:"red",shape:"ring"});
167
+ }
168
+ }
169
+ RED.nodes.registerType(logger.label,filesystemNode);
170
+ }