matterbridge 3.2.8-dev-20250920-80e7900 → 3.2.9-dev-20250922-6e00637

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,10 +8,31 @@ If you like this project and find it useful, please consider giving it a star on
8
8
  <img src="bmc-button.svg" alt="Buy me a coffee" width="120">
9
9
  </a>
10
10
 
11
- ## [3.2.8] - 2025-09-20
11
+ ## [3.2.9] - 2025-09-??
12
12
 
13
13
  ### Breaking Changes
14
14
 
15
+ - [profiles]: Profile management has changed. Now, each profile has its own independent directory with storage, matterstorage, plugin config, and plugin directory. This means that if you are using profiles, Matterbridge will not find the old profile data.
16
+
17
+ ### Added
18
+
19
+ - [frontend]: Bumped `frontend` version to 3.1.0. Fully typed with the backend.
20
+ - [frontend]: Removed legacy `react-table` and created an autonomous component `MbfTable`. Features: unique UI for all tables with integrated column sorting and column selection.
21
+ - [frontend]: Use MbfTable for Plugins, Devices, Registered devices and Clusters tables.
22
+
23
+ ### Changed
24
+
25
+ - [matter]: Bumped `matter.js` version to 0.15.4. Thanks matter.js!
26
+ - [package]: Updated dependencies.
27
+
28
+ ### Fixed
29
+
30
+ <a href="https://www.buymeacoffee.com/luligugithub">
31
+ <img src="bmc-button.svg" alt="Buy me a coffee" width="80">
32
+ </a>
33
+
34
+ ## [3.2.8] - 2025-09-20
35
+
15
36
  ### Added
16
37
 
17
38
  - [logger]: Set different color for log names to matterbridge, frontend and matter.js.
package/dist/frontend.js CHANGED
@@ -12,6 +12,7 @@ import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE,
12
12
  import { Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, Lifecycle, LogDestination, Diagnostic, Time, FabricIndex } from '@matter/main';
13
13
  import { BridgedDeviceBasicInformation, PowerSource } from '@matter/main/clusters';
14
14
  import { DeviceAdvertiser, DeviceCommissioner, FabricManager } from '@matter/main/protocol';
15
+ import { CommissioningOptions } from '@matter/main/types';
15
16
  import { createZip, isValidArray, isValidNumber, isValidObject, isValidString, isValidBoolean, withTimeout, hasParameter, wait, inspectError } from './utils/export.js';
16
17
  import { plg } from './matterbridgeTypes.js';
17
18
  import { capitalizeFirstLetter, getAttribute } from './matterbridgeEndpointHelpers.js';
@@ -1214,8 +1215,8 @@ export class Frontend extends EventEmitter {
1214
1215
  }
1215
1216
  else if (data.method === '/api/shellynetconfig') {
1216
1217
  this.log.debug('/api/shellynetconfig:', data.params);
1217
- const { triggerShellyChangeIp: triggerShellyChangeNet } = await import('./shelly.js');
1218
- triggerShellyChangeNet(this.matterbridge, data.params);
1218
+ const { triggerShellyChangeIp } = await import('./shelly.js');
1219
+ triggerShellyChangeIp(this.matterbridge, data.params);
1219
1220
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
1220
1221
  }
1221
1222
  else if (data.method === '/api/softreset') {
@@ -1359,7 +1360,7 @@ export class Frontend extends EventEmitter {
1359
1360
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/devices' });
1360
1361
  return;
1361
1362
  }
1362
- const selectDeviceValues = plugin.platform?.getSelectDevices().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
1363
+ const selectDeviceValues = !plugin.platform ? [] : plugin.platform.getSelectDevices().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
1363
1364
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true, response: selectDeviceValues });
1364
1365
  }
1365
1366
  else if (data.method === '/api/select/entities') {
@@ -1372,7 +1373,7 @@ export class Frontend extends EventEmitter {
1372
1373
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/entities' });
1373
1374
  return;
1374
1375
  }
1375
- const selectEntityValues = plugin.platform?.getSelectEntities().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
1376
+ const selectEntityValues = !plugin.platform ? [] : plugin.platform.getSelectEntities().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
1376
1377
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true, response: selectEntityValues });
1377
1378
  }
