node-red-contrib-teamogy-api 0.0.2 → 0.0.3
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 +10 -2
- package/package.json +5 -4
- package/teamogy-client.html +72 -14
- package/teamogy-client.js +130 -40
package/README.md
CHANGED
|
@@ -31,8 +31,15 @@ You must configure a Connection before using this node.
|
|
|
31
31
|
| Limit | number | Optional | Limitation of the total number of records in the response (if not specified, the value 0 is used, the value 0 means no limit) |
|
|
32
32
|
| Paging | number | Optional | Division of responses into multiple parts with the number of records returned (if not specified, the value 1000 is used) |
|
|
33
33
|
| Offset | number | Optional | Determining from which records to return, e.g. if you have a total of 100 records and want to return records 50-100, set Offset to 50, if you want to return all records leave the option at 0 (if not specified, the value 0 is used) |
|
|
34
|
+
| Delay | number | Optional | Specifies the delay between requests, which is used for pagination (if not specified, the value 0 is used) |
|
|
35
|
+
| Req. repeat | number | Optional | Specifies the number of errors after which the request will be repeated (if not specified, the value 5 is used) |
|
|
36
|
+
| Req. delay (s) | number | Optional | Specifies the delay between requests, which is used when retrying a request in case of an error (if not specified, the value 30 is used) |
|
|
34
37
|
| Skip | boolean | Optional, in message only | Adding the msg.skip=true will allow the message to pass through to the output without processing |
|
|
35
|
-
|
|
38
|
+
| Connection | string | Optional, in message only | Replaces connection from configuration, use connection name |
|
|
39
|
+
| Unit | number | Optional, in message only | Replaces unit from connection configuration, use unit/agency id |
|
|
40
|
+
| Entity | string | Optional, in message only | Replaces entity from configuration, use v_entityName for views or r_entityName |
|
|
41
|
+
| Method | string | Optional, in message only | Replaces method from configuration, use the available method for the given entity |
|
|
42
|
+
|
|
36
43
|
## Examples
|
|
37
44
|
|
|
38
45
|
### Static Request Examples
|
|
@@ -89,8 +96,9 @@ msg.body.address = addresses // array of objects
|
|
|
89
96
|
|
|
90
97
|
| Property | Type | Description |
|
|
91
98
|
|----------|------|-------------|
|
|
92
|
-
| payload | string \| object | The standard output
|
|
99
|
+
| payload | string \| object | The standard output of the response |
|
|
93
100
|
| count | number | Number of records in the output |
|
|
101
|
+
| error | string | Error message |
|
|
94
102
|
| msg.* | string \| object | All properties of the input message |
|
|
95
103
|
|
|
96
104
|
## References
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-teamogy-api",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
7
|
},
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=18.0.0"
|
|
10
|
+
},
|
|
8
11
|
"keywords": [
|
|
9
12
|
"node-red",
|
|
10
13
|
"teamogy",
|
|
@@ -17,11 +20,9 @@
|
|
|
17
20
|
"author": "",
|
|
18
21
|
"license": "",
|
|
19
22
|
"node-red": {
|
|
23
|
+
"version": ">=4.0.0",
|
|
20
24
|
"nodes": {
|
|
21
25
|
"teamogy-client": "teamogy-client.js"
|
|
22
26
|
}
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"node-fetch": "^3.3.2"
|
|
26
27
|
}
|
|
27
28
|
}
|
package/teamogy-client.html
CHANGED
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
|
|
74
74
|
<div class="form-row">
|
|
75
75
|
<label for="node-config-input-unit"><i class="fa fa-square-o"></i> <span>Unit/Agency</span></label>
|
|
76
|
-
<input type="number" id="node-config-input-unit" min="
|
|
76
|
+
<input type="number" id="node-config-input-unit" min="0" max="100" step="1" placeholder="1" style="width: 20%">
|
|
77
77
|
</div>
|
|
78
78
|
|
|
79
79
|
<div class="form-row">
|
|
@@ -167,7 +167,7 @@ RED.nodes.registerType('teamogy-config', {
|
|
|
167
167
|
|
|
168
168
|
$('#node-config-input-unit').on('change', function() {
|
|
169
169
|
if(!$.isNumeric($(this).val())) { $(this).val(1) } else {
|
|
170
|
-
if($(this).val() <
|
|
170
|
+
if($(this).val() < 0 || $(this).val() > 100 ) { $(this).val(1) }
|
|
171
171
|
}
|
|
172
172
|
})
|
|
173
173
|
|
|
@@ -220,7 +220,7 @@ RED.nodes.registerType('teamogy-config', {
|
|
|
220
220
|
</div>
|
|
221
221
|
|
|
222
222
|
<div class="form-row">
|
|
223
|
-
<label for="node-input-mode" style="width: 130px"><i class="fa fa-
|
|
223
|
+
<label for="node-input-mode" style="width: 130px"><i class="fa fa-refresh"></i> <span>Request views</span></label>
|
|
224
224
|
<input type="checkbox" id="node-input-mode" style=" width:20px;">
|
|
225
225
|
</div>
|
|
226
226
|
|
|
@@ -260,8 +260,9 @@ RED.nodes.registerType('teamogy-config', {
|
|
|
260
260
|
</div>
|
|
261
261
|
|
|
262
262
|
<div class="form-row" id="node-row-response-option">
|
|
263
|
-
<label style="width: 130px"><span>Response option</span></label>
|
|
264
263
|
<div style="margin-bottom: 10px;"></div>
|
|
264
|
+
<label style="width: 130px"></i><span>View option</span></label>
|
|
265
|
+
<div style="margin-bottom: 5px;"></div>
|
|
265
266
|
<div class="form-row">
|
|
266
267
|
<label for="node-input-merge" style="width: 130px"><i class="fa fa-compress"></i> <span> Merge</span></label>
|
|
267
268
|
<input type="checkbox" id="node-input-merge" style=" width:20px;">
|
|
@@ -278,6 +279,10 @@ RED.nodes.registerType('teamogy-config', {
|
|
|
278
279
|
<label for="node-input-offset" style="width: 130px"><i class="fa fa-forward"></i><span> Offset</span></label>
|
|
279
280
|
<input type="number" id="node-input-offset" min="0" step="1" style="width:20%">
|
|
280
281
|
</div>
|
|
282
|
+
<div class="form-row">
|
|
283
|
+
<label for="node-input-delay" style="width: 130px"><i class="fa fa-clock-o"></i><span> Pag. delay (s)</span></label>
|
|
284
|
+
<input type="number" id="node-input-delay" min="0" max="600" step="1" style="width:20%">
|
|
285
|
+
</div>
|
|
281
286
|
</div>
|
|
282
287
|
|
|
283
288
|
<div class="form-row" id="node-row-editor-dynamic">
|
|
@@ -285,8 +290,23 @@ RED.nodes.registerType('teamogy-config', {
|
|
|
285
290
|
<label for="node-input-params" style="width: 130px"><i class="fa fa-code"></i> Source of body</label>
|
|
286
291
|
<input type="text" id="node-input-body-source" style="width: 65%">
|
|
287
292
|
<input type="hidden" id="node-input-body-source-type" style="width: 0px">
|
|
288
|
-
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
|
|
296
|
+
<div class="form-row" id="node-row-error-option">
|
|
297
|
+
<div style="margin-bottom: 10px;"></div>
|
|
298
|
+
<label style="width: 130px"><span>If an error occurs</span></label>
|
|
299
|
+
<div style="margin-bottom: 5px;"></div>
|
|
300
|
+
<div class="form-row">
|
|
301
|
+
<label for="node-input-repeat" style="width: 130px"><i class="fa fa-repeat"></i><span> Req. repeat</span></label>
|
|
302
|
+
<input type="number" id="node-input-repeat" min="0" max="10" step="1" style="width:20%">
|
|
303
|
+
</div>
|
|
304
|
+
<div class="form-row">
|
|
305
|
+
<label for="node-input-rdelay" style="width: 130px"><i class="fa fa-clock-o"></i><span> Req. delay (s)</span></label>
|
|
306
|
+
<input type="number" id="node-input-rdelay" min="0" max="600" step="1" style="width:20%">
|
|
307
|
+
</div>
|
|
289
308
|
</div>
|
|
309
|
+
|
|
290
310
|
</div>
|
|
291
311
|
</div>
|
|
292
312
|
</script>
|
|
@@ -338,7 +358,19 @@ RED.nodes.registerType('teamogy-client',{
|
|
|
338
358
|
offset: {
|
|
339
359
|
value: 0,
|
|
340
360
|
required: true
|
|
341
|
-
}
|
|
361
|
+
},
|
|
362
|
+
delay: {
|
|
363
|
+
value: 0,
|
|
364
|
+
required: true
|
|
365
|
+
},
|
|
366
|
+
repeat: {
|
|
367
|
+
value: 5,
|
|
368
|
+
required: true
|
|
369
|
+
},
|
|
370
|
+
rdelay: {
|
|
371
|
+
value: 30,
|
|
372
|
+
required: true
|
|
373
|
+
}
|
|
342
374
|
},
|
|
343
375
|
inputs: 1,
|
|
344
376
|
outputs:1,
|
|
@@ -367,6 +399,9 @@ RED.nodes.registerType('teamogy-client',{
|
|
|
367
399
|
$('#node-input-limit').val(this.limit);
|
|
368
400
|
$('#node-input-paging').val(this.paging);
|
|
369
401
|
$('#node-input-offset').val(this.offset);
|
|
402
|
+
$('#node-input-delay').val(this.delay);
|
|
403
|
+
$('#node-input-repeat').val(this.repeat);
|
|
404
|
+
$('#node-input-rdelay').val(this.rdelay);
|
|
370
405
|
|
|
371
406
|
$('#node-input-mode').val(this.mode);
|
|
372
407
|
$('#node-input-body-source').val(this.bodysource);
|
|
@@ -460,6 +495,17 @@ RED.nodes.registerType('teamogy-client',{
|
|
|
460
495
|
if(!$.isNumeric($(this).val())) { $(this).val(0) }
|
|
461
496
|
})
|
|
462
497
|
|
|
498
|
+
$('#node-input-delay').on('change', function() {
|
|
499
|
+
if(!$.isNumeric($(this).val())) { $(this).val(0) }
|
|
500
|
+
})
|
|
501
|
+
$('#node-input-repeat').on('change', function() {
|
|
502
|
+
if(!$.isNumeric($(this).val())) { $(this).val(5) }
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
$('#node-input-rdelay').on('change', function() {
|
|
506
|
+
if(!$.isNumeric($(this).val())) { $(this).val(30) }
|
|
507
|
+
})
|
|
508
|
+
|
|
463
509
|
this.editorp = RED.editor.createEditor({
|
|
464
510
|
id: 'node-input-params',
|
|
465
511
|
mode: 'ace/mode/text',
|
|
@@ -496,7 +542,11 @@ RED.nodes.registerType('teamogy-client',{
|
|
|
496
542
|
if(!$("#node-input-limit").val()) {this.limit = 0} else {this.limit = $("#node-input-limit").val();}
|
|
497
543
|
if(!$("#node-input-offset").val()) {this.offset = 0} else {this.offset = $("#node-input-offset").val();}
|
|
498
544
|
this.paging = $("#node-input-paging").val();
|
|
499
|
-
|
|
545
|
+
|
|
546
|
+
if(!$("#node-input-delay").val()) {this.delay = 0} else {this.delay = $("#node-input-delay").val();}
|
|
547
|
+
if(!$("#node-input-repeat").val()) {this.repeat = 0} else {this.repeat = $("#node-input-repeat").val();}
|
|
548
|
+
if(!$("#node-input-rdelay").val()) {this.rdelay = 0} else {this.rdelay = $("#node-input-rdelay").val();}
|
|
549
|
+
|
|
500
550
|
this.cparams = this.editorp.getValue();
|
|
501
551
|
this.editorp.destroy();
|
|
502
552
|
delete this.editorp;
|
|
@@ -574,17 +624,25 @@ RED.nodes.registerType('teamogy-client',{
|
|
|
574
624
|
<dd> msg.body.address = addresses // array of objects</dd>
|
|
575
625
|
<dd> </dd>
|
|
576
626
|
<dd> If you use requests for API views you can use additional options, the options can also be used in dynamic requests</dd>
|
|
577
|
-
<dt class="optional">Merge (optional)<span class="property-type">checkbox - yes/no</span></dt><dd> check if you want the output message to contain all returned records. In the background, processing is still taking place according to the Paging settings, but individual messages are not sent to the output, but only the final merged one containing all the returned records. (if not specified the value no is used)</dd>
|
|
578
|
-
<dt class="optional">Limit (optional)<span class="property-type">number</span></dt><dd> limitation of the total number of records in the response (if not specified, the value 0 is used, the value 0 means no limit)</dd>
|
|
579
|
-
<dt class="optional">Paging (optional)<span class="property-type">number</span></dt><dd> division of responses into multiple parts with the number of records returned (if not specified, the value 1000 is used)</dd>
|
|
580
|
-
<dt class="optional">Offset (optional)<span class="property-type">number</span></dt><dd>
|
|
581
|
-
<dt class="optional">
|
|
582
|
-
|
|
627
|
+
<dt class="optional">Merge (optional) (also in msg.merge (boolean))<span class="property-type">checkbox - yes/no</span></dt><dd> check if you want the output message to contain all returned records. In the background, processing is still taking place according to the Paging settings, but individual messages are not sent to the output, but only the final merged one containing all the returned records. (if not specified the value no is used)</dd>
|
|
628
|
+
<dt class="optional">Limit (optional) (also in msg.limit)<span class="property-type">number</span></dt><dd> limitation of the total number of records in the response (if not specified, the value 0 is used, the value 0 means no limit)</dd>
|
|
629
|
+
<dt class="optional">Paging (optional) (also in msg.paging)<span class="property-type">number</span></dt><dd> division of responses into multiple parts with the number of records returned (if not specified, the value 1000 is used)</dd>
|
|
630
|
+
<dt class="optional">Offset (optional) (also in msg.offset)<span class="property-type">number</span></dt><dd> specifies from which record to start returning data. For example, if you have 100 records total and want to return records 50-100, set Offset to 50. To return all records from the beginning, leave it at 0 (if not specified, the value 0 is used))</dd>
|
|
631
|
+
<dt class="optional">Delay (optional) (also in msg.delay)<span class="property-type">number</span></dt><dd> specifies the delay between requests, which is used for pagination (if not specified, the value 0 is used)</dd>
|
|
632
|
+
<dt class="optional">Req. repeat (optional) (also in msg.repeat)<span class="property-type">number</span></dt><dd> specifies the number of errors after which the request will be repeated (if not specified, the value 5 is used)</dd>
|
|
633
|
+
<dt class="optional">Req. delay (s) (optional) (also in msg.rdelay)<span class="property-type">number</span></dt><dd> specifies the delay between requests, which is used when retrying a request in case of an error (if not specified, the value 30 is used)</dd>
|
|
634
|
+
<dt class="optional">Skip (optional in message only, msg.skip)<span class="property-type">boolean</span></dt><dd> adding the msg.skip=true will allow the message to pass through to the output without processing</dd>
|
|
635
|
+
<dt class="optional">Connection (optional in message, msg.connection)<span class="property-type">string</span></dt><dd> replaces connection from configuration, use connection name</dd>
|
|
636
|
+
<dt class="optional">Unit (optional in message, msg.unit)<span class="property-type">number</span></dt><dd> replaces unit from connection configuration, use unit/agency id</dd>
|
|
637
|
+
<dt class="optional">Entity (optional in message, msg.entity)<span class="property-type">string</span></dt><dd> replaces entity from configuration, use v_entityName for views or r_entityName</dd>
|
|
638
|
+
<dt class="optional">Method (optional in message, msg.method)<span class="property-type">string</span></dt><dd> replaces method from configuration, use the available method for the given entity</dd>
|
|
639
|
+
</dl>
|
|
583
640
|
|
|
584
641
|
<h3>Output</h3>
|
|
585
642
|
<dl class="message-properties">
|
|
586
|
-
<dt>payload<span class="property-type">string | object</span></dt><dd> the standard output
|
|
643
|
+
<dt>payload<span class="property-type">string | object</span></dt><dd> the standard output of the response</dd>
|
|
587
644
|
<dt>count<span class="property-type">number</span></dt><dd> number of records in the output</dd>
|
|
645
|
+
<dt>error<span class="property-type">string</span></dt><dd> error message</dd>
|
|
588
646
|
<dt>msg.*<span class="property-type">string | object</span></dt><dd> all properties of the input message</dd>
|
|
589
647
|
</dl>
|
|
590
648
|
|
package/teamogy-client.js
CHANGED
|
@@ -1,7 +1,49 @@
|
|
|
1
1
|
function isEmpty(value) { return (value == null || (typeof value === "string" && value.trim().length === 0)); }
|
|
2
2
|
|
|
3
|
+
async function fetchWithRetry(url, options, retries, delay, node) {
|
|
4
|
+
for (let i = 0; i <= retries; i++) {
|
|
5
|
+
try {
|
|
6
|
+
const response = await fetch(url, options);
|
|
7
|
+
if (response.status >= 200 && response.status < 300) {
|
|
8
|
+
return response;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let o = {}
|
|
12
|
+
o.status = response.status;
|
|
13
|
+
o.message = await response.text();
|
|
14
|
+
o.attempt = i + 1;
|
|
15
|
+
o.delay = delay / 1000;
|
|
16
|
+
|
|
17
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
18
|
+
|
|
19
|
+
} catch (error) {
|
|
20
|
+
|
|
21
|
+
let o = {}
|
|
22
|
+
o.status = 0;
|
|
23
|
+
o.message = 'Request failed';
|
|
24
|
+
o.attempt = i + 1;
|
|
25
|
+
o.delay = delay / 1000;
|
|
26
|
+
|
|
27
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
3
33
|
module.exports = function(RED) {
|
|
4
34
|
|
|
35
|
+
function getConfigId(name) {
|
|
36
|
+
var configNodes = [];
|
|
37
|
+
RED.nodes.eachNode(function(node) {
|
|
38
|
+
if (node.type === "teamogy-config") {
|
|
39
|
+
configNodes.push(node);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const configId = configNodes.find(item => item.name === name)?.id;
|
|
44
|
+
return configId;
|
|
45
|
+
}
|
|
46
|
+
|
|
5
47
|
function ConnectionNode(n) {
|
|
6
48
|
try {
|
|
7
49
|
RED.nodes.createNode(this, n);
|
|
@@ -42,6 +84,7 @@ module.exports = function(RED) {
|
|
|
42
84
|
let token = this.config.credentials.token
|
|
43
85
|
let host = this.config.host.replace(/^https?:\/\//, '').split('/')[0];
|
|
44
86
|
let unit = this.config.unit
|
|
87
|
+
let connName = this.config.name
|
|
45
88
|
|
|
46
89
|
let clientid = data.id
|
|
47
90
|
let c = this.context().global.get('cache_' + host)
|
|
@@ -56,7 +99,12 @@ module.exports = function(RED) {
|
|
|
56
99
|
let mlimit = 0
|
|
57
100
|
let mpaging = 1000
|
|
58
101
|
let moffset = 0
|
|
59
|
-
|
|
102
|
+
let entity = ''
|
|
103
|
+
let method = 'GET'
|
|
104
|
+
let delay = 0;
|
|
105
|
+
let repeat = 5;
|
|
106
|
+
let rdelay = 30;
|
|
107
|
+
|
|
60
108
|
if(data.source=='dynamic') {
|
|
61
109
|
if(typeof msg.params == 'string') { mparams = msg.params }
|
|
62
110
|
if(typeof msg.params == 'object') {
|
|
@@ -74,11 +122,30 @@ module.exports = function(RED) {
|
|
|
74
122
|
if(typeof msg[data.bodysource] == 'string') { body = msg[data.bodysource] }
|
|
75
123
|
if(typeof msg[data.bodysource] == 'object') { body = JSON.stringify(msg[data.bodysource]) }
|
|
76
124
|
|
|
77
|
-
if(typeof msg.merge == 'boolean') { mmerge = msg.merge }
|
|
78
|
-
if(typeof msg.limit == 'number') { mlimit = msg.limit }
|
|
79
|
-
if(typeof msg.paging == 'number') { mpaging = msg.paging }
|
|
80
|
-
if(typeof msg.offset == 'number') { moffset = msg.offset }
|
|
125
|
+
if(typeof msg.merge == 'boolean') { mmerge = msg.merge }
|
|
126
|
+
if(typeof msg.limit == 'number') { mlimit = msg.limit }
|
|
127
|
+
if(typeof msg.paging == 'number') { mpaging = msg.paging }
|
|
128
|
+
if(typeof msg.offset == 'number') { moffset = msg.offset }
|
|
129
|
+
if(typeof msg.unit == 'number') { unit = msg.unit }
|
|
130
|
+
if(typeof msg.entity == 'string') { entity = msg.entity } else { entity = data.entity }
|
|
131
|
+
if(typeof msg.method == 'string') { method = msg.method } else { method = data.method }
|
|
132
|
+
if(typeof msg.delay == 'number') { delay = msg.delay * 1000 } else { delay = data.delay * 1000 }
|
|
133
|
+
if(typeof msg.repeat == 'number') { repeat = msg.repeat ?? 5 } else { repeat = data.repeat ?? 5 }
|
|
134
|
+
if(typeof msg.rdelay == 'number') { rdelay = msg.rdelay * 1000 } else { rdelay = data.rdelay * 1000 }
|
|
81
135
|
|
|
136
|
+
if(typeof msg.connection == 'string') {
|
|
137
|
+
if(msg.connection) {
|
|
138
|
+
const customConfig = RED.nodes.getNode(getConfigId(msg.connection));
|
|
139
|
+
if(customConfig) {
|
|
140
|
+
token = customConfig.credentials.token;
|
|
141
|
+
host = customConfig.host.replace(/^https?:\/\//, '').split('/')[0];
|
|
142
|
+
unit = customConfig.unit;
|
|
143
|
+
} else {
|
|
144
|
+
node.warn("Specified connection not found: " + msg.connection + ", using default: " + connName);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
82
149
|
}
|
|
83
150
|
|
|
84
151
|
if(data.source=='static') {
|
|
@@ -95,40 +162,44 @@ module.exports = function(RED) {
|
|
|
95
162
|
mlimit = data.limit
|
|
96
163
|
mpaging = data.paging
|
|
97
164
|
moffset = data.offset
|
|
165
|
+
entity = data.entity
|
|
166
|
+
method = data.method
|
|
167
|
+
delay = data.delay * 1000
|
|
168
|
+
repeat = data.repeat ?? 5
|
|
169
|
+
rdelay = data.rdelay * 1000
|
|
98
170
|
}
|
|
99
|
-
|
|
171
|
+
|
|
100
172
|
const headers = {
|
|
101
173
|
'Authorization': 'Bearer ' + token,
|
|
102
174
|
'Accept': 'application/json',
|
|
103
175
|
'Content-type': 'application/json'
|
|
104
176
|
};
|
|
105
|
-
|
|
177
|
+
|
|
106
178
|
let url = `https://${host}/rest/v1/${unit}/`
|
|
107
179
|
|
|
108
|
-
if(
|
|
180
|
+
if(entity.split('_')[0] == 'v') { url = url + 'views/'}
|
|
109
181
|
|
|
110
|
-
url = url +
|
|
182
|
+
url = url + entity.split('_')[1].replaceAll('-','.')
|
|
111
183
|
|
|
112
184
|
if(!isEmpty(mparams)) { url = url + '?' + mparams }
|
|
113
|
-
|
|
185
|
+
|
|
114
186
|
const doAsyncJobs = async () => {
|
|
115
187
|
try {
|
|
116
188
|
|
|
117
|
-
let newMsg = JSON.parse(JSON.stringify(mesg.msg));
|
|
118
|
-
|
|
119
189
|
let metadata = {};
|
|
120
190
|
metadata.count = 0
|
|
121
191
|
metadata.limit = 0
|
|
122
192
|
let rdata = [];
|
|
123
|
-
|
|
124
|
-
let method = data.method
|
|
193
|
+
|
|
125
194
|
let offset = moffset
|
|
126
|
-
|
|
195
|
+
|
|
127
196
|
if(method == 'GET') { body = null }
|
|
128
197
|
|
|
129
|
-
if(
|
|
198
|
+
if(entity.split('_')[0] == 'v') {
|
|
130
199
|
if(isEmpty(mparams)) { url = url + '?' } else { url = url + '&' }
|
|
131
200
|
|
|
201
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
202
|
+
|
|
132
203
|
while (offset != null) {
|
|
133
204
|
|
|
134
205
|
if(parseInt(mlimit) == 0) { mlimit = 1000000000}
|
|
@@ -136,9 +207,9 @@ module.exports = function(RED) {
|
|
|
136
207
|
|
|
137
208
|
eurl = encodeURI(url + 'limit=' + mpaging +'&offset=' + offset)
|
|
138
209
|
|
|
139
|
-
|
|
210
|
+
const response = await fetchWithRetry(eurl, { headers, method, body }, repeat, rdelay, node);
|
|
140
211
|
|
|
141
|
-
if(response.status >= 200 && response.status < 300) {
|
|
212
|
+
if(response && response.status >= 200 && response.status < 300) {
|
|
142
213
|
|
|
143
214
|
const body = await response.json();
|
|
144
215
|
offset = body?.metadata?.nextOffset
|
|
@@ -149,9 +220,9 @@ module.exports = function(RED) {
|
|
|
149
220
|
if(mlimit - metadata.count < mpaging) { mpaging = mlimit - metadata.count}
|
|
150
221
|
|
|
151
222
|
if(mmerge == false) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
node.send(
|
|
223
|
+
msg.payload = body;
|
|
224
|
+
msg.count = body.data.length;
|
|
225
|
+
node.send(msg);
|
|
155
226
|
}
|
|
156
227
|
|
|
157
228
|
if(mmerge == true) {
|
|
@@ -161,10 +232,22 @@ module.exports = function(RED) {
|
|
|
161
232
|
}
|
|
162
233
|
|
|
163
234
|
if(mlimit <= metadata.count) { break; }
|
|
164
|
-
|
|
235
|
+
if (offset != null && delay > 0) { await sleep(delay); }
|
|
236
|
+
|
|
165
237
|
} else {
|
|
166
|
-
|
|
167
|
-
|
|
238
|
+
if (!response) {
|
|
239
|
+
node.error('Request failed after all attempts.');
|
|
240
|
+
msg.error = 'Request failed after all attempts.'
|
|
241
|
+
msg.payload = null;
|
|
242
|
+
if(msg.res){
|
|
243
|
+
msg.payload = JSON.stringify('Request failed after all attempts.');
|
|
244
|
+
msg.statusCode = 500;
|
|
245
|
+
}
|
|
246
|
+
node.send(msg);
|
|
247
|
+
} else {
|
|
248
|
+
node.error('Response status: ' + response.status);
|
|
249
|
+
node.error('Response text: ' + await response.text());
|
|
250
|
+
}
|
|
168
251
|
break;
|
|
169
252
|
}
|
|
170
253
|
}
|
|
@@ -174,27 +257,34 @@ module.exports = function(RED) {
|
|
|
174
257
|
metadata.limit = parseInt(data.paging)
|
|
175
258
|
body.metadata = metadata
|
|
176
259
|
body.data = rdata
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
node.send(
|
|
260
|
+
msg.payload = body
|
|
261
|
+
msg.count = rdata.length
|
|
262
|
+
node.send(msg);
|
|
180
263
|
}
|
|
181
264
|
}
|
|
182
265
|
|
|
183
|
-
if(
|
|
266
|
+
if(entity.split('_')[0] == 'r') {
|
|
184
267
|
|
|
185
|
-
|
|
268
|
+
const response = await fetchWithRetry(encodeURI(url), { headers, method, body }, repeat, rdelay, node);
|
|
186
269
|
|
|
187
|
-
if(response.status >= 200 && response.status < 300) {
|
|
270
|
+
if(response && response.status >= 200 && response.status < 300) {
|
|
188
271
|
const body = await response.json();
|
|
189
|
-
|
|
190
|
-
node.send(
|
|
272
|
+
msg.payload = body
|
|
273
|
+
node.send(msg);
|
|
191
274
|
} else {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
275
|
+
if (!response) {
|
|
276
|
+
node.error('Request failed after all attempts.');
|
|
277
|
+
msg.error = 'Request failed after all attempts.'
|
|
278
|
+
msg.payload = null;
|
|
279
|
+
if(msg.res){
|
|
280
|
+
msg.payload = JSON.stringify('Request failed after all attempts.');
|
|
281
|
+
msg.statusCode = 500;
|
|
282
|
+
}
|
|
283
|
+
node.send(msg);
|
|
284
|
+
} else {
|
|
285
|
+
node.error('Response status: ' + response.status);
|
|
286
|
+
node.error('Response text: ' + await response.text());
|
|
287
|
+
}
|
|
198
288
|
}
|
|
199
289
|
}
|
|
200
290
|
} catch (e) {
|
|
@@ -202,7 +292,7 @@ module.exports = function(RED) {
|
|
|
202
292
|
}
|
|
203
293
|
}
|
|
204
294
|
|
|
205
|
-
|
|
295
|
+
await doAsyncJobs();
|
|
206
296
|
|
|
207
297
|
} catch (e) {
|
|
208
298
|
node.error(e);
|
|
@@ -285,4 +375,4 @@ module.exports = function(RED) {
|
|
|
285
375
|
}
|
|
286
376
|
|
|
287
377
|
RED.nodes.registerType("teamogy-client",teamogyClient);
|
|
288
|
-
}
|
|
378
|
+
}
|