matterbridge 3.4.1-dev-20251127-826b2bf → 3.4.1-dev-20251129-ff1e22f
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 +8 -3
- package/README-DEV.md +20 -4
- package/README.md +2 -0
- package/dist/broadcastServer.js +88 -24
- package/dist/deviceManager.js +11 -11
- package/dist/frontend.js +26 -28
- package/dist/jestutils/jestHelpers.js +51 -0
- package/dist/matterNode.js +9 -5
- package/dist/matterbridge.js +29 -25
- package/dist/matterbridgePlatform.js +1 -1
- package/dist/pluginManager.js +59 -35
- package/dist/shelly.js +12 -12
- package/dist/update.js +69 -53
- package/dist/utils/error.js +3 -1
- package/dist/workerGlobalPrefix.js +39 -0
- package/dist/workerTypes.js +1 -0
- package/dist/workers.js +35 -0
- package/frontend/build/assets/index.css +1 -1
- package/frontend/build/assets/index.js +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/matterbridge.js
CHANGED
|
@@ -133,32 +133,43 @@ export class Matterbridge extends EventEmitter {
|
|
|
133
133
|
this.server.close();
|
|
134
134
|
}
|
|
135
135
|
async msgHandler(msg) {
|
|
136
|
-
if (this.server.isWorkerRequest(msg
|
|
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,
|
|
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,
|
|
145
|
+
this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
|
|
146
146
|
break;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
case '
|
|
147
|
+
case 'matterbridge_latest_version':
|
|
148
|
+
this.matterbridgeLatestVersion = msg.params.version;
|
|
149
|
+
await this.nodeContext?.set('matterbridgeLatestVersion', msg.params.version);
|
|
150
|
+
this.server.respond({ ...msg, result: { success: true } });
|
|
151
|
+
break;
|
|
152
|
+
case 'matterbridge_dev_version':
|
|
153
|
+
this.matterbridgeDevVersion = msg.params.version;
|
|
154
|
+
await this.nodeContext?.set('matterbridgeDevVersion', msg.params.version);
|
|
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 } });
|
|
161
|
+
break;
|
|
162
|
+
case 'matterbridge_sys_update':
|
|
163
|
+
this.shellySysUpdate = true;
|
|
164
|
+
this.server.respond({ ...msg, result: { success: true } });
|
|
165
|
+
break;
|
|
166
|
+
case 'matterbridge_main_update':
|
|
167
|
+
this.shellyMainUpdate = true;
|
|
168
|
+
this.server.respond({ ...msg, result: { success: true } });
|
|
158
169
|
break;
|
|
159
170
|
default:
|
|
160
171
|
if (this.verbose)
|
|
161
|
-
this.log.debug(`Unknown broadcast
|
|
172
|
+
this.log.debug(`Unknown broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
|
|
162
173
|
}
|
|
163
174
|
}
|
|
164
175
|
}
|
|
@@ -814,16 +825,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
814
825
|
}
|
|
815
826
|
}
|
|
816
827
|
else {
|
|
817
|
-
this.log.debug(`
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
this.globalModulesDirectory = await getGlobalNodeModules();
|
|
821
|
-
this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
|
|
822
|
-
await this.nodeContext?.set('globalModulesDirectory', this.globalModulesDirectory);
|
|
823
|
-
}
|
|
824
|
-
catch (error) {
|
|
825
|
-
this.log.error(`Error checking global node_modules directory: ${error}`);
|
|
826
|
-
}
|
|
828
|
+
this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
|
|
829
|
+
const { createESMWorker } = await import('./workers.js');
|
|
830
|
+
createESMWorker('NpmGlobalPrefix', './dist/workerGlobalPrefix.js');
|
|
827
831
|
}
|
|
828
832
|
this.log.debug(`Reading matterbridge package.json...`);
|
|
829
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 } })).
|
|
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 } });
|
package/dist/pluginManager.js
CHANGED
|
@@ -24,61 +24,61 @@ export class PluginManager extends EventEmitter {
|
|
|
24
24
|
this.server.close();
|
|
25
25
|
}
|
|
26
26
|
async msgHandler(msg) {
|
|
27
|
-
if (this.server.isWorkerRequest(msg
|
|
27
|
+
if (this.server.isWorkerRequest(msg) && (msg.dst === 'all' || msg.dst === 'plugins')) {
|
|
28
28
|
if (this.verbose)
|
|
29
29
|
this.log.debug(`Received request message ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
|
|
30
30
|
switch (msg.type) {
|
|
31
31
|
case 'get_log_level':
|
|
32
|
-
this.server.respond({ ...msg,
|
|
32
|
+
this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
|
|
33
33
|
break;
|
|
34
34
|
case 'set_log_level':
|
|
35
35
|
this.log.logLevel = msg.params.logLevel;
|
|
36
|
-
this.server.respond({ ...msg,
|
|
36
|
+
this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
|
|
37
37
|
break;
|
|
38
38
|
case 'plugins_length':
|
|
39
|
-
this.server.respond({ ...msg,
|
|
39
|
+
this.server.respond({ ...msg, result: { length: this.length } });
|
|
40
40
|
break;
|
|
41
41
|
case 'plugins_size':
|
|
42
|
-
this.server.respond({ ...msg,
|
|
42
|
+
this.server.respond({ ...msg, result: { size: this.size } });
|
|
43
43
|
break;
|
|
44
44
|
case 'plugins_has':
|
|
45
|
-
this.server.respond({ ...msg,
|
|
45
|
+
this.server.respond({ ...msg, result: { has: this.has(msg.params.name) } });
|
|
46
46
|
break;
|
|
47
47
|
case 'plugins_get':
|
|
48
48
|
{
|
|
49
49
|
const plugin = this.get(msg.params.name);
|
|
50
50
|
if (plugin) {
|
|
51
|
-
this.server.respond({ ...msg,
|
|
51
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
52
52
|
}
|
|
53
53
|
else {
|
|
54
54
|
this.log.debug(`***Plugin ${plg}${msg.params.name}${db} not found in plugins_get`);
|
|
55
|
-
this.server.respond({ ...msg,
|
|
55
|
+
this.server.respond({ ...msg, result: { plugin: undefined } });
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
break;
|
|
59
59
|
case 'plugins_set':
|
|
60
|
-
this.server.respond({ ...msg,
|
|
60
|
+
this.server.respond({ ...msg, result: { plugin: this.set(msg.params.plugin) } });
|
|
61
61
|
break;
|
|
62
62
|
case 'plugins_storagepluginarray':
|
|
63
|
-
this.server.respond({ ...msg,
|
|
63
|
+
this.server.respond({ ...msg, result: { plugins: this.storagePluginArray() } });
|
|
64
64
|
break;
|
|
65
65
|
case 'plugins_apipluginarray':
|
|
66
|
-
this.server.respond({ ...msg,
|
|
66
|
+
this.server.respond({ ...msg, result: { plugins: this.apiPluginArray() } });
|
|
67
67
|
break;
|
|
68
68
|
case 'plugins_install':
|
|
69
|
-
this.server.respond({ ...msg,
|
|
69
|
+
this.server.respond({ ...msg, result: { packageName: msg.params.packageName, success: await this.install(msg.params.packageName) } });
|
|
70
70
|
break;
|
|
71
71
|
case 'plugins_uninstall':
|
|
72
|
-
this.server.respond({ ...msg,
|
|
72
|
+
this.server.respond({ ...msg, result: { packageName: msg.params.packageName, success: await this.uninstall(msg.params.packageName) } });
|
|
73
73
|
break;
|
|
74
74
|
case 'plugins_add':
|
|
75
75
|
{
|
|
76
76
|
const plugin = await this.add(msg.params.nameOrPath);
|
|
77
77
|
if (plugin) {
|
|
78
|
-
this.server.respond({ ...msg,
|
|
78
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
|
-
this.server.respond({ ...msg,
|
|
81
|
+
this.server.respond({ ...msg, result: { plugin } });
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
break;
|
|
@@ -86,10 +86,10 @@ export class PluginManager extends EventEmitter {
|
|
|
86
86
|
{
|
|
87
87
|
const plugin = await this.remove(msg.params.nameOrPath);
|
|
88
88
|
if (plugin) {
|
|
89
|
-
this.server.respond({ ...msg,
|
|
89
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
90
90
|
}
|
|
91
91
|
else {
|
|
92
|
-
this.server.respond({ ...msg,
|
|
92
|
+
this.server.respond({ ...msg, result: { plugin } });
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
break;
|
|
@@ -97,10 +97,10 @@ export class PluginManager extends EventEmitter {
|
|
|
97
97
|
{
|
|
98
98
|
const plugin = await this.enable(msg.params.nameOrPath);
|
|
99
99
|
if (plugin) {
|
|
100
|
-
this.server.respond({ ...msg,
|
|
100
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
this.server.respond({ ...msg,
|
|
103
|
+
this.server.respond({ ...msg, result: { plugin } });
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
break;
|
|
@@ -108,10 +108,10 @@ export class PluginManager extends EventEmitter {
|
|
|
108
108
|
{
|
|
109
109
|
const plugin = await this.disable(msg.params.nameOrPath);
|
|
110
110
|
if (plugin) {
|
|
111
|
-
this.server.respond({ ...msg,
|
|
111
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
112
112
|
}
|
|
113
113
|
else {
|
|
114
|
-
this.server.respond({ ...msg,
|
|
114
|
+
this.server.respond({ ...msg, result: { plugin } });
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
break;
|
|
@@ -119,10 +119,10 @@ export class PluginManager extends EventEmitter {
|
|
|
119
119
|
{
|
|
120
120
|
const platform = await this.load(msg.params.plugin);
|
|
121
121
|
if (platform) {
|
|
122
|
-
this.server.respond({ ...msg,
|
|
122
|
+
this.server.respond({ ...msg, result: { platform: {} } });
|
|
123
123
|
}
|
|
124
124
|
else {
|
|
125
|
-
this.server.respond({ ...msg,
|
|
125
|
+
this.server.respond({ ...msg, result: { platform } });
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
break;
|
|
@@ -130,10 +130,10 @@ export class PluginManager extends EventEmitter {
|
|
|
130
130
|
{
|
|
131
131
|
const plugin = await this.start(msg.params.plugin, msg.params.message, msg.params.configure);
|
|
132
132
|
if (plugin) {
|
|
133
|
-
this.server.respond({ ...msg,
|
|
133
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
134
134
|
}
|
|
135
135
|
else {
|
|
136
|
-
this.server.respond({ ...msg,
|
|
136
|
+
this.server.respond({ ...msg, result: { plugin } });
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
break;
|
|
@@ -141,10 +141,10 @@ export class PluginManager extends EventEmitter {
|
|
|
141
141
|
{
|
|
142
142
|
const plugin = await this.configure(msg.params.plugin);
|
|
143
143
|
if (plugin) {
|
|
144
|
-
this.server.respond({ ...msg,
|
|
144
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
145
145
|
}
|
|
146
146
|
else {
|
|
147
|
-
this.server.respond({ ...msg,
|
|
147
|
+
this.server.respond({ ...msg, result: { plugin } });
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
break;
|
|
@@ -152,10 +152,10 @@ export class PluginManager extends EventEmitter {
|
|
|
152
152
|
{
|
|
153
153
|
const plugin = await this.shutdown(msg.params.plugin, msg.params.reason, msg.params.removeAllDevices, msg.params.force);
|
|
154
154
|
if (plugin) {
|
|
155
|
-
this.server.respond({ ...msg,
|
|
155
|
+
this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
|
|
156
156
|
}
|
|
157
157
|
else {
|
|
158
|
-
this.server.respond({ ...msg,
|
|
158
|
+
this.server.respond({ ...msg, result: { plugin } });
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
break;
|
|
@@ -163,10 +163,10 @@ export class PluginManager extends EventEmitter {
|
|
|
163
163
|
{
|
|
164
164
|
const plugin = this.get(msg.params.name);
|
|
165
165
|
if (plugin) {
|
|
166
|
-
this.server.respond({ ...msg,
|
|
166
|
+
this.server.respond({ ...msg, result: { schema: plugin.schemaJson } });
|
|
167
167
|
}
|
|
168
168
|
else {
|
|
169
|
-
this.server.respond({ ...msg,
|
|
169
|
+
this.server.respond({ ...msg, result: { schema: undefined } });
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
break;
|
|
@@ -175,10 +175,10 @@ export class PluginManager extends EventEmitter {
|
|
|
175
175
|
const plugin = this.get(msg.params.name);
|
|
176
176
|
if (plugin) {
|
|
177
177
|
plugin.schemaJson = msg.params.schema;
|
|
178
|
-
this.server.respond({ ...msg,
|
|
178
|
+
this.server.respond({ ...msg, result: { success: true } });
|
|
179
179
|
}
|
|
180
180
|
else {
|
|
181
|
-
this.server.respond({ ...msg,
|
|
181
|
+
this.server.respond({ ...msg, error: `Plugin ${msg.params.name} not found` });
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
break;
|
|
@@ -187,10 +187,34 @@ export class PluginManager extends EventEmitter {
|
|
|
187
187
|
const plugin = this.get(msg.params.name);
|
|
188
188
|
if (plugin) {
|
|
189
189
|
this.saveConfigFromJson(plugin, msg.params.config, msg.params.restartRequired);
|
|
190
|
-
this.server.respond({ ...msg,
|
|
190
|
+
this.server.respond({ ...msg, result: { success: true } });
|
|
191
191
|
}
|
|
192
192
|
else {
|
|
193
|
-
this.server.respond({ ...msg,
|
|
193
|
+
this.server.respond({ ...msg, error: `Plugin ${msg.params.name} not found` });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
case 'plugins_set_latest_version':
|
|
198
|
+
{
|
|
199
|
+
const plugin = this.get(msg.params.plugin.name);
|
|
200
|
+
if (plugin) {
|
|
201
|
+
plugin.latestVersion = msg.params.version;
|
|
202
|
+
this.server.respond({ ...msg, result: { success: true } });
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
this.server.respond({ ...msg, error: `Plugin ${msg.params.plugin.name} not found` });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
case 'plugins_set_dev_version':
|
|
210
|
+
{
|
|
211
|
+
const plugin = this.get(msg.params.plugin.name);
|
|
212
|
+
if (plugin) {
|
|
213
|
+
plugin.devVersion = msg.params.version;
|
|
214
|
+
this.server.respond({ ...msg, result: { success: true } });
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
this.server.respond({ ...msg, error: `Plugin ${msg.params.plugin.name} not found` });
|
|
194
218
|
}
|
|
195
219
|
}
|
|
196
220
|
break;
|
package/dist/shelly.js
CHANGED
|
@@ -7,22 +7,22 @@ export function setVerifyIntervalSecs(seconds) {
|
|
|
7
7
|
export function setVerifyTimeoutSecs(seconds) {
|
|
8
8
|
verifyTimeoutSecs = seconds;
|
|
9
9
|
}
|
|
10
|
-
export async function getShellySysUpdate(matterbridge) {
|
|
10
|
+
export async function getShellySysUpdate(matterbridge, log, server) {
|
|
11
11
|
try {
|
|
12
12
|
const updates = (await getShelly('/api/updates/sys/check'));
|
|
13
13
|
if (updates.length === 0)
|
|
14
14
|
return;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
server.request({ type: 'matterbridge_sys_update', src: server.name, dst: 'matterbridge', params: { available: true } });
|
|
16
|
+
server.request({ type: 'frontend_broadcast_message', src: server.name, dst: 'frontend', params: { msg: { id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'shelly_sys_update', success: true, response: { available: true } } } });
|
|
17
17
|
for (const { name } of updates) {
|
|
18
18
|
if (!name)
|
|
19
19
|
continue;
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
log.notice(`Shelly system update available: ${name}`);
|
|
21
|
+
server.request({ type: 'frontend_snackbarmessage', src: server.name, dst: 'frontend', params: { message: `Shelly system update available: ${name}`, timeout: 10 } });
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
catch (err) {
|
|
25
|
-
|
|
25
|
+
log.error(`Error getting Shelly system updates: ${err instanceof Error ? err.message : String(err)}`);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
export async function triggerShellySysUpdate(matterbridge) {
|
|
@@ -38,22 +38,22 @@ export async function triggerShellySysUpdate(matterbridge) {
|
|
|
38
38
|
matterbridge.log.error(`Error triggering Shelly system update: ${err instanceof Error ? err.message : String(err)}`);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
export async function getShellyMainUpdate(matterbridge) {
|
|
41
|
+
export async function getShellyMainUpdate(matterbridge, log, server) {
|
|
42
42
|
try {
|
|
43
43
|
const updates = (await getShelly('/api/updates/main/check'));
|
|
44
44
|
if (updates.length === 0)
|
|
45
45
|
return;
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
server.request({ type: 'matterbridge_main_update', src: server.name, dst: 'matterbridge', params: { available: true } });
|
|
47
|
+
server.request({ type: 'frontend_broadcast_message', src: server.name, dst: 'frontend', params: { msg: { id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'shelly_main_update', success: true, response: { available: true } } } });
|
|
48
48
|
for (const { name } of updates) {
|
|
49
49
|
if (!name)
|
|
50
50
|
continue;
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
log.notice(`Shelly software update available: ${name}`);
|
|
52
|
+
server.request({ type: 'frontend_snackbarmessage', src: server.name, dst: 'frontend', params: { message: `Shelly software update available: ${name}`, timeout: 10 } });
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
catch (err) {
|
|
56
|
-
|
|
56
|
+
log.error(`Error getting Shelly main updates: ${err instanceof Error ? err.message : String(err)}`);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
export async function triggerShellyMainUpdate(matterbridge) {
|
package/dist/update.js
CHANGED
|
@@ -1,121 +1,137 @@
|
|
|
1
|
-
import { db, debugStringify, nt, wr } from 'node-ansi-logger';
|
|
1
|
+
import { AnsiLogger, db, debugStringify, nt, wr } from 'node-ansi-logger';
|
|
2
2
|
import { plg } from './matterbridgeTypes.js';
|
|
3
|
+
import { BroadcastServer } from './broadcastServer.js';
|
|
4
|
+
import { hasParameter } from './utils/commandLine.js';
|
|
5
|
+
import { isValidString } from './utils/isvalid.js';
|
|
3
6
|
export async function checkUpdates(matterbridge) {
|
|
4
|
-
const {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
const log = new AnsiLogger({ logName: 'MatterbridgeUpdates', logTimestampFormat: 4, logLevel: matterbridge.logLevel });
|
|
8
|
+
const server = new BroadcastServer('updates', log);
|
|
9
|
+
const checkUpdatePromise = checkUpdatesAndLog(matterbridge, log, server);
|
|
10
|
+
const latestVersionPromise = getMatterbridgeLatestVersion(matterbridge, log, server);
|
|
11
|
+
const devVersionPromise = getMatterbridgeDevVersion(matterbridge, log, server);
|
|
12
|
+
const pluginsVersionPromises = [];
|
|
13
|
+
const pluginsDevVersionPromises = [];
|
|
14
|
+
const shellyUpdatesPromises = [];
|
|
15
|
+
const plugins = (await server.fetch({ type: 'plugins_apipluginarray', src: server.name, dst: 'plugins' })).result.plugins;
|
|
16
|
+
for (const plugin of plugins) {
|
|
17
|
+
pluginsVersionPromises.push(getPluginLatestVersion(log, server, plugin));
|
|
18
|
+
pluginsDevVersionPromises.push(getPluginDevVersion(log, server, plugin));
|
|
16
19
|
}
|
|
17
20
|
if (hasParameter('shelly')) {
|
|
18
21
|
const { getShellySysUpdate, getShellyMainUpdate } = await import('./shelly.js');
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const mainUpdate = getShellyMainUpdate(matterbridge);
|
|
22
|
-
shellyUpdates.push(mainUpdate);
|
|
22
|
+
shellyUpdatesPromises.push(getShellySysUpdate(matterbridge, log, server));
|
|
23
|
+
shellyUpdatesPromises.push(getShellyMainUpdate(matterbridge, log, server));
|
|
23
24
|
}
|
|
24
|
-
await Promise.all([
|
|
25
|
+
await Promise.all([checkUpdatePromise, latestVersionPromise, devVersionPromise, ...pluginsVersionPromises, ...pluginsDevVersionPromises, ...shellyUpdatesPromises]);
|
|
26
|
+
server.close();
|
|
25
27
|
}
|
|
26
|
-
export async function checkUpdatesAndLog(matterbridge) {
|
|
28
|
+
export async function checkUpdatesAndLog(matterbridge, log, server) {
|
|
27
29
|
const { getGitHubUpdate } = await import('./utils/network.js');
|
|
28
|
-
const { isValidString } = await import('./utils/isvalid.js');
|
|
29
30
|
const branch = matterbridge.matterbridgeVersion.includes('-dev-') ? 'dev' : 'main';
|
|
30
31
|
try {
|
|
31
32
|
const updateJson = await getGitHubUpdate(branch, 'update.json', 5_000);
|
|
32
|
-
|
|
33
|
+
log.debug(`GitHub ${branch} update status: ${debugStringify(updateJson)}.`);
|
|
33
34
|
if (isValidString(branch === 'main' ? updateJson.latestMessage : updateJson.devMessage, 1) &&
|
|
34
35
|
isValidString(branch === 'main' ? updateJson.latestMessageSeverity : updateJson.devMessageSeverity, 4) &&
|
|
35
36
|
['info', 'warning', 'error', 'success'].includes(branch === 'main' ? updateJson.latestMessageSeverity : updateJson.devMessageSeverity)) {
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
log.notice(`GitHub ${branch} update message: ${branch === 'main' ? updateJson.latestMessage : updateJson.devMessage}`);
|
|
38
|
+
server.request({
|
|
39
|
+
type: 'frontend_snackbarmessage',
|
|
40
|
+
src: server.name,
|
|
41
|
+
dst: 'frontend',
|
|
42
|
+
params: { message: branch === 'main' ? updateJson.latestMessage : updateJson.devMessage, timeout: 0, severity: branch === 'main' ? updateJson.latestMessageSeverity : updateJson.devMessageSeverity },
|
|
43
|
+
});
|
|
38
44
|
}
|
|
39
45
|
}
|
|
40
46
|
catch (error) {
|
|
41
|
-
|
|
47
|
+
log.debug(`Error checking GitHub ${branch} updates: ${error instanceof Error ? error.message : error}`);
|
|
42
48
|
}
|
|
43
49
|
}
|
|
44
|
-
export async function getMatterbridgeLatestVersion(matterbridge) {
|
|
50
|
+
export async function getMatterbridgeLatestVersion(matterbridge, log, server) {
|
|
45
51
|
const { getNpmPackageVersion } = await import('./utils/network.js');
|
|
46
52
|
try {
|
|
47
53
|
const version = await getNpmPackageVersion('matterbridge');
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
server.request({ type: 'matterbridge_latest_version', src: server.name, dst: 'matterbridge', params: { version } });
|
|
55
|
+
if (matterbridge.matterbridgeVersion !== version) {
|
|
56
|
+
log.notice(`Matterbridge is out of date. Current version: ${matterbridge.matterbridgeVersion}. Latest version: ${version}.`);
|
|
57
|
+
server.request({
|
|
58
|
+
type: 'frontend_snackbarmessage',
|
|
59
|
+
src: server.name,
|
|
60
|
+
dst: 'frontend',
|
|
61
|
+
params: { message: 'Matterbridge latest update available', timeout: 0, severity: 'info' },
|
|
62
|
+
});
|
|
63
|
+
server.request({ type: 'frontend_updaterequired', src: server.name, dst: 'frontend', params: { devVersion: false } });
|
|
64
|
+
server.request({ type: 'frontend_refreshrequired', src: server.name, dst: 'frontend', params: { changed: 'settings' } });
|
|
55
65
|
}
|
|
56
66
|
else {
|
|
57
|
-
|
|
67
|
+
log.debug(`Matterbridge is up to date. Current version: ${matterbridge.matterbridgeVersion}. Latest version: ${version}.`);
|
|
58
68
|
}
|
|
59
69
|
return version;
|
|
60
70
|
}
|
|
61
71
|
catch (error) {
|
|
62
|
-
|
|
72
|
+
log.warn(`Error getting Matterbridge latest version: ${error instanceof Error ? error.message : error}`);
|
|
63
73
|
}
|
|
64
74
|
}
|
|
65
|
-
export async function getMatterbridgeDevVersion(matterbridge) {
|
|
75
|
+
export async function getMatterbridgeDevVersion(matterbridge, log, server) {
|
|
66
76
|
const { getNpmPackageVersion } = await import('./utils/network.js');
|
|
67
77
|
try {
|
|
68
78
|
const version = await getNpmPackageVersion('matterbridge', 'dev');
|
|
69
|
-
|
|
70
|
-
await matterbridge.nodeContext?.set('matterbridgeDevVersion', version);
|
|
79
|
+
server.request({ type: 'matterbridge_dev_version', src: server.name, dst: 'matterbridge', params: { version } });
|
|
71
80
|
if (matterbridge.matterbridgeVersion.includes('-dev-') && matterbridge.matterbridgeVersion !== version) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
log.notice(`Matterbridge@dev is out of date. Current version: ${matterbridge.matterbridgeVersion}. Latest dev version: ${version}.`);
|
|
82
|
+
server.request({
|
|
83
|
+
type: 'frontend_snackbarmessage',
|
|
84
|
+
src: server.name,
|
|
85
|
+
dst: 'frontend',
|
|
86
|
+
params: { message: 'Matterbridge dev update available', timeout: 0, severity: 'info' },
|
|
87
|
+
});
|
|
88
|
+
server.request({ type: 'frontend_updaterequired', src: server.name, dst: 'frontend', params: { devVersion: true } });
|
|
89
|
+
server.request({ type: 'frontend_refreshrequired', src: server.name, dst: 'frontend', params: { changed: 'settings' } });
|
|
76
90
|
}
|
|
77
91
|
else if (matterbridge.matterbridgeVersion.includes('-dev-') && matterbridge.matterbridgeVersion === version) {
|
|
78
|
-
|
|
92
|
+
log.debug(`Matterbridge@dev is up to date. Current version: ${matterbridge.matterbridgeVersion}. Latest dev version: ${version}.`);
|
|
79
93
|
}
|
|
80
94
|
return version;
|
|
81
95
|
}
|
|
82
96
|
catch (error) {
|
|
83
|
-
|
|
97
|
+
log.warn(`Error getting Matterbridge latest dev version: ${error instanceof Error ? error.message : error}`);
|
|
84
98
|
}
|
|
85
99
|
}
|
|
86
|
-
export async function getPluginLatestVersion(
|
|
100
|
+
export async function getPluginLatestVersion(log, server, plugin) {
|
|
87
101
|
const { getNpmPackageVersion } = await import('./utils/network.js');
|
|
88
102
|
try {
|
|
89
103
|
const version = await getNpmPackageVersion(plugin.name);
|
|
90
104
|
plugin.latestVersion = version;
|
|
105
|
+
server.request({ type: 'plugins_set_latest_version', src: server.name, dst: 'plugins', params: { plugin, version } });
|
|
91
106
|
if (plugin.version !== plugin.latestVersion) {
|
|
92
|
-
|
|
93
|
-
|
|
107
|
+
log.notice(`The plugin ${plg}${plugin.name}${nt} is out of date. Current version: ${plugin.version}. Latest version: ${plugin.latestVersion}.`);
|
|
108
|
+
server.request({ type: 'frontend_refreshrequired', src: server.name, dst: 'frontend', params: { changed: 'plugins' } });
|
|
94
109
|
}
|
|
95
110
|
else {
|
|
96
|
-
|
|
111
|
+
log.debug(`The plugin ${plg}${plugin.name}${db} is up to date. Current version: ${plugin.version}. Latest version: ${plugin.latestVersion}.`);
|
|
97
112
|
}
|
|
98
113
|
return version;
|
|
99
114
|
}
|
|
100
115
|
catch (error) {
|
|
101
|
-
|
|
116
|
+
log.warn(`Error getting plugin ${plg}${plugin.name}${wr} latest version: ${error instanceof Error ? error.message : error}`);
|
|
102
117
|
}
|
|
103
118
|
}
|
|
104
|
-
export async function getPluginDevVersion(
|
|
119
|
+
export async function getPluginDevVersion(log, server, plugin) {
|
|
105
120
|
const { getNpmPackageVersion } = await import('./utils/network.js');
|
|
106
121
|
try {
|
|
107
122
|
const version = await getNpmPackageVersion(plugin.name, 'dev');
|
|
108
123
|
plugin.devVersion = version;
|
|
124
|
+
server.request({ type: 'plugins_set_dev_version', src: server.name, dst: 'plugins', params: { plugin, version } });
|
|
109
125
|
if (plugin.version.includes('-dev-') && plugin.version !== plugin.devVersion) {
|
|
110
|
-
|
|
111
|
-
|
|
126
|
+
log.notice(`The plugin ${plg}${plugin.name}${nt} is out of date. Current version: ${plugin.version}. Latest dev version: ${plugin.devVersion}.`);
|
|
127
|
+
server.request({ type: 'frontend_refreshrequired', src: server.name, dst: 'frontend', params: { changed: 'plugins' } });
|
|
112
128
|
}
|
|
113
129
|
else if (plugin.version.includes('-dev-') && plugin.version === plugin.devVersion) {
|
|
114
|
-
|
|
130
|
+
log.debug(`The plugin ${plg}${plugin.name}${db} is up to date. Current version: ${plugin.version}. Latest dev version: ${plugin.devVersion}.`);
|
|
115
131
|
}
|
|
116
132
|
return version;
|
|
117
133
|
}
|
|
118
134
|
catch (error) {
|
|
119
|
-
|
|
135
|
+
log.debug(`Error getting plugin ${plg}${plugin.name}${db} latest dev version: ${error instanceof Error ? error.message : error}`);
|
|
120
136
|
}
|
|
121
137
|
}
|
package/dist/utils/error.js
CHANGED
|
@@ -6,5 +6,7 @@ export function logError(log, message, error) {
|
|
|
6
6
|
export function inspectError(log, message, error) {
|
|
7
7
|
const errorMessage = error instanceof Error ? `${error.message} \n` : '';
|
|
8
8
|
const inspectedError = inspect(error, { depth: 10, colors: true, showHidden: false });
|
|
9
|
-
|
|
9
|
+
const fullMessage = `${message}: ${errorMessage}${RESET}${inspectedError}`;
|
|
10
|
+
log.error(fullMessage);
|
|
11
|
+
return fullMessage;
|
|
10
12
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { threadId, isMainThread, parentPort, workerData } from 'node:worker_threads';
|
|
2
|
+
import { AnsiLogger } from 'node-ansi-logger';
|
|
3
|
+
import { getGlobalNodeModules } from './utils/network.js';
|
|
4
|
+
import { BroadcastServer } from './broadcastServer.js';
|
|
5
|
+
import { inspectError } from './utils/error.js';
|
|
6
|
+
import { logWorkerInfo, parentLog, parentPost } from './workers.js';
|
|
7
|
+
import { hasParameter } from './utils/commandLine.js';
|
|
8
|
+
const debug = hasParameter('debug') || hasParameter('verbose');
|
|
9
|
+
const verbose = hasParameter('verbose');
|
|
10
|
+
if (!isMainThread && parentPort) {
|
|
11
|
+
parentPost({ type: 'init', threadId, threadName: workerData.threadName, success: true });
|
|
12
|
+
if (debug)
|
|
13
|
+
parentLog('MatterbridgePrefix', "info", `Worker ${workerData.threadName}:${threadId} initialized.`);
|
|
14
|
+
}
|
|
15
|
+
const log = new AnsiLogger({ logName: 'MatterbridgePrefix', logTimestampFormat: 4, logLevel: debug ? "debug" : "info" });
|
|
16
|
+
const server = new BroadcastServer('matterbridge', log);
|
|
17
|
+
if (verbose)
|
|
18
|
+
logWorkerInfo(log, verbose);
|
|
19
|
+
let prefix;
|
|
20
|
+
let success = false;
|
|
21
|
+
try {
|
|
22
|
+
prefix = await getGlobalNodeModules();
|
|
23
|
+
log.debug(`Global node_modules Directory: ${prefix}`);
|
|
24
|
+
server.request({ type: 'matterbridge_global_prefix', src: `matterbridge`, dst: 'matterbridge', params: { prefix } });
|
|
25
|
+
success = true;
|
|
26
|
+
if (!isMainThread && parentPort)
|
|
27
|
+
parentLog('MatterbridgePrefix', "debug", `Global node_modules Directory: ${prefix}`);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
const errorMessage = inspectError(log, `Failed to get global node modules`, error);
|
|
31
|
+
if (!isMainThread && parentPort)
|
|
32
|
+
parentLog('MatterbridgePrefix', "error", errorMessage);
|
|
33
|
+
}
|
|
34
|
+
server.close();
|
|
35
|
+
if (!isMainThread && parentPort) {
|
|
36
|
+
parentPost({ type: 'exit', threadId, threadName: workerData.threadName, success });
|
|
37
|
+
if (debug)
|
|
38
|
+
parentLog('MatterbridgePrefix', "info", `Worker ${workerData.threadName}:${threadId} exiting with success: ${success}.`);
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|