matterbridge 3.4.0-dev-20251126-5087664 → 3.4.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 (314) hide show
  1. package/dist/broadcastServer.d.ts +115 -0
  2. package/dist/broadcastServer.d.ts.map +1 -0
  3. package/dist/broadcastServer.js +93 -1
  4. package/dist/broadcastServer.js.map +1 -0
  5. package/dist/broadcastServerTypes.d.ts +838 -0
  6. package/dist/broadcastServerTypes.d.ts.map +1 -0
  7. package/dist/broadcastServerTypes.js +24 -0
  8. package/dist/broadcastServerTypes.js.map +1 -0
  9. package/dist/cli.d.ts +30 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +97 -1
  12. package/dist/cli.js.map +1 -0
  13. package/dist/cliEmitter.d.ts +50 -0
  14. package/dist/cliEmitter.d.ts.map +1 -0
  15. package/dist/cliEmitter.js +37 -0
  16. package/dist/cliEmitter.js.map +1 -0
  17. package/dist/cliHistory.d.ts +48 -0
  18. package/dist/cliHistory.d.ts.map +1 -0
  19. package/dist/cliHistory.js +38 -0
  20. package/dist/cliHistory.js.map +1 -0
  21. package/dist/clusters/export.d.ts +2 -0
  22. package/dist/clusters/export.d.ts.map +1 -0
  23. package/dist/clusters/export.js +2 -0
  24. package/dist/clusters/export.js.map +1 -0
  25. package/dist/defaultConfigSchema.d.ts +28 -0
  26. package/dist/defaultConfigSchema.d.ts.map +1 -0
  27. package/dist/defaultConfigSchema.js +24 -0
  28. package/dist/defaultConfigSchema.js.map +1 -0
  29. package/dist/deviceManager.d.ts +135 -0
  30. package/dist/deviceManager.d.ts.map +1 -0
  31. package/dist/deviceManager.js +113 -1
  32. package/dist/deviceManager.js.map +1 -0
  33. package/dist/devices/airConditioner.d.ts +98 -0
  34. package/dist/devices/airConditioner.d.ts.map +1 -0
  35. package/dist/devices/airConditioner.js +57 -0
  36. package/dist/devices/airConditioner.js.map +1 -0
  37. package/dist/devices/batteryStorage.d.ts +48 -0
  38. package/dist/devices/batteryStorage.d.ts.map +1 -0
  39. package/dist/devices/batteryStorage.js +48 -1
  40. package/dist/devices/batteryStorage.js.map +1 -0
  41. package/dist/devices/cooktop.d.ts +61 -0
  42. package/dist/devices/cooktop.d.ts.map +1 -0
  43. package/dist/devices/cooktop.js +56 -0
  44. package/dist/devices/cooktop.js.map +1 -0
  45. package/dist/devices/dishwasher.d.ts +71 -0
  46. package/dist/devices/dishwasher.d.ts.map +1 -0
  47. package/dist/devices/dishwasher.js +57 -0
  48. package/dist/devices/dishwasher.js.map +1 -0
  49. package/dist/devices/evse.d.ts +76 -0
  50. package/dist/devices/evse.d.ts.map +1 -0
  51. package/dist/devices/evse.js +74 -10
  52. package/dist/devices/evse.js.map +1 -0
  53. package/dist/devices/export.d.ts +17 -0
  54. package/dist/devices/export.d.ts.map +1 -0
  55. package/dist/devices/export.js +5 -0
  56. package/dist/devices/export.js.map +1 -0
  57. package/dist/devices/extractorHood.d.ts +46 -0
  58. package/dist/devices/extractorHood.d.ts.map +1 -0
  59. package/dist/devices/extractorHood.js +43 -0
  60. package/dist/devices/extractorHood.js.map +1 -0
  61. package/dist/devices/heatPump.d.ts +47 -0
  62. package/dist/devices/heatPump.d.ts.map +1 -0
  63. package/dist/devices/heatPump.js +50 -2
  64. package/dist/devices/heatPump.js.map +1 -0
  65. package/dist/devices/laundryDryer.d.ts +67 -0
  66. package/dist/devices/laundryDryer.d.ts.map +1 -0
  67. package/dist/devices/laundryDryer.js +62 -3
  68. package/dist/devices/laundryDryer.js.map +1 -0
  69. package/dist/devices/laundryWasher.d.ts +81 -0
  70. package/dist/devices/laundryWasher.d.ts.map +1 -0
  71. package/dist/devices/laundryWasher.js +70 -4
  72. package/dist/devices/laundryWasher.js.map +1 -0
  73. package/dist/devices/microwaveOven.d.ts +168 -0
  74. package/dist/devices/microwaveOven.d.ts.map +1 -0
  75. package/dist/devices/microwaveOven.js +88 -5
  76. package/dist/devices/microwaveOven.js.map +1 -0
  77. package/dist/devices/oven.d.ts +105 -0
  78. package/dist/devices/oven.d.ts.map +1 -0
  79. package/dist/devices/oven.js +85 -0
  80. package/dist/devices/oven.js.map +1 -0
  81. package/dist/devices/refrigerator.d.ts +118 -0
  82. package/dist/devices/refrigerator.d.ts.map +1 -0
  83. package/dist/devices/refrigerator.js +102 -0
  84. package/dist/devices/refrigerator.js.map +1 -0
  85. package/dist/devices/roboticVacuumCleaner.d.ts +112 -0
  86. package/dist/devices/roboticVacuumCleaner.d.ts.map +1 -0
  87. package/dist/devices/roboticVacuumCleaner.js +100 -9
  88. package/dist/devices/roboticVacuumCleaner.js.map +1 -0
  89. package/dist/devices/solarPower.d.ts +40 -0
  90. package/dist/devices/solarPower.d.ts.map +1 -0
  91. package/dist/devices/solarPower.js +38 -0
  92. package/dist/devices/solarPower.js.map +1 -0
  93. package/dist/devices/speaker.d.ts +87 -0
  94. package/dist/devices/speaker.d.ts.map +1 -0
  95. package/dist/devices/speaker.js +84 -0
  96. package/dist/devices/speaker.js.map +1 -0
  97. package/dist/devices/temperatureControl.d.ts +166 -0
  98. package/dist/devices/temperatureControl.d.ts.map +1 -0
  99. package/dist/devices/temperatureControl.js +24 -3
  100. package/dist/devices/temperatureControl.js.map +1 -0
  101. package/dist/devices/waterHeater.d.ts +111 -0
  102. package/dist/devices/waterHeater.d.ts.map +1 -0
  103. package/dist/devices/waterHeater.js +82 -2
  104. package/dist/devices/waterHeater.js.map +1 -0
  105. package/dist/dgram/coap.d.ts +205 -0
  106. package/dist/dgram/coap.d.ts.map +1 -0
  107. package/dist/dgram/coap.js +126 -13
  108. package/dist/dgram/coap.js.map +1 -0
  109. package/dist/dgram/dgram.d.ts +141 -0
  110. package/dist/dgram/dgram.d.ts.map +1 -0
  111. package/dist/dgram/dgram.js +114 -2
  112. package/dist/dgram/dgram.js.map +1 -0
  113. package/dist/dgram/mb_coap.d.ts +24 -0
  114. package/dist/dgram/mb_coap.d.ts.map +1 -0
  115. package/dist/dgram/mb_coap.js +41 -3
  116. package/dist/dgram/mb_coap.js.map +1 -0
  117. package/dist/dgram/mb_mdns.d.ts +24 -0
  118. package/dist/dgram/mb_mdns.d.ts.map +1 -0
  119. package/dist/dgram/mb_mdns.js +80 -15
  120. package/dist/dgram/mb_mdns.js.map +1 -0
  121. package/dist/dgram/mdns.d.ts +290 -0
  122. package/dist/dgram/mdns.d.ts.map +1 -0
  123. package/dist/dgram/mdns.js +299 -137
  124. package/dist/dgram/mdns.js.map +1 -0
  125. package/dist/dgram/multicast.d.ts +67 -0
  126. package/dist/dgram/multicast.d.ts.map +1 -0
  127. package/dist/dgram/multicast.js +62 -1
  128. package/dist/dgram/multicast.js.map +1 -0
  129. package/dist/dgram/unicast.d.ts +56 -0
  130. package/dist/dgram/unicast.d.ts.map +1 -0
  131. package/dist/dgram/unicast.js +54 -0
  132. package/dist/dgram/unicast.js.map +1 -0
  133. package/dist/frontend.d.ts +238 -0
  134. package/dist/frontend.d.ts.map +1 -0
  135. package/dist/frontend.js +455 -35
  136. package/dist/frontend.js.map +1 -0
  137. package/dist/frontendTypes.d.ts +529 -0
  138. package/dist/frontendTypes.d.ts.map +1 -0
  139. package/dist/frontendTypes.js +45 -0
  140. package/dist/frontendTypes.js.map +1 -0
  141. package/dist/helpers.d.ts +48 -0
  142. package/dist/helpers.d.ts.map +1 -0
  143. package/dist/helpers.js +53 -0
  144. package/dist/helpers.js.map +1 -0
  145. package/dist/index.d.ts +34 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +25 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/jestutils/export.d.ts +2 -0
  150. package/dist/jestutils/export.d.ts.map +1 -0
  151. package/dist/jestutils/export.js +1 -0
  152. package/dist/jestutils/export.js.map +1 -0
  153. package/dist/jestutils/jestHelpers.d.ts +303 -0
  154. package/dist/jestutils/jestHelpers.d.ts.map +1 -0
  155. package/dist/jestutils/jestHelpers.js +352 -13
  156. package/dist/jestutils/jestHelpers.js.map +1 -0
  157. package/dist/logger/export.d.ts +2 -0
  158. package/dist/logger/export.d.ts.map +1 -0
  159. package/dist/logger/export.js +1 -0
  160. package/dist/logger/export.js.map +1 -0
  161. package/dist/matter/behaviors.d.ts +2 -0
  162. package/dist/matter/behaviors.d.ts.map +1 -0
  163. package/dist/matter/behaviors.js +2 -0
  164. package/dist/matter/behaviors.js.map +1 -0
  165. package/dist/matter/clusters.d.ts +2 -0
  166. package/dist/matter/clusters.d.ts.map +1 -0
  167. package/dist/matter/clusters.js +2 -0
  168. package/dist/matter/clusters.js.map +1 -0
  169. package/dist/matter/devices.d.ts +2 -0
  170. package/dist/matter/devices.d.ts.map +1 -0
  171. package/dist/matter/devices.js +2 -0
  172. package/dist/matter/devices.js.map +1 -0
  173. package/dist/matter/endpoints.d.ts +2 -0
  174. package/dist/matter/endpoints.d.ts.map +1 -0
  175. package/dist/matter/endpoints.js +2 -0
  176. package/dist/matter/endpoints.js.map +1 -0
  177. package/dist/matter/export.d.ts +5 -0
  178. package/dist/matter/export.d.ts.map +1 -0
  179. package/dist/matter/export.js +3 -0
  180. package/dist/matter/export.js.map +1 -0
  181. package/dist/matter/types.d.ts +3 -0
  182. package/dist/matter/types.d.ts.map +1 -0
  183. package/dist/matter/types.js +3 -0
  184. package/dist/matter/types.js.map +1 -0
  185. package/dist/matterNode.d.ts +342 -0
  186. package/dist/matterNode.d.ts.map +1 -0
  187. package/dist/matterNode.js +369 -8
  188. package/dist/matterNode.js.map +1 -0
  189. package/dist/matterbridge.d.ts +473 -0
  190. package/dist/matterbridge.d.ts.map +1 -0
  191. package/dist/matterbridge.js +787 -46
  192. package/dist/matterbridge.js.map +1 -0
  193. package/dist/matterbridgeAccessoryPlatform.d.ts +41 -0
  194. package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
  195. package/dist/matterbridgeAccessoryPlatform.js +38 -0
  196. package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
  197. package/dist/matterbridgeBehaviors.d.ts +2404 -0
  198. package/dist/matterbridgeBehaviors.d.ts.map +1 -0
  199. package/dist/matterbridgeBehaviors.js +68 -5
  200. package/dist/matterbridgeBehaviors.js.map +1 -0
  201. package/dist/matterbridgeDeviceTypes.d.ts +698 -0
  202. package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
  203. package/dist/matterbridgeDeviceTypes.js +635 -14
  204. package/dist/matterbridgeDeviceTypes.js.map +1 -0
  205. package/dist/matterbridgeDynamicPlatform.d.ts +41 -0
  206. package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
  207. package/dist/matterbridgeDynamicPlatform.js +38 -0
  208. package/dist/matterbridgeDynamicPlatform.js.map +1 -0
  209. package/dist/matterbridgeEndpoint.d.ts +1507 -0
  210. package/dist/matterbridgeEndpoint.d.ts.map +1 -0
  211. package/dist/matterbridgeEndpoint.js +1444 -53
  212. package/dist/matterbridgeEndpoint.js.map +1 -0
  213. package/dist/matterbridgeEndpointHelpers.d.ts +787 -0
  214. package/dist/matterbridgeEndpointHelpers.d.ts.map +1 -0
  215. package/dist/matterbridgeEndpointHelpers.js +483 -20
  216. package/dist/matterbridgeEndpointHelpers.js.map +1 -0
  217. package/dist/matterbridgeEndpointTypes.d.ts +166 -0
  218. package/dist/matterbridgeEndpointTypes.d.ts.map +1 -0
  219. package/dist/matterbridgeEndpointTypes.js +25 -0
  220. package/dist/matterbridgeEndpointTypes.js.map +1 -0
  221. package/dist/matterbridgePlatform.d.ts +524 -0
  222. package/dist/matterbridgePlatform.d.ts.map +1 -0
  223. package/dist/matterbridgePlatform.js +439 -1
  224. package/dist/matterbridgePlatform.js.map +1 -0
  225. package/dist/matterbridgeTypes.d.ts +251 -0
  226. package/dist/matterbridgeTypes.d.ts.map +1 -0
  227. package/dist/matterbridgeTypes.js +26 -0
  228. package/dist/matterbridgeTypes.js.map +1 -0
  229. package/dist/pluginManager.d.ts +371 -0
  230. package/dist/pluginManager.d.ts.map +1 -0
  231. package/dist/pluginManager.js +340 -5
  232. package/dist/pluginManager.js.map +1 -0
  233. package/dist/shelly.d.ts +174 -0
  234. package/dist/shelly.d.ts.map +1 -0
  235. package/dist/shelly.js +168 -7
  236. package/dist/shelly.js.map +1 -0
  237. package/dist/storage/export.d.ts +2 -0
  238. package/dist/storage/export.d.ts.map +1 -0
  239. package/dist/storage/export.js +1 -0
  240. package/dist/storage/export.js.map +1 -0
  241. package/dist/update.d.ts +75 -0
  242. package/dist/update.d.ts.map +1 -0
  243. package/dist/update.js +69 -0
  244. package/dist/update.js.map +1 -0
  245. package/dist/utils/colorUtils.d.ts +101 -0
  246. package/dist/utils/colorUtils.d.ts.map +1 -0
  247. package/dist/utils/colorUtils.js +97 -2
  248. package/dist/utils/colorUtils.js.map +1 -0
  249. package/dist/utils/commandLine.d.ts +66 -0
  250. package/dist/utils/commandLine.d.ts.map +1 -0
  251. package/dist/utils/commandLine.js +60 -0
  252. package/dist/utils/commandLine.js.map +1 -0
  253. package/dist/utils/copyDirectory.d.ts +35 -0
  254. package/dist/utils/copyDirectory.d.ts.map +1 -0
  255. package/dist/utils/copyDirectory.js +37 -0
  256. package/dist/utils/copyDirectory.js.map +1 -0
  257. package/dist/utils/createDirectory.d.ts +34 -0
  258. package/dist/utils/createDirectory.d.ts.map +1 -0
  259. package/dist/utils/createDirectory.js +33 -0
  260. package/dist/utils/createDirectory.js.map +1 -0
  261. package/dist/utils/createZip.d.ts +39 -0
  262. package/dist/utils/createZip.d.ts.map +1 -0
  263. package/dist/utils/createZip.js +47 -2
  264. package/dist/utils/createZip.js.map +1 -0
  265. package/dist/utils/deepCopy.d.ts +32 -0
  266. package/dist/utils/deepCopy.d.ts.map +1 -0
  267. package/dist/utils/deepCopy.js +39 -0
  268. package/dist/utils/deepCopy.js.map +1 -0
  269. package/dist/utils/deepEqual.d.ts +54 -0
  270. package/dist/utils/deepEqual.d.ts.map +1 -0
  271. package/dist/utils/deepEqual.js +72 -1
  272. package/dist/utils/deepEqual.js.map +1 -0
  273. package/dist/utils/error.d.ts +44 -0
  274. package/dist/utils/error.d.ts.map +1 -0
  275. package/dist/utils/error.js +41 -0
  276. package/dist/utils/error.js.map +1 -0
  277. package/dist/utils/export.d.ts +13 -0
  278. package/dist/utils/export.d.ts.map +1 -0
  279. package/dist/utils/export.js +1 -0
  280. package/dist/utils/export.js.map +1 -0
  281. package/dist/utils/format.d.ts +53 -0
  282. package/dist/utils/format.d.ts.map +1 -0
  283. package/dist/utils/format.js +49 -0
  284. package/dist/utils/format.js.map +1 -0
  285. package/dist/utils/hex.d.ts +89 -0
  286. package/dist/utils/hex.d.ts.map +1 -0
  287. package/dist/utils/hex.js +124 -0
  288. package/dist/utils/hex.js.map +1 -0
  289. package/dist/utils/inspector.d.ts +87 -0
  290. package/dist/utils/inspector.d.ts.map +1 -0
  291. package/dist/utils/inspector.js +69 -1
  292. package/dist/utils/inspector.js.map +1 -0
  293. package/dist/utils/isvalid.d.ts +103 -0
  294. package/dist/utils/isvalid.d.ts.map +1 -0
  295. package/dist/utils/isvalid.js +101 -0
  296. package/dist/utils/isvalid.js.map +1 -0
  297. package/dist/utils/network.d.ts +111 -0
  298. package/dist/utils/network.d.ts.map +1 -0
  299. package/dist/utils/network.js +96 -5
  300. package/dist/utils/network.js.map +1 -0
  301. package/dist/utils/spawn.d.ts +33 -0
  302. package/dist/utils/spawn.d.ts.map +1 -0
  303. package/dist/utils/spawn.js +71 -1
  304. package/dist/utils/spawn.js.map +1 -0
  305. package/dist/utils/tracker.d.ts +108 -0
  306. package/dist/utils/tracker.d.ts.map +1 -0
  307. package/dist/utils/tracker.js +64 -1
  308. package/dist/utils/tracker.js.map +1 -0
  309. package/dist/utils/wait.d.ts +54 -0
  310. package/dist/utils/wait.d.ts.map +1 -0
  311. package/dist/utils/wait.js +60 -8
  312. package/dist/utils/wait.js.map +1 -0
  313. package/npm-shrinkwrap.json +2 -2
  314. package/package.json +2 -1
