iobroker.toyota 0.0.4 → 0.2.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.
- package/admin/index_m.html +74 -75
- package/io-package.json +30 -21
- package/main.js +52 -21
- package/package.json +18 -17
package/admin/index_m.html
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
<html>
|
|
2
|
-
|
|
3
|
-
<head>
|
|
4
|
-
|
|
2
|
+
<head>
|
|
5
3
|
<!-- Load ioBroker scripts and styles-->
|
|
6
4
|
<link rel="stylesheet" type="text/css" href="../../css/adapter.css" />
|
|
7
|
-
<link rel="stylesheet" type="text/css" href="../../lib/css/materialize.css"
|
|
5
|
+
<link rel="stylesheet" type="text/css" href="../../lib/css/materialize.css" />
|
|
8
6
|
|
|
9
7
|
<script type="text/javascript" src="../../lib/js/jquery-3.2.1.min.js"></script>
|
|
10
8
|
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
|
|
@@ -18,84 +16,85 @@
|
|
|
18
16
|
<script type="text/javascript" src="words.js"></script>
|
|
19
17
|
|
|
20
18
|
<script type="text/javascript">
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
callback(obj);
|
|
61
|
-
}
|
|
19
|
+
// This will be called by the admin adapter when the settings page loads
|
|
20
|
+
function load(settings, onChange) {
|
|
21
|
+
// example: select elements with id=key and class=value and insert value
|
|
22
|
+
if (!settings) return;
|
|
23
|
+
$(".value").each(function () {
|
|
24
|
+
var $key = $(this);
|
|
25
|
+
var id = $key.attr("id");
|
|
26
|
+
if ($key.attr("type") === "checkbox") {
|
|
27
|
+
// do not call onChange direct, because onChange could expect some arguments
|
|
28
|
+
$key.prop("checked", settings[id]).on("change", () => onChange());
|
|
29
|
+
} else {
|
|
30
|
+
// do not call onChange direct, because onChange could expect some arguments
|
|
31
|
+
$key
|
|
32
|
+
.val(settings[id])
|
|
33
|
+
.on("change", () => onChange())
|
|
34
|
+
.on("keyup", () => onChange());
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
onChange(false);
|
|
38
|
+
// reinitialize all the Materialize labels on the page if you are dynamically adding inputs:
|
|
39
|
+
if (M) M.updateTextFields();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// This will be called by the admin adapter when the user presses the save button
|
|
43
|
+
function save(callback) {
|
|
44
|
+
// example: select elements with class=value and build settings object
|
|
45
|
+
var obj = {};
|
|
46
|
+
$(".value").each(function () {
|
|
47
|
+
var $this = $(this);
|
|
48
|
+
if ($this.attr("type") === "checkbox") {
|
|
49
|
+
obj[$this.attr("id")] = $this.prop("checked");
|
|
50
|
+
} else if ($this.attr("type") === "number") {
|
|
51
|
+
obj[$this.attr("id")] = parseFloat($this.val());
|
|
52
|
+
} else {
|
|
53
|
+
obj[$this.attr("id")] = $this.val();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
callback(obj);
|
|
57
|
+
}
|
|
62
58
|
</script>
|
|
59
|
+
</head>
|
|
63
60
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<body>
|
|
67
|
-
|
|
61
|
+
<body>
|
|
68
62
|
<div class="m adapter-container">
|
|
69
|
-
|
|
70
|
-
<div class="
|
|
71
|
-
|
|
72
|
-
<img src="toyota.png" class="logo">
|
|
73
|
-
</div>
|
|
63
|
+
<div class="row">
|
|
64
|
+
<div class="col s12 m4 l2">
|
|
65
|
+
<img src="toyota.png" class="logo" />
|
|
74
66
|
</div>
|
|
67
|
+
</div>
|
|
75
68
|
|
|
76
|
-
|
|
69
|
+
<!-- Put your content here -->
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
</div>
|
|
71
|
+
<div class="row">
|
|
72
|
+
<div class="col s6 input-field">
|
|
73
|
+
<input type="text" class="value" id="username" />
|
|
74
|
+
<label for="username" class="translate">App Email</label>
|
|
83
75
|
</div>
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
</div>
|
|
77
|
+
<div class="row">
|
|
78
|
+
<div class="col s6 input-field">
|
|
79
|
+
<input type="password" class="value" id="password" />
|
|
80
|
+
<label for="password" class="translate">App Password</label>
|
|
89
81
|
</div>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
</
|
|
82
|
+
</div>
|
|
83
|
+
<div class="row">
|
|
84
|
+
<div class="col s2 input-field">
|
|
85
|
+
<select id="type" class="value">
|
|
86
|
+
<option value="toyota">Toyota</option>
|
|
87
|
+
<option value="lexus">Lexus</option>
|
|
88
|
+
</select>
|
|
89
|
+
<label for="type" class="translate">App Toyota or Lexus</label>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="row">
|
|
93
|
+
<div class="col s2 input-field">
|
|
94
|
+
<input type="number" class="value" id="interval" />
|
|
95
|
+
<label for="interval" class="translate">Update interval in minutes</label>
|
|
96
96
|
</div>
|
|
97
|
+
</div>
|
|
97
98
|
</div>
|
|
98
|
-
|
|
99
|
-
</
|
|
100
|
-
|
|
101
|
-
</html>
|
|
99
|
+
</body>
|
|
100
|
+
</html>
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "toyota",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.2.0": {
|
|
7
|
+
"en": "added Lexus support",
|
|
8
|
+
"de": "Lexus Unterstützung hinzugefügt"
|
|
9
|
+
},
|
|
10
|
+
"0.1.0": {
|
|
11
|
+
"en": "added new Charging API endpoints and AC Remote Control",
|
|
12
|
+
"de": "hinzugefügt neue API-Endpunkte für das Laden und starten der Klimaanlage Remote Control"
|
|
13
|
+
},
|
|
6
14
|
"0.0.4": {
|
|
7
15
|
"en": "updated new API endpoints",
|
|
8
16
|
"de": "aktualisierte neue API-Endpunkte"
|
|
@@ -20,33 +28,33 @@
|
|
|
20
28
|
"zh-cn": "首次出版"
|
|
21
29
|
}
|
|
22
30
|
},
|
|
23
|
-
"title": "
|
|
31
|
+
"title": "myT Toyota/Lexus",
|
|
24
32
|
"titleLang": {
|
|
25
|
-
"en": "
|
|
26
|
-
"de": "
|
|
27
|
-
"ru": "
|
|
28
|
-
"pt": "
|
|
33
|
+
"en": "myT Toyota/Lexus",
|
|
34
|
+
"de": "myT Toyota/Lexus",
|
|
35
|
+
"ru": "myT Toyota/Lexus",
|
|
36
|
+
"pt": "myT Toyota/Lexus",
|
|
29
37
|
"nl": "MijnT Toyota",
|
|
30
|
-
"fr": "
|
|
31
|
-
"it": "
|
|
32
|
-
"es": "
|
|
33
|
-
"pl": "
|
|
38
|
+
"fr": "myT Toyota/Lexus",
|
|
39
|
+
"it": "myT Toyota/Lexus",
|
|
40
|
+
"es": "myT Toyota/Lexus",
|
|
41
|
+
"pl": "myT Toyota/Lexus",
|
|
34
42
|
"zh-cn": "丰田"
|
|
35
43
|
},
|
|
36
44
|
"desc": {
|
|
37
|
-
"en": "Adapter for myT Toyota App",
|
|
38
|
-
"de": "Adapter für myT Toyota App",
|
|
39
|
-
"ru": "Адаптер для приложения myT Toyota",
|
|
40
|
-
"pt": "Adaptador para myT Toyota App",
|
|
41
|
-
"nl": "Adapter voor myT Toyota-app",
|
|
42
|
-
"fr": "Adaptateur pour l'application myT Toyota",
|
|
43
|
-
"it": "Adattatore per app myT Toyota",
|
|
44
|
-
"es": "Adaptador para la aplicación myT Toyota",
|
|
45
|
-
"pl": "Adapter do aplikacji myT Toyota",
|
|
46
|
-
"zh-cn": "适用于 myT Toyota App 的适配器"
|
|
45
|
+
"en": "Adapter for myT Toyota/Lexus App",
|
|
46
|
+
"de": "Adapter für myT Toyota/Lexus App",
|
|
47
|
+
"ru": "Адаптер для приложения myT Toyota/Lexus",
|
|
48
|
+
"pt": "Adaptador para myT Toyota/Lexus App",
|
|
49
|
+
"nl": "Adapter voor myT Toyota/Lexus-app",
|
|
50
|
+
"fr": "Adaptateur pour l'application myT Toyota/Lexus",
|
|
51
|
+
"it": "Adattatore per app myT Toyota/Lexus",
|
|
52
|
+
"es": "Adaptador para la aplicación myT Toyota/Lexus",
|
|
53
|
+
"pl": "Adapter do aplikacji myT Toyota/Lexus",
|
|
54
|
+
"zh-cn": "适用于 myT Toyota/Lexus App 的适配器"
|
|
47
55
|
},
|
|
48
56
|
"authors": ["TA2k <tombox2020@gmail.com>"],
|
|
49
|
-
"keywords": ["toyota", "myt"],
|
|
57
|
+
"keywords": ["toyota", "myt", "lexus"],
|
|
50
58
|
"license": "MIT",
|
|
51
59
|
"platform": "Javascript/Node.js",
|
|
52
60
|
"main": "main.js",
|
|
@@ -82,6 +90,7 @@
|
|
|
82
90
|
"native": {
|
|
83
91
|
"username": "",
|
|
84
92
|
"password": "",
|
|
93
|
+
"type": "toyota",
|
|
85
94
|
"interval": 10
|
|
86
95
|
},
|
|
87
96
|
"objects": [],
|
package/main.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
// The adapter-core module gives you access to the core ioBroker functions
|
|
8
8
|
// you need to create an adapter
|
|
9
9
|
const utils = require("@iobroker/adapter-core");
|
|
10
|
-
const axios = require("axios");
|
|
11
|
-
const Json2iob = require("
|
|
10
|
+
const axios = require("axios").default;
|
|
11
|
+
const Json2iob = require("json2iob");
|
|
12
12
|
|
|
13
13
|
class Toyota extends utils.Adapter {
|
|
14
14
|
/**
|
|
@@ -30,6 +30,8 @@ class Toyota extends utils.Adapter {
|
|
|
30
30
|
this.updateInterval = null;
|
|
31
31
|
this.reLoginTimeout = null;
|
|
32
32
|
this.refreshTokenTimeout = null;
|
|
33
|
+
this.hostName = "" + this.hostName + "";
|
|
34
|
+
this.brand = "TOYOTA";
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/**
|
|
@@ -43,7 +45,11 @@ class Toyota extends utils.Adapter {
|
|
|
43
45
|
this.config.interval = 0.5;
|
|
44
46
|
}
|
|
45
47
|
this.subscribeStates("*");
|
|
46
|
-
|
|
48
|
+
if (this.config.type === "lexus") {
|
|
49
|
+
this.log.info("Login to Lexus");
|
|
50
|
+
this.brand = "LEXUS";
|
|
51
|
+
this.hostName = "lexuslink-agg.toyota-europe.com";
|
|
52
|
+
}
|
|
47
53
|
await this.login();
|
|
48
54
|
|
|
49
55
|
if (this.token && this.uuid) {
|
|
@@ -60,14 +66,14 @@ class Toyota extends utils.Adapter {
|
|
|
60
66
|
async login() {
|
|
61
67
|
this.session_data = await this.requestClient({
|
|
62
68
|
method: "post",
|
|
63
|
-
url: "https://
|
|
69
|
+
url: "https://" + this.hostName + "/cma/api/user/login",
|
|
64
70
|
headers: {
|
|
65
71
|
accept: "*/*",
|
|
66
72
|
"content-type": "application/json",
|
|
67
73
|
"x-tme-locale": "en-gb",
|
|
68
|
-
"x-tme-brand":
|
|
69
|
-
"x-tme-app-version": "4.
|
|
70
|
-
"user-agent": "MyT/4.
|
|
74
|
+
"x-tme-brand": this.brand,
|
|
75
|
+
"x-tme-app-version": "4.18.1",
|
|
76
|
+
"user-agent": "MyT/4.18.1 iPhone10,5 iOS/14.8 CFNetwork/1240.0.4 Darwin/20.6.0",
|
|
71
77
|
"accept-language": "de-DE",
|
|
72
78
|
},
|
|
73
79
|
data: JSON.stringify({
|
|
@@ -95,15 +101,15 @@ class Toyota extends utils.Adapter {
|
|
|
95
101
|
async getDeviceList() {
|
|
96
102
|
await this.requestClient({
|
|
97
103
|
method: "get",
|
|
98
|
-
url: "https://
|
|
104
|
+
url: "https://" + this.hostName + "/cma/api/user/" + this.uuid + "/vehicle/details?allServices=true",
|
|
99
105
|
headers: {
|
|
100
106
|
cookie: "iPlanetDirectoryPro=" + this.token,
|
|
101
107
|
accept: "*/*",
|
|
102
108
|
"x-tme-locale": "de-de",
|
|
103
|
-
"x-tme-app-version": "4.
|
|
104
|
-
"user-agent": "MyT/4.
|
|
109
|
+
"x-tme-app-version": "4.18.1",
|
|
110
|
+
"user-agent": "MyT/4.18.1 iPhone10,5 iOS/14.8 CFNetwork/1240.0.4 Darwin/20.6.0",
|
|
105
111
|
"accept-language": "de-DE",
|
|
106
|
-
"x-tme-brand":
|
|
112
|
+
"x-tme-brand": this.brand,
|
|
107
113
|
},
|
|
108
114
|
})
|
|
109
115
|
.then(async (res) => {
|
|
@@ -116,6 +122,7 @@ class Toyota extends utils.Adapter {
|
|
|
116
122
|
}
|
|
117
123
|
this.deviceArray.push(device.vin);
|
|
118
124
|
const name = device.alias;
|
|
125
|
+
this.log.info("Create vehicle " + device.vin + " " + name);
|
|
119
126
|
await this.setObjectNotExistsAsync(device.vin, {
|
|
120
127
|
type: "device",
|
|
121
128
|
common: {
|
|
@@ -168,24 +175,29 @@ class Toyota extends utils.Adapter {
|
|
|
168
175
|
const statusArray = [
|
|
169
176
|
{
|
|
170
177
|
path: "status",
|
|
171
|
-
url: "https://
|
|
178
|
+
url: "https://" + this.hostName + "/cma/api/users/" + this.uuid + "/vehicles/$vin/vehicleStatus",
|
|
172
179
|
desc: "Status of the car",
|
|
173
180
|
},
|
|
174
181
|
{
|
|
175
182
|
path: "addtionalInfo",
|
|
176
|
-
url: "https://
|
|
183
|
+
url: "https://" + this.hostName + "/cma/api/vehicle/$vin/addtionalInfo",
|
|
177
184
|
desc: "AddtionalInfo of the car",
|
|
178
185
|
},
|
|
179
186
|
{
|
|
180
187
|
path: "location",
|
|
181
|
-
url: "https://
|
|
188
|
+
url: "https://" + this.hostName + "/cma/api/users/" + this.uuid + "/vehicle/location",
|
|
182
189
|
desc: "Location of the car",
|
|
183
190
|
},
|
|
184
191
|
{
|
|
185
192
|
path: "parking",
|
|
186
|
-
url: "https://
|
|
193
|
+
url: "https://" + this.hostName + "/cma/api/users/" + this.uuid + "/vehicles/$vin/parking",
|
|
187
194
|
desc: "Parking of the car",
|
|
188
195
|
},
|
|
196
|
+
{
|
|
197
|
+
path: "statusV2",
|
|
198
|
+
url: "https://" + this.hostName + "/cma/api/vehicles/$vin/remoteControl/status",
|
|
199
|
+
desc: "Additional Status Information",
|
|
200
|
+
},
|
|
189
201
|
];
|
|
190
202
|
|
|
191
203
|
const headers = {
|
|
@@ -196,7 +208,7 @@ class Toyota extends utils.Adapter {
|
|
|
196
208
|
"x-tme-app-version": "4.15.0",
|
|
197
209
|
"user-agent": "MyT/4.15.0 iPhone10,5 iOS/14.8 CFNetwork/1240.0.4 Darwin/20.6.0",
|
|
198
210
|
"accept-language": "de-DE",
|
|
199
|
-
"x-tme-brand":
|
|
211
|
+
"x-tme-brand": this.brand,
|
|
200
212
|
};
|
|
201
213
|
this.deviceArray.forEach(async (vin) => {
|
|
202
214
|
statusArray.forEach(async (element) => {
|
|
@@ -279,8 +291,27 @@ class Toyota extends utils.Adapter {
|
|
|
279
291
|
if (path === "hvac-temperature") {
|
|
280
292
|
return;
|
|
281
293
|
}
|
|
282
|
-
const
|
|
283
|
-
|
|
294
|
+
const hvacTemperatureState = await this.getStateAsync(deviceId + ".remote.hvac-temperature");
|
|
295
|
+
let hvacTemperature = 22;
|
|
296
|
+
if (hvacTemperatureState) {
|
|
297
|
+
hvacTemperature = hvacTemperatureState.val;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const data = {
|
|
301
|
+
RemoteHvac: {
|
|
302
|
+
Option: {
|
|
303
|
+
RearDefogger: 0,
|
|
304
|
+
FrontDefogger: 0,
|
|
305
|
+
},
|
|
306
|
+
Sw: state.val ? 1 : 0,
|
|
307
|
+
Temperature: {
|
|
308
|
+
TemperatureUnit: 1,
|
|
309
|
+
SettingType: 0,
|
|
310
|
+
SettingTemperature: hvacTemperature,
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
const url = "https://" + this.hostName + "/cma/api/user/" + this.uuid + "/vehicle/" + deviceId + "/remoteControl";
|
|
284
315
|
this.log.debug(JSON.stringify(data));
|
|
285
316
|
this.log.debug(url);
|
|
286
317
|
await this.requestClient({
|
|
@@ -290,10 +321,10 @@ class Toyota extends utils.Adapter {
|
|
|
290
321
|
cookie: "iPlanetDirectoryPro=" + this.token,
|
|
291
322
|
accept: "*/*",
|
|
292
323
|
"x-tme-locale": "de-de",
|
|
293
|
-
"x-tme-app-version": "4.
|
|
294
|
-
"user-agent": "MyT/4.
|
|
324
|
+
"x-tme-app-version": "4.18.1",
|
|
325
|
+
"user-agent": "MyT/4.18.1 iPhone10,5 iOS/14.8 CFNetwork/1240.0.4 Darwin/20.6.0",
|
|
295
326
|
"accept-language": "de-DE",
|
|
296
|
-
"x-tme-brand":
|
|
327
|
+
"x-tme-brand": this.brand,
|
|
297
328
|
},
|
|
298
329
|
data: data,
|
|
299
330
|
})
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.toyota",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "Adapter for myT Toyota App",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Adapter for myT Toyota/Lexus App",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TA2k",
|
|
7
7
|
"email": "tombox2020@gmail.com"
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"keywords": [
|
|
17
17
|
"toyota",
|
|
18
|
+
"lexus",
|
|
18
19
|
"myt"
|
|
19
20
|
],
|
|
20
21
|
"repository": {
|
|
@@ -22,28 +23,28 @@
|
|
|
22
23
|
"url": "https://github.com/TA2k/ioBroker.toyota"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
|
-
"@iobroker/adapter-core": "^
|
|
26
|
-
"axios": "^1.
|
|
27
|
-
"
|
|
26
|
+
"@iobroker/adapter-core": "^3.0.4",
|
|
27
|
+
"axios": "^1.5.1",
|
|
28
|
+
"json2iob": "^2.4.8"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@iobroker/testing": "^4.1.0",
|
|
31
|
-
"@types/chai": "^4.3.
|
|
32
|
-
"@types/chai-as-promised": "^7.1.
|
|
33
|
-
"@types/gulp": "^4.0.
|
|
34
|
-
"@types/mocha": "^10.0.
|
|
35
|
-
"@types/node": "^
|
|
36
|
-
"@types/proxyquire": "^1.3.
|
|
37
|
-
"@types/sinon": "^10.0.
|
|
38
|
-
"@types/sinon-chai": "^3.2.
|
|
39
|
-
"chai": "^4.3.
|
|
32
|
+
"@types/chai": "^4.3.9",
|
|
33
|
+
"@types/chai-as-promised": "^7.1.7",
|
|
34
|
+
"@types/gulp": "^4.0.16",
|
|
35
|
+
"@types/mocha": "^10.0.2",
|
|
36
|
+
"@types/node": "^20.8.6",
|
|
37
|
+
"@types/proxyquire": "^1.3.29",
|
|
38
|
+
"@types/sinon": "^10.0.19",
|
|
39
|
+
"@types/sinon-chai": "^3.2.10",
|
|
40
|
+
"chai": "^4.3.10",
|
|
40
41
|
"chai-as-promised": "^7.1.1",
|
|
41
|
-
"eslint": "^8.
|
|
42
|
+
"eslint": "^8.51.0",
|
|
42
43
|
"mocha": "^10.2.0",
|
|
43
44
|
"proxyquire": "^2.1.3",
|
|
44
|
-
"sinon": "^15.0
|
|
45
|
+
"sinon": "^15.2.0",
|
|
45
46
|
"sinon-chai": "^3.7.0",
|
|
46
|
-
"typescript": "~5.
|
|
47
|
+
"typescript": "~5.2.2"
|
|
47
48
|
},
|
|
48
49
|
"main": "main.js",
|
|
49
50
|
"files": [
|