@matterbridge/core 3.6.1-dev-20260311-7da5ff8 → 3.6.1-dev-20260312-a699c0e
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/dist/frontend.js +19 -19
- package/dist/matterNode.js +1 -1
- package/dist/matterbridge.js +12 -17
- package/dist/matterbridgeBehaviors.d.ts +0 -1
- package/dist/matterbridgeBehaviors.js +0 -11
- package/dist/matterbridgeEndpoint.js +1 -1
- package/dist/pluginManager.d.ts +15 -0
- package/dist/pluginManager.js +52 -158
- package/package.json +6 -6
- package/dist/spawn.d.ts +0 -1
- package/dist/spawn.js +0 -96
package/dist/frontend.js
CHANGED
|
@@ -727,6 +727,7 @@ export class Frontend extends EventEmitter {
|
|
|
727
727
|
});
|
|
728
728
|
});
|
|
729
729
|
this.expressApp.post('/api/uploadpackage', upload.single('file'), async (req, res) => {
|
|
730
|
+
this.log.debug('The frontend sent /api/uploadpackage');
|
|
730
731
|
if (!this.validateReq(req, res))
|
|
731
732
|
return;
|
|
732
733
|
const { filename } = req.body;
|
|
@@ -736,35 +737,34 @@ export class Frontend extends EventEmitter {
|
|
|
736
737
|
res.status(400).send('Invalid request: file and filename are required');
|
|
737
738
|
return;
|
|
738
739
|
}
|
|
739
|
-
this.wssSendSnackbarMessage(`Installing package ${filename}
|
|
740
|
+
this.wssSendSnackbarMessage(`Installing package ${filename}...`, 0);
|
|
740
741
|
const filePath = path.join(this.matterbridge.matterbridgeDirectory, 'uploads', filename);
|
|
741
742
|
try {
|
|
742
743
|
const fs = await import('node:fs');
|
|
743
744
|
await fs.promises.rename(file.path, filePath);
|
|
744
745
|
this.log.info(`File ${plg}${filename}${nf} uploaded successfully`);
|
|
745
746
|
if (filename.endsWith('.tgz')) {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
else {
|
|
762
|
-
res.send(`File ${filename} uploaded successfully`);
|
|
747
|
+
this.server.request({
|
|
748
|
+
type: 'manager_run',
|
|
749
|
+
src: 'frontend',
|
|
750
|
+
dst: 'manager',
|
|
751
|
+
params: {
|
|
752
|
+
name: 'SpawnCommand',
|
|
753
|
+
workerData: {
|
|
754
|
+
threadName: 'SpawnCommand',
|
|
755
|
+
command: 'npm',
|
|
756
|
+
args: ['install', '-g', filePath, '--omit=dev', '--verbose'],
|
|
757
|
+
packageCommand: 'install',
|
|
758
|
+
packageName: filename,
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
});
|
|
763
762
|
}
|
|
763
|
+
res.send(`File ${filename} uploaded successfully`);
|
|
764
764
|
}
|
|
765
765
|
catch (err) {
|
|
766
766
|
this.log.error(`Error uploading or installing plugin package file ${plg}${filename}${er}:`, err);
|
|
767
|
-
this.wssSendCloseSnackbarMessage(`Installing package ${filename}
|
|
767
|
+
this.wssSendCloseSnackbarMessage(`Installing package ${filename}...`);
|
|
768
768
|
this.wssSendSnackbarMessage(`Error uploading or installing plugin package ${filename}`, 10, 'error');
|
|
769
769
|
res.status(500).send(`Error uploading or installing plugin package ${filename}`);
|
|
770
770
|
}
|
package/dist/matterNode.js
CHANGED
|
@@ -333,7 +333,7 @@ export class MatterNode extends EventEmitter {
|
|
|
333
333
|
await storageContext.set('productId', productId);
|
|
334
334
|
await storageContext.set('productName', productName.slice(0, 32));
|
|
335
335
|
await storageContext.set('nodeLabel', productName.slice(0, 32));
|
|
336
|
-
await storageContext.set('productLabel', productName.slice(0, 32));
|
|
336
|
+
await storageContext.set('productLabel', productName.replace(vendorName, '').trim().slice(0, 32));
|
|
337
337
|
await storageContext.set('serialNumber', await storageContext.get('serialNumber', serialNumber ? serialNumber.slice(0, 32) : 'SN' + random));
|
|
338
338
|
await storageContext.set('uniqueId', await storageContext.get('uniqueId', uniqueId ? uniqueId.slice(0, 32) : 'UI' + random));
|
|
339
339
|
await storageContext.set('softwareVersion', isValidNumber(parseVersionString(this.matterbridge.matterbridgeVersion), 0, UINT32_MAX) ? parseVersionString(this.matterbridge.matterbridgeVersion) : 1);
|
package/dist/matterbridge.js
CHANGED
|
@@ -16,7 +16,7 @@ import { DeviceTypeId, VendorId } from '@matter/types/datatype';
|
|
|
16
16
|
import { BroadcastServer } from '@matterbridge/thread/server';
|
|
17
17
|
import { dev, MATTER_LOGGER_FILE, MATTER_STORAGE_NAME, MATTERBRIDGE_LOGGER_FILE, NODE_STORAGE_DIR, plg, typ } from '@matterbridge/types';
|
|
18
18
|
import { wait } from '@matterbridge/utils';
|
|
19
|
-
import { getIntParameter, getParameter, hasParameter } from '@matterbridge/utils/cli';
|
|
19
|
+
import { getIntParameter, getParameter, hasAnyParameter, hasParameter } from '@matterbridge/utils/cli';
|
|
20
20
|
import { copyDirectory } from '@matterbridge/utils/copy-dir';
|
|
21
21
|
import { createDirectory } from '@matterbridge/utils/create-dir';
|
|
22
22
|
import { formatBytes, formatPercent, formatUptime } from '@matterbridge/utils/format';
|
|
@@ -124,7 +124,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
124
124
|
aggregatorVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
|
|
125
125
|
aggregatorVendorName = getParameter('vendorName') ?? 'Matterbridge';
|
|
126
126
|
aggregatorProductId = getIntParameter('productId') ?? 0x8000;
|
|
127
|
-
aggregatorProductName = getParameter('productName') ?? 'Matterbridge
|
|
127
|
+
aggregatorProductName = getParameter('productName') ?? 'Matterbridge Aggregator';
|
|
128
128
|
aggregatorDeviceType = DeviceTypeId(getIntParameter('deviceType') ?? bridge.code);
|
|
129
129
|
aggregatorSerialNumber = getParameter('serialNumber');
|
|
130
130
|
aggregatorUniqueId = getParameter('uniqueId');
|
|
@@ -132,7 +132,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
132
132
|
controllerVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
|
|
133
133
|
controllerVendorName = getParameter('vendorName') ?? 'Matterbridge';
|
|
134
134
|
controllerProductId = getIntParameter('productId') ?? 0x8000;
|
|
135
|
-
controllerProductName = getParameter('productName') ?? 'Matterbridge
|
|
135
|
+
controllerProductName = getParameter('productName') ?? 'Matterbridge Controller';
|
|
136
136
|
advertisingNodes = new Map();
|
|
137
137
|
server;
|
|
138
138
|
verbose = hasParameter('verbose');
|
|
@@ -251,7 +251,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
251
251
|
if (msg.result && msg.result.success && msg.result.packageCommand === 'install') {
|
|
252
252
|
this.restartRequired = true;
|
|
253
253
|
this.fixedRestartRequired = true;
|
|
254
|
-
|
|
254
|
+
const packageName = msg.result.packageName.replace(/@.*$/, '');
|
|
255
|
+
if (packageName === 'matterbridge') {
|
|
255
256
|
this.log.info('Matterbridge has been updated. Full restart required.');
|
|
256
257
|
if (this.restartMode !== '')
|
|
257
258
|
await this.cleanup('updating...', false);
|
|
@@ -565,17 +566,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
565
566
|
this.devices.logLevel = this.log.logLevel;
|
|
566
567
|
for (const plugin of this.plugins) {
|
|
567
568
|
this.log.debug(`Parsing plugin ${plg}${plugin.name}${db} from path ${CYAN}${plugin.path}${db} with version ${CYAN}${plugin.version}${db} and type ${CYAN}${plugin.type}${db}.`);
|
|
568
|
-
if (!fs.existsSync(plugin.path) &&
|
|
569
|
-
!hasParameter('add') &&
|
|
570
|
-
!hasParameter('remove') &&
|
|
571
|
-
!hasParameter('enable') &&
|
|
572
|
-
!hasParameter('disable') &&
|
|
573
|
-
!hasParameter('reset') &&
|
|
574
|
-
!hasParameter('factoryreset') &&
|
|
575
|
-
!hasParameter('systemcheck')) {
|
|
569
|
+
if (!fs.existsSync(plugin.path) && !hasAnyParameter('add', 'remove', 'enable', 'disable', 'reset', 'factoryreset', 'systemcheck')) {
|
|
576
570
|
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm...`);
|
|
577
|
-
const {
|
|
578
|
-
|
|
571
|
+
const { execSync } = await import('node:child_process');
|
|
572
|
+
const sudo = hasParameter('sudo') || (process.platform !== 'win32' && !hasParameter('docker') && !hasParameter('nosudo') && !process.env.PATH?.includes('/.nvm/versions/node/'));
|
|
573
|
+
if (execSync(`${sudo ? 'sudo ' : ''}npm install -g ${plugin.name}${plugin.version.includes('-dev-') ? '@dev' : ''} --omit=dev`)) {
|
|
579
574
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
580
575
|
plugin.error = false;
|
|
581
576
|
}
|
|
@@ -1515,7 +1510,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1515
1510
|
await this.controllerContext.set('vendorName', this.controllerVendorName.slice(0, 32));
|
|
1516
1511
|
await this.controllerContext.set('productId', this.controllerProductId);
|
|
1517
1512
|
await this.controllerContext.set('productName', this.controllerProductName.slice(0, 32));
|
|
1518
|
-
await this.controllerContext.set('productLabel', this.controllerProductName.slice(0, 32));
|
|
1513
|
+
await this.controllerContext.set('productLabel', this.controllerProductName.replace(this.controllerVendorName, '').trim().slice(0, 32));
|
|
1519
1514
|
await this.controllerContext.set('nodeLabel', storeId.slice(0, 32));
|
|
1520
1515
|
await this.controllerContext.set('serialNumber', await this.controllerContext.get('serialNumber', 'SN' + random));
|
|
1521
1516
|
await this.controllerContext.set('uniqueId', await this.controllerContext.get('uniqueId', 'UI' + random));
|
|
@@ -1791,7 +1786,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1791
1786
|
await storageContext.set('vendorName', vendorName.slice(0, 32));
|
|
1792
1787
|
await storageContext.set('productId', productId);
|
|
1793
1788
|
await storageContext.set('productName', productName.slice(0, 32));
|
|
1794
|
-
await storageContext.set('productLabel', productName.slice(0, 32));
|
|
1789
|
+
await storageContext.set('productLabel', productName.replace(vendorName, '').trim().slice(0, 32));
|
|
1795
1790
|
await storageContext.set('nodeLabel', deviceName.slice(0, 32));
|
|
1796
1791
|
await storageContext.set('serialNumber', await storageContext.get('serialNumber', serialNumber ? serialNumber.slice(0, 32) : 'SN' + random));
|
|
1797
1792
|
await storageContext.set('uniqueId', await storageContext.get('uniqueId', uniqueId ? uniqueId.slice(0, 32) : 'UI' + random));
|
|
@@ -1860,7 +1855,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1860
1855
|
vendorName: await storageContext.get('vendorName'),
|
|
1861
1856
|
productId: await storageContext.get('productId'),
|
|
1862
1857
|
productName: await storageContext.get('productName'),
|
|
1863
|
-
productLabel: await storageContext.get('
|
|
1858
|
+
productLabel: await storageContext.get('productLabel'),
|
|
1864
1859
|
serialNumber: await storageContext.get('serialNumber'),
|
|
1865
1860
|
uniqueId: await storageContext.get('uniqueId'),
|
|
1866
1861
|
softwareVersion: await storageContext.get('softwareVersion'),
|
|
@@ -1615,7 +1615,6 @@ declare const MatterbridgeThermostatServer_base: import("@matter/node").ClusterB
|
|
|
1615
1615
|
}];
|
|
1616
1616
|
}>, readonly [Thermostat.Feature.Cooling, Thermostat.Feature.Heating, Thermostat.Feature.AutoMode]>, typeof ThermostatServer, import("@matter/node/behaviors/thermostat").ThermostatInterface>;
|
|
1617
1617
|
export declare class MatterbridgeThermostatServer extends MatterbridgeThermostatServer_base {
|
|
1618
|
-
initialize(): Promise<void>;
|
|
1619
1618
|
setpointRaiseLower(request: Thermostat.SetpointRaiseLowerRequest): MaybePromise;
|
|
1620
1619
|
}
|
|
1621
1620
|
declare const MatterbridgePresetThermostatServer_base: import("@matter/node").ClusterBehavior.Type<import("@matter/types").ClusterComposer.WithFeatures<import("@matter/types").ClusterType.Of<{
|
|
@@ -321,17 +321,6 @@ export class MatterbridgeFanControlServer extends FanControlServer.with(FanContr
|
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
export class MatterbridgeThermostatServer extends ThermostatServer.with(Thermostat.Feature.Cooling, Thermostat.Feature.Heating, Thermostat.Feature.AutoMode) {
|
|
324
|
-
async initialize() {
|
|
325
|
-
await super.initialize();
|
|
326
|
-
this.endpoint.construction.onSuccess(async () => {
|
|
327
|
-
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
328
|
-
device.log.debug(`Removing atomic commands (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
329
|
-
await this.endpoint.setStateOf(ThermostatServer, {
|
|
330
|
-
acceptedCommandList: [0],
|
|
331
|
-
generatedCommandList: [],
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
324
|
setpointRaiseLower(request) {
|
|
336
325
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
337
326
|
device.log.info(`Setting setpoint by ${request.amount} in mode ${request.mode} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
@@ -506,7 +506,7 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
506
506
|
vendorName: vendorName.slice(0, 32),
|
|
507
507
|
productName: productName.slice(0, 32),
|
|
508
508
|
productUrl: this.productUrl.slice(0, 256),
|
|
509
|
-
productLabel: productName.slice(0, 64),
|
|
509
|
+
productLabel: productName.replace(vendorName, '').trim().slice(0, 64),
|
|
510
510
|
nodeLabel: deviceName.slice(0, 32),
|
|
511
511
|
serialNumber: serialNumber.slice(0, 32),
|
|
512
512
|
uniqueId: this.uniqueId.slice(0, 32),
|
package/dist/pluginManager.d.ts
CHANGED
|
@@ -29,6 +29,16 @@ interface PluginManagerEvents {
|
|
|
29
29
|
configured: [name: string];
|
|
30
30
|
shutdown: [name: string];
|
|
31
31
|
}
|
|
32
|
+
type PackageJsonDependencies = Record<string, string> | string[];
|
|
33
|
+
type PackageJsonLike = Record<string, unknown> & {
|
|
34
|
+
name?: string;
|
|
35
|
+
dependencies?: PackageJsonDependencies;
|
|
36
|
+
devDependencies?: PackageJsonDependencies;
|
|
37
|
+
peerDependencies?: PackageJsonDependencies;
|
|
38
|
+
optionalDependencies?: PackageJsonDependencies;
|
|
39
|
+
bundledDependencies?: PackageJsonDependencies;
|
|
40
|
+
bundleDependencies?: PackageJsonDependencies;
|
|
41
|
+
};
|
|
32
42
|
export declare class PluginManager extends EventEmitter<PluginManagerEvents> {
|
|
33
43
|
private readonly matterbridge;
|
|
34
44
|
private readonly _plugins;
|
|
@@ -36,8 +46,13 @@ export declare class PluginManager extends EventEmitter<PluginManagerEvents> {
|
|
|
36
46
|
private readonly server;
|
|
37
47
|
private readonly debug;
|
|
38
48
|
private readonly verbose;
|
|
49
|
+
private readonly dependencyTypes;
|
|
39
50
|
constructor(matterbridge: Matterbridge);
|
|
40
51
|
destroy(): void;
|
|
52
|
+
private getDependencyNames;
|
|
53
|
+
private findInvalidDependencies;
|
|
54
|
+
private logInvalidDependencies;
|
|
55
|
+
checkDependencies(packageJson: PackageJsonLike): boolean;
|
|
41
56
|
private msgHandler;
|
|
42
57
|
get length(): number;
|
|
43
58
|
get size(): number;
|
package/dist/pluginManager.js
CHANGED
|
@@ -16,6 +16,7 @@ export class PluginManager extends EventEmitter {
|
|
|
16
16
|
server;
|
|
17
17
|
debug = hasParameter('debug') || hasParameter('verbose');
|
|
18
18
|
verbose = hasParameter('verbose');
|
|
19
|
+
dependencyTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies', 'bundledDependencies', 'bundleDependencies'];
|
|
19
20
|
constructor(matterbridge) {
|
|
20
21
|
super();
|
|
21
22
|
this.matterbridge = matterbridge;
|
|
@@ -29,6 +30,43 @@ export class PluginManager extends EventEmitter {
|
|
|
29
30
|
this.server.off('broadcast_message', this.msgHandler.bind(this));
|
|
30
31
|
this.server.close();
|
|
31
32
|
}
|
|
33
|
+
getDependencyNames(dependencies) {
|
|
34
|
+
if (!dependencies)
|
|
35
|
+
return [];
|
|
36
|
+
return Array.isArray(dependencies) ? dependencies : Object.keys(dependencies);
|
|
37
|
+
}
|
|
38
|
+
findInvalidDependencies(packageJson) {
|
|
39
|
+
for (const dependencyType of this.dependencyTypes) {
|
|
40
|
+
const packages = this.getDependencyNames(packageJson[dependencyType]);
|
|
41
|
+
const matterbridgePackages = packages.filter((pkg) => pkg.startsWith('matterbridge'));
|
|
42
|
+
if (matterbridgePackages.length > 0) {
|
|
43
|
+
return { dependencyType, packages: matterbridgePackages, isMatterbridgePackage: true };
|
|
44
|
+
}
|
|
45
|
+
const scopedPackages = packages.filter((pkg) => pkg.startsWith('@project-chip') || pkg.startsWith('@matterbridge') || pkg.startsWith('@matter'));
|
|
46
|
+
if (scopedPackages.length > 0) {
|
|
47
|
+
return { dependencyType, packages: scopedPackages, isMatterbridgePackage: false };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
logInvalidDependencies(packageJson, invalidDependencies, pluginName) {
|
|
53
|
+
if (invalidDependencies.isMatterbridgePackage) {
|
|
54
|
+
this.log.error(`Found matterbridge package in the plugin${pluginName ? ` ${plg}${pluginName}${er}` : ''} ${invalidDependencies.dependencyType}.`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.log.error(`Found invalid packages "${invalidDependencies.packages.join(', ')}" in plugin${pluginName ? ` ${plg}${pluginName}${er}` : ''} ${invalidDependencies.dependencyType}.`);
|
|
58
|
+
}
|
|
59
|
+
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
60
|
+
this.server.request({
|
|
61
|
+
type: 'frontend_snackbarmessage',
|
|
62
|
+
src: 'plugins',
|
|
63
|
+
dst: 'frontend',
|
|
64
|
+
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
checkDependencies(packageJson) {
|
|
68
|
+
return this.findInvalidDependencies(packageJson) === null;
|
|
69
|
+
}
|
|
32
70
|
async msgHandler(msg) {
|
|
33
71
|
if (this.server.isWorkerRequest(msg)) {
|
|
34
72
|
if (this.verbose)
|
|
@@ -237,18 +275,20 @@ export class PluginManager extends EventEmitter {
|
|
|
237
275
|
switch (msg.type) {
|
|
238
276
|
case 'manager_spawn_response':
|
|
239
277
|
if (msg.result && msg.result.packageCommand === 'install') {
|
|
278
|
+
if (msg.result.packageName.endsWith('.tgz'))
|
|
279
|
+
return;
|
|
240
280
|
if (msg.result.success) {
|
|
241
|
-
|
|
242
|
-
if (
|
|
243
|
-
if (!this.has(
|
|
244
|
-
await this.add(
|
|
245
|
-
const plugin = this.get(
|
|
281
|
+
const packageName = msg.result.packageName.replace(/@.*$/, '');
|
|
282
|
+
if (packageName !== 'matterbridge') {
|
|
283
|
+
if (!this.has(packageName))
|
|
284
|
+
await this.add(packageName);
|
|
285
|
+
const plugin = this.get(packageName);
|
|
246
286
|
if (plugin && !plugin.loaded) {
|
|
247
287
|
await this.load(plugin);
|
|
248
288
|
this.server.request({ type: 'frontend_refreshrequired', src: 'plugins', dst: 'frontend', params: { changed: 'plugins' } });
|
|
249
289
|
}
|
|
250
290
|
}
|
|
251
|
-
this.log.info(`Installed plugin ${plg}${
|
|
291
|
+
this.log.info(`Installed plugin ${plg}${packageName}${db} successfully`);
|
|
252
292
|
}
|
|
253
293
|
else {
|
|
254
294
|
this.log.error(`Failed to install plugin ${plg}${msg.result.packageName}${er}`);
|
|
@@ -435,82 +475,9 @@ export class PluginManager extends EventEmitter {
|
|
|
435
475
|
this.log.error(`Plugin at ${packageJsonPath} has no main entrypoint in package.json`);
|
|
436
476
|
return null;
|
|
437
477
|
}
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
const projectChipDependencies = checkForProjectChipPackages(packageJson.dependencies || {});
|
|
442
|
-
if (projectChipDependencies.length > 0) {
|
|
443
|
-
this.log.error(`Found @project-chip packages "${projectChipDependencies.join(', ')}" in plugin dependencies.`);
|
|
444
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
445
|
-
this.server.request({
|
|
446
|
-
type: 'frontend_snackbarmessage',
|
|
447
|
-
src: 'plugins',
|
|
448
|
-
dst: 'frontend',
|
|
449
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
450
|
-
});
|
|
451
|
-
return null;
|
|
452
|
-
}
|
|
453
|
-
const projectChipDevDependencies = checkForProjectChipPackages(packageJson.devDependencies || {});
|
|
454
|
-
if (projectChipDevDependencies.length > 0) {
|
|
455
|
-
this.log.error(`Found @project-chip packages "${projectChipDevDependencies.join(', ')}" in plugin devDependencies.`);
|
|
456
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
457
|
-
this.server.request({
|
|
458
|
-
type: 'frontend_snackbarmessage',
|
|
459
|
-
src: 'plugins',
|
|
460
|
-
dst: 'frontend',
|
|
461
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
462
|
-
});
|
|
463
|
-
return null;
|
|
464
|
-
}
|
|
465
|
-
const projectChipPeerDependencies = checkForProjectChipPackages(packageJson.peerDependencies || {});
|
|
466
|
-
if (projectChipPeerDependencies.length > 0) {
|
|
467
|
-
this.log.error(`Found @project-chip packages "${projectChipPeerDependencies.join(', ')}" in plugin peerDependencies.`);
|
|
468
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
469
|
-
this.server.request({
|
|
470
|
-
type: 'frontend_snackbarmessage',
|
|
471
|
-
src: 'plugins',
|
|
472
|
-
dst: 'frontend',
|
|
473
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
474
|
-
});
|
|
475
|
-
return null;
|
|
476
|
-
}
|
|
477
|
-
const checkForMatterbridgePackage = (dependencies) => {
|
|
478
|
-
return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
|
|
479
|
-
};
|
|
480
|
-
const matterbridgeDependencies = checkForMatterbridgePackage(packageJson.dependencies || {});
|
|
481
|
-
if (matterbridgeDependencies.length > 0) {
|
|
482
|
-
this.log.error(`Found matterbridge package in the plugin dependencies.`);
|
|
483
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
484
|
-
this.server.request({
|
|
485
|
-
type: 'frontend_snackbarmessage',
|
|
486
|
-
src: 'plugins',
|
|
487
|
-
dst: 'frontend',
|
|
488
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
489
|
-
});
|
|
490
|
-
return null;
|
|
491
|
-
}
|
|
492
|
-
const matterbridgeDevDependencies = checkForMatterbridgePackage(packageJson.devDependencies || {});
|
|
493
|
-
if (matterbridgeDevDependencies.length > 0) {
|
|
494
|
-
this.log.error(`Found matterbridge package in the plugin devDependencies.`);
|
|
495
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
496
|
-
this.server.request({
|
|
497
|
-
type: 'frontend_snackbarmessage',
|
|
498
|
-
src: 'plugins',
|
|
499
|
-
dst: 'frontend',
|
|
500
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
501
|
-
});
|
|
502
|
-
return null;
|
|
503
|
-
}
|
|
504
|
-
const matterbridgePeerDependencies = checkForMatterbridgePackage(packageJson.peerDependencies || {});
|
|
505
|
-
if (matterbridgePeerDependencies.length > 0) {
|
|
506
|
-
this.log.error(`Found matterbridge package in the plugin peerDependencies.`);
|
|
507
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
508
|
-
this.server.request({
|
|
509
|
-
type: 'frontend_snackbarmessage',
|
|
510
|
-
src: 'plugins',
|
|
511
|
-
dst: 'frontend',
|
|
512
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
513
|
-
});
|
|
478
|
+
const invalidDependencies = this.findInvalidDependencies(packageJson);
|
|
479
|
+
if (invalidDependencies) {
|
|
480
|
+
this.logInvalidDependencies(packageJson, invalidDependencies);
|
|
514
481
|
return null;
|
|
515
482
|
}
|
|
516
483
|
this.log.debug(`Resolved plugin path ${plg}${nameOrPath}${db}: ${packageJsonPath}`);
|
|
@@ -667,82 +634,9 @@ export class PluginManager extends EventEmitter {
|
|
|
667
634
|
plugin.funding = this.getFunding(packageJson);
|
|
668
635
|
if (!plugin.type)
|
|
669
636
|
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no type`);
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
const projectChipDependencies = checkForProjectChipPackages(packageJson.dependencies || {});
|
|
674
|
-
if (projectChipDependencies.length > 0) {
|
|
675
|
-
this.log.error(`Found @project-chip packages "${projectChipDependencies.join(', ')}" in plugin ${plg}${plugin.name}${er} dependencies.`);
|
|
676
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
677
|
-
this.server.request({
|
|
678
|
-
type: 'frontend_snackbarmessage',
|
|
679
|
-
src: 'plugins',
|
|
680
|
-
dst: 'frontend',
|
|
681
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
682
|
-
});
|
|
683
|
-
return null;
|
|
684
|
-
}
|
|
685
|
-
const projectChipDevDependencies = checkForProjectChipPackages(packageJson.devDependencies || {});
|
|
686
|
-
if (projectChipDevDependencies.length > 0) {
|
|
687
|
-
this.log.error(`Found @project-chip packages "${projectChipDevDependencies.join(', ')}" in plugin ${plg}${plugin.name}${er} devDependencies.`);
|
|
688
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
689
|
-
this.server.request({
|
|
690
|
-
type: 'frontend_snackbarmessage',
|
|
691
|
-
src: 'plugins',
|
|
692
|
-
dst: 'frontend',
|
|
693
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
694
|
-
});
|
|
695
|
-
return null;
|
|
696
|
-
}
|
|
697
|
-
const projectChipPeerDependencies = checkForProjectChipPackages(packageJson.peerDependencies || {});
|
|
698
|
-
if (projectChipPeerDependencies.length > 0) {
|
|
699
|
-
this.log.error(`Found @project-chip packages "${projectChipPeerDependencies.join(', ')}" in plugin ${plg}${plugin.name}${er} peerDependencies.`);
|
|
700
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
701
|
-
this.server.request({
|
|
702
|
-
type: 'frontend_snackbarmessage',
|
|
703
|
-
src: 'plugins',
|
|
704
|
-
dst: 'frontend',
|
|
705
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
706
|
-
});
|
|
707
|
-
return null;
|
|
708
|
-
}
|
|
709
|
-
const checkForMatterbridgePackage = (dependencies) => {
|
|
710
|
-
return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
|
|
711
|
-
};
|
|
712
|
-
const matterbridgeDependencies = checkForMatterbridgePackage(packageJson.dependencies || {});
|
|
713
|
-
if (matterbridgeDependencies.length > 0) {
|
|
714
|
-
this.log.error(`Found matterbridge package in the plugin ${plg}${plugin.name}${er} dependencies.`);
|
|
715
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
716
|
-
this.server.request({
|
|
717
|
-
type: 'frontend_snackbarmessage',
|
|
718
|
-
src: 'plugins',
|
|
719
|
-
dst: 'frontend',
|
|
720
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
721
|
-
});
|
|
722
|
-
return null;
|
|
723
|
-
}
|
|
724
|
-
const matterbridgeDevDependencies = checkForMatterbridgePackage(packageJson.devDependencies || {});
|
|
725
|
-
if (matterbridgeDevDependencies.length > 0) {
|
|
726
|
-
this.log.error(`Found matterbridge package in the plugin ${plg}${plugin.name}${er} devDependencies.`);
|
|
727
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
728
|
-
this.server.request({
|
|
729
|
-
type: 'frontend_snackbarmessage',
|
|
730
|
-
src: 'plugins',
|
|
731
|
-
dst: 'frontend',
|
|
732
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
733
|
-
});
|
|
734
|
-
return null;
|
|
735
|
-
}
|
|
736
|
-
const matterbridgePeerDependencies = checkForMatterbridgePackage(packageJson.peerDependencies || {});
|
|
737
|
-
if (matterbridgePeerDependencies.length > 0) {
|
|
738
|
-
this.log.error(`Found matterbridge package in the plugin ${plg}${plugin.name}${er} peerDependencies.`);
|
|
739
|
-
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
740
|
-
this.server.request({
|
|
741
|
-
type: 'frontend_snackbarmessage',
|
|
742
|
-
src: 'plugins',
|
|
743
|
-
dst: 'frontend',
|
|
744
|
-
params: { message: `Found not allowed package in plugin ${packageJson.name} package.json`, timeout: 30, severity: 'error' },
|
|
745
|
-
});
|
|
637
|
+
const invalidDependencies = this.findInvalidDependencies(packageJson);
|
|
638
|
+
if (invalidDependencies) {
|
|
639
|
+
this.logInvalidDependencies(packageJson, invalidDependencies, plugin.name);
|
|
746
640
|
return null;
|
|
747
641
|
}
|
|
748
642
|
return packageJson;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matterbridge/core",
|
|
3
|
-
"version": "3.6.1-dev-
|
|
3
|
+
"version": "3.6.1-dev-20260312-a699c0e",
|
|
4
4
|
"description": "Matterbridge core library",
|
|
5
5
|
"author": "https://github.com/Luligu",
|
|
6
6
|
"homepage": "https://matterbridge.io/",
|
|
@@ -121,11 +121,11 @@
|
|
|
121
121
|
"CHANGELOG.md"
|
|
122
122
|
],
|
|
123
123
|
"dependencies": {
|
|
124
|
-
"@matter/main": "0.17.0-alpha.0-
|
|
125
|
-
"@matterbridge/dgram": "3.6.1-dev-
|
|
126
|
-
"@matterbridge/thread": "3.6.1-dev-
|
|
127
|
-
"@matterbridge/types": "3.6.1-dev-
|
|
128
|
-
"@matterbridge/utils": "3.6.1-dev-
|
|
124
|
+
"@matter/main": "0.17.0-alpha.0-20260311-3dbb8a732",
|
|
125
|
+
"@matterbridge/dgram": "3.6.1-dev-20260312-a699c0e",
|
|
126
|
+
"@matterbridge/thread": "3.6.1-dev-20260312-a699c0e",
|
|
127
|
+
"@matterbridge/types": "3.6.1-dev-20260312-a699c0e",
|
|
128
|
+
"@matterbridge/utils": "3.6.1-dev-20260312-a699c0e",
|
|
129
129
|
"archiver": "7.0.1",
|
|
130
130
|
"express": "5.2.1",
|
|
131
131
|
"glob": "13.0.6",
|
package/dist/spawn.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function spawnCommand(command: string, args: string[], packageCommand?: 'install' | 'uninstall', packageName?: string): Promise<boolean>;
|
package/dist/spawn.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { BroadcastServer } from '@matterbridge/thread/server';
|
|
2
|
-
import { hasParameter } from '@matterbridge/utils/cli';
|
|
3
|
-
import { AnsiLogger } from 'node-ansi-logger';
|
|
4
|
-
export async function spawnCommand(command, args, packageCommand, packageName) {
|
|
5
|
-
const { spawn } = await import('node:child_process');
|
|
6
|
-
const debug = hasParameter('debug') || hasParameter('verbose') || hasParameter('debug-spawn') || hasParameter('verbose-spawn');
|
|
7
|
-
const verbose = hasParameter('verbose') || hasParameter('verbose-spawn');
|
|
8
|
-
const log = new AnsiLogger({ logName: 'Spawn', logTimestampFormat: 4, logLevel: debug ? "debug" : "info" });
|
|
9
|
-
const server = new BroadcastServer('spawn', log);
|
|
10
|
-
const sendLog = (name, message) => {
|
|
11
|
-
try {
|
|
12
|
-
server.request({ type: 'frontend_logmessage', src: 'spawn', dst: 'frontend', params: { level: 'spawn', time: log.now(), name, message } });
|
|
13
|
-
}
|
|
14
|
-
catch (err) {
|
|
15
|
-
log.debug(`Failed to send log message to frontend: ${err instanceof Error ? err.message : String(err)}`);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
if (verbose)
|
|
19
|
-
log.debug(`Spawning command: ${command} with ${args.join(' ')} ${packageCommand} ${packageName}`);
|
|
20
|
-
const cmdLine = command + ' ' + args.join(' ');
|
|
21
|
-
if (process.platform === 'win32' && command === 'npm') {
|
|
22
|
-
const argstring = 'npm ' + args.join(' ');
|
|
23
|
-
args.splice(0, args.length, '/c', argstring);
|
|
24
|
-
command = 'cmd.exe';
|
|
25
|
-
}
|
|
26
|
-
if (hasParameter('sudo') ||
|
|
27
|
-
(process.platform !== 'win32' && command === 'npm' && !hasParameter('docker') && !hasParameter('nosudo') && !process.env.PATH?.includes('/.nvm/versions/node/'))) {
|
|
28
|
-
args.unshift(command);
|
|
29
|
-
command = 'sudo';
|
|
30
|
-
}
|
|
31
|
-
log.debug(`Spawn command ${command} with ${args.join(' ')}`);
|
|
32
|
-
const success = await new Promise((resolve) => {
|
|
33
|
-
if (packageCommand === 'install')
|
|
34
|
-
sendLog('Matterbridge:spawn-init', `Installing ${packageName}`);
|
|
35
|
-
else if (packageCommand === 'uninstall')
|
|
36
|
-
sendLog('Matterbridge:spawn-init', `Uninstalling ${packageName}`);
|
|
37
|
-
const childProcess = spawn(command, args, {
|
|
38
|
-
stdio: ['inherit', 'pipe', 'pipe'],
|
|
39
|
-
});
|
|
40
|
-
childProcess.on('error', (err) => {
|
|
41
|
-
log.error(`Failed to start child process "${cmdLine}": ${err.message}`);
|
|
42
|
-
sendLog('Matterbridge:spawn-exit-error', 'Spawn process error');
|
|
43
|
-
resolve(false);
|
|
44
|
-
});
|
|
45
|
-
childProcess.on('close', (code, signal) => {
|
|
46
|
-
if (code === 0) {
|
|
47
|
-
log.debug(`Child process "${cmdLine}" closed with code ${code} and signal ${signal}`);
|
|
48
|
-
sendLog('Matterbridge:spawn-exit-success', 'Child process closed');
|
|
49
|
-
resolve(true);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
log.error(`Child process "${cmdLine}" closed with code ${code} and signal ${signal}`);
|
|
53
|
-
sendLog('Matterbridge:spawn-exit-error', 'Child process closed');
|
|
54
|
-
resolve(false);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
childProcess.on('exit', (code, signal) => {
|
|
58
|
-
if (code === 0) {
|
|
59
|
-
log.debug(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
60
|
-
sendLog('Matterbridge:spawn-exit-success', 'Child process exited');
|
|
61
|
-
resolve(true);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
log.error(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
65
|
-
sendLog('Matterbridge:spawn-exit-error', 'Child process exited');
|
|
66
|
-
resolve(false);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
childProcess.on('disconnect', () => {
|
|
70
|
-
log.debug(`Child process "${cmdLine}" has been disconnected from the parent`);
|
|
71
|
-
resolve(true);
|
|
72
|
-
});
|
|
73
|
-
if (childProcess.stdout) {
|
|
74
|
-
childProcess.stdout.on('data', (data) => {
|
|
75
|
-
const message = data.toString().trim();
|
|
76
|
-
const lines = message.split('\n');
|
|
77
|
-
for (const line of lines) {
|
|
78
|
-
log.debug(`Spawn output (stdout): ${line}`);
|
|
79
|
-
sendLog('Matterbridge:spawn', line);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
if (childProcess.stderr) {
|
|
84
|
-
childProcess.stderr.on('data', (data) => {
|
|
85
|
-
const message = data.toString().trim();
|
|
86
|
-
const lines = message.split('\n');
|
|
87
|
-
for (const line of lines) {
|
|
88
|
-
log.debug(`Spawn verbose (stderr): ${line}`);
|
|
89
|
-
sendLog('Matterbridge:spawn', line);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
server.close();
|
|
95
|
-
return success;
|
|
96
|
-
}
|