@@ -1,9 +1,37 @@
1
+ /**
2
+ * This file contains the Plugins class.
3
+ *
4
+ * @file plugins.ts
5
+ * @author Luca Liguori
6
+ * @created 2024-07-14
7
+ * @version 1.3.1
8
+ * @license Apache-2.0
9
+ *
10
+ * Copyright 2024, 2025, 2026 Luca Liguori.
11
+ *
12
+ * Licensed under the Apache License, Version 2.0 (the "License");
13
+ * you may not use this file except in compliance with the License.
14
+ * You may obtain a copy of the License at
15
+ *
16
+ * http://www.apache.org/licenses/LICENSE-2.0
17
+ *
18
+ * Unless required by applicable law or agreed to in writing, software
19
+ * distributed under the License is distributed on an "AS IS" BASIS,
20
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+ * See the License for the specific language governing permissions and
22
+ * limitations under the License.
23
+ */
24
+ // Node.js import
1
25
  import EventEmitter from 'node:events';
26
+ // AnsiLogger module
2
27
  import { AnsiLogger, UNDERLINE, UNDERLINEOFF, BLUE, db, er, nf, nt, rs, wr, debugStringify, CYAN } from 'node-ansi-logger';
3
28
  import { plg, typ } from './matterbridgeTypes.js';
