matterbridge 3.4.1-dev-20251128-441f8db → 3.4.1-dev-20251130-f066d82

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
@@ -14,8 +14,9 @@ The project will evolve to a multi-threaded architecture (the CLI will become th
14
14
  - frontend;
15
15
  - plugins;
16
16
  - devices;
17
- - check_updates;
18
- - npm_install;
17
+ - check updates;
18
+ - npm install;
19
+ - ✅ get global node_modules;
19
20
  - all plugins in bridge mode;
20
21
  - each plugin in childbridge mode;
21
22
 
@@ -31,7 +32,10 @@ Advantages:
31
32
  ### Added
32
33
 
33
34
  - [matterbridge.io]: Updated website https://matterbridge.io with all guides.
34
- - [matterbridge]: Added addVirtualEndpoint() to match thread module.
35
+ - [matterbridge]: Added addVirtualEndpoint() to match Matterbridge thread module.
36
+ - [BroadcastServer]: Backport BroadcastServer v.2.0.0 from Matterbridge thread module.
37
+ - [MatterbridgePrefix]: Added worker thread to get global node_modules.
38
+ - [PluginManager]: Improved the resolve method to resolve automatically also in the plugin directory Usefull for developing with DevContainer.
35
39
 
36
40
  ### Changed
37
41
 
@@ -25,24 +25,64 @@ export class BroadcastServer extends EventEmitter {
25
25
  this.broadcastChannel.close();
26
26
  }
27
27
  getUniqueId() {
28
- return Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000;
28
+ return Math.floor(Math.random() * 900000000) + 100000000;
29
29
  }
30
- isWorkerRequest(msg, type) {
31
- return typeof msg === 'object' && msg !== null && 'id' in msg && 'timestamp' in msg && 'type' in msg && msg.type === type && !('response' in msg) && 'src' in msg && 'dst' in msg;
30
+ isWorkerRequest(value) {
31
+ if (typeof value !== 'object' || value === null) {
32
+ return false;
33
+ }
34
+ const message = value;
35
+ if (typeof message.type !== 'string' || typeof message.src !== 'string' || typeof message.dst !== 'string' || typeof message.id !== 'number' || typeof message.timestamp !== 'number') {
36
+ return false;
37
+ }
38
+ return message.result === undefined && message.error === undefined;
39
+ }
40
+ isWorkerRequestOfType(value, type) {
41
+ return this.isWorkerRequest(value) && value.type === type;
42
+ }
43
+ isWorkerResponse(value) {
44
+ if (typeof value !== 'object' || value === null) {
45
+ return false;
46
+ }
47
+ const message = value;
48
+ if (typeof message.type !== 'string' || typeof message.src !== 'string' || typeof message.dst !== 'string' || typeof message.id !== 'number' || typeof message.timestamp !== 'number') {
49
+ return false;
50
+ }
51
+ const hasError = typeof message.error === 'string';
52
+ const hasResult = message.result !== undefined;
53
+ return hasError !== hasResult;
32
54
  }
33
- isWorkerResponse(msg, type) {
34
- return typeof msg === 'object' && msg !== null && 'id' in msg && 'timestamp' in msg && 'type' in msg && msg.type === type && 'response' in msg && 'src' in msg && 'dst' in msg;
55
+ isWorkerResponseOfType(value, type) {
56
+ return this.isWorkerResponse(value) && value.type === type;
35
57
  }
36
58
  broadcastMessageHandler(event) {
37
- const data = event.data;
38
- if (this.verbose && (data.dst === this.name || data.dst === 'all'))
39
- this.log.debug(`Server ${CYAN}${this.name}${db} received broadcast message: ${debugStringify(data)}`);
40
- this.emit('broadcast_message', data);
59
+ const msg = event.data;
60
+ if (msg.dst === this.name || msg.dst === 'all') {
61
+ if (this.verbose)
62
+ this.log.debug(`Server ${CYAN}${this.name}${db} received broadcast message: ${debugStringify(msg)}`);
63
+ this.emit('broadcast_message', msg);
64
+ }
65
+ else {
66
+ if (this.verbose)
67
+ this.log.debug(`Server ${CYAN}${this.name}${db} received unrelated broadcast message: ${debugStringify(msg)}`);
68
+ }
41
69
  }
42
70
  broadcast(message) {
71
+ if (message.id === undefined) {
72
+ message.id = this.getUniqueId();
73
+ }
74
+ if (message.timestamp === undefined) {
75
+ message.timestamp = Date.now();
76
+ }
77
+ message.src = this.name;
43
78
  if (this.verbose)
44
79
  this.log.debug(`Broadcasting message: ${debugStringify(message)}`);
45
- this.broadcastChannel.postMessage(message);
80
+ try {
81
+ this.broadcastChannel.postMessage(message);
82
+ }
83
+ catch (error) {
84
+ logError(this.log, `Failed to broadcast message ${debugStringify(message)}${er}`, error);
85
+ }
46
86
  }
47
87
  request(message) {
48
88
  if (message.id === undefined) {
@@ -51,8 +91,9 @@ export class BroadcastServer extends EventEmitter {
51
91
  if (message.timestamp === undefined) {
52
92
  message.timestamp = Date.now();
53
93
  }
54
- if (!this.isWorkerRequest(message, message.type)) {
55
- this.log.error(`Invalid request message format for broadcast: ${debugStringify(message)}`);
94
+ message.src = this.name;
95
+ if (!this.isWorkerRequest(message)) {
96
+ this.log.error(`Invalid request message format: ${debugStringify(message)}`);
56
97
  return;
57
98
  }
58
99
  if (this.verbose)
@@ -65,11 +106,18 @@ export class BroadcastServer extends EventEmitter {
65
106
  }
66
107
  }
67
108
  respond(message) {
109
+ if (typeof message.timestamp === 'number') {
110
+ message.elapsed = Date.now() - message.timestamp;
111
+ }
68
112
  if (message.timestamp === undefined) {
69
113
  message.timestamp = Date.now();
70
114
  }
71
- if (!this.isWorkerResponse(message, message.type)) {
72
- this.log.error(`Invalid response message format for broadcast: ${debugStringify(message)}`);
115
+ if (message.dst === this.name || message.dst === 'all') {
116
+ message.dst = message.src;
117
+ }
118
+ message.src = this.name;
119
+ if (!this.isWorkerResponse(message)) {
120
+ this.log.error(`Invalid response message format: ${debugStringify(message)}`);
73
121
  return;
74
122
  }
75
123
  if (this.verbose)
@@ -92,16 +140,21 @@ export class BroadcastServer extends EventEmitter {
92
140
  this.log.debug(`Fetching message: ${debugStringify(message)}`);
93
141
  return new Promise((resolve, reject) => {
94
142
  const responseHandler = (msg) => {
95
- if (this.isWorkerResponse(msg, message.type) && msg.id === message.id) {
143
+ if (this.isWorkerResponseOfType(msg, message.type) && msg.id === message.id) {
96
144
  clearTimeout(timeoutId);
97
145
  this.off('broadcast_message', responseHandler);
98
146
  if (this.verbose)
99
147
  this.log.debug(`Fetch response: ${debugStringify(msg)}`);
100
- resolve(msg);
101
- }
102
- else if (this.isWorkerResponse(msg, message.type) && msg.id !== message.id) {
103
- if (this.verbose)
104
- this.log.debug(`Fetch received unrelated response: ${debugStringify(msg)}`);
148
+ if ('error' in msg && typeof msg.error === 'string') {
149
+ reject(new Error(`Fetch received error response ${msg.error} to message type ${message.type} id ${message.id} from ${message.src} to ${message.dst}`));
150
+ }
151
+ else if ('result' in msg) {
152
+ resolve(msg);
153
+ }
154
+ else {
155
+ reject(new Error(`Fetch received malformed response for message type ${message.type} id ${message.id} from ${message.src} to ${message.dst}`));
156
+ }
157
+ return;
105
158
  }
106
159
  };
107
160
  this.on('broadcast_message', responseHandler);
@@ -41,47 +41,48 @@ export class DeviceManager {
41
41
  this.log.debug('Matterbridge device manager started');
42
42
  }
43
43
  destroy() {
44
+ this.server.off('broadcast_message', this.msgHandler.bind(this));
44
45
  this.server.close();
45
46
  }
46
47
  async msgHandler(msg) {
47
- if (this.server.isWorkerRequest(msg, msg.type) && (msg.dst === 'all' || msg.dst === 'devices')) {
48
+ if (this.server.isWorkerRequest(msg)) {
48
49
  if (this.verbose)
49
50
  this.log.debug(`Received request message ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
50
51
  switch (msg.type) {
51
52
  case 'get_log_level':
52
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
53
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
53
54
  break;
54
55
  case 'set_log_level':
55
56
  this.log.logLevel = msg.params.logLevel;
56
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
57
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
57
58
  break;
58
59
  case 'devices_length':
59
- this.server.respond({ ...msg, response: { length: this.length } });
60
+ this.server.respond({ ...msg, result: { length: this.length } });
60
61
  break;
61
62
  case 'devices_size':
62
- this.server.respond({ ...msg, response: { size: this.size } });
63
+ this.server.respond({ ...msg, result: { size: this.size } });
63
64
  break;
64
65
  case 'devices_has':
65
- this.server.respond({ ...msg, response: { has: this.has(msg.params.uniqueId) } });
66
+ this.server.respond({ ...msg, result: { has: this.has(msg.params.uniqueId) } });
66
67
  break;
67
68
  case 'devices_get':
68
69
  {
69
70
  const endpoint = this.get(msg.params.uniqueId);
70
- this.server.respond({ ...msg, response: { device: endpoint ? toBaseDevice(endpoint) : undefined } });
71
+ this.server.respond({ ...msg, result: { device: endpoint ? toBaseDevice(endpoint) : undefined } });
71
72
  }
72
73
  break;
73
74
  case 'devices_set':
74
- this.server.respond({ ...msg, response: { device: this.set(toBaseDevice(msg.params.device)) } });
75
+ this.server.respond({ ...msg, result: { device: this.set(toBaseDevice(msg.params.device)) } });
75
76
  break;
76
77
  case 'devices_remove':
77
- this.server.respond({ ...msg, response: { success: this.remove(toBaseDevice(msg.params.device)) } });
78
+ this.server.respond({ ...msg, result: { success: this.remove(toBaseDevice(msg.params.device)) } });
78
79
  break;
79
80
  case 'devices_clear':
80
81
  this.clear();
81
- this.server.respond({ ...msg, response: { success: true } });
82
+ this.server.respond({ ...msg, result: { success: true } });
82
83
  break;
83
84
  case 'devices_basearray':
84
- this.server.respond({ ...msg, response: { devices: this.baseArray(msg.params.pluginName) } });
85
+ this.server.respond({ ...msg, result: { devices: this.baseArray(msg.params.pluginName) } });
85
86
  break;
86
87
  default:
87
88
  if (this.verbose)
package/dist/frontend.js CHANGED
@@ -43,97 +43,92 @@ export class Frontend extends EventEmitter {
43
43
  this.server.on('broadcast_message', this.msgHandler.bind(this));
44
44
  }
45
45
  destroy() {
46
+ this.server.off('broadcast_message', this.msgHandler.bind(this));
46
47
  this.server.close();
47
48
  }
48
49
  async msgHandler(msg) {
49
- if (this.server.isWorkerRequest(msg, msg.type) && (msg.dst === 'all' || msg.dst === 'frontend')) {
50
+ if (this.server.isWorkerRequest(msg)) {
50
51
  if (this.verbose)
51
52
  this.log.debug(`Received broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
52
53
  switch (msg.type) {
53
54
  case 'get_log_level':
54
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
55
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
55
56
  break;
56
57
  case 'set_log_level':
57
58
  this.log.logLevel = msg.params.logLevel;
58
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
59
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
59
60
  break;
60
61
  case 'frontend_start':
61
62
  await this.start(msg.params.port);
62
- this.server.respond({ ...msg, response: { success: true } });
63
+ this.server.respond({ ...msg, result: { success: true } });
63
64
  break;
64
65
  case 'frontend_stop':
65
66
  await this.stop();
66
- this.server.respond({ ...msg, response: { success: true } });
67
+ this.server.respond({ ...msg, result: { success: true } });
67
68
  break;
68
69
  case 'frontend_refreshrequired':
69
70
  this.wssSendRefreshRequired(msg.params.changed, msg.params.matter ? { matter: msg.params.matter } : undefined);
70
- this.server.respond({ ...msg, response: { success: true } });
71
+ this.server.respond({ ...msg, result: { success: true } });
71
72
  break;
72
73
  case 'frontend_restartrequired':
73
74
  this.wssSendRestartRequired(msg.params.snackbar, msg.params.fixed);
74
- this.server.respond({ ...msg, response: { success: true } });
75
+ this.server.respond({ ...msg, result: { success: true } });
75
76
  break;
76
77
  case 'frontend_restartnotrequired':
77
78
  this.wssSendRestartNotRequired(msg.params.snackbar);
78
- this.server.respond({ ...msg, response: { success: true } });
79
+ this.server.respond({ ...msg, result: { success: true } });
79
80
  break;
80
81
  case 'frontend_updaterequired':
81
82
  this.wssSendUpdateRequired(msg.params.devVersion);
82
- this.server.respond({ ...msg, response: { success: true } });
83
+ this.server.respond({ ...msg, result: { success: true } });
83
84
  break;
84
85
  case 'frontend_snackbarmessage':
85
86
  this.wssSendSnackbarMessage(msg.params.message, msg.params.timeout, msg.params.severity);
86
- this.server.respond({ ...msg, response: { success: true } });
87
+ this.server.respond({ ...msg, result: { success: true } });
87
88
  break;
88
89
  case 'frontend_attributechanged':
89
90
  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
- this.server.respond({ ...msg, response: { success: true } });
91
+ this.server.respond({ ...msg, result: { success: true } });
91
92
  break;
92
93
  case 'frontend_logmessage':
93
94
  this.wssSendLogMessage(msg.params.level, msg.params.time, msg.params.name, msg.params.message);
94
- this.server.respond({ ...msg, response: { success: true } });
95
+ this.server.respond({ ...msg, result: { success: true } });
95
96
  break;
96
97
  case 'frontend_broadcast_message':
97
98
  this.wssBroadcastMessage(msg.params.msg);
98
- this.server.respond({ ...msg, response: { success: true } });
99
+ this.server.respond({ ...msg, result: { success: true } });
99
100
  break;
100
101
  default:
101
102
  if (this.verbose)
102
103
  this.log.debug(`Unknown broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
103
104
  }
104
105
  }
105
- if (this.server.isWorkerResponse(msg, msg.type)) {
106
+ if (this.server.isWorkerResponse(msg) && msg.result) {
106
107
  if (this.verbose)
107
108
  this.log.debug(`Received broadcast response ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
108
109
  switch (msg.type) {
109
- case 'get_log_level':
110
- case 'set_log_level':
111
- break;
112
110
  case 'plugins_install':
113
- this.wssSendCloseSnackbarMessage(`Installing package ${msg.response.packageName}...`);
114
- if (msg.response.success) {
111
+ this.wssSendCloseSnackbarMessage(`Installing package ${msg.result.packageName}...`);
112
+ if (msg.result.success) {
115
113
  this.wssSendRestartRequired(true, true);
116
114
  this.wssSendRefreshRequired('plugins');
117
- this.wssSendSnackbarMessage(`Installed package ${msg.response.packageName}`, 5, 'success');
115
+ this.wssSendSnackbarMessage(`Installed package ${msg.result.packageName}`, 5, 'success');
118
116
  }
119
117
  else {
120
- this.wssSendSnackbarMessage(`Package ${msg.response.packageName} not installed`, 10, 'error');
118
+ this.wssSendSnackbarMessage(`Package ${msg.result.packageName} not installed`, 10, 'error');
121
119
  }
122
120
  break;
123
121
  case 'plugins_uninstall':
124
- this.wssSendCloseSnackbarMessage(`Uninstalling package ${msg.response.packageName}...`);
125
- if (msg.response.success) {
122
+ this.wssSendCloseSnackbarMessage(`Uninstalling package ${msg.result.packageName}...`);
123
+ if (msg.result.success) {
126
124
  this.wssSendRestartRequired(true, true);
127
125
  this.wssSendRefreshRequired('plugins');
128
- this.wssSendSnackbarMessage(`Uninstalled package ${msg.response.packageName}`, 5, 'success');
126
+ this.wssSendSnackbarMessage(`Uninstalled package ${msg.result.packageName}`, 5, 'success');
129
127
  }
130
128
  else {
131
- this.wssSendSnackbarMessage(`Package ${msg.response.packageName} not uninstalled`, 10, 'error');
129
+ this.wssSendSnackbarMessage(`Package ${msg.result.packageName} not uninstalled`, 10, 'error');
132
130
  }
133
131
  break;
134
- default:
135
- if (this.verbose)
136
- this.log.debug(`Unknown broadcast response ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
137
132
  }
138
133
  }
139
134
  }
@@ -50,6 +50,7 @@ export let wssSendRestartRequiredSpy;
50
50
  export let wssSendRestartNotRequiredSpy;
51
51
  export let broadcastServerIsWorkerRequestSpy;
52
52
  export let broadcastServerIsWorkerResponseSpy;
53
+ export let broadcastServerBroadcastSpy;
53
54
  export let broadcastServerRequestSpy;
54
55
  export let broadcastServerRespondSpy;
55
56
  export let broadcastServerFetchSpy;
@@ -116,6 +117,7 @@ export async function setupTest(name, debug = false) {
116
117
  wssSendRestartNotRequiredSpy = jest.spyOn(Frontend.prototype, 'wssSendRestartNotRequired');
117
118
  broadcastServerIsWorkerRequestSpy = jest.spyOn(BroadcastServer.prototype, 'isWorkerRequest');
118
119
  broadcastServerIsWorkerResponseSpy = jest.spyOn(BroadcastServer.prototype, 'isWorkerResponse');
120
+ broadcastServerBroadcastSpy = jest.spyOn(BroadcastServer.prototype, 'broadcast');
119
121
  broadcastServerRequestSpy = jest.spyOn(BroadcastServer.prototype, 'request');
120
122
  broadcastServerRespondSpy = jest.spyOn(BroadcastServer.prototype, 'respond');
121
123
  broadcastServerFetchSpy = jest.spyOn(BroadcastServer.prototype, 'fetch');
@@ -92,23 +92,23 @@ export class MatterNode extends EventEmitter {
92
92
  this.log.debug(`MatterNode ${this.pluginName ? 'for plugin ' + this.pluginName : 'bridge'} loaded`);
93
93
  }
94
94
  async msgHandler(msg) {
95
- if (this.server.isWorkerRequest(msg, msg.type) && (msg.dst === 'all' || msg.dst === 'matter')) {
95
+ if (this.server.isWorkerRequest(msg) && (msg.dst === 'all' || msg.dst === 'matter')) {
96
96
  if (this.verbose)
97
97
  this.log.debug(`Received broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
98
98
  switch (msg.type) {
99
99
  case 'get_log_level':
100
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
100
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
101
101
  break;
102
102
  case 'set_log_level':
103
103
  this.log.logLevel = msg.params.logLevel;
104
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
104
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
105
105
  break;
106
106
  default:
107
107
  if (this.verbose)
108
108
  this.log.debug(`Unknown broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
109
109
  }
110
110
  }
111
- if (this.server.isWorkerResponse(msg, msg.type) && (msg.dst === 'all' || msg.dst === 'matter')) {
111
+ if (this.server.isWorkerResponse(msg) && (msg.dst === 'all' || msg.dst === 'matter')) {
112
112
  if (this.verbose)
113
113
  this.log.debug(`Received broadcast response ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
114
114
  switch (msg.type) {
@@ -669,6 +669,7 @@ export class MatterNode extends EventEmitter {
669
669
  await device.construction.ready;
670
670
  await this.subscribeAttributeChanged(plugin, device);
671
671
  this.log.info(`Added endpoint #${plugin.registeredDevices} ${plg}${pluginName}${nf}:${dev}${device.deviceName}${nf} (${zb}${device.name}${nf})`);
672
+ await this.yieldToNode(10);
672
673
  return device;
673
674
  }
674
675
  async removeBridgedEndpoint(pluginName, device) {
@@ -697,6 +698,7 @@ export class MatterNode extends EventEmitter {
697
698
  if (plugin.registeredDevices !== undefined)
698
699
  plugin.registeredDevices--;
699
700
  await this.server.fetch({ type: 'devices_remove', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
701
+ await this.yieldToNode(10);
700
702
  return device;
701
703
  }
702
704
  async removeAllBridgedEndpoints(pluginName, delay = 0) {
@@ -704,7 +706,7 @@ export class MatterNode extends EventEmitter {
704
706
  if (!plugin)
705
707
  throw new Error(`Error removing all bridged endpoints for plugin ${plg}${pluginName}${er}: plugin not found`);
706
708
  this.log.debug(`Removing all #${plugin.registeredDevices} bridged endpoints for plugin ${plg}${pluginName}${db}${delay > 0 ? ` with delay ${delay} ms` : ''}...`);
707
- const devices = (await this.server.fetch({ type: 'devices_basearray', src: this.server.name, dst: 'devices', params: { pluginName } })).response.devices;
709
+ const devices = (await this.server.fetch({ type: 'devices_basearray', src: this.server.name, dst: 'devices', params: { pluginName } })).result.devices;
708
710
  for (const device of devices) {
709
711
  const endpoint = (this.aggregatorNode?.parts.get(device.id || '') || this.serverNode?.parts.get(device.id || ''));
710
712
  if (!endpoint)
@@ -715,6 +717,7 @@ export class MatterNode extends EventEmitter {
715
717
  if (plugin.registeredDevices !== undefined)
716
718
  plugin.registeredDevices--;
717
719
  await this.server.fetch({ type: 'devices_remove', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
720
+ await this.yieldToNode(10);
718
721
  if (delay > 0)
719
722
  await wait(delay);
720
723
  }
@@ -742,6 +745,7 @@ export class MatterNode extends EventEmitter {
742
745
  }
743
746
  await addVirtualDevice(this.aggregatorNode, name.slice(0, 32), type, callback);
744
747
  this.log.debug(`Created virtual device ${plg}${pluginName}${db}:${dev}${name}${db}`);
748
+ await this.yieldToNode(10);
745
749
  return true;
746
750
  }
747
751
  async subscribeAttributeChanged(plugin, device) {
@@ -133,52 +133,45 @@ export class Matterbridge extends EventEmitter {
133
133
  this.server.close();
134
134
  }
135
135
  async msgHandler(msg) {
136
- if (this.server.isWorkerRequest(msg, msg.type) && (msg.dst === 'all' || msg.dst === 'matterbridge')) {
136
+ if (this.server.isWorkerRequest(msg) && (msg.dst === 'all' || msg.dst === 'matterbridge')) {
137
137
  if (this.verbose)
138
138
  this.log.debug(`Received broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
139
139
  switch (msg.type) {
140
140
  case 'get_log_level':
141
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
141
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
142
142
  break;
143
143
  case 'set_log_level':
144
144
  this.log.logLevel = msg.params.logLevel;
145
- this.server.respond({ ...msg, response: { success: true, logLevel: this.log.logLevel } });
145
+ this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
146
146
  break;
147
147
  case 'matterbridge_latest_version':
148
148
  this.matterbridgeLatestVersion = msg.params.version;
149
149
  await this.nodeContext?.set('matterbridgeLatestVersion', msg.params.version);
150
- this.server.respond({ ...msg, response: { success: true } });
150
+ this.server.respond({ ...msg, result: { success: true } });
151
151
  break;
152
152
  case 'matterbridge_dev_version':
153
153
  this.matterbridgeDevVersion = msg.params.version;
154
154
  await this.nodeContext?.set('matterbridgeDevVersion', msg.params.version);
155
- this.server.respond({ ...msg, response: { success: true } });
155
+ this.server.respond({ ...msg, result: { success: true } });
156
+ break;
157
+ case 'matterbridge_global_prefix':
158
+ this.globalModulesDirectory = msg.params.prefix;
159
+ await this.nodeContext?.set('globalModulesDirectory', msg.params.prefix);
160
+ this.server.respond({ ...msg, result: { success: true } });
156
161
  break;
157
162
  case 'matterbridge_sys_update':
158
163
  this.shellySysUpdate = true;
159
- this.server.respond({ ...msg, response: { success: true } });
164
+ this.server.respond({ ...msg, result: { success: true } });
160
165
  break;
161
166
  case 'matterbridge_main_update':
162
167
  this.shellyMainUpdate = true;
163
- this.server.respond({ ...msg, response: { success: true } });
168
+ this.server.respond({ ...msg, result: { success: true } });
164
169
  break;
165
170
  default:
166
171
  if (this.verbose)
167
172
  this.log.debug(`Unknown broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
168
173
  }
169
174
  }
170
- if (this.server.isWorkerResponse(msg, msg.type)) {
171
- if (this.verbose)
172
- this.log.debug(`Received broadcast response ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
173
- switch (msg.type) {
174
- case 'get_log_level':
175
- case 'set_log_level':
176
- break;
177
- default:
178
- if (this.verbose)
179
- this.log.debug(`Unknown broadcast response ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
180
- }
181
- }
182
175
  }
183
176
  static async loadInstance(initialize = false) {
184
177
  if (!Matterbridge.instance) {
@@ -832,16 +825,9 @@ export class Matterbridge extends EventEmitter {
832
825
  }
833
826
  }
834
827
  else {
835
- this.log.debug(`Checking global node_modules directory: ${this.globalModulesDirectory}`);
836
- try {
837
- const { getGlobalNodeModules } = await import('./utils/network.js');
838
- this.globalModulesDirectory = await getGlobalNodeModules();
839
- this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
840
- await this.nodeContext?.set('globalModulesDirectory', this.globalModulesDirectory);
841
- }
842
- catch (error) {
843
- this.log.error(`Error checking global node_modules directory: ${error}`);
844
- }
828
+ this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
829
+ const { createESMWorker } = await import('./workers.js');
830
+ createESMWorker('NpmGlobalPrefix', './dist/workerGlobalPrefix.js');
845
831
  }
846
832
  this.log.debug(`Reading matterbridge package.json...`);
847
833
  const packageJson = JSON.parse(await fs.promises.readFile(path.join(this.rootDirectory, 'package.json'), 'utf-8'));
@@ -124,7 +124,7 @@ export class MatterbridgePlatform {
124
124
  this.#server.request({ type: 'plugins_saveconfigfromjson', src: 'platform', dst: 'plugins', params: { name: this.name, config } });
125
125
  }
126
126
  async getSchema() {
127
- return (await this.#server.fetch({ type: 'plugins_getschema', src: 'platform', dst: 'plugins', params: { name: this.name } })).response.schema;
127
+ return (await this.#server.fetch({ type: 'plugins_getschema', src: 'platform', dst: 'plugins', params: { name: this.name } })).result.schema;
128
128
  }
129
129
  setSchema(schema) {
130
130
  this.#server.request({ type: 'plugins_setschema', src: 'platform', dst: 'plugins', params: { name: this.name, schema } });