1378
1379
  else if (data.method === '/api/action') {
@@ -1544,7 +1545,7 @@ export class Frontend extends EventEmitter {
1544
1545
  break;
1545
1546
  case 'setmatterdiscriminator':
1546
1547
  const discriminator = isValidString(data.params.value) ? parseInt(data.params.value) : 0;
1547
- if (isValidNumber(discriminator, 1000, 4095)) {
1548
+ if (isValidNumber(discriminator, 0, 4095)) {
1548
1549
  this.log.debug(`Set matter commissioning discriminator to ${CYAN}${discriminator}${db}`);
1549
1550
  this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
1550
1551
  await this.matterbridge.nodeContext?.set('matterdiscriminator', discriminator);
@@ -1561,7 +1562,7 @@ export class Frontend extends EventEmitter {
1561
1562
  break;
1562
1563
  case 'setmatterpasscode':
1563
1564
  const passcode = isValidString(data.params.value) ? parseInt(data.params.value) : 0;
1564
- if (isValidNumber(passcode, 10000000, 90000000)) {
1565
+ if (isValidNumber(passcode, 1, 99999998) && CommissioningOptions.FORBIDDEN_PASSCODES.includes(passcode) === false) {
1565
1566
  this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
1566
1567
  this.log.debug(`Set matter commissioning passcode to ${CYAN}${passcode}${db}`);
1567
1568
  await this.matterbridge.nodeContext?.set('matterpasscode', passcode);
@@ -88,13 +88,13 @@ export class Matterbridge extends EventEmitter {
88
88
  shutdown = false;
89
89
  failCountLimit = hasParameter('shelly') ? 600 : 120;
90
90
  log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
91
- matterbridgeLoggerFile = 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.log';
91
+ matterbridgeLoggerFile = 'matterbridge.log';
92
92
  matterLog = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4, logLevel: "debug" });
93
- matterLoggerFile = 'matter' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.log';
93
+ matterLoggerFile = 'matter.log';
94
94
  plugins = new PluginManager(this);
95
95
  devices = new DeviceManager(this);
96
96
  frontend = new Frontend(this);
97
- nodeStorageName = 'storage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
97
+ nodeStorageName = 'storage';
98
98
  nodeStorage;
99
99
  nodeContext;
100
100
  hasCleanupStarted = false;
@@ -110,7 +110,7 @@ export class Matterbridge extends EventEmitter {
110
110
  exceptionHandler;
111
111
  rejectionHandler;
112
112
  environment = Environment.default;
113
- matterStorageName = 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
113
+ matterStorageName = 'matterstorage';
114
114
  matterStorageService;
115
115
  matterStorageManager;
116
116
  matterbridgeContext;
@@ -216,15 +216,15 @@ export class Matterbridge extends EventEmitter {
216
216
  this.homeDirectory = getParameter('homedir') ?? os.homedir();
217
217
  this.matterbridgeInformation.homeDirectory = this.homeDirectory;
218
218
  await createDirectory(this.homeDirectory, 'Matterbridge Home Directory', this.log);
219
- this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
219
+ this.matterbridgeDirectory = this.profile ? path.join(this.homeDirectory, '.matterbridge', 'profiles', this.profile) : path.join(this.homeDirectory, '.matterbridge');
220
220
  this.matterbridgeInformation.matterbridgeDirectory = this.matterbridgeDirectory;
221
221
  await createDirectory(this.matterbridgeDirectory, 'Matterbridge Directory', this.log);
222
222
  await createDirectory(path.join(this.matterbridgeDirectory, 'certs'), 'Matterbridge Frontend Certificate Directory', this.log);
223
223
  await createDirectory(path.join(this.matterbridgeDirectory, 'uploads'), 'Matterbridge Frontend Uploads Directory', this.log);
224
- this.matterbridgePluginDirectory = path.join(this.homeDirectory, 'Matterbridge');
224
+ this.matterbridgePluginDirectory = this.profile ? path.join(this.homeDirectory, 'Matterbridge', 'profiles', this.profile) : path.join(this.homeDirectory, 'Matterbridge');
225
225
  this.matterbridgeInformation.matterbridgePluginDirectory = this.matterbridgePluginDirectory;
226
226
  await createDirectory(this.matterbridgePluginDirectory, 'Matterbridge Plugin Directory', this.log);
227
- this.matterbridgeCertDirectory = path.join(this.homeDirectory, '.mattercert');
227
+ this.matterbridgeCertDirectory = this.profile ? path.join(this.homeDirectory, '.mattercert', 'profiles', this.profile) : path.join(this.homeDirectory, '.mattercert');
228
228
  this.matterbridgeInformation.matterbridgeCertDirectory = this.matterbridgeCertDirectory;
229
229
  await createDirectory(this.matterbridgeCertDirectory, 'Matterbridge Matter Certificate Directory', this.log);
230
230
  const { fileURLToPath } = await import('node:url');