iobroker.zigbee2mqtt 3.0.10 → 3.0.14

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/lib/rgb.js CHANGED
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-prototype-builtins */
1
+
2
2
  /*
3
3
  With these functions you can convert the CIE color space to the RGB color space and vice versa.
4
4
 
@@ -44,7 +44,11 @@ const colors = require('./colors.js');
44
44
 
45
45
  /**
46
46
  * Converts CIE color space to RGB color space
47
- * @return {Array} Array that contains the color values for red, green and blue
47
+ *
48
+ * @param x
49
+ * @param y
50
+ * @param brightness
51
+ * @returns {Array} Array that contains the color values for red, green and blue
48
52
  */
49
53
  function cie_to_rgb(x, y, brightness) {
50
54
  //Set to maximum brightness if no custom value was given (Not the slick ECMAScript 6 way for compatibility reasons)
@@ -54,17 +58,12 @@ function cie_to_rgb(x, y, brightness) {
54
58
 
55
59
  const z = 1.0 - x - y;
56
60
  const Y = (brightness / 254).toFixed(2);
57
- // @ts-ignore
58
61
  const X = (Y / y) * x;
59
- // @ts-ignore
60
62
  const Z = (Y / y) * z;
61
63
 
62
64
  //Convert to RGB using Wide RGB D65 conversion
63
- // @ts-ignore
64
65
  let red = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
65
- // @ts-ignore
66
66
  let green = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
67
- // @ts-ignore
68
67
  let blue = X * 0.051713 - Y * 0.121364 + Z * 1.01153;
69
68
 
70
69
  //If red, green or blue is larger than 1.0 set it back to the maximum of 1.0
@@ -109,10 +108,11 @@ function cie_to_rgb(x, y, brightness) {
109
108
 
110
109
  /**
111
110
  * Converts RGB color space to CIE color space
112
- * @param {Number} red
113
- * @param {Number} green
114
- * @param {Number} blue
115
- * @return {Array} Array that contains the CIE color values for x and y
111
+ *
112
+ * @param {number} red
113
+ * @param {number} green
114
+ * @param {number} blue
115
+ * @returns {Array} Array that contains the CIE color values for x and y
116
116
  */
117
117
  function rgb_to_cie(red, green, blue) {
118
118
  // Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
@@ -129,21 +129,23 @@ function rgb_to_cie(red, green, blue) {
129
129
  let x = (X / (X + Y + Z)).toFixed(4);
130
130
  let y = (Y / (X + Y + Z)).toFixed(4);
131
131
 
132
- // @ts-ignore
133
132
  if (isNaN(x)) {
134
- // @ts-ignore
135
133
  x = 0;
136
134
  }
137
135
 
138
- // @ts-ignore
139
136
  if (isNaN(y)) {
140
- // @ts-ignore
141
137
  y = 0;
142
138
  }
143
139
 
144
140
  return [x, y];
145
141
  }
146
142
 
143
+ /**
144
+ *
145
+ * @param h
146
+ * @param s
147
+ * @param v
148
+ */
147
149
  function hsvToRGB(h, s, v) {
148
150
  h = (h % 360) / 360;
149
151
  s = s / 100;
@@ -187,6 +189,13 @@ function hsvToRGB(h, s, v) {
187
189
  };
188
190
  }
189
191
 
192
+ /**
193
+ *
194
+ * @param r
195
+ * @param g
196
+ * @param b
197
+ * @param numeric
198
+ */
190
199
  function rgbToHSV(r, g, b, numeric) {
191
200
  if (arguments.length === 1) {
192
201
  (g = r.g), (b = r.b), (r = r.r);
@@ -215,21 +224,26 @@ function rgbToHSV(r, g, b, numeric) {
215
224
  h /= 6 * d;
216
225
  break;
217
226
  }
218
- if (numeric)
219
- return {
220
- // @ts-ignore
227
+ if (numeric) {
228
+ return {
229
+
221
230
  h: Math.round(h * 360),
222
231
  s: Math.round(s * 100),
223
232
  v: Math.round(v * 100),
224
233
  };
225
- return {
226
- // @ts-ignore
234
+ }
235
+ return {
236
+
227
237
  h: (h * 360).toFixed(3),
228
238
  s: (s * 100).toFixed(3),
229
239
  v: (v * 100).toFixed(3),
230
- };
231
- }
240
+ };
241
+ }
232
242
 
243
+ /**
244
+ *
245
+ * @param value
246
+ */
233
247
  function colorArrayFromString(value) {
234
248
  if (typeof value === 'string') {
235
249
  const rv = [];
@@ -241,6 +255,10 @@ function colorArrayFromString(value) {
241
255
  return [{ r: 0, g: 128, b: 255 }];
242
256
  }
243
257
 
258
+ /**
259
+ *
260
+ * @param payload
261
+ */
244
262
  function colorStringFromRGBArray(payload) {
245
263
  const rv = [];
246
264
  payload.forEach((element) => {
@@ -249,6 +267,12 @@ function colorStringFromRGBArray(payload) {
249
267
  return rv.toString();
250
268
  }
251
269
 
270
+ /**
271
+ *
272
+ * @param h
273
+ * @param s
274
+ * @param v
275
+ */
252
276
  function hsv_to_cie(h, s, v) {
253
277
  const rgb = hsvToRGB(h, s, v);
254
278
  return rgb_to_cie(rgb.r, rgb.g, rgb.b);
@@ -256,20 +280,35 @@ function hsv_to_cie(h, s, v) {
256
280
 
257
281
  function rgb_to_rgbstring(element) {
258
282
  let col = '#';
259
- if (element && element.hasOwnProperty('r')) col = col + element.r.toString(16).padStart(2, '0');
260
- else col = col + '00';
261
- if (element && element.hasOwnProperty('g')) col = col + element.g.toString(16).padStart(2, '0');
262
- else col = col + '00';
263
- if (element && element.hasOwnProperty('b')) col = col + element.b.toString(16).padStart(2, '0');
264
- else col = col + '00';
283
+ if (element && element.hasOwnProperty('r')) {
284
+ col = col + element.r.toString(16).padStart(2, '0');
285
+ } else {
286
+ col = `${col }00`;
287
+ }
288
+ if (element && element.hasOwnProperty('g')) {
289
+ col = col + element.g.toString(16).padStart(2, '0');
290
+ } else {
291
+ col = `${col }00`;
292
+ }
293
+ if (element && element.hasOwnProperty('b')) {
294
+ col = col + element.b.toString(16).padStart(2, '0');
295
+ } else {
296
+ col = `${col }00`;
297
+ }
265
298
  return col;
266
299
  }
267
300
 
301
+ /**
302
+ *
303
+ * @param h
304
+ * @param s
305
+ * @param b
306
+ */
268
307
  function hsbToRGB(h, s, b) {
269
308
  const br = Math.round(b * 2.55);
270
309
  if (s == 0) {
271
310
  return [br, br, br];
272
- } else {
311
+ }
273
312
  const hue = h % 360;
274
313
  const f = hue % 60;
275
314
  const p = Math.round(b * (100 - s) * 0.0255);
@@ -289,10 +328,16 @@ function hsbToRGB(h, s, b) {
289
328
  case 5:
290
329
  return [br, p, q];
291
330
  }
292
- }
331
+
293
332
  return false;
294
333
  }
295
334
 
335
+ /**
336
+ *
337
+ * @param h
338
+ * @param s
339
+ * @param v
340
+ */
296
341
  function hsvToRGBString(h, s, v) {
297
342
  return rgb_to_rgbstring(hsvToRGB(h, s, v));
298
343
  }
@@ -2,7 +2,18 @@ const utils = require('./utils');
2
2
  const incStatsQueue = [];
3
3
  const timeOutCache = {};
4
4
 
5
+ /**
6
+ *
7
+ */
5
8
  class StatesController {
9
+ /**
10
+ *
11
+ * @param adapter
12
+ * @param deviceCache
13
+ * @param groupCache
14
+ * @param logCustomizations
15
+ * @param createCache
16
+ */
6
17
  constructor(adapter, deviceCache, groupCache, logCustomizations, createCache) {
7
18
  this.adapter = adapter;
8
19
  this.groupCache = groupCache;
@@ -11,6 +22,10 @@ class StatesController {
11
22
  this.createCache = createCache;
12
23
  }
13
24
 
25
+ /**
26
+ *
27
+ * @param messageObj
28
+ */
14
29
  processDeviceMessage(messageObj) {
15
30
  // Is payload present?
16
31
  if (messageObj.payload == '') {
@@ -30,6 +45,11 @@ class StatesController {
30
45
  }
31
46
  }
32
47
 
48
+ /**
49
+ *
50
+ * @param messageObj
51
+ * @param device
52
+ */
33
53
  async setDeviceStateSafely(messageObj, device) {
34
54
  if (this.logCustomizations.debugDevices.includes(device.ieee_address)) {
35
55
  this.adapter.log.warn(`--->>> fromZ2M -> ${device.ieee_address} states: ${JSON.stringify(messageObj)}`);
@@ -142,6 +162,11 @@ class StatesController {
142
162
  } else {
143
163
  await this.setStateChangedSafelyAsync(stateName, state.getter(messageObj.payload));
144
164
  }
165
+
166
+ // publish the action into action dp
167
+ if (state.prop && state.prop == 'action') {
168
+ await this.setStateSafelyAsync(`${device.ieee_address}.action`, messageObj.payload.action);
169
+ }
145
170
  } catch (err) {
146
171
  incStatsQueue[incStatsQueue.length] = messageObj;
147
172
  this.adapter.log.debug(`Can not set ${stateName}, queue state in incStatsQueue!`);
@@ -149,6 +174,11 @@ class StatesController {
149
174
  }
150
175
  }
151
176
 
177
+ /**
178
+ *
179
+ * @param stateName
180
+ * @param value
181
+ */
152
182
  async setStateSafelyAsync(stateName, value) {
153
183
  if (value === undefined || value === null) {
154
184
  return;
@@ -156,6 +186,11 @@ class StatesController {
156
186
  await this.adapter.setStateAsync(stateName, value, true);
157
187
  }
158
188
 
189
+ /**
190
+ *
191
+ * @param stateName
192
+ * @param value
193
+ */
159
194
  async setStateChangedSafelyAsync(stateName, value) {
160
195
  if (value === undefined || value === null) {
161
196
  return;
@@ -163,6 +198,12 @@ class StatesController {
163
198
  await this.adapter.setStateChangedAsync(stateName, value, true);
164
199
  }
165
200
 
201
+ /**
202
+ *
203
+ * @param stateName
204
+ * @param value
205
+ * @param timeout
206
+ */
166
207
  async setStateWithTimeoutAsync(stateName, value, timeout) {
167
208
  if (value === undefined || value === null) {
168
209
  return;
@@ -177,6 +218,9 @@ class StatesController {
177
218
  }, timeout);
178
219
  }
179
220
 
221
+ /**
222
+ *
223
+ */
180
224
  processQueue() {
181
225
  const oldIncStatsQueue = [];
182
226
  utils.moveArray(incStatsQueue, oldIncStatsQueue);
@@ -185,6 +229,9 @@ class StatesController {
185
229
  }
186
230
  }
187
231
 
232
+ /**
233
+ *
234
+ */
188
235
  async subscribeWritableStates() {
189
236
  await this.adapter.unsubscribeObjectsAsync('*');
190
237
  for (const device of this.groupCache.concat(this.deviceCache)) {
@@ -199,6 +246,9 @@ class StatesController {
199
246
  this.adapter.subscribeStates('info.coordinator_check');
200
247
  }
201
248
 
249
+ /**
250
+ *
251
+ */
202
252
  async setAllAvailableToFalse() {
203
253
  const availableStates = await this.adapter.getStatesAsync('*.available');
204
254
  for (const availableState in availableStates) {
@@ -206,6 +256,9 @@ class StatesController {
206
256
  }
207
257
  }
208
258
 
259
+ /**
260
+ *
261
+ */
209
262
  async allTimerClear() {
210
263
  for (const timer in timeOutCache) {
211
264
  clearTimeout(timeOutCache[timer]);
package/lib/utils.js CHANGED
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * Converts a bulb level of range [0...254] to an adapter level of range [0...100]
3
+ *
4
+ * @param bulbLevel
3
5
  */
4
6
  function bulbLevelToAdapterLevel(bulbLevel) {
5
7
  // Convert from bulb levels [0...254] to adapter levels [0...100]:
@@ -19,14 +21,16 @@ function bulbLevelToAdapterLevel(bulbLevel) {
19
21
  if (bulbLevel >= 2) {
20
22
  // Perform linear mapping of range [2...254] to [1...100]
21
23
  return Math.round(((bulbLevel - 2) * 99) / 252) + 1;
22
- } else {
24
+ }
23
25
  // The bulb is considered off. Even a bulb level of "1" is considered as off.
24
26
  return 0;
25
- } // else
27
+ // else
26
28
  }
27
29
 
28
30
  /**
29
31
  * Converts an adapter level of range [0...100] to a bulb level of range [0...254]
32
+ *
33
+ * @param adapterLevel
30
34
  */
31
35
  function adapterLevelToBulbLevel(adapterLevel) {
32
36
  // Convert from adapter levels [0...100] to bulb levels [0...254].
@@ -35,13 +39,17 @@ function adapterLevelToBulbLevel(adapterLevel) {
35
39
  if (adapterLevel) {
36
40
  // Perform linear mapping of range [1...100] to [2...254]
37
41
  return Math.round(((adapterLevel - 1) * 252) / 99) + 2;
38
- } else {
42
+ }
39
43
  // Switch the bulb off. Some bulbs need "0" (IKEA), others "1" (HUE), and according to the
40
44
  // ZigBee docs "1" is the "minimum possible level"... we choose "0" here which seems to work.
41
45
  return 0;
42
- } // else
46
+ // else
43
47
  }
44
48
 
49
+ /**
50
+ *
51
+ * @param ba
52
+ */
45
53
  function bytesArrayToWordArray(ba) {
46
54
  const wa = [];
47
55
  for (let i = 0; i < ba.length; i++) {
@@ -52,6 +60,10 @@ function bytesArrayToWordArray(ba) {
52
60
 
53
61
  // If the value is greater than 1000, kelvin is assumed.
54
62
  // If smaller, it is assumed to be mired.
63
+ /**
64
+ *
65
+ * @param t
66
+ */
55
67
  function toMired(t) {
56
68
  let miredValue = t;
57
69
  if (t > 1000) {
@@ -60,12 +72,19 @@ function toMired(t) {
60
72
  return miredValue;
61
73
  }
62
74
 
75
+ /**
76
+ *
77
+ * @param t
78
+ */
63
79
  function miredKelvinConversion(t) {
64
80
  return Math.round(1000000 / t);
65
81
  }
66
82
 
67
83
  /**
68
84
  * Converts a decimal number to a hex string with zero-padding
85
+ *
86
+ * @param decimal
87
+ * @param padding
69
88
  */
70
89
  function decimalToHex(decimal, padding) {
71
90
  let hex = Number(decimal).toString(16);
@@ -78,32 +97,60 @@ function decimalToHex(decimal, padding) {
78
97
  return hex;
79
98
  }
80
99
 
100
+ /**
101
+ *
102
+ * @param adapterDevId
103
+ */
81
104
  function getZbId(adapterDevId) {
82
105
  const idx = adapterDevId.indexOf('group');
83
- if (idx > 0) return adapterDevId.substr(idx + 6);
84
- return '0x' + adapterDevId.split('.')[2];
106
+ if (idx > 0) {
107
+ return adapterDevId.substr(idx + 6);
108
+ }
109
+ return `0x${ adapterDevId.split('.')[2]}`;
85
110
  }
86
111
 
112
+ /**
113
+ *
114
+ * @param adapter
115
+ * @param id
116
+ */
87
117
  function getAdId(adapter, id) {
88
- return adapter.namespace + '.' + id.split('.')[2]; // iobroker device id
118
+ return `${adapter.namespace }.${ id.split('.')[2]}`; // iobroker device id
89
119
  }
90
120
 
121
+ /**
122
+ *
123
+ * @param array
124
+ */
91
125
  function clearArray(array) {
92
126
  while (array.length > 0) {
93
127
  array.pop();
94
128
  }
95
129
  }
96
130
 
131
+ /**
132
+ *
133
+ * @param source
134
+ * @param target
135
+ */
97
136
  function moveArray(source, target) {
98
137
  while (source.length > 0) {
99
138
  target.push(source.shift());
100
139
  }
101
140
  }
102
141
 
142
+ /**
143
+ *
144
+ * @param item
145
+ */
103
146
  function isObject(item) {
104
147
  return typeof item === 'object' && !Array.isArray(item) && item !== null;
105
148
  }
106
149
 
150
+ /**
151
+ *
152
+ * @param item
153
+ */
107
154
  function isJson(item) {
108
155
  let value = typeof item !== 'string' ? JSON.stringify(item) : item;
109
156
  try {
@@ -6,11 +6,21 @@ let ping;
6
6
  let pingTimeout;
7
7
  let autoRestartTimeout;
8
8
 
9
+ /**
10
+ *
11
+ */
9
12
  class WebsocketController {
13
+ /**
14
+ *
15
+ * @param adapter
16
+ */
10
17
  constructor(adapter) {
11
18
  this.adapter = adapter;
12
19
  }
13
20
 
21
+ /**
22
+ *
23
+ */
14
24
  initWsClient() {
15
25
  try {
16
26
  let wsURL = `${this.adapter.config.wsScheme}://${this.adapter.config.wsServerIP}:${this.adapter.config.wsServerPort}/api`;
@@ -53,6 +63,10 @@ class WebsocketController {
53
63
  }
54
64
  }
55
65
 
66
+ /**
67
+ *
68
+ * @param message
69
+ */
56
70
  send(message) {
57
71
  if (wsClient.readyState !== WebSocket.OPEN) {
58
72
  this.adapter.log.warn('Cannot set State, no websocket connection to Zigbee2MQTT!');
@@ -61,6 +75,9 @@ class WebsocketController {
61
75
  wsClient.send(message);
62
76
  }
63
77
 
78
+ /**
79
+ *
80
+ */
64
81
  sendPingToServer() {
65
82
  //this.logDebug('Send ping to server');
66
83
  wsClient.ping();
@@ -69,6 +86,9 @@ class WebsocketController {
69
86
  }, wsHeartbeatIntervall);
70
87
  }
71
88
 
89
+ /**
90
+ *
91
+ */
72
92
  wsHeartbeat() {
73
93
  clearTimeout(pingTimeout);
74
94
  pingTimeout = setTimeout(() => {
@@ -77,6 +97,9 @@ class WebsocketController {
77
97
  }, wsHeartbeatIntervall + 3000);
78
98
  }
79
99
 
100
+ /**
101
+ *
102
+ */
80
103
  async autoRestart() {
81
104
  this.adapter.log.warn(`Start try again in ${restartTimeout / 1000} seconds...`);
82
105
  autoRestartTimeout = setTimeout(() => {
@@ -84,12 +107,18 @@ class WebsocketController {
84
107
  }, restartTimeout);
85
108
  }
86
109
 
110
+ /**
111
+ *
112
+ */
87
113
  closeConnection() {
88
114
  if (wsClient && wsClient.readyState !== WebSocket.CLOSED) {
89
115
  wsClient.close();
90
116
  }
91
117
  }
92
118
 
119
+ /**
120
+ *
121
+ */
93
122
  async allTimerClear() {
94
123
  clearTimeout(pingTimeout);
95
124
  clearTimeout(ping);
@@ -1,4 +1,14 @@
1
+ /**
2
+ *
3
+ */
1
4
  class Z2mController {
5
+ /**
6
+ *
7
+ * @param adapter
8
+ * @param deviceCache
9
+ * @param groupCache
10
+ * @param logCustomizations
11
+ */
2
12
  constructor(adapter, deviceCache, groupCache, logCustomizations) {
3
13
  this.adapter = adapter;
4
14
  this.groupCache = groupCache;
@@ -6,6 +16,11 @@ class Z2mController {
6
16
  this.logCustomizations = logCustomizations;
7
17
  }
8
18
 
19
+ /**
20
+ *
21
+ * @param id
22
+ * @param state
23
+ */
9
24
  async createZ2MMessage(id, state) {
10
25
  const splitedID = id.split('.');
11
26
  if (splitedID.length < 4) {
@@ -114,6 +129,10 @@ class Z2mController {
114
129
  return controlObj;
115
130
  }
116
131
 
132
+ /**
133
+ *
134
+ * @param messageObj
135
+ */
117
136
  async proxyZ2MLogs(messageObj) {
118
137
  const logMessage = messageObj.payload.message;
119
138
  if (this.logCustomizations.logfilter.some((x) => logMessage.includes(x))) {
package/main.js CHANGED
@@ -68,8 +68,7 @@ class Zigbee2mqtt extends core.Adapter {
68
68
  }
69
69
 
70
70
  const logfilterState = await this.getStateAsync('info.logfilter');
71
- if (logfilterState && logfilterState.val) {
72
- // @ts-ignore
71
+ if (logfilterState && logfilterState.val) {
73
72
  logCustomizations.logfilter = String(logfilterState.val)
74
73
  .split(';')
75
74
  .filter((x) => x); // filter removes empty strings here
@@ -111,9 +110,8 @@ class Zigbee2mqtt extends core.Adapter {
111
110
  `mqtt://${this.config.externalMqttServerIP}:${this.config.externalMqttServerPort}`,
112
111
  mqttClientOptions
113
112
  );
114
- }
113
+ } else {
115
114
  // Internal MQTT-Server
116
- else {
117
115
  mqttServerController = new MqttServerController(this);
118
116
  await mqttServerController.createMQTTServer();
119
117
  await this.delay(1500);
@@ -137,9 +135,8 @@ class Zigbee2mqtt extends core.Adapter {
137
135
  const newMessage = `{"payload":${payload.toString() == '' ? '"null"' : payload.toString()},"topic":"${topic.slice(topic.search('/') + 1)}"}`;
138
136
  this.messageParse(newMessage);
139
137
  });
140
- }
138
+ } else if (this.config.connectionType == 'ws') {
141
139
  // Websocket
142
- else if (this.config.connectionType == 'ws') {
143
140
  if (this.config.wsServerIP == '') {
144
141
  this.log.warn('Please configure the Websoket connection!');
145
142
  return;
@@ -316,9 +313,8 @@ class Zigbee2mqtt extends core.Adapter {
316
313
  } catch (e) {
317
314
  this.log.error(e);
318
315
  }
319
- }
316
+ } else if (this.config.connectionType == 'ws') {
320
317
  // Websocket
321
- else if (this.config.connectionType == 'ws') {
322
318
  try {
323
319
  if (websocketController) {
324
320
  websocketController.closeConnection();
@@ -352,6 +348,8 @@ class Zigbee2mqtt extends core.Adapter {
352
348
  this.log.error(e);
353
349
  }
354
350
 
351
+ this.setState('info.connection', false, true);
352
+
355
353
  callback();
356
354
  }
357
355
 
@@ -382,8 +380,8 @@ class Zigbee2mqtt extends core.Adapter {
382
380
  if (require.main !== module) {
383
381
  // Export the constructor in compact mode
384
382
  /**
385
- * @param {Partial<core.AdapterOptions>} [options={}]
386
- */
383
+ * @param {Partial<core.AdapterOptions>} [options]
384
+ */
387
385
  module.exports = (options) => new Zigbee2mqtt(options);
388
386
  } else {
389
387
  // otherwise start the instance directly
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee2mqtt",
3
- "version": "3.0.10",
3
+ "version": "3.0.14",
4
4
  "description": "Zigbee2MQTT adapter for ioBroker",
5
5
  "author": {
6
6
  "name": "Dennis Rathjen and Arthur Rupp",
@@ -31,7 +31,7 @@
31
31
  "mqtt": "^5.14.1",
32
32
  "net": "^1.0.2",
33
33
  "node-schedule": "^2.1.1",
34
- "sharp": "^0.34.5",
34
+ "sharp": "^0.33.5",
35
35
  "ws": "^8.18.3"
36
36
  },
37
37
  "devDependencies": {
@@ -43,12 +43,8 @@
43
43
  "@iobroker/testing": "^5.2.2",
44
44
  "@iobroker/eslint-config": "^2.1.0",
45
45
  "@tsconfig/node14": "^14.1.8",
46
- "@types/node": "^24.10.1",
46
+ "@types/node": "^25.0.3",
47
47
  "@types/node-schedule": "^2.1.8",
48
- "eslint": "^9.39.1",
49
- "eslint-config-prettier": "^10.1.8",
50
- "eslint-plugin-prettier": "^5.5.4",
51
- "prettier": "^3.6.2",
52
48
  "typescript": "~5.9.2"
53
49
  },
54
50
  "main": "main.js",