matterbridge 3.4.1-dev-20251130-422c2fc → 3.4.1

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 (324) hide show
  1. package/CHANGELOG.md +10 -9
  2. package/README-SERVICE-OPT.md +1 -0
  3. package/dist/broadcastServer.d.ts +136 -0
  4. package/dist/broadcastServer.d.ts.map +1 -0
  5. package/dist/broadcastServer.js +112 -0
  6. package/dist/broadcastServer.js.map +1 -0
  7. package/dist/broadcastServerTypes.d.ts +841 -0
  8. package/dist/broadcastServerTypes.d.ts.map +1 -0
  9. package/dist/broadcastServerTypes.js +24 -0
  10. package/dist/broadcastServerTypes.js.map +1 -0
  11. package/dist/cli.d.ts +30 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +97 -1
  14. package/dist/cli.js.map +1 -0
  15. package/dist/cliEmitter.d.ts +50 -0
  16. package/dist/cliEmitter.d.ts.map +1 -0
  17. package/dist/cliEmitter.js +37 -0
  18. package/dist/cliEmitter.js.map +1 -0
  19. package/dist/cliHistory.d.ts +48 -0
  20. package/dist/cliHistory.d.ts.map +1 -0
  21. package/dist/cliHistory.js +38 -0
  22. package/dist/cliHistory.js.map +1 -0
  23. package/dist/clusters/export.d.ts +2 -0
  24. package/dist/clusters/export.d.ts.map +1 -0
  25. package/dist/clusters/export.js +2 -0
  26. package/dist/clusters/export.js.map +1 -0
  27. package/dist/deviceManager.d.ts +135 -0
  28. package/dist/deviceManager.d.ts.map +1 -0
  29. package/dist/deviceManager.js +113 -1
  30. package/dist/deviceManager.js.map +1 -0
  31. package/dist/devices/airConditioner.d.ts +98 -0
  32. package/dist/devices/airConditioner.d.ts.map +1 -0
  33. package/dist/devices/airConditioner.js +57 -0
  34. package/dist/devices/airConditioner.js.map +1 -0
  35. package/dist/devices/batteryStorage.d.ts +48 -0
  36. package/dist/devices/batteryStorage.d.ts.map +1 -0
  37. package/dist/devices/batteryStorage.js +48 -1
  38. package/dist/devices/batteryStorage.js.map +1 -0
  39. package/dist/devices/cooktop.d.ts +61 -0
  40. package/dist/devices/cooktop.d.ts.map +1 -0
  41. package/dist/devices/cooktop.js +56 -0
  42. package/dist/devices/cooktop.js.map +1 -0
  43. package/dist/devices/dishwasher.d.ts +71 -0
  44. package/dist/devices/dishwasher.d.ts.map +1 -0
  45. package/dist/devices/dishwasher.js +57 -0
  46. package/dist/devices/dishwasher.js.map +1 -0
  47. package/dist/devices/evse.d.ts +76 -0
  48. package/dist/devices/evse.d.ts.map +1 -0
  49. package/dist/devices/evse.js +74 -10
  50. package/dist/devices/evse.js.map +1 -0
  51. package/dist/devices/export.d.ts +17 -0
  52. package/dist/devices/export.d.ts.map +1 -0
  53. package/dist/devices/export.js +5 -0
  54. package/dist/devices/export.js.map +1 -0
  55. package/dist/devices/extractorHood.d.ts +46 -0
  56. package/dist/devices/extractorHood.d.ts.map +1 -0
  57. package/dist/devices/extractorHood.js +43 -0
  58. package/dist/devices/extractorHood.js.map +1 -0
  59. package/dist/devices/heatPump.d.ts +47 -0
  60. package/dist/devices/heatPump.d.ts.map +1 -0
  61. package/dist/devices/heatPump.js +50 -2
  62. package/dist/devices/heatPump.js.map +1 -0
  63. package/dist/devices/laundryDryer.d.ts +67 -0
  64. package/dist/devices/laundryDryer.d.ts.map +1 -0
  65. package/dist/devices/laundryDryer.js +62 -3
  66. package/dist/devices/laundryDryer.js.map +1 -0
  67. package/dist/devices/laundryWasher.d.ts +81 -0
  68. package/dist/devices/laundryWasher.d.ts.map +1 -0
  69. package/dist/devices/laundryWasher.js +70 -4
  70. package/dist/devices/laundryWasher.js.map +1 -0
  71. package/dist/devices/microwaveOven.d.ts +168 -0
  72. package/dist/devices/microwaveOven.d.ts.map +1 -0
  73. package/dist/devices/microwaveOven.js +88 -5
  74. package/dist/devices/microwaveOven.js.map +1 -0
  75. package/dist/devices/oven.d.ts +105 -0
  76. package/dist/devices/oven.d.ts.map +1 -0
  77. package/dist/devices/oven.js +85 -0
  78. package/dist/devices/oven.js.map +1 -0
  79. package/dist/devices/refrigerator.d.ts +118 -0
  80. package/dist/devices/refrigerator.d.ts.map +1 -0
  81. package/dist/devices/refrigerator.js +102 -0
  82. package/dist/devices/refrigerator.js.map +1 -0
  83. package/dist/devices/roboticVacuumCleaner.d.ts +112 -0
  84. package/dist/devices/roboticVacuumCleaner.d.ts.map +1 -0
  85. package/dist/devices/roboticVacuumCleaner.js +100 -9
  86. package/dist/devices/roboticVacuumCleaner.js.map +1 -0
  87. package/dist/devices/solarPower.d.ts +40 -0
  88. package/dist/devices/solarPower.d.ts.map +1 -0
  89. package/dist/devices/solarPower.js +38 -0
  90. package/dist/devices/solarPower.js.map +1 -0
  91. package/dist/devices/speaker.d.ts +87 -0
  92. package/dist/devices/speaker.d.ts.map +1 -0
  93. package/dist/devices/speaker.js +84 -0
  94. package/dist/devices/speaker.js.map +1 -0
  95. package/dist/devices/temperatureControl.d.ts +166 -0
  96. package/dist/devices/temperatureControl.d.ts.map +1 -0
  97. package/dist/devices/temperatureControl.js +24 -3
  98. package/dist/devices/temperatureControl.js.map +1 -0
  99. package/dist/devices/waterHeater.d.ts +111 -0
  100. package/dist/devices/waterHeater.d.ts.map +1 -0
  101. package/dist/devices/waterHeater.js +82 -2
  102. package/dist/devices/waterHeater.js.map +1 -0
  103. package/dist/dgram/coap.d.ts +205 -0
  104. package/dist/dgram/coap.d.ts.map +1 -0
  105. package/dist/dgram/coap.js +126 -13
  106. package/dist/dgram/coap.js.map +1 -0
  107. package/dist/dgram/dgram.d.ts +141 -0
  108. package/dist/dgram/dgram.d.ts.map +1 -0
  109. package/dist/dgram/dgram.js +114 -2
  110. package/dist/dgram/dgram.js.map +1 -0
  111. package/dist/dgram/mb_coap.d.ts +24 -0
  112. package/dist/dgram/mb_coap.d.ts.map +1 -0
  113. package/dist/dgram/mb_coap.js +41 -3
  114. package/dist/dgram/mb_coap.js.map +1 -0
  115. package/dist/dgram/mb_mdns.d.ts +24 -0
  116. package/dist/dgram/mb_mdns.d.ts.map +1 -0
  117. package/dist/dgram/mb_mdns.js +80 -15
  118. package/dist/dgram/mb_mdns.js.map +1 -0
  119. package/dist/dgram/mdns.d.ts +290 -0
  120. package/dist/dgram/mdns.d.ts.map +1 -0
  121. package/dist/dgram/mdns.js +299 -137
  122. package/dist/dgram/mdns.js.map +1 -0
  123. package/dist/dgram/multicast.d.ts +67 -0
  124. package/dist/dgram/multicast.d.ts.map +1 -0
  125. package/dist/dgram/multicast.js +62 -1
  126. package/dist/dgram/multicast.js.map +1 -0
  127. package/dist/dgram/unicast.d.ts +56 -0
  128. package/dist/dgram/unicast.d.ts.map +1 -0
  129. package/dist/dgram/unicast.js +54 -0
  130. package/dist/dgram/unicast.js.map +1 -0
  131. package/dist/frontend.d.ts +238 -0
  132. package/dist/frontend.d.ts.map +1 -0
  133. package/dist/frontend.js +455 -35
  134. package/dist/frontend.js.map +1 -0
  135. package/dist/frontendTypes.d.ts +529 -0
  136. package/dist/frontendTypes.d.ts.map +1 -0
  137. package/dist/frontendTypes.js +45 -0
  138. package/dist/frontendTypes.js.map +1 -0
  139. package/dist/helpers.d.ts +48 -0
  140. package/dist/helpers.d.ts.map +1 -0
  141. package/dist/helpers.js +53 -0
  142. package/dist/helpers.js.map +1 -0
  143. package/dist/index.d.ts +34 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +25 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/jestutils/export.d.ts +2 -0
  148. package/dist/jestutils/export.d.ts.map +1 -0
  149. package/dist/jestutils/export.js +1 -0
  150. package/dist/jestutils/export.js.map +1 -0
  151. package/dist/jestutils/jestHelpers.d.ts +340 -0
  152. package/dist/jestutils/jestHelpers.d.ts.map +1 -0
  153. package/dist/jestutils/jestHelpers.js +375 -14
  154. package/dist/jestutils/jestHelpers.js.map +1 -0
  155. package/dist/logger/export.d.ts +2 -0
  156. package/dist/logger/export.d.ts.map +1 -0
  157. package/dist/logger/export.js +1 -0
  158. package/dist/logger/export.js.map +1 -0
  159. package/dist/matter/behaviors.d.ts +2 -0
  160. package/dist/matter/behaviors.d.ts.map +1 -0
  161. package/dist/matter/behaviors.js +2 -0
  162. package/dist/matter/behaviors.js.map +1 -0
  163. package/dist/matter/clusters.d.ts +2 -0
  164. package/dist/matter/clusters.d.ts.map +1 -0
  165. package/dist/matter/clusters.js +2 -0
  166. package/dist/matter/clusters.js.map +1 -0
  167. package/dist/matter/devices.d.ts +2 -0
  168. package/dist/matter/devices.d.ts.map +1 -0
  169. package/dist/matter/devices.js +2 -0
  170. package/dist/matter/devices.js.map +1 -0
  171. package/dist/matter/endpoints.d.ts +2 -0
  172. package/dist/matter/endpoints.d.ts.map +1 -0
  173. package/dist/matter/endpoints.js +2 -0
  174. package/dist/matter/endpoints.js.map +1 -0
  175. package/dist/matter/export.d.ts +5 -0
  176. package/dist/matter/export.d.ts.map +1 -0
  177. package/dist/matter/export.js +3 -0
  178. package/dist/matter/export.js.map +1 -0
  179. package/dist/matter/types.d.ts +3 -0
  180. package/dist/matter/types.d.ts.map +1 -0
  181. package/dist/matter/types.js +3 -0
  182. package/dist/matter/types.js.map +1 -0
  183. package/dist/matterNode.d.ts +342 -0
  184. package/dist/matterNode.d.ts.map +1 -0
  185. package/dist/matterNode.js +369 -8
  186. package/dist/matterNode.js.map +1 -0
  187. package/dist/matterbridge.d.ts +493 -0
  188. package/dist/matterbridge.d.ts.map +1 -0
  189. package/dist/matterbridge.js +808 -46
  190. package/dist/matterbridge.js.map +1 -0
  191. package/dist/matterbridgeAccessoryPlatform.d.ts +41 -0
  192. package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
  193. package/dist/matterbridgeAccessoryPlatform.js +38 -0
  194. package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
  195. package/dist/matterbridgeBehaviors.d.ts +2404 -0
  196. package/dist/matterbridgeBehaviors.d.ts.map +1 -0
  197. package/dist/matterbridgeBehaviors.js +68 -5
  198. package/dist/matterbridgeBehaviors.js.map +1 -0
  199. package/dist/matterbridgeDeviceTypes.d.ts +698 -0
  200. package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
  201. package/dist/matterbridgeDeviceTypes.js +635 -14
  202. package/dist/matterbridgeDeviceTypes.js.map +1 -0
  203. package/dist/matterbridgeDynamicPlatform.d.ts +41 -0
  204. package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
  205. package/dist/matterbridgeDynamicPlatform.js +38 -0
  206. package/dist/matterbridgeDynamicPlatform.js.map +1 -0
  207. package/dist/matterbridgeEndpoint.d.ts +1507 -0
  208. package/dist/matterbridgeEndpoint.d.ts.map +1 -0
  209. package/dist/matterbridgeEndpoint.js +1444 -53
  210. package/dist/matterbridgeEndpoint.js.map +1 -0
  211. package/dist/matterbridgeEndpointHelpers.d.ts +787 -0
  212. package/dist/matterbridgeEndpointHelpers.d.ts.map +1 -0
  213. package/dist/matterbridgeEndpointHelpers.js +483 -20
  214. package/dist/matterbridgeEndpointHelpers.js.map +1 -0
  215. package/dist/matterbridgeEndpointTypes.d.ts +166 -0
  216. package/dist/matterbridgeEndpointTypes.d.ts.map +1 -0
  217. package/dist/matterbridgeEndpointTypes.js +25 -0
  218. package/dist/matterbridgeEndpointTypes.js.map +1 -0
  219. package/dist/matterbridgePlatform.d.ts +537 -0
  220. package/dist/matterbridgePlatform.d.ts.map +1 -0
  221. package/dist/matterbridgePlatform.js +471 -8
  222. package/dist/matterbridgePlatform.js.map +1 -0
  223. package/dist/matterbridgeTypes.d.ts +251 -0
  224. package/dist/matterbridgeTypes.d.ts.map +1 -0
  225. package/dist/matterbridgeTypes.js +26 -0
  226. package/dist/matterbridgeTypes.js.map +1 -0
  227. package/dist/pluginManager.d.ts +372 -0
  228. package/dist/pluginManager.d.ts.map +1 -0
  229. package/dist/pluginManager.js +342 -5
  230. package/dist/pluginManager.js.map +1 -0
  231. package/dist/shelly.d.ts +181 -0
  232. package/dist/shelly.d.ts.map +1 -0
  233. package/dist/shelly.js +178 -7
  234. package/dist/shelly.js.map +1 -0
  235. package/dist/storage/export.d.ts +2 -0
  236. package/dist/storage/export.d.ts.map +1 -0
  237. package/dist/storage/export.js +1 -0
  238. package/dist/storage/export.js.map +1 -0
  239. package/dist/update.d.ts +84 -0
  240. package/dist/update.d.ts.map +1 -0
  241. package/dist/update.js +93 -1
  242. package/dist/update.js.map +1 -0
  243. package/dist/utils/colorUtils.d.ts +101 -0
  244. package/dist/utils/colorUtils.d.ts.map +1 -0
  245. package/dist/utils/colorUtils.js +97 -2
  246. package/dist/utils/colorUtils.js.map +1 -0
  247. package/dist/utils/commandLine.d.ts +66 -0
  248. package/dist/utils/commandLine.d.ts.map +1 -0
  249. package/dist/utils/commandLine.js +60 -0
  250. package/dist/utils/commandLine.js.map +1 -0
  251. package/dist/utils/copyDirectory.d.ts +35 -0
  252. package/dist/utils/copyDirectory.d.ts.map +1 -0
  253. package/dist/utils/copyDirectory.js +37 -0
  254. package/dist/utils/copyDirectory.js.map +1 -0
  255. package/dist/utils/createDirectory.d.ts +34 -0
  256. package/dist/utils/createDirectory.d.ts.map +1 -0
  257. package/dist/utils/createDirectory.js +33 -0
  258. package/dist/utils/createDirectory.js.map +1 -0
  259. package/dist/utils/createZip.d.ts +39 -0
  260. package/dist/utils/createZip.d.ts.map +1 -0
  261. package/dist/utils/createZip.js +47 -2
  262. package/dist/utils/createZip.js.map +1 -0
  263. package/dist/utils/deepCopy.d.ts +32 -0
  264. package/dist/utils/deepCopy.d.ts.map +1 -0
  265. package/dist/utils/deepCopy.js +39 -0
  266. package/dist/utils/deepCopy.js.map +1 -0
  267. package/dist/utils/deepEqual.d.ts +54 -0
  268. package/dist/utils/deepEqual.d.ts.map +1 -0
  269. package/dist/utils/deepEqual.js +72 -1
  270. package/dist/utils/deepEqual.js.map +1 -0
  271. package/dist/utils/error.d.ts +45 -0
  272. package/dist/utils/error.d.ts.map +1 -0
  273. package/dist/utils/error.js +42 -0
  274. package/dist/utils/error.js.map +1 -0
  275. package/dist/utils/export.d.ts +13 -0
  276. package/dist/utils/export.d.ts.map +1 -0
  277. package/dist/utils/export.js +1 -0
  278. package/dist/utils/export.js.map +1 -0
  279. package/dist/utils/format.d.ts +53 -0
  280. package/dist/utils/format.d.ts.map +1 -0
  281. package/dist/utils/format.js +49 -0
  282. package/dist/utils/format.js.map +1 -0
  283. package/dist/utils/hex.d.ts +89 -0
  284. package/dist/utils/hex.d.ts.map +1 -0
  285. package/dist/utils/hex.js +124 -0
  286. package/dist/utils/hex.js.map +1 -0
  287. package/dist/utils/inspector.d.ts +87 -0
  288. package/dist/utils/inspector.d.ts.map +1 -0
  289. package/dist/utils/inspector.js +69 -1
  290. package/dist/utils/inspector.js.map +1 -0
  291. package/dist/utils/isvalid.d.ts +103 -0
  292. package/dist/utils/isvalid.d.ts.map +1 -0
  293. package/dist/utils/isvalid.js +101 -0
  294. package/dist/utils/isvalid.js.map +1 -0
  295. package/dist/utils/network.d.ts +111 -0
  296. package/dist/utils/network.d.ts.map +1 -0
  297. package/dist/utils/network.js +96 -5
  298. package/dist/utils/network.js.map +1 -0
  299. package/dist/utils/spawn.d.ts +33 -0
  300. package/dist/utils/spawn.d.ts.map +1 -0
  301. package/dist/utils/spawn.js +71 -1
  302. package/dist/utils/spawn.js.map +1 -0
  303. package/dist/utils/tracker.d.ts +108 -0
  304. package/dist/utils/tracker.d.ts.map +1 -0
  305. package/dist/utils/tracker.js +64 -1
  306. package/dist/utils/tracker.js.map +1 -0
  307. package/dist/utils/wait.d.ts +54 -0
  308. package/dist/utils/wait.d.ts.map +1 -0
  309. package/dist/utils/wait.js +60 -8
  310. package/dist/utils/wait.js.map +1 -0
  311. package/dist/workerGlobalPrefix.d.ts +25 -0
  312. package/dist/workerGlobalPrefix.d.ts.map +1 -0
  313. package/dist/workerGlobalPrefix.js +37 -5
  314. package/dist/workerGlobalPrefix.js.map +1 -0
  315. package/dist/workerTypes.d.ts +52 -0
  316. package/dist/workerTypes.d.ts.map +1 -0
  317. package/dist/workerTypes.js +24 -0
  318. package/dist/workerTypes.js.map +1 -0
  319. package/dist/workers.d.ts +69 -0
  320. package/dist/workers.d.ts.map +1 -0
  321. package/dist/workers.js +68 -4
  322. package/dist/workers.js.map +1 -0
  323. package/npm-shrinkwrap.json +2 -2
  324. 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.4
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));
@@ -187,7 +220,7 @@ export class PluginManager extends EventEmitter {
187
220
  {
188
221
  const plugin = this.get(msg.params.name);
189
222
  if (plugin) {
190
- this.saveConfigFromJson(plugin, msg.params.config, msg.params.restartRequired);
223
+ this.saveConfigFromJson(plugin, msg.params.config, msg.params.restartRequired); // No await as it's not necessary to wait
191
224
  this.server.respond({ ...msg, result: { success: true } });
192
225
  }
193
226
  else {
@@ -225,25 +258,62 @@ export class PluginManager extends EventEmitter {
225
258
  }
226
259
  }
227
260
  }
261
+ /**
262
+ * Gets the number of plugins.
263
+ *
264
+ * @returns {number} The number of plugins.
265
+ */
228
266
  get length() {
229
267
  return this._plugins.size;
230
268
  }
269
+ /**
270
+ * Gets the number of plugins.
271
+ *
272
+ * @returns {number} The number of plugins.
273
+ */
231
274
  get size() {
232
275
  return this._plugins.size;
233
276
  }
277
+ /**
278
+ * Checks if a plugin with the specified name exists.
279
+ *
280
+ * @param {string} name - The name of the plugin.
281
+ * @returns {boolean} True if the plugin exists, false otherwise.
282
+ */
234
283
  has(name) {
235
284
  return this._plugins.has(name);
236
285
  }
286
+ /**
287
+ * Gets a plugin by its name.
288
+ *
289
+ * @param {string} name - The name of the plugin.
290
+ * @returns {Plugin | undefined} The plugin, or undefined if not found.
291
+ */
237
292
  get(name) {
238
293
  return this._plugins.get(name);
239
294
  }
295
+ /**
296
+ * Adds a plugin to the manager.
297
+ *
298
+ * @param {Plugin} plugin - The plugin to add.
299
+ * @returns {Plugin} The added plugin.
300
+ */
240
301
  set(plugin) {
241
302
  this._plugins.set(plugin.name, plugin);
242
303
  return plugin;
243
304
  }
305
+ /**
306
+ * Clears all plugins from the manager.
307
+ */
244
308
  clear() {
245
309
  this._plugins.clear();
246
310
  }
311
+ /**
312
+ * Converts a plugin or API plugin to a storage plugin.
313
+ *
314
+ * @param {Plugin | ApiPlugin} plugin - The plugin or API plugin to convert.
315
+ * @returns {StoragePlugin} The converted storage plugin.
316
+ */
247
317
  toStoragePlugin(plugin) {
248
318
  return {
249
319
  name: plugin.name,
@@ -255,6 +325,12 @@ export class PluginManager extends EventEmitter {
255
325
  enabled: plugin.enabled,
256
326
  };
257
327
  }
328
+ /**
329
+ * Converts a plugin to an API plugin.
330
+ *
331
+ * @param {Plugin} plugin - The plugin to convert.
332
+ * @returns {ApiPlugin} The converted API plugin.
333
+ */
258
334
  toApiPlugin(plugin) {
259
335
  return {
260
336
  name: plugin.name,
@@ -284,9 +360,19 @@ export class PluginManager extends EventEmitter {
284
360
  matter: plugin.serverNode ? this.matterbridge.getServerNodeData(plugin.serverNode) : undefined,
285
361
  };
286
362
  }
363
+ /**
364
+ * Gets an array of all plugins.
365
+ *
366
+ * @returns {Plugin[]} An array of all plugins.
367
+ */
287
368
  array() {
288
369
  return Array.from(this._plugins.values());
289
370
  }
371
+ /**
372
+ * Gets a StoragePlugin array of all plugins suitable for serialization.
373
+ *
374
+ * @returns {StoragePlugin[]} An array of all plugins.
375
+ */
290
376
  storagePluginArray() {
291
377
  const storagePlugins = [];
292
378
  for (const plugin of this._plugins.values()) {
@@ -294,6 +380,11 @@ export class PluginManager extends EventEmitter {
294
380
  }
295
381
  return storagePlugins;
296
382
  }
383
+ /**
384
+ * Gets an ApiPlugin array of all plugins suitable for serialization.
385
+ *
386
+ * @returns {ApiPlugin[]} An array of all plugins.
387
+ */
297
388
  apiPluginArray() {
298
389
  const apiPlugins = [];
299
390
  for (const plugin of this._plugins.values()) {
@@ -301,9 +392,20 @@ export class PluginManager extends EventEmitter {
301
392
  }
302
393
  return apiPlugins;
303
394
  }
395
+ /**
396
+ * Gets an iterator for the plugins.
397
+ *
398
+ * @returns {IterableIterator<Plugin>} An iterator for the plugins.
399
+ */
304
400
  [Symbol.iterator]() {
305
401
  return this._plugins.values();
306
402
  }
403
+ /**
404
+ * Executes a provided function once for each plugin.
405
+ *
406
+ * @param {Function} callback - The function to execute for each plugin.
407
+ * @returns {Promise<void>}
408
+ */
307
409
  async forEach(callback) {
308
410
  if (this.size === 0)
309
411
  return;
@@ -317,23 +419,40 @@ export class PluginManager extends EventEmitter {
317
419
  });
318
420
  await Promise.all(tasks);
319
421
  }
422
+ /**
423
+ * Sets the log level for the plugin manager.
424
+ *
425
+ * @param {LogLevel} logLevel - The log level to set.
426
+ */
320
427
  set logLevel(logLevel) {
321
428
  this.log.logLevel = logLevel;
322
429
  }
430
+ /**
431
+ * Loads registered plugins from storage.
432
+ *
433
+ * @returns {Promise<StoragePlugin[]>} A promise that resolves to an array of registered plugins.
434
+ */
323
435
  async loadFromStorage() {
324
436
  if (!this.matterbridge.nodeContext) {
325
437
  throw new Error('loadFromStorage: node context is not available.');
326
438
  }
439
+ // Load the array from storage and convert it to a map
327
440
  const pluginsArray = await this.matterbridge.nodeContext.get('plugins', []);
328
441
  for (const plugin of pluginsArray)
329
442
  this._plugins.set(plugin.name, plugin);
330
443
  this.log.debug(`Loaded ${BLUE}${pluginsArray.length}${db} plugins from storage`);
331
444
  return pluginsArray;
332
445
  }
446
+ /**
447
+ * Saves registered plugins to storage.
448
+ *
449
+ * @returns {Promise<number>} A promise that resolves to the number of registered plugins.
450
+ */
333
451
  async saveToStorage() {
334
452
  if (!this.matterbridge.nodeContext) {
335
453
  throw new Error('loadFromStorage: node context is not available.');
336
454
  }
455
+ // Convert the map to an array
337
456
  const plugins = [];
338
457
  for (const plugin of this.array()) {
339
458
  plugins.push({
@@ -350,13 +469,22 @@ export class PluginManager extends EventEmitter {
350
469
  this.log.debug(`Saved ${BLUE}${plugins.length}${db} plugins to storage`);
351
470
  return plugins.length;
352
471
  }
472
+ /**
473
+ * Resolves the name of a plugin by loading and parsing its package.json file.
474
+ * It will first try to resolve the path as is, then in the global modules directory, and finally in the matterbridge plugin directory.
475
+ *
476
+ * @param {string} nameOrPath - The name of the plugin or the path to the plugin's package.json file.
477
+ * @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.
478
+ */
353
479
  async resolve(nameOrPath) {
354
480
  const { default: path } = await import('node:path');
355
481
  const { promises } = await import('node:fs');
356
482
  if (!nameOrPath.endsWith('package.json'))
357
483
  nameOrPath = path.join(nameOrPath, 'package.json');
484
+ // Resolve the package.json of the plugin
358
485
  let packageJsonPath = path.resolve(nameOrPath);
359
486
  this.log.debug(`Resolving plugin path ${plg}${packageJsonPath}${db}`);
487
+ // Check if the package.json file exists at the specified path or next try in the global modules directory
360
488
  try {
361
489
  await promises.access(packageJsonPath);
362
490
  }
@@ -365,6 +493,7 @@ export class PluginManager extends EventEmitter {
365
493
  packageJsonPath = path.join(this.matterbridge.globalModulesDirectory, nameOrPath);
366
494
  this.log.debug(`Trying at ${plg}${packageJsonPath}${db}`);
367
495
  }
496
+ // Check if the package.json file exists at the global modules directory or next try in the matterbridge plugin directory
368
497
  try {
369
498
  await promises.access(packageJsonPath);
370
499
  }
@@ -374,7 +503,9 @@ export class PluginManager extends EventEmitter {
374
503
  this.log.debug(`Trying at ${plg}${packageJsonPath}${db}`);
375
504
  }
376
505
  try {
506
+ // Load the package.json of the plugin or fails if even not found in the matterbridge plugin directory
377
507
  const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
508
+ // Check for main issues
378
509
  if (!packageJson.name) {
379
510
  this.log.error(`Package.json name not found at ${packageJsonPath}`);
380
511
  return null;
@@ -387,6 +518,7 @@ export class PluginManager extends EventEmitter {
387
518
  this.log.error(`Plugin at ${packageJsonPath} has no main entrypoint in package.json`);
388
519
  return null;
389
520
  }
521
+ // Check for @project-chip and @matter packages in dependencies and devDependencies
390
522
  const checkForProjectChipPackages = (dependencies) => {
391
523
  return Object.keys(dependencies).filter((pkg) => pkg.startsWith('@project-chip') || pkg.startsWith('@matter'));
392
524
  };
@@ -408,6 +540,7 @@ export class PluginManager extends EventEmitter {
408
540
  this.log.error(`Please open an issue on the plugin repository to remove them.`);
409
541
  return null;
410
542
  }
543
+ // Check for matterbridge package in dependencies and devDependencies
411
544
  const checkForMatterbridgePackage = (dependencies) => {
412
545
  return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
413
546
  };
@@ -437,13 +570,19 @@ export class PluginManager extends EventEmitter {
437
570
  return null;
438
571
  }
439
572
  }
573
+ /**
574
+ * Installs a package globally using npm.
575
+ *
576
+ * @param {string} packageName - The name of the package to install.
577
+ * @returns {Promise<boolean>} A promise that resolves to true if the installation was successful, false otherwise.
578
+ */
440
579
  async install(packageName) {
441
580
  this.log.debug(`Installing plugin ${plg}${packageName}${db}...`);
442
581
  const { spawnCommand } = await import('./utils/spawn.js');
443
582
  if (await spawnCommand('npm', ['install', '-g', packageName, '--omit=dev', '--verbose'], 'install', packageName)) {
444
583
  this.matterbridge.restartRequired = true;
445
584
  this.matterbridge.fixedRestartRequired = true;
446
- packageName = packageName.replace(/@.*$/, '');
585
+ packageName = packageName.replace(/@.*$/, ''); // Remove @version if present
447
586
  if (packageName !== 'matterbridge') {
448
587
  if (!this.has(packageName))
449
588
  await this.add(packageName);
@@ -464,6 +603,12 @@ export class PluginManager extends EventEmitter {
464
603
  return false;
465
604
  }
466
605
  }
606
+ /**
607
+ * Uninstalls a package globally using npm.
608
+ *
609
+ * @param {string} packageName - The name of the package to uninstall.
610
+ * @returns {Promise<boolean>} A promise that resolves to true if the uninstallation was successful, false otherwise.
611
+ */
467
612
  async uninstall(packageName) {
468
613
  this.log.debug(`Uninstalling plugin ${plg}${packageName}${db}...`);
469
614
  const { spawnCommand } = await import('./utils/spawn.js');
@@ -485,6 +630,12 @@ export class PluginManager extends EventEmitter {
485
630
  return false;
486
631
  }
487
632
  }
633
+ /**
634
+ * Get the author of a plugin from its package.json.
635
+ *
636
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
637
+ * @returns {string} The author of the plugin, or 'Unknown author' if not found.
638
+ */
488
639
  getAuthor(packageJson) {
489
640
  if (packageJson.author && typeof packageJson.author === 'string')
490
641
  return packageJson.author;
@@ -492,6 +643,12 @@ export class PluginManager extends EventEmitter {
492
643
  return packageJson.author.name;
493
644
  return 'Unknown author';
494
645
  }
646
+ /**
647
+ * Get the homepage of a plugin from its package.json.
648
+ *
649
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
650
+ * @returns {string | undefined} The homepage of the plugin, or undefined if not found.
651
+ */
495
652
  getHomepage(packageJson) {
496
653
  if (packageJson.homepage && typeof packageJson.homepage === 'string' && packageJson.homepage.includes('http')) {
497
654
  return packageJson.homepage.replace('git+', '').replace('.git', '');
@@ -500,7 +657,14 @@ export class PluginManager extends EventEmitter {
500
657
  return packageJson.repository.url.replace('git+', '').replace('.git', '');
501
658
  }
502
659
  }
660
+ /**
661
+ * Get the help URL of a plugin from its package.json.
662
+ *
663
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
664
+ * @returns {string | undefined} The URL to the help page or to the README file, or undefined if not found.
665
+ */
503
666
  getHelp(packageJson) {
667
+ // If there's a help field that looks like a URL, return it.
504
668
  if (packageJson.help && typeof packageJson.help === 'string' && packageJson.help.startsWith('http')) {
505
669
  return packageJson.help;
506
670
  }
@@ -511,7 +675,14 @@ export class PluginManager extends EventEmitter {
511
675
  return packageJson.homepage.replace('git+', '').replace('.git', '');
512
676
  }
513
677
  }
678
+ /**
679
+ * Get the changelog URL of a plugin from its package.json.
680
+ *
681
+ * @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
682
+ * @returns {string | undefined} The URL to the CHANGELOG file, or undefined if not found.
683
+ */
514
684
  getChangelog(packageJson) {
685
+ // If there's a changelog field that looks like a URL, return it.
515
686
  if (packageJson.changelog && typeof packageJson.changelog === 'string' && packageJson.changelog.startsWith('http')) {
516
687
  return packageJson.changelog;
517
688
  }
@@ -522,6 +693,13 @@ export class PluginManager extends EventEmitter {
522
693
  return packageJson.homepage.replace('git+', '').replace('.git', '');
523
694
  }
524
695
  }
696
+ /**
697
+ * Get the first funding URL(s) of a plugin from its package.json.
698
+ *
699
+ * @param {Record<string, any>} packageJson - The package.json object of the plugin.
700
+ * @returns {string | undefined} The first funding URLs, or undefined if not found.
701
+ */
702
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
525
703
  getFunding(packageJson) {
526
704
  const funding = packageJson.funding;
527
705
  if (!funding)
@@ -530,16 +708,27 @@ export class PluginManager extends EventEmitter {
530
708
  return;
531
709
  if (typeof funding === 'string' && funding.startsWith('http'))
532
710
  return funding;
711
+ // Normalize funding into an array.
533
712
  const fundingEntries = Array.isArray(funding) ? funding : [funding];
534
713
  for (const entry of fundingEntries) {
535
714
  if (entry && typeof entry === 'string' && entry.startsWith('http')) {
715
+ // If the funding entry is a string, assume it is a URL.
536
716
  return entry;
537
717
  }
538
718
  else if (entry && typeof entry === 'object' && typeof entry.url === 'string' && entry.url.startsWith('http')) {
719
+ // If it's an object with a 'url' property, use that.
539
720
  return entry.url;
540
721
  }
541
722
  }
542
723
  }
724
+ /**
725
+ * Parses the plugin package.json and returns it.
726
+ * It will also log warnings and errors for missing or invalid fields.
727
+ * It will return null if critical errors are found.
728
+ *
729
+ * @param {Plugin | PluginName} plugin - The plugin to load the package from.
730
+ * @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.
731
+ */
543
732
  async parse(plugin) {
544
733
  const { promises } = await import('node:fs');
545
734
  if (typeof plugin === 'string') {
@@ -577,6 +766,7 @@ export class PluginManager extends EventEmitter {
577
766
  plugin.funding = this.getFunding(packageJson);
578
767
  if (!plugin.type)
579
768
  this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no type`);
769
+ // Check for @project-chip and @matter packages in dependencies and devDependencies
580
770
  const checkForProjectChipPackages = (dependencies) => {
581
771
  return Object.keys(dependencies).filter((pkg) => pkg.startsWith('@project-chip') || pkg.startsWith('@matter'));
582
772
  };
@@ -598,6 +788,7 @@ export class PluginManager extends EventEmitter {
598
788
  this.log.error(`Please open an issue on the plugin repository to remove them.`);
599
789
  return null;
600
790
  }
791
+ // Check for matterbridge package in dependencies and devDependencies
601
792
  const checkForMatterbridgePackage = (dependencies) => {
602
793
  return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
603
794
  };
@@ -627,6 +818,16 @@ export class PluginManager extends EventEmitter {
627
818
  return null;
628
819
  }
629
820
  }
821
+ /**
822
+ * Enables a plugin by its name or path.
823
+ *
824
+ * This method enables a plugin by setting its `enabled` property to `true` and saving the updated
825
+ * plugin information to storage. It first checks if the plugin is already registered in the `_plugins` map.
826
+ * If not, it attempts to resolve the plugin's `package.json` file to retrieve its name and enable it.
827
+ *
828
+ * @param {string} nameOrPath - The name or path of the plugin to enable.
829
+ * @returns {Promise<Plugin | null>} A promise that resolves to the enabled plugin object, or null if the plugin could not be enabled.
830
+ */
630
831
  async enable(nameOrPath) {
631
832
  const { promises } = await import('node:fs');
632
833
  if (!nameOrPath)
@@ -662,6 +863,16 @@ export class PluginManager extends EventEmitter {
662
863
  return null;
663
864
  }
664
865
  }
866
+ /**
867
+ * Disables a plugin by its name or path.
868
+ *
869
+ * This method disables a plugin by setting its `enabled` property to `false` and saving the updated
870
+ * plugin information to storage. It first checks if the plugin is already registered in the `_plugins` map.
871
+ * If not, it attempts to resolve the plugin's `package.json` file to retrieve its name and disable it.
872
+ *
873
+ * @param {string} nameOrPath - The name or path of the plugin to enable.
874
+ * @returns {Promise<Plugin | null>} A promise that resolves to the disabled plugin object, or null if the plugin could not be disabled.
875
+ */
665
876
  async disable(nameOrPath) {
666
877
  const { promises } = await import('node:fs');
667
878
  if (!nameOrPath)
@@ -697,6 +908,16 @@ export class PluginManager extends EventEmitter {
697
908
  return null;
698
909
  }
699
910
  }
911
+ /**
912
+ * Removes a plugin by its name or path.
913
+ *
914
+ * This method removes a plugin from the `_plugins` map and saves the updated plugin information to storage.
915
+ * It first checks if the plugin is already registered in the `_plugins` map. If not, it attempts to resolve
916
+ * the plugin's `package.json` file to retrieve its name and remove it.
917
+ *
918
+ * @param {string} nameOrPath - The name or path of the plugin to remove.
919
+ * @returns {Promise<Plugin | null>} A promise that resolves to the removed plugin object, or null if the plugin could not be removed.
920
+ */
700
921
  async remove(nameOrPath) {
701
922
  const { promises } = await import('node:fs');
702
923
  if (!nameOrPath)
@@ -732,6 +953,17 @@ export class PluginManager extends EventEmitter {
732
953
  return null;
733
954
  }
734
955
  }
956
+ /**
957
+ * Adds a plugin by its name or path.
958
+ *
959
+ * This method adds a plugin to the plugins map and saves the updated plugin information to storage.
960
+ * It first resolves the plugin's `package.json` file to retrieve its details. If the plugin is already
961
+ * registered, it logs an info message and returns null. Otherwise, it registers the plugin, enables it,
962
+ * and saves the updated plugin information to storage.
963
+ *
964
+ * @param {string} nameOrPath - The name or path of the plugin to add.
965
+ * @returns {Promise<Plugin | null>} A promise that resolves to the added plugin object, or null if the plugin could not be added.
966
+ */
735
967
  async add(nameOrPath) {
736
968
  const { promises } = await import('node:fs');
737
969
  if (!nameOrPath)
@@ -771,6 +1003,15 @@ export class PluginManager extends EventEmitter {
771
1003
  return null;
772
1004
  }
773
1005
  }
1006
+ /**
1007
+ * Loads a plugin and returns the corresponding MatterbridgePlatform instance.
1008
+ *
1009
+ * @param {Plugin | PluginName} plugin - The plugin to load.
1010
+ * @param {boolean} start - Optional flag indicating whether to start the plugin after loading. Default is false.
1011
+ * @param {string} message - Optional message to pass to the plugin when starting.
1012
+ * @param {boolean} configure - Optional flag indicating whether to configure the plugin after loading. Default is false.
1013
+ * @returns {Promise<MatterbridgePlatform | undefined>} A Promise that resolves to the loaded MatterbridgePlatform instance or undefined.
1014
+ */
774
1015
  async load(plugin, start = false, message = '', configure = false) {
775
1016
  const { promises } = await import('node:fs');
776
1017
  const { default: path } = await import('node:path');
@@ -792,15 +1033,20 @@ export class PluginManager extends EventEmitter {
792
1033
  }
793
1034
  this.log.info(`Loading plugin ${plg}${plugin.name}${nf} type ${typ}${plugin.type}${nf}`);
794
1035
  try {
1036
+ // Load the package.json of the plugin
795
1037
  const packageJson = JSON.parse(await promises.readFile(plugin.path, 'utf8'));
1038
+ // Resolve the main module path relative to package.json
796
1039
  const pluginEntry = path.resolve(path.dirname(plugin.path), packageJson.main);
1040
+ // Dynamically import the plugin
797
1041
  const { pathToFileURL } = await import('node:url');
798
1042
  const pluginUrl = pathToFileURL(pluginEntry);
799
1043
  this.log.debug(`Importing plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
800
1044
  const pluginInstance = (await import(pluginUrl.href));
801
1045
  this.log.debug(`Imported plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
1046
+ // Call the default export function of the plugin, passing this MatterBridge instance, the log and the config
802
1047
  if (pluginInstance.default) {
803
1048
  const config = await this.loadConfig(plugin);
1049
+ // 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.
804
1050
  plugin.name = packageJson.name;
805
1051
  plugin.description = packageJson.description ?? 'No description';
806
1052
  plugin.version = packageJson.version;
@@ -809,13 +1055,15 @@ export class PluginManager extends EventEmitter {
809
1055
  plugin.schemaJson = await this.loadSchema(plugin);
810
1056
  config.name = packageJson.name;
811
1057
  config.version = packageJson.version;
812
- const log = new AnsiLogger({ logName: plugin.description, logTimestampFormat: 4, logLevel: config.debug ? "debug" : this.matterbridge.logLevel });
1058
+ const log = new AnsiLogger({ logName: plugin.description, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: config.debug ? "debug" /* LogLevel.DEBUG */ : this.matterbridge.logLevel });
813
1059
  const platform = pluginInstance.default(this.matterbridge, log, config);
814
1060
  config.type = platform.type;
815
1061
  platform.name = packageJson.name;
816
1062
  platform.config = config;
817
1063
  platform.version = packageJson.version;
818
1064
  platform.isLoaded = true;
1065
+ // @ts-expect-error - setMatterNode is intentionally private
1066
+ platform.setMatterNode?.(this.matterbridge.addBridgedEndpoint.bind(this.matterbridge), this.matterbridge.removeBridgedEndpoint.bind(this.matterbridge), this.matterbridge.removeAllBridgedEndpoints.bind(this.matterbridge), this.matterbridge.addVirtualEndpoint.bind(this.matterbridge));
819
1067
  plugin.name = packageJson.name;
820
1068
  plugin.description = packageJson.description ?? 'No description';
821
1069
  plugin.version = packageJson.version;
@@ -828,7 +1076,7 @@ export class PluginManager extends EventEmitter {
828
1076
  plugin.platform = platform;
829
1077
  plugin.loaded = true;
830
1078
  plugin.registeredDevices = 0;
831
- await this.saveToStorage();
1079
+ await this.saveToStorage(); // Save the plugin to storage
832
1080
  this.log.notice(`Loaded plugin ${plg}${plugin.name}${nt} type ${typ}${platform.type}${nt} (entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
833
1081
  this.emit('loaded', plugin.name);
834
1082
  if (start)
@@ -848,6 +1096,14 @@ export class PluginManager extends EventEmitter {
848
1096
  }
849
1097
  return undefined;
850
1098
  }
1099
+ /**
1100
+ * Starts a plugin.
1101
+ *
1102
+ * @param {Plugin | PluginName} plugin - The plugin to start.
1103
+ * @param {string} [message] - Optional message to pass to the plugin's onStart method.
1104
+ * @param {boolean} [configure] - Indicates whether to configure the plugin after starting (default false).
1105
+ * @returns {Promise<Plugin | undefined>} A promise that resolves when the plugin is started successfully, or rejects with an error if starting the plugin fails.
1106
+ */
851
1107
  async start(plugin, message, configure = false) {
852
1108
  if (typeof plugin === 'string') {
853
1109
  const p = this._plugins.get(plugin);
@@ -887,6 +1143,12 @@ export class PluginManager extends EventEmitter {
887
1143
  }
888
1144
  return undefined;
889
1145
  }
1146
+ /**
1147
+ * Configures a plugin.
1148
+ *
1149
+ * @param {Plugin | PluginName} plugin - The plugin to configure.
1150
+ * @returns {Promise<Plugin | undefined>} A promise that resolves when the plugin is configured successfully, or rejects with an error if configuration fails.
1151
+ */
890
1152
  async configure(plugin) {
891
1153
  if (typeof plugin === 'string') {
892
1154
  const p = this._plugins.get(plugin);
@@ -927,6 +1189,18 @@ export class PluginManager extends EventEmitter {
927
1189
  }
928
1190
  return undefined;
929
1191
  }
1192
+ /**
1193
+ * Shuts down a plugin.
1194
+ *
1195
+ * This method shuts down a plugin by calling its `onShutdown` method and resetting its state.
1196
+ * It logs the shutdown process and optionally removes all devices associated with the plugin.
1197
+ *
1198
+ * @param {Plugin | PluginName} plugin - The plugin to shut down.
1199
+ * @param {string} [reason] - The reason for shutting down the plugin.
1200
+ * @param {boolean} [removeAllDevices] - Whether to remove all devices associated with the plugin.
1201
+ * @param {boolean} [force] - Whether to force the shutdown even if the plugin is not loaded or started.
1202
+ * @returns {Promise<Plugin | undefined>} A promise that resolves to the shut down plugin object, or undefined if the shutdown failed.
1203
+ */
930
1204
  async shutdown(plugin, reason, removeAllDevices = false, force = false) {
931
1205
  if (typeof plugin === 'string') {
932
1206
  const p = this._plugins.get(plugin);
@@ -981,6 +1255,15 @@ export class PluginManager extends EventEmitter {
981
1255
  }
982
1256
  return undefined;
983
1257
  }
1258
+ /**
1259
+ * Loads the configuration for a plugin.
1260
+ * If the configuration file exists, it reads the file and returns the parsed JSON data.
1261
+ * If the configuration file does not exist, it creates a new file with default configuration and returns it.
1262
+ * If any error occurs during file access or creation, it logs an error and return un empty config.
1263
+ *
1264
+ * @param {Plugin} plugin - The plugin for which to load the configuration.
1265
+ * @returns {Promise<PlatformConfig>} A promise that resolves to the loaded or created configuration.
1266
+ */
984
1267
  async loadConfig(plugin) {
985
1268
  const { default: path } = await import('node:path');
986
1269
  const { promises } = await import('node:fs');
@@ -991,6 +1274,8 @@ export class PluginManager extends EventEmitter {
991
1274
  const data = await promises.readFile(configFile, 'utf8');
992
1275
  const config = JSON.parse(data);
993
1276
  this.log.debug(`Loaded config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
1277
+ // this.log.debug(`Loaded config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
1278
+ // The first time a plugin is added to the system, the config file is created with the plugin name and type "AnyPlatform".
994
1279
  config.name = plugin.name;
995
1280
  config.type = plugin.type;
996
1281
  if (config.debug === undefined)
@@ -1017,6 +1302,7 @@ export class PluginManager extends EventEmitter {
1017
1302
  try {
1018
1303
  await promises.writeFile(configFile, JSON.stringify(config, null, 2), 'utf8');
1019
1304
  this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
1305
+ // this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
1020
1306
  return config;
1021
1307
  }
1022
1308
  catch (err) {
@@ -1030,6 +1316,19 @@ export class PluginManager extends EventEmitter {
1030
1316
  }
1031
1317
  }
1032
1318
  }
1319
+ /**
1320
+ * Saves the configuration of a plugin to a file.
1321
+ *
1322
+ * This method saves the configuration of the specified plugin to a JSON file in the matterbridge directory.
1323
+ * If the plugin's configuration is not found, it logs an error and rejects the promise. If the configuration
1324
+ * is successfully saved, it logs a debug message. If an error occurs during the file write operation, it logs
1325
+ * the error and rejects the promise.
1326
+ *
1327
+ * @param {Plugin} plugin - The plugin whose configuration is to be saved.
1328
+ * @param {boolean} [restartRequired] - Indicates whether a restart is required after saving the configuration.
1329
+ * @returns {Promise<void>} A promise that resolves when the configuration is successfully saved, or rejects if an error occurs.
1330
+ * @throws {Error} If the plugin's configuration is not found.
1331
+ */
1033
1332
  async saveConfigFromPlugin(plugin, restartRequired = false) {
1034
1333
  const { default: path } = await import('node:path');
1035
1334
  const { promises } = await import('node:fs');
@@ -1044,6 +1343,7 @@ export class PluginManager extends EventEmitter {
1044
1343
  if (restartRequired)
1045
1344
  plugin.restartRequired = true;
1046
1345
  this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
1346
+ // this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, plugin.platform.config);
1047
1347
  return Promise.resolve();
1048
1348
  }
1049
1349
  catch (err) {
@@ -1051,6 +1351,20 @@ export class PluginManager extends EventEmitter {
1051
1351
  return Promise.reject(err);
1052
1352
  }
1053
1353
  }
1354
+ /**
1355
+ * Saves the configuration of a plugin from a JSON object to a file.
1356
+ *
1357
+ * This method saves the provided configuration of the specified plugin to a JSON file in the matterbridge directory.
1358
+ * It first checks if the configuration data is valid by ensuring it contains the correct name and type, and matches
1359
+ * the plugin's name. If the configuration data is invalid, it logs an error and returns. If the configuration is
1360
+ * successfully saved, it updates the plugin's `configJson` property and logs a debug message. If an error occurs
1361
+ * during the file write operation, it logs the error and returns.
1362
+ *
1363
+ * @param {Plugin} plugin - The plugin whose configuration is to be saved.
1364
+ * @param {PlatformConfig} config - The configuration data to be saved.
1365
+ * @param {boolean} [restartRequired] - Indicates whether a restart is required after saving the configuration.
1366
+ * @returns {Promise<void>} A promise that resolves when the configuration is successfully saved, or returns if an error occurs.
1367
+ */
1054
1368
  async saveConfigFromJson(plugin, config, restartRequired = false) {
1055
1369
  const { default: path } = await import('node:path');
1056
1370
  const { promises } = await import('node:fs');
@@ -1069,12 +1383,23 @@ export class PluginManager extends EventEmitter {
1069
1383
  plugin.platform.onConfigChanged(config).catch((err) => this.log.error(`Error calling onConfigChanged for plugin ${plg}${plugin.name}${er}: ${err}`));
1070
1384
  }
1071
1385
  this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
1386
+ // this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
1072
1387
  }
1073
1388
  catch (err) {
1074
1389
  logError(this.log, `Error saving config file ${configFile} for plugin ${plg}${plugin.name}${er}`, err);
1075
1390
  return;
1076
1391
  }
1077
1392
  }
1393
+ /**
1394
+ * Loads the schema for a plugin.
1395
+ *
1396
+ * This method attempts to load the schema file for the specified plugin. If the schema file is found,
1397
+ * it reads and parses the file, updates the schema's title and description, and logs the process.
1398
+ * If the schema file is not found, it logs the event and loads a default schema for the plugin.
1399
+ *
1400
+ * @param {Plugin} plugin - The plugin whose schema is to be loaded.
1401
+ * @returns {Promise<PlatformSchema>} A promise that resolves to the loaded schema object, or the default schema if the schema file is not found.
1402
+ */
1078
1403
  async loadSchema(plugin) {
1079
1404
  const { promises } = await import('node:fs');
1080
1405
  const schemaFile = plugin.path.replace('package.json', `${plugin.name}.schema.json`);
@@ -1085,6 +1410,7 @@ export class PluginManager extends EventEmitter {
1085
1410
  schema.title = plugin.description;
1086
1411
  schema.description = plugin.name + ' v. ' + plugin.version + ' by ' + plugin.author;
1087
1412
  this.log.debug(`Loaded schema file ${schemaFile} for plugin ${plg}${plugin.name}${db}.`);
1413
+ // this.log.debug(`Loaded schema file ${schemaFile} for plugin ${plg}${plugin.name}${db}.\nSchema:${rs}\n`, schema);
1088
1414
  return schema;
1089
1415
  }
1090
1416
  catch (_err) {
@@ -1092,6 +1418,16 @@ export class PluginManager extends EventEmitter {
1092
1418
  return this.getDefaultSchema(plugin);
1093
1419
  }
1094
1420
  }
1421
+ /**
1422
+ * Returns the default schema for a plugin.
1423
+ *
1424
+ * This method generates a default schema object for the specified plugin. The schema includes
1425
+ * metadata such as the plugin's title, description, version, and author. It also defines the
1426
+ * properties of the schema, including the plugin's name, type, debug flag, and unregisterOnShutdown flag.
1427
+ *
1428
+ * @param {Plugin} plugin - The plugin for which the default schema is to be generated.
1429
+ * @returns {PlatformSchema} The default schema object for the plugin.
1430
+ */
1095
1431
  getDefaultSchema(plugin) {
1096
1432
  return {
1097
1433
  title: plugin.description,
@@ -1122,3 +1458,4 @@ export class PluginManager extends EventEmitter {
1122
1458
  };
1123
1459
  }
1124
1460
  }
1461
+ //# sourceMappingURL=pluginManager.js.map