4
29
  import { inspectError, logError } from './utils/error.js';
5
30
  import { hasParameter } from './utils/commandLine.js';
6
31
  import { BroadcastServer } from './broadcastServer.js';
32
+ /**
33
+ * Manages Matterbridge plugins.
34
+ */
7
35
  export class PluginManager extends EventEmitter {
8
36
  matterbridge;
9
37
  _plugins = new Map();
@@ -11,10 +39,15 @@ export class PluginManager extends EventEmitter {
11
39
  server;
12
40
  debug = hasParameter('debug') || hasParameter('verbose');
13
41
  verbose = hasParameter('verbose');
42
+ /**
43
+ * Creates an instance of PluginManager.
44
+ *
45
+ * @param {Matterbridge} matterbridge - The Matterbridge instance.
46
+ */
14
47
  constructor(matterbridge) {
15
48
  super();
16
49
  this.matterbridge = matterbridge;
17
- this.log = new AnsiLogger({ logName: 'PluginManager', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
50
+ this.log = new AnsiLogger({ logName: 'PluginManager', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
18
51
  this.log.debug('Matterbridge plugin manager starting...');
19
52
  this.server = new BroadcastServer('plugins', this.log);
20
53
  this.server.on('broadcast_message', this.msgHandler.bind(this));
@@ -186,7 +219,7 @@ export class PluginManager extends EventEmitter {
186
219
  {
187
220
  const plugin = this.get(msg.params.name);
188
221
  if (plugin) {
189
- this.saveConfigFromJson(plugin, msg.params.config, msg.params.restartRequired);
222
+ this.saveConfigFromJson(plugin, msg.params.config, msg.params.restartRequired); // No await as it's not necessary to wait
190
223
  this.server.respond({ ...msg, response: { success: true } });
191
224
  }
192
225
  else {
@@ -200,25 +233,62 @@ export class PluginManager extends EventEmitter {
200
233
  }
201
234
  }
202
235
  }
236
+ /**
237
+ * Gets the number of plugins.
238
+ *
239
+ * @returns {number} The number of plugins.
240
+ */
203
241
  get length() {
204
242
  return this._plugins.size;
205
243
  }
244
+ /**
245
+ * Gets the number of plugins.
246
+ *
247
+ * @returns {number} The number of plugins.
248
+ */
206
249
  get size() {
207
250
  return this._plugins.size;
208
251
  }
252
+ /**
253
+ * Checks if a plugin with the specified name exists.
254
+ *
255
+ * @param {string} name - The name of the plugin.
256
+ * @returns {boolean} True if the plugin exists, false otherwise.
257
+ */
209
258
  has(name) {
210
259
  return this._plugins.has(name);
211
260
  }
261
+ /**
262
+ * Gets a plugin by its name.
263
+ *
264
+ * @param {string} name - The name of the plugin.
265
+ * @returns {Plugin | undefined} The plugin, or undefined if not found.
266
+ */
212
267
  get(name) {
213
268
  return this._plugins.get(name);
214
269
  }
270
+ /**
271
+ * Adds a plugin to the manager.
272
+ *
273
+ * @param {Plugin} plugin - The plugin to add.
274
+ * @returns {Plugin} The added plugin.
275
+ */
215
276
  set(plugin) {
216
277
  this._plugins.set(plugin.name, plugin);
217
278
  return plugin;
218
279
  }
280
+ /**
281
+ * Clears all plugins from the manager.
282
+ */
219
283
  clear() {
220
284
  this._plugins.clear();
221
285
  }
286
+ /**
287
+ * Converts a plugin or API plugin to a storage plugin.
288
+ *
289
+ * @param {Plugin | ApiPlugin} plugin - The plugin or API plugin to convert.
290
+ * @returns {StoragePlugin} The converted storage plugin.
291
+ */
222
292
  toStoragePlugin(plugin) {
223
293
  return {
224
294
  name: plugin.name,
@@ -230,6 +300,12 @@ export class PluginManager extends EventEmitter {
230
300
  enabled: plugin.enabled,
231
301
  };
232
302
  }
303
+ /**
304
+ * Converts a plugin to an API plugin.
305
+ *
306
+ * @param {Plugin} plugin - The plugin to convert.
307
+ * @returns {ApiPlugin} The converted API plugin.
308
+ */
233
309
  toApiPlugin(plugin) {
234
310
  return {
235
311
  name: plugin.name,
@@ -259,9 +335,19 @@ export class PluginManager extends EventEmitter {
259
335
  matter: plugin.serverNode ? this.matterbridge.getServerNodeData(plugin.serverNode) : undefined,
260
336
  };
261
337
  }
338
+ /**
339
+ * Gets an array of all plugins.
340
+ *
341
+ * @returns {Plugin[]} An array of all plugins.
342
+ */
262
343
  array() {
263
344
  return Array.from(this._plugins.values());
264
345
  }
346
+ /**
347
+ * Gets a StoragePlugin array of all plugins suitable for serialization.
348
+ *
349
+ * @returns {StoragePlugin[]} An array of all plugins.
350
+ */
265
351
  storagePluginArray() {
266
352
  const storagePlugins = [];
267
353
  for (const plugin of this._plugins.values()) {
@@ -269,6 +355,11 @@ export class PluginManager extends EventEmitter {
269
355
  }
270
356
  return storagePlugins;
271
357
  }
358
+ /**
359
+ * Gets an ApiPlugin array of all plugins suitable for serialization.
360
+ *
361
+ * @returns {ApiPlugin[]} An array of all plugins.
362
+ */
272
363
  apiPluginArray() {
273
364
  const apiPlugins = [];
274
365
  for (const plugin of this._plugins.values()) {
@@ -276,9 +367,20 @@ export class PluginManager extends EventEmitter {
276
367
  }
277
368
  return apiPlugins;
278
369
  }
370
+ /**
371
+ * Gets an iterator for the plugins.
372
+ *
373
+ * @returns {IterableIterator<Plugin>} An iterator for the plugins.
374
+ */
279
375
  [Symbol.iterator]() {
280
376
  return this._plugins.values();
281
377
  }
378
+ /**
379
+ * Executes a provided function once for each plugin.
380
+ *
381
+ * @param {Function} callback - The function to execute for each plugin.
382
+ * @returns {Promise<void>}
383
+ */
282
384
  async forEach(callback) {
283
385
  if (this.size === 0)
284
386
  return;
@@ -292,23 +394,40 @@ export class PluginManager extends EventEmitter {
292
394
  });
293
395
  await Promise.all(tasks);
294
396
  }
397
+ /**
398
+ * Sets the log level for the plugin manager.
399
+ *
400
+ * @param {LogLevel} logLevel - The log level to set.
401
+ */
295
402
  set logLevel(logLevel) {
296
403
  this.log.logLevel = logLevel;
297
404
  }
405
+ /**
406
+ * Loads registered plugins from storage.
407
+ *
408
+ * @returns {Promise<StoragePlugin[]>} A promise that resolves to an array of registered plugins.
409
+ */
298
410
  async loadFromStorage() {
299
411
  if (!this.matterbridge.nodeContext) {
300
412
  throw new Error('loadFromStorage: node context is not available.');
301
413
  }
414
+ // Load the array from storage and convert it to a map
302
415
  const pluginsArray = await this.matterbridge.nodeContext.get('plugins', []);
303
416
  for (const plugin of pluginsArray)
304
417
  this._plugins.set(plugin.name, plugin);
305
418
  this.log.debug(`Loaded ${BLUE}${pluginsArray.length}${db} plugins from storage`);
306
419
  return pluginsArray;
307
420
  }
421
+ /**
422
+ * Saves registered plugins to storage.
423
+ *
424
+ * @returns {Promise<number>} A promise that resolves to the number of registered plugins.
425
+ */
308
426
  async saveToStorage() {
309
427
  if (!this.matterbridge.nodeContext) {
310
428
  throw new Error('loadFromStorage: node context is not available.');
311
429
  }
430
+ // Convert the map to an array
312
431
  const plugins = [];
313
432
  for (const plugin of this.array()) {
314
433
  plugins.push({
@@ -325,13 +444,21 @@ export class PluginManager extends EventEmitter {
325
444
  this.log.debug(`Saved ${BLUE}${plugins.length}${db} plugins to storage`);
326
445
  return plugins.length;
327
446
  }
447
+ /**
448
+ * Resolves the name of a plugin by loading and parsing its package.json file.
449
+ *
450
+ * @param {string} nameOrPath - The name of the plugin or the path to the plugin's package.json file.
451
+ * @returns {Promise<string | null>} A promise that resolves to the path of the plugin's package.json file or null if it could not be resolved.
452
+ */
328
453
  async resolve(nameOrPath) {
329
454
  const { default: path } = await import('node:path');
330
455
  const { promises } = await import('node:fs');
331
456
  if (!nameOrPath.endsWith('package.json'))
332
457
  nameOrPath = path.join(nameOrPath, 'package.json');
458
+ // Resolve the package.json of the plugin
333
459
  let packageJsonPath = path.resolve(nameOrPath);
334
460
  this.log.debug(`Resolving plugin path ${plg}${packageJsonPath}${db}`);
461
+ // Check if the package.json file exists
335
462
  try {
336
463
  await promises.access(packageJsonPath);
337
464
  }
@@ -341,7 +468,9 @@ export class PluginManager extends EventEmitter {
341
468
  this.log.debug(`Trying at ${plg}${packageJsonPath}${db}`);
342
469
  }
343
470
  try {
471
+ // Load the package.json of the plugin
344
472
  const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
473
+ // Check for main issues
345
474
  if (!packageJson.name) {
346
475
  this.log.error(`Package.json name not found at ${packageJsonPath}`);
347
476
  return null;
@@ -354,6 +483,7 @@ export class PluginManager extends EventEmitter {
354
483
  this.log.error(`Plugin at ${packageJsonPath} has no main entrypoint in package.json`);
355
484
  return null;
356
485
  }
486
+ // Check for @project-chip and @matter packages in dependencies and devDependencies
357
487
  const checkForProjectChipPackages = (dependencies) => {
358
488
  return Object.keys(dependencies).filter((pkg) => pkg.startsWith('@project-chip') || pkg.startsWith('@matter'));
359
489
  };
@@ -375,6 +505,7 @@ export class PluginManager extends EventEmitter {
375
505
  this.log.error(`Please open an issue on the plugin repository to remove them.`);
376
506
  return null;
377
507
  }
508
+ // Check for matterbridge package in dependencies and devDependencies
378
509
  const checkForMatterbridgePackage = (dependencies) => {
379
510
  return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
380
511
  };
@@ -404,13 +535,19 @@ export class PluginManager extends EventEmitter {
404
535
  return null;
405
536
  }
406
537
  }
538
+ /**
539
+ * Installs a package globally using npm.
540
+ *
541
+ * @param {string} packageName - The name of the package to install.
542
+ * @returns {Promise<boolean>} A promise that resolves to true if the installation was successful, false otherwise.
543
+ */
407
544
  async install(packageName) {
408
545
  this.log.debug(`Installing plugin ${plg}${packageName}${db}...`);
409
546
  const { spawnCommand } = await import('./utils/spawn.js');
410
547
  if (await spawnCommand('npm', ['install', '-g', packageName, '--omit=dev', '--verbose'], 'install', packageName)) {
411
548
  this.matterbridge.restartRequired = true;
412
549
  this.matterbridge.fixedRestartRequired = true;
413
- packageName = packageName.replace(/@.*$/, '');
550
+ packageName = packageName.replace(/@.*$/, ''); // Remove @version if present
414
551
  if (packageName !== 'matterbridge') {
415
552
  if (!this.has(packageName))
416
553
  await this.add(packageName);
@@ -431,6 +568,12 @@ export class PluginManager extends EventEmitter {
431
568
  return false;
432
569
  }
433
570
  }
571
+ /**
572
+ * Uninstalls a package globally using npm.
573
+ *
574
+ * @param {string} packageName - The name of the package to uninstall.
575
+ * @returns {Promise<boolean>} A promise that resolves to true if the uninstallation was successful, false otherwise.
576
+ */
434
577
  async uninstall(packageName) {
435
578
  this.log.debug(`Uninstalling plugin ${plg}${packageName}${db}...`);
436
579
  const { spawnCommand } = await import('./utils/spawn.js');
@@ -452,6 +595,12 @@ export class PluginManager extends EventEmitter {
452
595
  return false;
453
596
  }
454
597
  }
598
+ /**
599
+ * Get the author of a plugin from its package.json.
600
+ *
601
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
602
+ * @returns {string} The author of the plugin, or 'Unknown author' if not found.
603
+ */
455
604
  getAuthor(packageJson) {
456
605
  if (packageJson.author && typeof packageJson.author === 'string')
457
606
  return packageJson.author;
@@ -459,6 +608,12 @@ export class PluginManager extends EventEmitter {
459
608
  return packageJson.author.name;
460
609
  return 'Unknown author';
461
610
  }
611
+ /**
612
+ * Get the homepage of a plugin from its package.json.
613
+ *
614
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
615
+ * @returns {string | undefined} The homepage of the plugin, or undefined if not found.
616
+ */
462
617
  getHomepage(packageJson) {
463
618
  if (packageJson.homepage && typeof packageJson.homepage === 'string' && packageJson.homepage.includes('http')) {
464
619
  return packageJson.homepage.replace('git+', '').replace('.git', '');
@@ -467,7 +622,14 @@ export class PluginManager extends EventEmitter {
467
622
  return packageJson.repository.url.replace('git+', '').replace('.git', '');
468
623
  }
469
624
  }
625
+ /**
626
+ * Get the help URL of a plugin from its package.json.
627
+ *
628
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
629
+ * @returns {string | undefined} The URL to the help page or to the README file, or undefined if not found.
630
+ */
470
631
  getHelp(packageJson) {
632
+ // If there's a help field that looks like a URL, return it.
471
633
  if (packageJson.help && typeof packageJson.help === 'string' && packageJson.help.startsWith('http')) {
472
634
  return packageJson.help;
473
635
  }
@@ -478,7 +640,14 @@ export class PluginManager extends EventEmitter {
478
640
  return packageJson.homepage.replace('git+', '').replace('.git', '');
479
641
  }
480
642
  }
643
+ /**
644
+ * Get the changelog URL of a plugin from its package.json.
645
+ *
646
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
647
+ * @returns {string | undefined} The URL to the CHANGELOG file, or undefined if not found.
648
+ */
481
649
  getChangelog(packageJson) {
650
+ // If there's a changelog field that looks like a URL, return it.
482
651
  if (packageJson.changelog && typeof packageJson.changelog === 'string' && packageJson.changelog.startsWith('http')) {
483
652
  return packageJson.changelog;
484
653
  }
@@ -489,6 +658,13 @@ export class PluginManager extends EventEmitter {
489
658
  return packageJson.homepage.replace('git+', '').replace('.git', '');
490
659
  }
491
660
  }
661
+ /**
662
+ * Get the first funding URL(s) of a plugin from its package.json.
663
+ *
664
+ * @param {Record<string, any>} packageJson - The package.json object of the plugin.
665
+ * @returns {string | undefined} The first funding URLs, or undefined if not found.
666
+ */
667
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
492
668
  getFunding(packageJson) {
493
669
  const funding = packageJson.funding;
494
670
  if (!funding)
@@ -497,16 +673,27 @@ export class PluginManager extends EventEmitter {
497
673
  return;
498
674
  if (typeof funding === 'string' && funding.startsWith('http'))
499
675
  return funding;
676
+ // Normalize funding into an array.
500
677
  const fundingEntries = Array.isArray(funding) ? funding : [funding];
501
678
  for (const entry of fundingEntries) {
502
679
  if (entry && typeof entry === 'string' && entry.startsWith('http')) {
680
+ // If the funding entry is a string, assume it is a URL.
503
681
  return entry;
504
682
  }
505
683
  else if (entry && typeof entry === 'object' && typeof entry.url === 'string' && entry.url.startsWith('http')) {
684
+ // If it's an object with a 'url' property, use that.
506
685
  return entry.url;
507
686
  }
508
687
  }
509
688
  }
689
+ /**
690
+ * Parses the plugin package.json and returns it.
691
+ * It will also log warnings and errors for missing or invalid fields.
692
+ * It will return null if critical errors are found.
693
+ *
694
+ * @param {Plugin | PluginName} plugin - The plugin to load the package from.
695
+ * @returns {Promise<Record<string, string | number | object> | null>} A promise that resolves to the parsed package.json object or null if it could not be parsed.
696
+ */
510
697
  async parse(plugin) {
511
698
  const { promises } = await import('node:fs');
512
699
  if (typeof plugin === 'string') {
@@ -544,6 +731,7 @@ export class PluginManager extends EventEmitter {
544
731
  plugin.funding = this.getFunding(packageJson);
545
732
  if (!plugin.type)
546
733
  this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no type`);
734
+ // Check for @project-chip and @matter packages in dependencies and devDependencies
547
735
  const checkForProjectChipPackages = (dependencies) => {
548
736
  return Object.keys(dependencies).filter((pkg) => pkg.startsWith('@project-chip') || pkg.startsWith('@matter'));
549
737
  };
@@ -565,6 +753,7 @@ export class PluginManager extends EventEmitter {
565
753
  this.log.error(`Please open an issue on the plugin repository to remove them.`);
566
754
  return null;
567
755
  }
756
+ // Check for matterbridge package in dependencies and devDependencies
568
757
  const checkForMatterbridgePackage = (dependencies) => {
569
758
  return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
570
759
  };
@@ -594,6 +783,16 @@ export class PluginManager extends EventEmitter {
594
783
  return null;
595
784
  }
596
785
  }
786
+ /**
787
+ * Enables a plugin by its name or path.
788
+ *
789
+ * This method enables a plugin by setting its `enabled` property to `true` and saving the updated
790
+ * plugin information to storage. It first checks if the plugin is already registered in the `_plugins` map.
791
+ * If not, it attempts to resolve the plugin's `package.json` file to retrieve its name and enable it.
792
+ *
793
+ * @param {string} nameOrPath - The name or path of the plugin to enable.
794
+ * @returns {Promise<Plugin | null>} A promise that resolves to the enabled plugin object, or null if the plugin could not be enabled.
795
+ */
597
796
  async enable(nameOrPath) {
598
797
  const { promises } = await import('node:fs');
599
798
  if (!nameOrPath)
@@ -629,6 +828,16 @@ export class PluginManager extends EventEmitter {
629
828
  return null;
630
829
  }
631
830
  }
831
+ /**
832
+ * Disables a plugin by its name or path.
833
+ *
834
+ * This method disables a plugin by setting its `enabled` property to `false` and saving the updated
835
+ * plugin information to storage. It first checks if the plugin is already registered in the `_plugins` map.
836
+ * If not, it attempts to resolve the plugin's `package.json` file to retrieve its name and disable it.
837
+ *
838
+ * @param {string} nameOrPath - The name or path of the plugin to enable.
839
+ * @returns {Promise<Plugin | null>} A promise that resolves to the disabled plugin object, or null if the plugin could not be disabled.
840
+ */
632
841
  async disable(nameOrPath) {
633
842
  const { promises } = await import('node:fs');
634
843
  if (!nameOrPath)
@@ -664,6 +873,16 @@ export class PluginManager extends EventEmitter {
664
873
  return null;
665
874
  }
666
875
  }
876
+ /**
877
+ * Removes a plugin by its name or path.
878
+ *
879
+ * This method removes a plugin from the `_plugins` map and saves the updated plugin information to storage.
880
+ * It first checks if the plugin is already registered in the `_plugins` map. If not, it attempts to resolve
881
+ * the plugin's `package.json` file to retrieve its name and remove it.
882
+ *
883
+ * @param {string} nameOrPath - The name or path of the plugin to remove.
884
+ * @returns {Promise<Plugin | null>} A promise that resolves to the removed plugin object, or null if the plugin could not be removed.
885
+ */
667
886
  async remove(nameOrPath) {
668
887
  const { promises } = await import('node:fs');
669
888
  if (!nameOrPath)
@@ -699,6 +918,17 @@ export class PluginManager extends EventEmitter {
699
918
  return null;
700
919
  }
701
920
  }
921
+ /**
922
+ * Adds a plugin by its name or path.
923
+ *
924
+ * This method adds a plugin to the plugins map and saves the updated plugin information to storage.
925
+ * It first resolves the plugin's `package.json` file to retrieve its details. If the plugin is already
926
+ * registered, it logs an info message and returns null. Otherwise, it registers the plugin, enables it,
927
+ * and saves the updated plugin information to storage.
928
+ *
929
+ * @param {string} nameOrPath - The name or path of the plugin to add.
930
+ * @returns {Promise<Plugin | null>} A promise that resolves to the added plugin object, or null if the plugin could not be added.
931
+ */
702
932
  async add(nameOrPath) {
703
933
  const { promises } = await import('node:fs');
704
934
  if (!nameOrPath)
@@ -738,6 +968,15 @@ export class PluginManager extends EventEmitter {
738
968
  return null;
739
969
  }
740
970
  }
971
+ /**
972
+ * Loads a plugin and returns the corresponding MatterbridgePlatform instance.
973
+ *
974
+ * @param {Plugin | PluginName} plugin - The plugin to load.
975
+ * @param {boolean} start - Optional flag indicating whether to start the plugin after loading. Default is false.
976
+ * @param {string} message - Optional message to pass to the plugin when starting.
977
+ * @param {boolean} configure - Optional flag indicating whether to configure the plugin after loading. Default is false.
978
+ * @returns {Promise<MatterbridgePlatform | undefined>} A Promise that resolves to the loaded MatterbridgePlatform instance or undefined.
979
+ */
741
980
  async load(plugin, start = false, message = '', configure = false) {
742
981
  const { promises } = await import('node:fs');
743
982
  const { default: path } = await import('node:path');
@@ -759,15 +998,20 @@ export class PluginManager extends EventEmitter {
759
998
  }
760
999
  this.log.info(`Loading plugin ${plg}${plugin.name}${nf} type ${typ}${plugin.type}${nf}`);
761
1000
  try {
1001
+ // Load the package.json of the plugin
762
1002
  const packageJson = JSON.parse(await promises.readFile(plugin.path, 'utf8'));
1003
+ // Resolve the main module path relative to package.json
763
1004
  const pluginEntry = path.resolve(path.dirname(plugin.path), packageJson.main);
1005
+ // Dynamically import the plugin
764
1006
  const { pathToFileURL } = await import('node:url');
765
1007
  const pluginUrl = pathToFileURL(pluginEntry);
766
1008
  this.log.debug(`Importing plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
767
1009
  const pluginInstance = (await import(pluginUrl.href));
768
1010
  this.log.debug(`Imported plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
1011
+ // Call the default export function of the plugin, passing this MatterBridge instance, the log and the config
769
1012
  if (pluginInstance.default) {
770
1013
  const config = await this.loadConfig(plugin);
1014
+ // Preset the plugin properties here in case the plugin throws an error during loading. In this case the user can change the config and restart the plugin.
771
1015
  plugin.name = packageJson.name;
772
1016
  plugin.description = packageJson.description ?? 'No description';
773
1017
  plugin.version = packageJson.version;
@@ -776,7 +1020,7 @@ export class PluginManager extends EventEmitter {
776
1020
  plugin.schemaJson = await this.loadSchema(plugin);
777
1021
  config.name = packageJson.name;
778
1022
  config.version = packageJson.version;
779
- const log = new AnsiLogger({ logName: plugin.description, logTimestampFormat: 4, logLevel: config.debug ? "debug" : this.matterbridge.logLevel });
1023
+ const log = new AnsiLogger({ logName: plugin.description, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: config.debug ? "debug" /* LogLevel.DEBUG */ : this.matterbridge.logLevel });
780
1024
  const platform = pluginInstance.default(this.matterbridge, log, config);
781
1025
  config.type = platform.type;
782
1026
  platform.name = packageJson.name;
@@ -795,7 +1039,7 @@ export class PluginManager extends EventEmitter {
795
1039
  plugin.platform = platform;
796
1040
  plugin.loaded = true;
797
1041
  plugin.registeredDevices = 0;
798
- await this.saveToStorage();
1042
+ await this.saveToStorage(); // Save the plugin to storage
799
1043
  this.log.notice(`Loaded plugin ${plg}${plugin.name}${nt} type ${typ}${platform.type}${nt} (entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
800
1044
  this.emit('loaded', plugin.name);
801
1045
  if (start)
@@ -815,6 +1059,14 @@ export class PluginManager extends EventEmitter {
815
1059
  }
816
1060
  return undefined;
817
1061
  }
1062
+ /**
1063
+ * Starts a plugin.
1064
+ *
1065
+ * @param {Plugin | PluginName} plugin - The plugin to start.
1066
+ * @param {string} [message] - Optional message to pass to the plugin's onStart method.
1067
+ * @param {boolean} [configure] - Indicates whether to configure the plugin after starting (default false).
1068
+ * @returns {Promise<Plugin | undefined>} A promise that resolves when the plugin is started successfully, or rejects with an error if starting the plugin fails.
1069
+ */
818
1070
  async start(plugin, message, configure = false) {
819
1071
  if (typeof plugin === 'string') {
820
1072
  const p = this._plugins.get(plugin);
@@ -854,6 +1106,12 @@ export class PluginManager extends EventEmitter {
854
1106
  }
855
1107
  return undefined;
856
1108
  }
1109
+ /**
1110
+ * Configures a plugin.
1111
+ *
1112
+ * @param {Plugin | PluginName} plugin - The plugin to configure.
1113
+ * @returns {Promise<Plugin | undefined>} A promise that resolves when the plugin is configured successfully, or rejects with an error if configuration fails.
1114
+ */
857
1115
  async configure(plugin) {
858
1116
  if (typeof plugin === 'string') {
859
1117
  const p = this._plugins.get(plugin);
@@ -894,6 +1152,18 @@ export class PluginManager extends EventEmitter {
894
1152
  }
895
1153
  return undefined;
896
1154
  }
1155
+ /**
1156
+ * Shuts down a plugin.
1157
+ *
1158
+ * This method shuts down a plugin by calling its `onShutdown` method and resetting its state.
1159
+ * It logs the shutdown process and optionally removes all devices associated with the plugin.
1160
+ *
1161
+ * @param {Plugin | PluginName} plugin - The plugin to shut down.
1162
+ * @param {string} [reason] - The reason for shutting down the plugin.
1163
+ * @param {boolean} [removeAllDevices] - Whether to remove all devices associated with the plugin.
1164
+ * @param {boolean} [force] - Whether to force the shutdown even if the plugin is not loaded or started.
1165
+ * @returns {Promise<Plugin | undefined>} A promise that resolves to the shut down plugin object, or undefined if the shutdown failed.
1166
+ */
897
1167
  async shutdown(plugin, reason, removeAllDevices = false, force = false) {
898
1168
  if (typeof plugin === 'string') {
899
1169
  const p = this._plugins.get(plugin);
@@ -948,6 +1218,15 @@ export class PluginManager extends EventEmitter {
948
1218
  }
949
1219
  return undefined;
950
1220
  }
1221
+ /**
1222
+ * Loads the configuration for a plugin.
1223
+ * If the configuration file exists, it reads the file and returns the parsed JSON data.
1224
+ * If the configuration file does not exist, it creates a new file with default configuration and returns it.
1225
+ * If any error occurs during file access or creation, it logs an error and return un empty config.
1226
+ *
1227
+ * @param {Plugin} plugin - The plugin for which to load the configuration.
1228
+ * @returns {Promise<PlatformConfig>} A promise that resolves to the loaded or created configuration.
1229
+ */
951
1230
  async loadConfig(plugin) {
952
1231
  const { default: path } = await import('node:path');
953
1232
  const { promises } = await import('node:fs');
@@ -959,6 +1238,8 @@ export class PluginManager extends EventEmitter {
959
1238
  const data = await promises.readFile(configFile, 'utf8');
960
1239
  const config = JSON.parse(data);
961
1240
  this.log.debug(`Loaded config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
1241
+ // this.log.debug(`Loaded config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
1242
+ // The first time a plugin is added to the system, the config file is created with the plugin name and type "AnyPlatform".
962
1243
  config.name = plugin.name;
963
1244
  config.type = plugin.type;
964
1245
  if (config.debug === undefined)
@@ -980,6 +1261,8 @@ export class PluginManager extends EventEmitter {
980
1261
  }
981
1262
  catch (_err) {
982
1263
  this.log.debug(`Default config file ${defaultConfigFile} for plugin ${plg}${plugin.name}${db} does not exist, creating new config file...`);
1264
+ // TODO: Remove this when all these plugins have their own default config file
1265
+ // istanbul ignore next if
983
1266
  if (plugin.name === 'matterbridge-zigbee2mqtt')
984
1267
  config = zigbee2mqtt_config;
985
1268
  else if (plugin.name === 'matterbridge-somfy-tahoma')
@@ -992,6 +1275,7 @@ export class PluginManager extends EventEmitter {
992
1275
  try {
993
1276
  await promises.writeFile(configFile, JSON.stringify(config, null, 2), 'utf8');
994
1277
  this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
1278
+ // this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
995
1279
  return config;
996
1280
  }
997
1281
  catch (err) {
@@ -1005,6 +1289,19 @@ export class PluginManager extends EventEmitter {
1005
1289
  }
1006
1290
  }
1007
1291
  }
1292
+ /**
1293
+ * Saves the configuration of a plugin to a file.
1294
+ *
1295
+ * This method saves the configuration of the specified plugin to a JSON file in the matterbridge directory.
1296
+ * If the plugin's configuration is not found, it logs an error and rejects the promise. If the configuration
1297
+ * is successfully saved, it logs a debug message. If an error occurs during the file write operation, it logs
1298
+ * the error and rejects the promise.
1299
+ *
1300
+ * @param {Plugin} plugin - The plugin whose configuration is to be saved.
1301
+ * @param {boolean} [restartRequired] - Indicates whether a restart is required after saving the configuration.
1302
+ * @returns {Promise<void>} A promise that resolves when the configuration is successfully saved, or rejects if an error occurs.
1303
+ * @throws {Error} If the plugin's configuration is not found.
1304
+ */
1008
1305
  async saveConfigFromPlugin(plugin, restartRequired = false) {
1009
1306
  const { default: path } = await import('node:path');
1010
1307
  const { promises } = await import('node:fs');
@@ -1019,6 +1316,7 @@ export class PluginManager extends EventEmitter {
1019
1316
  if (restartRequired)
1020
1317
  plugin.restartRequired = true;
1021
1318
  this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
1319
+ // this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, plugin.platform.config);
1022
1320
  return Promise.resolve();
1023
1321
  }
1024
1322
  catch (err) {
@@ -1026,6 +1324,20 @@ export class PluginManager extends EventEmitter {
1026
1324
  return Promise.reject(err);
1027
1325
  }
1028
1326
  }
1327
+ /**
1328
+ * Saves the configuration of a plugin from a JSON object to a file.
1329
+ *
1330
+ * This method saves the provided configuration of the specified plugin to a JSON file in the matterbridge directory.
1331
+ * It first checks if the configuration data is valid by ensuring it contains the correct name and type, and matches
1332
+ * the plugin's name. If the configuration data is invalid, it logs an error and returns. If the configuration is
1333
+ * successfully saved, it updates the plugin's `configJson` property and logs a debug message. If an error occurs
1334
+ * during the file write operation, it logs the error and returns.
1335
+ *
1336
+ * @param {Plugin} plugin - The plugin whose configuration is to be saved.
1337
+ * @param {PlatformConfig} config - The configuration data to be saved.
1338
+ * @param {boolean} [restartRequired] - Indicates whether a restart is required after saving the configuration.
1339
+ * @returns {Promise<void>} A promise that resolves when the configuration is successfully saved, or returns if an error occurs.
1340
+ */
1029
1341
  async saveConfigFromJson(plugin, config, restartRequired = false) {
1030
1342
  const { default: path } = await import('node:path');
1031
1343
  const { promises } = await import('node:fs');
@@ -1044,12 +1356,23 @@ export class PluginManager extends EventEmitter {
1044
1356
  plugin.platform.onConfigChanged(config).catch((err) => this.log.error(`Error calling onConfigChanged for plugin ${plg}${plugin.name}${er}: ${err}`));
1045
1357
  }
1046
1358
  this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
1359
+ // this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
1047
1360
  }
1048
1361
  catch (err) {
1049
1362
  logError(this.log, `Error saving config file ${configFile} for plugin ${plg}${plugin.name}${er}`, err);
1050
1363
  return;
1051
1364
  }
1052
1365
  }
1366
+ /**
1367
+ * Loads the schema for a plugin.
1368
+ *
1369
+ * This method attempts to load the schema file for the specified plugin. If the schema file is found,
1370
+ * it reads and parses the file, updates the schema's title and description, and logs the process.
1371
+ * If the schema file is not found, it logs the event and loads a default schema for the plugin.
1372
+ *
1373
+ * @param {Plugin} plugin - The plugin whose schema is to be loaded.
1374
+ * @returns {Promise<PlatformSchema>} A promise that resolves to the loaded schema object, or the default schema if the schema file is not found.
1375
+ */
1053
1376
  async loadSchema(plugin) {
1054
1377
  const { promises } = await import('node:fs');
1055
1378
  const schemaFile = plugin.path.replace('package.json', `${plugin.name}.schema.json`);
@@ -1060,6 +1383,7 @@ export class PluginManager extends EventEmitter {
1060
1383
  schema.title = plugin.description;
1061
1384
  schema.description = plugin.name + ' v. ' + plugin.version + ' by ' + plugin.author;
1062
1385
  this.log.debug(`Loaded schema file ${schemaFile} for plugin ${plg}${plugin.name}${db}.`);
1386
+ // this.log.debug(`Loaded schema file ${schemaFile} for plugin ${plg}${plugin.name}${db}.\nSchema:${rs}\n`, schema);
1063
1387
  return schema;
1064
1388
  }
1065
1389
  catch (_err) {
@@ -1067,6 +1391,16 @@ export class PluginManager extends EventEmitter {
1067
1391
  return this.getDefaultSchema(plugin);
1068
1392
  }
1069
1393
  }
1394
+ /**
1395
+ * Returns the default schema for a plugin.
1396
+ *
1397
+ * This method generates a default schema object for the specified plugin. The schema includes
1398
+ * metadata such as the plugin's title, description, version, and author. It also defines the
1399
+ * properties of the schema, including the plugin's name, type, debug flag, and unregisterOnShutdown flag.
1400
+ *
1401
+ * @param {Plugin} plugin - The plugin for which the default schema is to be generated.
1402
+ * @returns {PlatformSchema} The default schema object for the plugin.
1403
+ */
1070
1404
  getDefaultSchema(plugin) {
1071
1405
  return {
1072
1406
  title: plugin.description,
@@ -1097,3 +1431,4 @@ export class PluginManager extends EventEmitter {
1097
1431
  };
1098
1432
  }
1099
1433
  }
1434
+ //# sourceMappingURL=pluginManager.js.map