matterbridge 3.3.9-dev-20251119-ea13a99 → 3.4.0-dev-20251120-21b4f48
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 +12 -1
- package/dist/broadcastServer.js +1 -1
- package/dist/deviceManager.js +33 -15
- package/dist/frontend.js +19 -7
- package/dist/matterbridge.js +8 -11
- package/dist/matterbridgeEndpoint.js +6 -0
- package/dist/pluginManager.js +16 -19
- package/dist/utils/copyDirectory.js +3 -5
- package/dist/utils/spawn.js +41 -23
- package/npm-shrinkwrap.json +13 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -28,7 +28,7 @@ Advantages:
|
|
|
28
28
|
- individual plugin isolation in childbridge mode;
|
|
29
29
|
- ability to update the plugin in childbridge mode without restarting matterbridge;
|
|
30
30
|
|
|
31
|
-
## [3.
|
|
31
|
+
## [3.4.0] - Not published
|
|
32
32
|
|
|
33
33
|
### Development Breaking Changes
|
|
34
34
|
|
|
@@ -38,9 +38,20 @@ Removed the following long deprecated elements:
|
|
|
38
38
|
- [endpoint]: uniqueStorageKey instead of id in MatterbridgeEndpointOptions (deprecated since months).
|
|
39
39
|
- [endpoint]: endpointId instead of number in MatterbridgeEndpointOptions (deprecated since months).
|
|
40
40
|
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- [endpoint]: Added getChildEndpointById() and getChildEndpointByOriginalId().
|
|
44
|
+
- [endpoint]: Deprecated getChildEndpointByName(). Use getChildEndpointById() or getChildEndpointByOriginalId().
|
|
45
|
+
- [platform]: Added wssSendSnackbarMessage method to MatterbridgePlatform for sending snackbar notifications to the frontend.
|
|
46
|
+
|
|
41
47
|
### Changed
|
|
42
48
|
|
|
43
49
|
- [package]: Updated dependencies.
|
|
50
|
+
- [deviceManager]: Bumped DeviceManager v.1.1.1.
|
|
51
|
+
- [pluginManager]: Bumped PluginManager v.1.3.1.
|
|
52
|
+
- [broadcastServer]: Bumped BroadcastServer v.1.0.3.
|
|
53
|
+
- [jest]: Bumped jestHelpers v.1.0.13.
|
|
54
|
+
- [spawn]: Bumped spawn module v.1.2.0.
|
|
44
55
|
|
|
45
56
|
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
46
57
|
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
package/dist/broadcastServer.js
CHANGED
|
@@ -70,7 +70,7 @@ export class BroadcastServer extends EventEmitter {
|
|
|
70
70
|
this.log.debug(`Broadcasting response message: ${debugStringify(message)}`);
|
|
71
71
|
this.broadcastChannel.postMessage(message);
|
|
72
72
|
}
|
|
73
|
-
async fetch(message, timeout =
|
|
73
|
+
async fetch(message, timeout = 250) {
|
|
74
74
|
if (message.id === undefined) {
|
|
75
75
|
message.id = this.getUniqueId();
|
|
76
76
|
}
|
package/dist/deviceManager.js
CHANGED
|
@@ -2,6 +2,31 @@ import { AnsiLogger, BLUE, CYAN, db, debugStringify, er } from 'node-ansi-logger
|
|
|
2
2
|
import { dev } from './matterbridgeTypes.js';
|
|
3
3
|
import { BroadcastServer } from './broadcastServer.js';
|
|
4
4
|
import { hasParameter } from './utils/commandLine.js';
|
|
5
|
+
export function toBaseDevice(device) {
|
|
6
|
+
return {
|
|
7
|
+
mode: device.mode,
|
|
8
|
+
plugin: device.plugin,
|
|
9
|
+
configUrl: device.configUrl,
|
|
10
|
+
deviceName: device.deviceName,
|
|
11
|
+
serialNumber: device.serialNumber,
|
|
12
|
+
uniqueId: device.uniqueId,
|
|
13
|
+
vendorId: device.vendorId,
|
|
14
|
+
vendorName: device.vendorName,
|
|
15
|
+
productId: device.productId,
|
|
16
|
+
productName: device.productName,
|
|
17
|
+
softwareVersion: device.softwareVersion,
|
|
18
|
+
softwareVersionString: device.softwareVersionString,
|
|
19
|
+
hardwareVersion: device.hardwareVersion,
|
|
20
|
+
hardwareVersionString: device.hardwareVersionString,
|
|
21
|
+
productUrl: device.productUrl,
|
|
22
|
+
tagList: device.tagList,
|
|
23
|
+
originalId: device.originalId,
|
|
24
|
+
name: device.name,
|
|
25
|
+
deviceType: device.deviceType,
|
|
26
|
+
number: device.number,
|
|
27
|
+
id: device.id,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
5
30
|
export class DeviceManager {
|
|
6
31
|
_devices = new Map();
|
|
7
32
|
log;
|
|
@@ -40,13 +65,16 @@ export class DeviceManager {
|
|
|
40
65
|
this.server.respond({ ...msg, response: { has: this.has(msg.params.uniqueId) } });
|
|
41
66
|
break;
|
|
42
67
|
case 'devices_get':
|
|
43
|
-
|
|
68
|
+
{
|
|
69
|
+
const endpoint = this.get(msg.params.uniqueId);
|
|
70
|
+
this.server.respond({ ...msg, response: { device: endpoint ? toBaseDevice(endpoint) : undefined } });
|
|
71
|
+
}
|
|
44
72
|
break;
|
|
45
73
|
case 'devices_set':
|
|
46
|
-
this.server.respond({ ...msg, response: { device: this.set(msg.params.device) } });
|
|
74
|
+
this.server.respond({ ...msg, response: { device: this.set(toBaseDevice(msg.params.device)) } });
|
|
47
75
|
break;
|
|
48
76
|
case 'devices_remove':
|
|
49
|
-
this.server.respond({ ...msg, response: { success: this.remove(msg.params.device) } });
|
|
77
|
+
this.server.respond({ ...msg, response: { success: this.remove(toBaseDevice(msg.params.device)) } });
|
|
50
78
|
break;
|
|
51
79
|
case 'devices_clear':
|
|
52
80
|
this.clear();
|
|
@@ -92,24 +120,14 @@ export class DeviceManager {
|
|
|
92
120
|
this._devices.clear();
|
|
93
121
|
}
|
|
94
122
|
toBaseDevice(device) {
|
|
95
|
-
return
|
|
96
|
-
pluginName: device.plugin,
|
|
97
|
-
deviceType: device.deviceType,
|
|
98
|
-
number: device.maybeNumber,
|
|
99
|
-
id: device.maybeId,
|
|
100
|
-
deviceName: device.deviceName,
|
|
101
|
-
serialNumber: device.serialNumber,
|
|
102
|
-
uniqueId: device.uniqueId,
|
|
103
|
-
productUrl: device.productUrl,
|
|
104
|
-
configUrl: device.configUrl,
|
|
105
|
-
};
|
|
123
|
+
return toBaseDevice(device);
|
|
106
124
|
}
|
|
107
125
|
array() {
|
|
108
126
|
return Array.from(this._devices.values());
|
|
109
127
|
}
|
|
110
128
|
baseArray(pluginName) {
|
|
111
129
|
const devices = [];
|
|
112
|
-
for (const device of this._devices.values()) {
|
|
130
|
+
for (const device of Array.from(this._devices.values())) {
|
|
113
131
|
if (pluginName && pluginName !== device.plugin)
|
|
114
132
|
continue;
|
|
115
133
|
devices.push(this.toBaseDevice(device));
|
package/dist/frontend.js
CHANGED
|
@@ -89,6 +89,10 @@ export class Frontend extends EventEmitter {
|
|
|
89
89
|
this.wssSendAttributeChangedMessage(msg.params.plugin, msg.params.serialNumber, msg.params.uniqueId, msg.params.number, msg.params.id, msg.params.cluster, msg.params.attribute, msg.params.value);
|
|
90
90
|
this.server.respond({ ...msg, response: { success: true } });
|
|
91
91
|
break;
|
|
92
|
+
case 'frontend_logmessage':
|
|
93
|
+
this.wssSendLogMessage(msg.params.level, msg.params.time, msg.params.name, msg.params.message);
|
|
94
|
+
this.server.respond({ ...msg, response: { success: true } });
|
|
95
|
+
break;
|
|
92
96
|
default:
|
|
93
97
|
if (this.verbose)
|
|
94
98
|
this.log.debug(`Unknown broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
|
|
@@ -689,15 +693,23 @@ export class Frontend extends EventEmitter {
|
|
|
689
693
|
this.log.info(`File ${plg}${filename}${nf} uploaded successfully`);
|
|
690
694
|
if (filename.endsWith('.tgz')) {
|
|
691
695
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
692
|
-
await spawnCommand(
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
696
|
+
if (await spawnCommand('npm', ['install', '-g', filePath, '--omit=dev', '--verbose'], 'install', filename)) {
|
|
697
|
+
this.log.info(`Plugin package ${plg}${filename}${nf} installed successfully. Full restart required.`);
|
|
698
|
+
this.wssSendCloseSnackbarMessage(`Installing package ${filename}. Please wait...`);
|
|
699
|
+
this.wssSendSnackbarMessage(`Installed package ${filename}`, 10, 'success');
|
|
700
|
+
this.wssSendRestartRequired();
|
|
701
|
+
res.send(`Plugin package ${filename} uploaded and installed successfully`);
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
this.log.error(`Error uploading or installing plugin package file ${plg}${filename}${er}`);
|
|
705
|
+
this.wssSendCloseSnackbarMessage(`Installing package ${filename}. Please wait...`);
|
|
706
|
+
this.wssSendSnackbarMessage(`Error uploading or installing plugin package ${filename}`, 10, 'error');
|
|
707
|
+
res.status(500).send(`Error uploading or installing plugin package ${filename}`);
|
|
708
|
+
}
|
|
698
709
|
}
|
|
699
|
-
else
|
|
710
|
+
else {
|
|
700
711
|
res.send(`File ${filename} uploaded successfully`);
|
|
712
|
+
}
|
|
701
713
|
}
|
|
702
714
|
catch (err) {
|
|
703
715
|
this.log.error(`Error uploading or installing plugin package file ${plg}${filename}${er}:`, err);
|
package/dist/matterbridge.js
CHANGED
|
@@ -28,7 +28,6 @@ import { bridge } from './matterbridgeDeviceTypes.js';
|
|
|
28
28
|
import { Frontend } from './frontend.js';
|
|
29
29
|
import { addVirtualDevices } from './helpers.js';
|
|
30
30
|
import { BroadcastServer } from './broadcastServer.js';
|
|
31
|
-
import { inspectError } from './utils/error.js';
|
|
32
31
|
export class Matterbridge extends EventEmitter {
|
|
33
32
|
systemInformation = {
|
|
34
33
|
interfaceName: '',
|
|
@@ -462,14 +461,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
462
461
|
for (const plugin of this.plugins) {
|
|
463
462
|
if (!fs.existsSync(plugin.path) && !hasParameter('add') && !hasParameter('remove') && !hasParameter('enable') && !hasParameter('disable') && !hasParameter('reset') && !hasParameter('factoryreset')) {
|
|
464
463
|
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm...`);
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
await spawnCommand(this, 'npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose'], 'install', plugin.name);
|
|
464
|
+
const { spawnCommand } = await import('./utils/spawn.js');
|
|
465
|
+
if (await spawnCommand('npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose'], 'install', plugin.name)) {
|
|
468
466
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
469
467
|
plugin.error = false;
|
|
470
468
|
}
|
|
471
|
-
|
|
472
|
-
|
|
469
|
+
else {
|
|
470
|
+
this.log.error(`Error reinstalling plugin ${plg}${plugin.name}${nf}. The plugin is disabled.`);
|
|
473
471
|
plugin.error = true;
|
|
474
472
|
plugin.enabled = false;
|
|
475
473
|
continue;
|
|
@@ -905,13 +903,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
905
903
|
}
|
|
906
904
|
async updateProcess() {
|
|
907
905
|
this.log.info('Updating matterbridge...');
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
await spawnCommand(this, 'npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose'], 'install', 'matterbridge');
|
|
906
|
+
const { spawnCommand } = await import('./utils/spawn.js');
|
|
907
|
+
if (await spawnCommand('npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose'], 'install', 'matterbridge')) {
|
|
911
908
|
this.log.info('Matterbridge has been updated. Full restart required.');
|
|
912
909
|
}
|
|
913
|
-
|
|
914
|
-
this.log.error(
|
|
910
|
+
else {
|
|
911
|
+
this.log.error('Error updating matterbridge.');
|
|
915
912
|
}
|
|
916
913
|
this.frontend.wssSendRestartRequired();
|
|
917
914
|
await this.cleanup('updating...', false);
|
|
@@ -368,6 +368,12 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
368
368
|
getChildEndpointByName(endpointName) {
|
|
369
369
|
return this.parts.find((part) => part.id === endpointName);
|
|
370
370
|
}
|
|
371
|
+
getChildEndpointById(id) {
|
|
372
|
+
return this.parts.find((part) => part.id === id);
|
|
373
|
+
}
|
|
374
|
+
getChildEndpointByOriginalId(originalId) {
|
|
375
|
+
return this.parts.find((part) => part.originalId === originalId);
|
|
376
|
+
}
|
|
371
377
|
getChildEndpoint(endpointNumber) {
|
|
372
378
|
return this.parts.find((part) => part.number === endpointNumber);
|
|
373
379
|
}
|
package/dist/pluginManager.js
CHANGED
|
@@ -266,6 +266,7 @@ export class PluginManager extends EventEmitter {
|
|
|
266
266
|
const pluginsArray = await this.matterbridge.nodeContext.get('plugins', []);
|
|
267
267
|
for (const plugin of pluginsArray)
|
|
268
268
|
this._plugins.set(plugin.name, plugin);
|
|
269
|
+
this.log.debug(`Loaded ${BLUE}${pluginsArray.length}${db} plugins from storage`);
|
|
269
270
|
return pluginsArray;
|
|
270
271
|
}
|
|
271
272
|
async saveToStorage() {
|
|
@@ -370,8 +371,7 @@ export class PluginManager extends EventEmitter {
|
|
|
370
371
|
async install(packageName) {
|
|
371
372
|
this.log.debug(`Installing plugin ${plg}${packageName}${db}...`);
|
|
372
373
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
373
|
-
|
|
374
|
-
await spawnCommand(this.matterbridge, 'npm', ['install', '-g', packageName, '--omit=dev', '--verbose'], 'install', packageName);
|
|
374
|
+
if (await spawnCommand('npm', ['install', '-g', packageName, '--omit=dev', '--verbose'], 'install', packageName)) {
|
|
375
375
|
this.matterbridge.restartRequired = true;
|
|
376
376
|
this.matterbridge.fixedRestartRequired = true;
|
|
377
377
|
packageName = packageName.replace(/@.*$/, '');
|
|
@@ -387,12 +387,11 @@ export class PluginManager extends EventEmitter {
|
|
|
387
387
|
await this.matterbridge.shutdownProcess();
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
|
-
this.log.
|
|
390
|
+
this.log.info(`Installed plugin ${plg}${packageName}${db} successfully`);
|
|
391
391
|
return true;
|
|
392
392
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
this.log.debug(`Failed to install plugin ${plg}${packageName}${db}`);
|
|
393
|
+
else {
|
|
394
|
+
this.log.error(`Failed to install plugin ${plg}${packageName}${er}`);
|
|
396
395
|
return false;
|
|
397
396
|
}
|
|
398
397
|
}
|
|
@@ -402,20 +401,18 @@ export class PluginManager extends EventEmitter {
|
|
|
402
401
|
packageName = packageName.replace(/@.*$/, '');
|
|
403
402
|
if (packageName === 'matterbridge')
|
|
404
403
|
return false;
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
this.log.debug(`Uninstalled plugin ${plg}${packageName}${db} successfully`);
|
|
404
|
+
if (this.has(packageName)) {
|
|
405
|
+
const plugin = this.get(packageName);
|
|
406
|
+
if (plugin && plugin.loaded)
|
|
407
|
+
await this.shutdown(plugin, 'Matterbridge is uninstalling the plugin');
|
|
408
|
+
await this.remove(packageName);
|
|
409
|
+
}
|
|
410
|
+
if (await spawnCommand('npm', ['uninstall', '-g', packageName, '--verbose'], 'uninstall', packageName)) {
|
|
411
|
+
this.log.info(`Uninstalled plugin ${plg}${packageName}${db} successfully`);
|
|
414
412
|
return true;
|
|
415
413
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
this.log.debug(`Failed to uninstall plugin ${plg}${packageName}${db}`);
|
|
414
|
+
else {
|
|
415
|
+
this.log.error(`Failed to uninstall plugin ${plg}${packageName}${er}`);
|
|
419
416
|
return false;
|
|
420
417
|
}
|
|
421
418
|
}
|
|
@@ -741,7 +738,7 @@ export class PluginManager extends EventEmitter {
|
|
|
741
738
|
plugin.author = this.getAuthor(packageJson);
|
|
742
739
|
plugin.configJson = config;
|
|
743
740
|
plugin.schemaJson = await this.loadSchema(plugin);
|
|
744
|
-
config.name =
|
|
741
|
+
config.name = packageJson.name;
|
|
745
742
|
config.version = packageJson.version;
|
|
746
743
|
const log = new AnsiLogger({ logName: plugin.description, logTimestampFormat: 4, logLevel: config.debug ? "debug" : this.matterbridge.log.logLevel });
|
|
747
744
|
const platform = pluginInstance.default(this.matterbridge, log, config);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export async function copyDirectory(srcDir, destDir) {
|
|
1
|
+
export async function copyDirectory(srcDir, destDir, log) {
|
|
3
2
|
if (srcDir === '') {
|
|
4
3
|
throw new Error('Source directory must be specified.');
|
|
5
4
|
}
|
|
@@ -15,10 +14,9 @@ export async function copyDirectory(srcDir, destDir) {
|
|
|
15
14
|
if (srcDir === destDir) {
|
|
16
15
|
throw new Error('Source and destination directories must be different.');
|
|
17
16
|
}
|
|
18
|
-
const log = new AnsiLogger({ logName: 'CopyDirectory', logTimestampFormat: 4, logLevel: "info" });
|
|
19
17
|
const fs = await import('node:fs').then((mod) => mod.promises);
|
|
20
18
|
const path = await import('node:path');
|
|
21
|
-
log
|
|
19
|
+
log?.debug(`copyDirectory: copying directory from ${srcDir} to ${destDir}`);
|
|
22
20
|
try {
|
|
23
21
|
await fs.mkdir(destDir, { recursive: true });
|
|
24
22
|
const entries = await fs.readdir(srcDir, { withFileTypes: true });
|
|
@@ -35,7 +33,7 @@ export async function copyDirectory(srcDir, destDir) {
|
|
|
35
33
|
return true;
|
|
36
34
|
}
|
|
37
35
|
catch (error) {
|
|
38
|
-
log
|
|
36
|
+
log?.error(`copyDirectory error copying from ${srcDir} to ${destDir}: ${error instanceof Error ? error.message : error}`);
|
|
39
37
|
return false;
|
|
40
38
|
}
|
|
41
39
|
}
|
package/dist/utils/spawn.js
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
|
+
import { AnsiLogger } from 'node-ansi-logger';
|
|
2
|
+
import { BroadcastServer } from '../broadcastServer.js';
|
|
1
3
|
import { hasParameter } from './commandLine.js';
|
|
2
|
-
export async function spawnCommand(
|
|
4
|
+
export async function spawnCommand(command, args, packageCommand, packageName) {
|
|
3
5
|
const { spawn } = await import('node:child_process');
|
|
6
|
+
const debug = hasParameter('debug') || hasParameter('verbose');
|
|
7
|
+
const verbose = hasParameter('verbose');
|
|
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}`);
|
|
4
20
|
const cmdLine = command + ' ' + args.join(' ');
|
|
5
21
|
if (process.platform === 'win32' && command === 'npm') {
|
|
6
22
|
const argstring = 'npm ' + args.join(' ');
|
|
@@ -11,46 +27,46 @@ export async function spawnCommand(matterbridge, command, args, packageCommand,
|
|
|
11
27
|
args.unshift(command);
|
|
12
28
|
command = 'sudo';
|
|
13
29
|
}
|
|
14
|
-
|
|
15
|
-
|
|
30
|
+
log.debug(`Spawn command ${command} with ${args.join(' ')}`);
|
|
31
|
+
const success = await new Promise((resolve) => {
|
|
16
32
|
if (packageCommand === 'install')
|
|
17
|
-
|
|
33
|
+
sendLog('Matterbridge:spawn-init', `Installing ${packageName}`);
|
|
18
34
|
else if (packageCommand === 'uninstall')
|
|
19
|
-
|
|
35
|
+
sendLog('Matterbridge:spawn-init', `Uninstalling ${packageName}`);
|
|
20
36
|
const childProcess = spawn(command, args, {
|
|
21
37
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
22
38
|
});
|
|
23
39
|
childProcess.on('error', (err) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
log.error(`Failed to start child process "${cmdLine}": ${err.message}`);
|
|
41
|
+
sendLog('Matterbridge:spawn-exit-error', 'Spawn process error');
|
|
42
|
+
resolve(false);
|
|
27
43
|
});
|
|
28
44
|
childProcess.on('close', (code, signal) => {
|
|
29
45
|
if (code === 0) {
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
log.debug(`Child process "${cmdLine}" closed with code ${code} and signal ${signal}`);
|
|
47
|
+
sendLog('Matterbridge:spawn-exit-success', 'Child process closed');
|
|
32
48
|
resolve(true);
|
|
33
49
|
}
|
|
34
50
|
else {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
log.error(`Child process "${cmdLine}" closed with code ${code} and signal ${signal}`);
|
|
52
|
+
sendLog('Matterbridge:spawn-exit-error', 'Child process closed');
|
|
53
|
+
resolve(false);
|
|
38
54
|
}
|
|
39
55
|
});
|
|
40
56
|
childProcess.on('exit', (code, signal) => {
|
|
41
57
|
if (code === 0) {
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
log.debug(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
59
|
+
sendLog('Matterbridge:spawn-exit-success', 'Child process exited');
|
|
44
60
|
resolve(true);
|
|
45
61
|
}
|
|
46
62
|
else {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
63
|
+
log.error(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
64
|
+
sendLog('Matterbridge:spawn-exit-error', 'Child process exited');
|
|
65
|
+
resolve(false);
|
|
50
66
|
}
|
|
51
67
|
});
|
|
52
68
|
childProcess.on('disconnect', () => {
|
|
53
|
-
|
|
69
|
+
log.debug(`Child process "${cmdLine}" has been disconnected from the parent`);
|
|
54
70
|
resolve(true);
|
|
55
71
|
});
|
|
56
72
|
if (childProcess.stdout) {
|
|
@@ -58,8 +74,8 @@ export async function spawnCommand(matterbridge, command, args, packageCommand,
|
|
|
58
74
|
const message = data.toString().trim();
|
|
59
75
|
const lines = message.split('\n');
|
|
60
76
|
for (const line of lines) {
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
log.debug(`Spawn output (stdout): ${line}`);
|
|
78
|
+
sendLog('Matterbridge:spawn', line);
|
|
63
79
|
}
|
|
64
80
|
});
|
|
65
81
|
}
|
|
@@ -68,10 +84,12 @@ export async function spawnCommand(matterbridge, command, args, packageCommand,
|
|
|
68
84
|
const message = data.toString().trim();
|
|
69
85
|
const lines = message.split('\n');
|
|
70
86
|
for (const line of lines) {
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
log.debug(`Spawn verbose (stderr): ${line}`);
|
|
88
|
+
sendLog('Matterbridge:spawn', line);
|
|
73
89
|
}
|
|
74
90
|
});
|
|
75
91
|
}
|
|
76
92
|
});
|
|
93
|
+
server.close();
|
|
94
|
+
return success;
|
|
77
95
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0-dev-20251120-21b4f48",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge",
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.4.0-dev-20251120-21b4f48",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@matter/main": "0.15.6",
|
|
@@ -284,9 +284,9 @@
|
|
|
284
284
|
}
|
|
285
285
|
},
|
|
286
286
|
"node_modules/archiver-utils/node_modules/glob": {
|
|
287
|
-
"version": "10.
|
|
288
|
-
"resolved": "https://registry.npmjs.org/glob/-/glob-10.
|
|
289
|
-
"integrity": "sha512-
|
|
287
|
+
"version": "10.5.0",
|
|
288
|
+
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
|
|
289
|
+
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
|
|
290
290
|
"license": "ISC",
|
|
291
291
|
"dependencies": {
|
|
292
292
|
"foreground-child": "^3.1.0",
|
|
@@ -581,15 +581,16 @@
|
|
|
581
581
|
}
|
|
582
582
|
},
|
|
583
583
|
"node_modules/content-disposition": {
|
|
584
|
-
"version": "1.0.
|
|
585
|
-
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.
|
|
586
|
-
"integrity": "sha512-
|
|
584
|
+
"version": "1.0.1",
|
|
585
|
+
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
|
|
586
|
+
"integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
|
|
587
587
|
"license": "MIT",
|
|
588
|
-
"dependencies": {
|
|
589
|
-
"safe-buffer": "5.2.1"
|
|
590
|
-
},
|
|
591
588
|
"engines": {
|
|
592
|
-
"node": ">=
|
|
589
|
+
"node": ">=18"
|
|
590
|
+
},
|
|
591
|
+
"funding": {
|
|
592
|
+
"type": "opencollective",
|
|
593
|
+
"url": "https://opencollective.com/express"
|
|
593
594
|
}
|
|
594
595
|
},
|
|
595
596
|
"node_modules/content-type": {
|
package/package.json
CHANGED