node-red-contrib-boolean-logic-ultimate 1.1.12 → 1.1.15
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/CHANGELOG.md +9 -1
- package/README.md +40 -10
- package/boolean-logic-ultimate/InjectUltimate.js +3 -2
- package/boolean-logic-ultimate/RailwaySwitchUltimate.html +51 -49
- package/boolean-logic-ultimate/RailwaySwitchUltimate.js +23 -50
- package/boolean-logic-ultimate/utils.js +28 -1
- package/img/railwaySwitch.png +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,9 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
# CHANGELOG
|
|
5
5
|
|
|
6
|
+
<p>
|
|
7
|
+
<b>Version 1.1.15</b> August 2024<br/>
|
|
8
|
+
- Railway Switcher: now you can choose between 5 different output instead of 2.</br>
|
|
9
|
+
</p>
|
|
10
|
+
<p>
|
|
11
|
+
<b>Version 1.1.14</b> Mai 2024<br/>
|
|
12
|
+
- FIX: inject node: fixed an error in JSON.parse.</br>
|
|
13
|
+
</p>
|
|
6
14
|
<p>
|
|
7
15
|
<b>Version 1.1.12</b> Mai 2024<br/>
|
|
8
|
-
- FIX: fixed the empty JSON for old injectUltimate nodes.</br>
|
|
16
|
+
- FIX: inject node: fixed the empty JSON for old injectUltimate nodes.</br>
|
|
9
17
|
</p>
|
|
10
18
|
<p>
|
|
11
19
|
<b>Version 1.1.11</b> Mai 2024<br/>
|
package/README.md
CHANGED
|
@@ -428,27 +428,57 @@ Any message that arrives on input, will be passwd through to the output with the
|
|
|
428
428
|
|
|
429
429
|
# RAILWAY SWITCH ULTIMATE
|
|
430
430
|
|
|
431
|
-
The railway switcher,
|
|
431
|
+
The railway switcher, redirect the incoming messages to one ot the avaiable output pins, just like a railway jinction switch.
|
|
432
432
|
|
|
433
433
|
<img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/railroadSwitchScambio.png' width='80%'>
|
|
434
434
|
|
|
435
435
|
### NODE CONFIGURATION
|
|
436
436
|
|
|
437
|
+
|
|
437
438
|
|Property|Description|
|
|
438
439
|
|--|--|
|
|
439
|
-
| Switcher topic | Whenever the node receives a payload from this **topic**, it
|
|
440
|
+
| Switcher topic | Whenever the node receives a payload from this **topic**, it redirects the input messages to a choosen output PIN. |
|
|
440
441
|
| With Input | It's the msg property to be evaluated. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
441
|
-
|
|
|
442
|
+
| Translator | Translates the incoming <code>payload</code> value. This allows the compatibility with, for example, **HomeAssistant** nodes. |
|
|
442
443
|
|
|
443
|
-
|
|
444
|
+
### Inputs
|
|
444
445
|
|
|
445
|
-
|
|
446
|
-
|
|
446
|
+
The *Switcher topic* controls where the railway switch must be switched, between the output PINs.
|
|
447
|
+
Once an output PIN has been choosen, all messages passing through the node will be deviated to te choosen output PIN.
|
|
447
448
|
|
|
448
|
-
|
|
449
|
+
: topic (string|number) : this is the topic of the switcher message.
|
|
450
|
+
: payload (number|boolean) : this is the ouput PIN selector, base 0 (0 is the first output PIN).
|
|
449
451
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
+
### JSON switcher message
|
|
453
|
+
|
|
454
|
+
Take the example where you choosen such properties:
|
|
455
|
+
**Switcher topic**: "switcher"
|
|
456
|
+
**With Input**: "payload"
|
|
457
|
+
this JSON input message redirects all input messages to the first PIN
|
|
458
|
+
|
|
459
|
+
```json
|
|
460
|
+
{
|
|
461
|
+
topic:"switcher",
|
|
462
|
+
payload:0
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
this JSON input message redirects all input messages to the second PIN
|
|
466
|
+
|
|
467
|
+
```json
|
|
468
|
+
{
|
|
469
|
+
topic:"switcher",
|
|
470
|
+
payload:1
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
this JSON input message redirects all input messages to the third PIN, and so on...
|
|
475
|
+
|
|
476
|
+
```json
|
|
477
|
+
{
|
|
478
|
+
topic:"switcher",
|
|
479
|
+
payload:2
|
|
480
|
+
}
|
|
481
|
+
```
|
|
452
482
|
|
|
453
483
|
</br>
|
|
454
484
|
|
|
@@ -458,7 +488,7 @@ See the example below.<br/>
|
|
|
458
488
|
|
|
459
489
|
Copy and paste it into your flow
|
|
460
490
|
```javascript
|
|
461
|
-
[{"id":"
|
|
491
|
+
[{"id":"8243309f7c926112","type":"RailwaySwitchUltimate","z":"aa3efc585a6c7b9b","name":"Railway Switch","triggertopic":"switcher","initializewith":"3","payloadPropName":"payload","translatorConfig":"","x":350,"y":260,"wires":[["7f5a2c19a9ef64c8"],["5a35a650b225d910"],[],[],[]]},{"id":"d7bbc077bc20f4ea","type":"InjectUltimate","z":"aa3efc585a6c7b9b","name":"Junction switcher to Rail 0","topic":"","curVal":true,"outputJSON":"{ \n\t\"payload\":0,\n\t\"topic\":\"switcher\"\n}","x":350,"y":80,"wires":[[],[],[],["8243309f7c926112"]]},{"id":"5656d0c2ba66ed5e","type":"InjectUltimate","z":"aa3efc585a6c7b9b","name":"Junction switcher to Rail 1","topic":"","curVal":true,"outputJSON":"{ \n\t\"payload\":\"1\",\n\t\"topic\":\"switcher\"\n}","x":350,"y":160,"wires":[[],[],[],["8243309f7c926112"]]},{"id":"2253336fa8374c78","type":"InjectUltimate","z":"aa3efc585a6c7b9b","name":"Train","topic":"","curVal":true,"outputJSON":"{ \n\t\"payload\":\"hello\",\n\t\"topic\":\"I'm a train!\"\n}","x":110,"y":280,"wires":[["8243309f7c926112"],[],[],[]]},{"id":"7f5a2c19a9ef64c8","type":"debug","z":"aa3efc585a6c7b9b","name":"Rail 0","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":590,"y":260,"wires":[]},{"id":"5a35a650b225d910","type":"debug","z":"aa3efc585a6c7b9b","name":"Rail 1","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":590,"y":300,"wires":[]}]
|
|
462
492
|
```
|
|
463
493
|
|
|
464
494
|
|
|
@@ -33,14 +33,15 @@ module.exports = function (RED) {
|
|
|
33
33
|
let msgFalse = { payload: false, topic: node.topic };
|
|
34
34
|
let msgToggled = { payload: node.curVal, topic: node.topic };
|
|
35
35
|
node.curVal = !node.curVal;
|
|
36
|
+
let jRet;
|
|
36
37
|
try {
|
|
37
|
-
|
|
38
|
+
jRet = JSON.parse(node.outputJSON);
|
|
38
39
|
if (node.outputJSON.topic === undefined) node.outputJSON.topic = node.topic; // Add topic if not present
|
|
39
40
|
} catch (error) {
|
|
40
41
|
setNodeStatus({ fill: "red", shape: "dot", text: "JSON error " + error.trace });
|
|
41
42
|
RED.log.error("injectUltimate: node.outputJSON = JSON.parse(node.outputJSON) error:" + error.trace);
|
|
42
43
|
}
|
|
43
|
-
node.send([msgTrue, msgFalse, msgToggled,
|
|
44
|
+
node.send([msgTrue, msgFalse, msgToggled, jRet]);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
function setNodeStatus({ fill, shape, text }) {
|
|
@@ -4,26 +4,15 @@
|
|
|
4
4
|
color: '#ff8080',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: { value: "Railway Switch" },
|
|
7
|
-
triggertopic: { value: "
|
|
8
|
-
initializewith: { value: "
|
|
9
|
-
autoToggle: { value: "0" },
|
|
7
|
+
triggertopic: { value: "switcher" },
|
|
8
|
+
initializewith: { value: "1" },
|
|
10
9
|
payloadPropName: { value: "payload", required: false },
|
|
11
|
-
translatorConfig: { type: "translator-config", required: false }
|
|
10
|
+
translatorConfig: { type: "translator-config", required: false }
|
|
12
11
|
},
|
|
13
12
|
inputs: 1,
|
|
14
|
-
outputs:
|
|
13
|
+
outputs: 5,
|
|
15
14
|
outputLabels: function (i) {
|
|
16
|
-
|
|
17
|
-
switch (i) {
|
|
18
|
-
case 0:
|
|
19
|
-
return "Upper PIN";
|
|
20
|
-
break;
|
|
21
|
-
case 1:
|
|
22
|
-
return "Lower PIN";
|
|
23
|
-
break;
|
|
24
|
-
default:
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
15
|
+
return "PIN " + i;
|
|
27
16
|
},
|
|
28
17
|
icon: "font-awesome/fa-train",
|
|
29
18
|
label:
|
|
@@ -60,59 +49,72 @@
|
|
|
60
49
|
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> With Input</label>
|
|
61
50
|
<input type="text" id="node-input-payloadPropName">
|
|
62
51
|
</div>
|
|
63
|
-
<div><i>An input msg having this topic and msg true or false<br/>will trigger the railway switch between the two output PINs<br/>
|
|
64
|
-
false switches to the upper PIN<br/>
|
|
65
|
-
true switches to the lower PIN<br/>
|
|
66
|
-
</i></div>
|
|
67
|
-
<br/>
|
|
68
52
|
<div class="form-row">
|
|
69
53
|
<label style="width:160px" for="node-input-initializewith"><i class="fa fa-home"></i> At node-red start</label>
|
|
70
54
|
<select type="text" id="node-input-initializewith" placeholder="" style="width:250px">
|
|
71
|
-
<option value="0">
|
|
72
|
-
<option value="1">
|
|
55
|
+
<option value="0">PIN 0</option>
|
|
56
|
+
<option value="1">PIN 1</option>
|
|
57
|
+
<option value="2">PIN 2</option>
|
|
58
|
+
<option value="3">PIN 3</option>
|
|
59
|
+
<option value="4">PIN 4</option>
|
|
73
60
|
</select>
|
|
74
61
|
</div>
|
|
75
62
|
<div class="form-row">
|
|
76
|
-
<label style="width:160px" for="node-input-autoToggle"><i class="fa fa-hourglass-o"></i> Then</label>
|
|
77
|
-
<select type="text" id="node-input-autoToggle" placeholder="" style="width:250px">
|
|
78
|
-
<option value="0">Nothing</option>
|
|
79
|
-
<option value="10">Toggle above option after 10 seconds</option>
|
|
80
|
-
<option value="20">Toggle above option after 20 seconds</option>
|
|
81
|
-
<option value="30">Toggle above option after 30 seconds</option>
|
|
82
|
-
<option value="40">Toggle above option after 40 seconds</option>
|
|
83
|
-
<option value="50">Toggle above option after 50 seconds</option>
|
|
84
|
-
<option value="60">Toggle above option after 60 seconds</option>
|
|
85
|
-
<option value="90">Toggle above option after 90 seconds</option>
|
|
86
|
-
<option value="120">Toggle above option after 120 seconds</option>
|
|
87
|
-
</select>
|
|
88
|
-
</div>
|
|
89
|
-
<div class="form-row">
|
|
90
|
-
<br />
|
|
91
|
-
<b>Translator</b>
|
|
92
|
-
<br />
|
|
93
63
|
<label for="node-input-translatorConfig">
|
|
94
|
-
<font color="green" size="4px"><i class="fa fa-sign-in" aria-hidden="true"></i></font>
|
|
64
|
+
<font color="green" size="4px"><i class="fa fa-sign-in" aria-hidden="true"></i></font> Translator
|
|
95
65
|
</label>
|
|
96
66
|
<input type="text" id="node-input-translatorConfig" />
|
|
97
67
|
</div>
|
|
98
68
|
</script>
|
|
99
69
|
|
|
100
70
|
<script type="text/markdown" data-help-name="RailwaySwitchUltimate">
|
|
101
|
-
<p>The railway switcher,
|
|
71
|
+
<p>The railway switcher, redirect the incoming messages to one ot the avaiable output pins, just like a railway jinction switch.</p>
|
|
102
72
|
|
|
103
73
|
|Property|Description|
|
|
104
74
|
|--|--|
|
|
105
|
-
| Switcher topic | Whenever the node receives a payload from this **topic**, it
|
|
75
|
+
| Switcher topic | Whenever the node receives a payload from this **topic**, it redirects the input messages to a choosen output PIN. |
|
|
106
76
|
| With Input | It's the msg property to be evaluated. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
107
|
-
|
|
|
108
|
-
|
|
77
|
+
| Translator | Translates the incoming <code>payload</code> value. This allows the compatibility with, for example, **HomeAssistant** nodes. |
|
|
78
|
+
|
|
79
|
+
### Inputs
|
|
80
|
+
|
|
81
|
+
The *Switcher topic* controls where the railway switch must be switched, between the output PINs.
|
|
82
|
+
Once an output PIN has been choosen, all messages passing through the node will be deviated to te choosen output PIN.
|
|
83
|
+
|
|
84
|
+
: topic (string|number) : this is the topic of the switcher message.
|
|
85
|
+
: payload (number|boolean) : this is the ouput PIN selector, base 0 (0 is the first output PIN).
|
|
86
|
+
|
|
87
|
+
### JSON switcher message
|
|
88
|
+
|
|
89
|
+
Take the example where you choosen such properties:
|
|
90
|
+
**Switcher topic**: "switcher"
|
|
91
|
+
**With Input**: "payload"
|
|
92
|
+
this JSON input message redirects all input messages to the first PIN
|
|
109
93
|
|
|
110
|
-
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
topic:"switcher",
|
|
97
|
+
payload:0
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
this JSON input message redirects all input messages to the second PIN
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
topic:"switcher",
|
|
105
|
+
payload:1
|
|
106
|
+
}
|
|
107
|
+
```
|
|
111
108
|
|
|
112
|
-
|
|
109
|
+
this JSON input message redirects all input messages to the third PIN, and so on...
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
topic:"switcher",
|
|
114
|
+
payload:2
|
|
115
|
+
}
|
|
116
|
+
```
|
|
113
117
|
|
|
114
|
-
Pass <code>msg.payload = false</code> switches the msg input to the UPPER output</br>
|
|
115
|
-
Pass <code>msg.payload = true</code> switches the msg input to the LOWER output</br>
|
|
116
118
|
|
|
117
119
|
<br/>
|
|
118
120
|
|
|
@@ -8,11 +8,8 @@ module.exports = function (RED) {
|
|
|
8
8
|
node.config.triggertopic.replace(
|
|
9
9
|
/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi,
|
|
10
10
|
""
|
|
11
|
-
) || "trigger"; // Topic controlling the
|
|
12
|
-
node.
|
|
13
|
-
node.autoToggle =
|
|
14
|
-
config.autoToggle === undefined ? 0 : parseInt(config.autoToggle); // Auto toggle the selected "initializewith" after a while (useful for homekit bridged, that sends junk after start)
|
|
15
|
-
node.timerAutoToggle = null;
|
|
11
|
+
) || "trigger"; // Topic controlling the sRailway
|
|
12
|
+
node.sRailway = String(node.config.initializewith); // Railway selector
|
|
16
13
|
|
|
17
14
|
function setNodeStatus({ fill, shape, text }) {
|
|
18
15
|
let dDate = new Date();
|
|
@@ -30,30 +27,13 @@ module.exports = function (RED) {
|
|
|
30
27
|
}
|
|
31
28
|
|
|
32
29
|
node.alignStatus = () => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
shape: "dot",
|
|
39
|
-
text: "-> UPPER PIN" + sAutoToggle,
|
|
40
|
-
});
|
|
41
|
-
} else {
|
|
42
|
-
setNodeStatus({
|
|
43
|
-
fill: "blue",
|
|
44
|
-
shape: "dot",
|
|
45
|
-
text: "-> LOWER PIN" + sAutoToggle,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
};
|
|
30
|
+
setNodeStatus({
|
|
31
|
+
fill: "green",
|
|
32
|
+
shape: "dot",
|
|
33
|
+
text: "-> PIN " + node.sRailway,
|
|
34
|
+
});
|
|
49
35
|
|
|
50
|
-
|
|
51
|
-
node.timerAutoToggle = setTimeout(() => {
|
|
52
|
-
node.autoToggle = 0;
|
|
53
|
-
node.iRailway === 0 ? (node.iRailway = 1) : (node.iRailway = 0);
|
|
54
|
-
node.alignStatus();
|
|
55
|
-
}, node.autoToggle * 1000);
|
|
56
|
-
}
|
|
36
|
+
};
|
|
57
37
|
|
|
58
38
|
node.alignStatus();
|
|
59
39
|
|
|
@@ -83,36 +63,29 @@ module.exports = function (RED) {
|
|
|
83
63
|
});
|
|
84
64
|
return;
|
|
85
65
|
}
|
|
86
|
-
|
|
87
|
-
msg.payload = utils.
|
|
66
|
+
sPayload = String(sPayload); // Must be always a string
|
|
67
|
+
msg.payload = utils.ToAny(
|
|
88
68
|
sPayload,
|
|
89
69
|
RED.nodes.getNode(config.translatorConfig) // Retrieve the config node. It can be null, but it's handled in utils.js;
|
|
90
|
-
);
|
|
70
|
+
);
|
|
91
71
|
if (msg.payload === undefined) return null;
|
|
92
|
-
if (node.timerAutoToggle !== null)
|
|
93
|
-
// 28/01/2022 Stop autotoggle
|
|
94
|
-
clearInterval(node.timerAutoToggle);
|
|
95
72
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
104
|
-
} else {
|
|
105
|
-
setNodeStatus({ fill: "blue", shape: "dot", text: "-> LOWER PIN" });
|
|
106
|
-
}
|
|
73
|
+
// Backward compatibility
|
|
74
|
+
// Pass msg.payload = false switches the msg input to the UPPER output
|
|
75
|
+
// Pass msg.payload = true switches the msg input to the LOWER output
|
|
76
|
+
if (msg.payload === false) msg.payload = '0';
|
|
77
|
+
if (msg.payload === true) msg.payload = '1';
|
|
78
|
+
node.sRailway = msg.payload;
|
|
79
|
+
node.alignStatus();
|
|
107
80
|
return; // DONT'S SEND THIS MESSAGE
|
|
108
81
|
}
|
|
109
82
|
}
|
|
110
83
|
node.currentMsg = RED.util.cloneMessage(msg);
|
|
111
|
-
if (node.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
84
|
+
if (node.sRailway === "0") node.send([msg, null, null, null, null]);
|
|
85
|
+
if (node.sRailway === "1") node.send([null, msg, null, null, null]);
|
|
86
|
+
if (node.sRailway === "2") node.send([null, null, msg, null, null]);
|
|
87
|
+
if (node.sRailway === "3") node.send([null, null, null, msg, null]);
|
|
88
|
+
if (node.sRailway === "4") node.send([null, null, null, null, msg]);
|
|
116
89
|
});
|
|
117
90
|
}
|
|
118
91
|
|
|
@@ -14,7 +14,7 @@ module.exports.ToBoolean = function ToBoolean(value, _configTranslationNode) {
|
|
|
14
14
|
}
|
|
15
15
|
for (let index = 0; index < translationTable.length; index++) {
|
|
16
16
|
let inputPayloadToBeTranslated = translationTable[index].split(":")[0];
|
|
17
|
-
let outputBoolean = Boolean(translationTable[index].split(":")[1]);
|
|
17
|
+
//let outputBoolean = Boolean(translationTable[index].split(":")[1]);
|
|
18
18
|
if (
|
|
19
19
|
value.toLowerCase() === inputPayloadToBeTranslated.toLowerCase() &&
|
|
20
20
|
inputPayloadToBeTranslated.toLowerCase() !== ""
|
|
@@ -38,6 +38,33 @@ module.exports.ToBoolean = function ToBoolean(value, _configTranslationNode) {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
module.exports.ToAny = function ToAny(value, _configTranslationNode) {
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
let translationTable = [];
|
|
45
|
+
if (_configTranslationNode === null) {
|
|
46
|
+
// Don't do translation, because the default translation input may contin unwanted translations
|
|
47
|
+
return value;
|
|
48
|
+
} else {
|
|
49
|
+
translationTable = _configTranslationNode.commandText.split("\n");
|
|
50
|
+
}
|
|
51
|
+
for (let index = 0; index < translationTable.length; index++) {
|
|
52
|
+
let inputPayloadToBeTranslated = translationTable[index].split(":")[0];
|
|
53
|
+
//let outputBoolean = Boolean(translationTable[index].split(":")[1]);
|
|
54
|
+
if (
|
|
55
|
+
String(value).toLowerCase() === inputPayloadToBeTranslated.toLowerCase() &&
|
|
56
|
+
inputPayloadToBeTranslated.toLowerCase() !== ""
|
|
57
|
+
) {
|
|
58
|
+
return translationTable[index].split(":")[1];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.log("Boolean-Logic-Ultimate:utils:toAny: " + error.message);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
};
|
|
67
|
+
|
|
41
68
|
module.exports.fetchFromObject = function fetchFromObject(
|
|
42
69
|
_msg,
|
|
43
70
|
_payloadPropName
|
package/img/railwaySwitch.png
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-boolean-logic-ultimate",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"description": "A set of Node-RED enhanced boolean logic and utility nodes, flow interruption, blinker, invert, filter, toggle etc.., with persistent values after reboot. Compatible also with Homeassistant values.",
|
|
5
5
|
"author": "Supergiovane (https://github.com/Supergiovane)",
|
|
6
6
|
"dependencies": {
|