matterbridge 2.2.6-dev.5 → 2.2.7
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 +23 -1
- package/dist/cli.d.ts +29 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +37 -2
- package/dist/cli.js.map +1 -0
- package/dist/cluster/export.d.ts +2 -0
- package/dist/cluster/export.d.ts.map +1 -0
- package/dist/cluster/export.js +2 -0
- package/dist/cluster/export.js.map +1 -0
- package/dist/defaultConfigSchema.d.ts +27 -0
- package/dist/defaultConfigSchema.d.ts.map +1 -0
- package/dist/defaultConfigSchema.js +23 -2
- package/dist/defaultConfigSchema.js.map +1 -0
- package/dist/deviceManager.d.ts +114 -0
- package/dist/deviceManager.d.ts.map +1 -0
- package/dist/deviceManager.js +94 -1
- package/dist/deviceManager.js.map +1 -0
- package/dist/frontend.d.ts +221 -0
- package/dist/frontend.d.ts.map +1 -0
- package/dist/frontend.js +329 -19
- package/dist/frontend.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -0
- package/dist/logger/export.d.ts +2 -0
- package/dist/logger/export.d.ts.map +1 -0
- package/dist/logger/export.js +1 -0
- package/dist/logger/export.js.map +1 -0
- package/dist/matter/behaviors.d.ts +2 -0
- package/dist/matter/behaviors.d.ts.map +1 -0
- package/dist/matter/behaviors.js +2 -0
- package/dist/matter/behaviors.js.map +1 -0
- package/dist/matter/clusters.d.ts +2 -0
- package/dist/matter/clusters.d.ts.map +1 -0
- package/dist/matter/clusters.js +2 -0
- package/dist/matter/clusters.js.map +1 -0
- package/dist/matter/devices.d.ts +2 -0
- package/dist/matter/devices.d.ts.map +1 -0
- package/dist/matter/devices.js +2 -0
- package/dist/matter/devices.js.map +1 -0
- package/dist/matter/endpoints.d.ts +2 -0
- package/dist/matter/endpoints.d.ts.map +1 -0
- package/dist/matter/endpoints.js +2 -0
- package/dist/matter/endpoints.js.map +1 -0
- package/dist/matter/export.d.ts +5 -0
- package/dist/matter/export.d.ts.map +1 -0
- package/dist/matter/export.js +2 -0
- package/dist/matter/export.js.map +1 -0
- package/dist/matter/types.d.ts +3 -0
- package/dist/matter/types.d.ts.map +1 -0
- package/dist/matter/types.js +2 -0
- package/dist/matter/types.js.map +1 -0
- package/dist/matterbridge.d.ts +425 -0
- package/dist/matterbridge.d.ts.map +1 -0
- package/dist/matterbridge.js +753 -47
- package/dist/matterbridge.js.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts +39 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.js +33 -0
- package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
- package/dist/matterbridgeBehaviors.d.ts +1056 -0
- package/dist/matterbridgeBehaviors.d.ts.map +1 -0
- package/dist/matterbridgeBehaviors.js +32 -1
- package/dist/matterbridgeBehaviors.js.map +1 -0
- package/dist/matterbridgeDeviceTypes.d.ts +177 -0
- package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
- package/dist/matterbridgeDeviceTypes.js +112 -11
- package/dist/matterbridgeDeviceTypes.js.map +1 -0
- package/dist/matterbridgeDynamicPlatform.d.ts +39 -0
- package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
- package/dist/matterbridgeDynamicPlatform.js +33 -0
- package/dist/matterbridgeDynamicPlatform.js.map +1 -0
- package/dist/matterbridgeEndpoint.d.ts +852 -0
- package/dist/matterbridgeEndpoint.d.ts.map +1 -0
- package/dist/matterbridgeEndpoint.js +737 -10
- package/dist/matterbridgeEndpoint.js.map +1 -0
- package/dist/matterbridgeEndpointHelpers.d.ts +2275 -0
- package/dist/matterbridgeEndpointHelpers.d.ts.map +1 -0
- package/dist/matterbridgeEndpointHelpers.js +118 -9
- package/dist/matterbridgeEndpointHelpers.js.map +1 -0
- package/dist/matterbridgePlatform.d.ts +285 -0
- package/dist/matterbridgePlatform.d.ts.map +1 -0
- package/dist/matterbridgePlatform.js +221 -12
- package/dist/matterbridgePlatform.js.map +1 -0
- package/dist/matterbridgeTypes.d.ts +183 -0
- package/dist/matterbridgeTypes.d.ts.map +1 -0
- package/dist/matterbridgeTypes.js +24 -0
- package/dist/matterbridgeTypes.js.map +1 -0
- package/dist/pluginManager.d.ts +271 -0
- package/dist/pluginManager.d.ts.map +1 -0
- package/dist/pluginManager.js +349 -7
- package/dist/pluginManager.js.map +1 -0
- package/dist/shelly.d.ts +92 -0
- package/dist/shelly.d.ts.map +1 -0
- package/dist/shelly.js +146 -6
- package/dist/shelly.js.map +1 -0
- package/dist/storage/export.d.ts +2 -0
- package/dist/storage/export.d.ts.map +1 -0
- package/dist/storage/export.js +1 -0
- package/dist/storage/export.js.map +1 -0
- package/dist/update.d.ts +32 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +45 -0
- package/dist/update.js.map +1 -0
- package/dist/utils/colorUtils.d.ts +61 -0
- package/dist/utils/colorUtils.d.ts.map +1 -0
- package/dist/utils/colorUtils.js +205 -2
- package/dist/utils/colorUtils.js.map +1 -0
- package/dist/utils/copyDirectory.d.ts +32 -0
- package/dist/utils/copyDirectory.d.ts.map +1 -0
- package/dist/utils/copyDirectory.js +37 -1
- package/dist/utils/copyDirectory.js.map +1 -0
- package/dist/utils/createZip.d.ts +38 -0
- package/dist/utils/createZip.d.ts.map +1 -0
- package/dist/utils/createZip.js +42 -2
- package/dist/utils/createZip.js.map +1 -0
- package/dist/utils/deepCopy.d.ts +31 -0
- package/dist/utils/deepCopy.d.ts.map +1 -0
- package/dist/utils/deepCopy.js +40 -0
- package/dist/utils/deepCopy.js.map +1 -0
- package/dist/utils/deepEqual.d.ts +53 -0
- package/dist/utils/deepEqual.d.ts.map +1 -0
- package/dist/utils/deepEqual.js +65 -1
- package/dist/utils/deepEqual.js.map +1 -0
- package/dist/utils/export.d.ts +10 -0
- package/dist/utils/export.d.ts.map +1 -0
- package/dist/utils/export.js +1 -0
- package/dist/utils/export.js.map +1 -0
- package/dist/utils/isvalid.d.ts +87 -0
- package/dist/utils/isvalid.d.ts.map +1 -0
- package/dist/utils/isvalid.js +86 -0
- package/dist/utils/isvalid.js.map +1 -0
- package/dist/utils/network.d.ts +69 -0
- package/dist/utils/network.d.ts.map +1 -0
- package/dist/utils/network.js +77 -8
- package/dist/utils/network.js.map +1 -0
- package/dist/utils/parameter.d.ts +44 -0
- package/dist/utils/parameter.d.ts.map +1 -0
- package/dist/utils/parameter.js +41 -0
- package/dist/utils/parameter.js.map +1 -0
- package/dist/utils/wait.d.ts +43 -0
- package/dist/utils/wait.d.ts.map +1 -0
- package/dist/utils/wait.js +48 -5
- package/dist/utils/wait.js.map +1 -0
- package/frontend/build/asset-manifest.json +3 -3
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/js/{main.f00179ca.js → main.1fa50342.js} +3 -3
- package/frontend/build/static/js/{main.f00179ca.js.map → main.1fa50342.js.map} +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
- /package/frontend/build/static/js/{main.f00179ca.js.LICENSE.txt → main.1fa50342.js.LICENSE.txt} +0 -0
package/dist/pluginManager.js
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file contains the Plugins class.
|
|
3
|
+
*
|
|
4
|
+
* @file plugins.ts
|
|
5
|
+
* @author Luca Liguori
|
|
6
|
+
* @date 2024-07-14
|
|
7
|
+
* @version 1.1.1
|
|
8
|
+
*
|
|
9
|
+
* Copyright 2024, 2025, 2026 Luca Liguori.
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
* you may not use this file except in compliance with the License.
|
|
13
|
+
* You may obtain a copy of the License at
|
|
14
|
+
*
|
|
15
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
* See the License for the specific language governing permissions and
|
|
21
|
+
* limitations under the License. *
|
|
22
|
+
*/
|
|
23
|
+
// AnsiLogger module
|
|
1
24
|
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, BLUE, db, er, nf, nt, rs, wr } from './logger/export.js';
|
|
2
25
|
import { plg, typ } from './matterbridgeTypes.js';
|
|
3
26
|
export class PluginManager {
|
|
@@ -7,8 +30,9 @@ export class PluginManager {
|
|
|
7
30
|
log;
|
|
8
31
|
constructor(matterbridge) {
|
|
9
32
|
this.matterbridge = matterbridge;
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
34
|
this.nodeContext = matterbridge.nodeContext;
|
|
11
|
-
this.log = new AnsiLogger({ logName: 'PluginManager', logTimestampFormat: 4
|
|
35
|
+
this.log = new AnsiLogger({ logName: 'PluginManager', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: matterbridge.log.logLevel });
|
|
12
36
|
this.log.debug('Matterbridge plugin manager starting...');
|
|
13
37
|
}
|
|
14
38
|
get length() {
|
|
@@ -45,6 +69,7 @@ export class PluginManager {
|
|
|
45
69
|
}
|
|
46
70
|
catch (error) {
|
|
47
71
|
this.log.error(`Error processing forEach plugin ${plg}${plugin.name}${er}:`, error);
|
|
72
|
+
// throw error;
|
|
48
73
|
}
|
|
49
74
|
});
|
|
50
75
|
await Promise.all(tasks);
|
|
@@ -52,13 +77,31 @@ export class PluginManager {
|
|
|
52
77
|
set logLevel(logLevel) {
|
|
53
78
|
this.log.logLevel = logLevel;
|
|
54
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Loads registered plugins from storage.
|
|
82
|
+
*
|
|
83
|
+
* This method retrieves an array of registered plugins from the storage and converts it
|
|
84
|
+
* into a map where the plugin names are the keys and the plugin objects are the values.
|
|
85
|
+
*
|
|
86
|
+
* @returns {Promise<RegisteredPlugin[]>} A promise that resolves to an array of registered plugins.
|
|
87
|
+
*/
|
|
55
88
|
async loadFromStorage() {
|
|
89
|
+
// Load the array from storage and convert it to a map
|
|
56
90
|
const pluginsArray = await this.nodeContext.get('plugins', []);
|
|
57
91
|
for (const plugin of pluginsArray)
|
|
58
92
|
this._plugins.set(plugin.name, plugin);
|
|
59
93
|
return pluginsArray;
|
|
60
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Loads registered plugins from storage.
|
|
97
|
+
*
|
|
98
|
+
* This method retrieves an array of registered plugins from the storage and converts it
|
|
99
|
+
* into a map where the plugin names are the keys and the plugin objects are the values.
|
|
100
|
+
*
|
|
101
|
+
* @returns {Promise<RegisteredPlugin[]>} A promise that resolves to an array of registered plugins.
|
|
102
|
+
*/
|
|
61
103
|
async saveToStorage() {
|
|
104
|
+
// Convert the map to an array
|
|
62
105
|
const plugins = [];
|
|
63
106
|
const pluginArrayFromMap = Array.from(this._plugins.values());
|
|
64
107
|
for (const plugin of pluginArrayFromMap) {
|
|
@@ -78,13 +121,20 @@ export class PluginManager {
|
|
|
78
121
|
this.log.debug(`Saved ${BLUE}${plugins.length}${db} plugins to storage`);
|
|
79
122
|
return plugins.length;
|
|
80
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Resolves the name of a plugin by loading and parsing its package.json file.
|
|
126
|
+
* @param pluginPath - The path to the plugin or the path to the plugin's package.json file.
|
|
127
|
+
* @returns The path to the resolved package.json file, or null if the package.json file is not found or does not contain a name.
|
|
128
|
+
*/
|
|
81
129
|
async resolve(pluginPath) {
|
|
82
130
|
const { default: path } = await import('node:path');
|
|
83
131
|
const { promises } = await import('node:fs');
|
|
84
132
|
if (!pluginPath.endsWith('package.json'))
|
|
85
133
|
pluginPath = path.join(pluginPath, 'package.json');
|
|
134
|
+
// Resolve the package.json of the plugin
|
|
86
135
|
let packageJsonPath = path.resolve(pluginPath);
|
|
87
136
|
this.log.debug(`Resolving plugin path ${plg}${packageJsonPath}${db}`);
|
|
137
|
+
// Check if the package.json file exists
|
|
88
138
|
try {
|
|
89
139
|
await promises.access(packageJsonPath);
|
|
90
140
|
}
|
|
@@ -94,7 +144,9 @@ export class PluginManager {
|
|
|
94
144
|
this.log.debug(`Trying at ${plg}${packageJsonPath}${db}`);
|
|
95
145
|
}
|
|
96
146
|
try {
|
|
147
|
+
// Load the package.json of the plugin
|
|
97
148
|
const packageJson = JSON.parse(await promises.readFile(packageJsonPath, 'utf8'));
|
|
149
|
+
// Check for main issues
|
|
98
150
|
if (!packageJson.name) {
|
|
99
151
|
this.log.error(`Package.json name not found at ${packageJsonPath}`);
|
|
100
152
|
return null;
|
|
@@ -107,6 +159,7 @@ export class PluginManager {
|
|
|
107
159
|
this.log.error(`Plugin at ${packageJsonPath} has no main entrypoint in package.json`);
|
|
108
160
|
return null;
|
|
109
161
|
}
|
|
162
|
+
// Check for @project-chip and @matter packages in dependencies and devDependencies
|
|
110
163
|
const checkForProjectChipPackages = (dependencies) => {
|
|
111
164
|
return Object.keys(dependencies).filter((pkg) => pkg.startsWith('@project-chip') || pkg.startsWith('@matter'));
|
|
112
165
|
};
|
|
@@ -128,6 +181,7 @@ export class PluginManager {
|
|
|
128
181
|
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
129
182
|
return null;
|
|
130
183
|
}
|
|
184
|
+
// Check for matterbridge package in dependencies and devDependencies
|
|
131
185
|
const checkForMatterbridgePackage = (dependencies) => {
|
|
132
186
|
return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
|
|
133
187
|
};
|
|
@@ -157,6 +211,115 @@ export class PluginManager {
|
|
|
157
211
|
return null;
|
|
158
212
|
}
|
|
159
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Get the author of a plugin from its package.json.
|
|
216
|
+
*
|
|
217
|
+
* @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
|
|
218
|
+
* @returns {string} The author of the plugin, or 'Unknown author' if not found.
|
|
219
|
+
*/
|
|
220
|
+
getAuthor(packageJson) {
|
|
221
|
+
if (packageJson.author && typeof packageJson.author === 'string')
|
|
222
|
+
return packageJson.author;
|
|
223
|
+
if (packageJson.author && typeof packageJson.author === 'object' && packageJson.author.name && typeof packageJson.author.name === 'string')
|
|
224
|
+
return packageJson.author.name;
|
|
225
|
+
return 'Unknown author';
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get the homepage of a plugin from its package.json.
|
|
229
|
+
*
|
|
230
|
+
* @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
|
|
231
|
+
* @returns {string | undefined} The homepage of the plugin, or undefined if not found.
|
|
232
|
+
*/
|
|
233
|
+
getHomepage(packageJson) {
|
|
234
|
+
if (packageJson.homepage && typeof packageJson.homepage === 'string') {
|
|
235
|
+
return packageJson.homepage.replace('git+', '').replace('.git', '');
|
|
236
|
+
}
|
|
237
|
+
if (packageJson.repository && typeof packageJson.repository === 'object' && packageJson.repository.url && typeof packageJson.repository.url === 'string') {
|
|
238
|
+
return packageJson.repository.url.replace('git+', '').replace('.git', '');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get the help URL of a plugin from its package.json.
|
|
243
|
+
*
|
|
244
|
+
* @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
|
|
245
|
+
* @returns {string | undefined} The URL to the help page or to the README file, or undefined if not found.
|
|
246
|
+
*/
|
|
247
|
+
getHelp(packageJson) {
|
|
248
|
+
// If there's a help field that looks like a URL, return it.
|
|
249
|
+
if (packageJson.help && typeof packageJson.help === 'string' && packageJson.help.startsWith('http')) {
|
|
250
|
+
return packageJson.help;
|
|
251
|
+
}
|
|
252
|
+
// Derive a base URL from homepage or repository.
|
|
253
|
+
let baseUrl;
|
|
254
|
+
if (packageJson.homepage && typeof packageJson.homepage === 'string') {
|
|
255
|
+
// Remove a trailing "/README.md" if present.
|
|
256
|
+
baseUrl = packageJson.homepage
|
|
257
|
+
.replace(/\/README\.md$/i, '')
|
|
258
|
+
.replace('git+', '')
|
|
259
|
+
.replace('.git', '');
|
|
260
|
+
}
|
|
261
|
+
else if (packageJson.repository && typeof packageJson.repository === 'object' && packageJson.repository.url && typeof packageJson.repository.url === 'string') {
|
|
262
|
+
baseUrl = packageJson.repository.url.replace('git+', '').replace('.git', '');
|
|
263
|
+
}
|
|
264
|
+
return baseUrl ? `${baseUrl}/blob/main/README.md` : undefined;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get the changelog URL of a plugin from its package.json.
|
|
268
|
+
*
|
|
269
|
+
* @param {Record<string, string | number | Record<string, string | number | object>>} packageJson - The package.json object of the plugin.
|
|
270
|
+
* @returns {string | undefined} The URL to the CHANGELOG file, or undefined if not found.
|
|
271
|
+
*/
|
|
272
|
+
getChangelog(packageJson) {
|
|
273
|
+
// If there's a changelog field that looks like a URL, return it.
|
|
274
|
+
if (packageJson.changelog && typeof packageJson.changelog === 'string' && packageJson.changelog.startsWith('http')) {
|
|
275
|
+
return packageJson.changelog;
|
|
276
|
+
}
|
|
277
|
+
// Derive a base URL from homepage or repository.
|
|
278
|
+
let baseUrl;
|
|
279
|
+
if (packageJson.homepage && typeof packageJson.homepage === 'string') {
|
|
280
|
+
baseUrl = packageJson.homepage
|
|
281
|
+
.replace(/\/README\.md$/i, '')
|
|
282
|
+
.replace('git+', '')
|
|
283
|
+
.replace('.git', '');
|
|
284
|
+
}
|
|
285
|
+
else if (packageJson.repository && typeof packageJson.repository === 'object' && packageJson.repository.url && typeof packageJson.repository.url === 'string') {
|
|
286
|
+
baseUrl = packageJson.repository.url.replace('git+', '').replace('.git', '');
|
|
287
|
+
}
|
|
288
|
+
return baseUrl ? `${baseUrl}/blob/main/CHANGELOG.md` : undefined;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Get the first funding URL(s) of a plugin from its package.json.
|
|
292
|
+
*
|
|
293
|
+
* @param {Record<string, any>} packageJson - The package.json object of the plugin.
|
|
294
|
+
* @returns {string | undefined} The first funding URLs, or undefined if not found.
|
|
295
|
+
*/
|
|
296
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
297
|
+
getFunding(packageJson) {
|
|
298
|
+
const funding = packageJson.funding;
|
|
299
|
+
if (!funding)
|
|
300
|
+
return undefined;
|
|
301
|
+
if (typeof funding === 'string' && !funding.startsWith('http'))
|
|
302
|
+
return;
|
|
303
|
+
if (typeof funding === 'string' && funding.startsWith('http'))
|
|
304
|
+
return funding;
|
|
305
|
+
// Normalize funding into an array.
|
|
306
|
+
const fundingEntries = Array.isArray(funding) ? funding : [funding];
|
|
307
|
+
for (const entry of fundingEntries) {
|
|
308
|
+
if (entry && typeof entry === 'string' && entry.startsWith('http')) {
|
|
309
|
+
// If the funding entry is a string, assume it is a URL.
|
|
310
|
+
return entry;
|
|
311
|
+
}
|
|
312
|
+
else if (entry && typeof entry === 'object' && typeof entry.url === 'string' && entry.url.startsWith('http')) {
|
|
313
|
+
// If it's an object with a 'url' property, use that.
|
|
314
|
+
return entry.url;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Loads and parse the plugin package.json and returns it.
|
|
320
|
+
* @param plugin - The plugin to load the package from.
|
|
321
|
+
* @returns A Promise that resolves to the package.json object or undefined if the package.json could not be loaded.
|
|
322
|
+
*/
|
|
160
323
|
async parse(plugin) {
|
|
161
324
|
const { promises } = await import('node:fs');
|
|
162
325
|
try {
|
|
@@ -170,6 +333,8 @@ export class PluginManager {
|
|
|
170
333
|
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no description in package.json`);
|
|
171
334
|
if (!packageJson.author)
|
|
172
335
|
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no author in package.json`);
|
|
336
|
+
if (!packageJson.homepage)
|
|
337
|
+
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no homepage in package.json`);
|
|
173
338
|
if (!packageJson.type || packageJson.type !== 'module')
|
|
174
339
|
this.log.error(`Plugin ${plg}${plugin.name}${er} is not a module`);
|
|
175
340
|
if (!packageJson.main)
|
|
@@ -177,11 +342,16 @@ export class PluginManager {
|
|
|
177
342
|
plugin.name = packageJson.name || 'Unknown name';
|
|
178
343
|
plugin.version = packageJson.version || '1.0.0';
|
|
179
344
|
plugin.description = packageJson.description || 'Unknown description';
|
|
180
|
-
plugin.author = packageJson
|
|
345
|
+
plugin.author = this.getAuthor(packageJson);
|
|
346
|
+
plugin.homepage = this.getHomepage(packageJson);
|
|
347
|
+
plugin.help = this.getHelp(packageJson);
|
|
348
|
+
plugin.changelog = this.getChangelog(packageJson);
|
|
349
|
+
plugin.funding = this.getFunding(packageJson);
|
|
181
350
|
if (!plugin.path)
|
|
182
351
|
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no path`);
|
|
183
352
|
if (!plugin.type)
|
|
184
353
|
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no type`);
|
|
354
|
+
// Check for @project-chip and @matter packages in dependencies and devDependencies
|
|
185
355
|
const checkForProjectChipPackages = (dependencies) => {
|
|
186
356
|
return Object.keys(dependencies).filter((pkg) => pkg.startsWith('@project-chip') || pkg.startsWith('@matter'));
|
|
187
357
|
};
|
|
@@ -203,6 +373,7 @@ export class PluginManager {
|
|
|
203
373
|
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
204
374
|
return null;
|
|
205
375
|
}
|
|
376
|
+
// Check for matterbridge package in dependencies and devDependencies
|
|
206
377
|
const checkForMatterbridgePackage = (dependencies) => {
|
|
207
378
|
return Object.keys(dependencies).filter((pkg) => pkg === 'matterbridge');
|
|
208
379
|
};
|
|
@@ -224,6 +395,7 @@ export class PluginManager {
|
|
|
224
395
|
this.log.error(`Please open an issue on the plugin repository to remove them.`);
|
|
225
396
|
return null;
|
|
226
397
|
}
|
|
398
|
+
// await this.saveToStorage(); // No need to save the plugin to storage
|
|
227
399
|
return packageJson;
|
|
228
400
|
}
|
|
229
401
|
catch (err) {
|
|
@@ -232,6 +404,16 @@ export class PluginManager {
|
|
|
232
404
|
return null;
|
|
233
405
|
}
|
|
234
406
|
}
|
|
407
|
+
/**
|
|
408
|
+
* Enables a plugin by its name or path.
|
|
409
|
+
*
|
|
410
|
+
* This method enables a plugin by setting its `enabled` property to `true` and saving the updated
|
|
411
|
+
* plugin information to storage. It first checks if the plugin is already registered in the `_plugins` map.
|
|
412
|
+
* If not, it attempts to resolve the plugin's `package.json` file to retrieve its name and enable it.
|
|
413
|
+
*
|
|
414
|
+
* @param {string} nameOrPath - The name or path of the plugin to enable.
|
|
415
|
+
* @returns {Promise<RegisteredPlugin | null>} A promise that resolves to the enabled plugin object, or null if the plugin could not be enabled.
|
|
416
|
+
*/
|
|
235
417
|
async enable(nameOrPath) {
|
|
236
418
|
const { promises } = await import('node:fs');
|
|
237
419
|
if (!nameOrPath || nameOrPath === '')
|
|
@@ -265,6 +447,16 @@ export class PluginManager {
|
|
|
265
447
|
return null;
|
|
266
448
|
}
|
|
267
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* Enables a plugin by its name or path.
|
|
452
|
+
*
|
|
453
|
+
* This method enables a plugin by setting its `enabled` property to `true` and saving the updated
|
|
454
|
+
* plugin information to storage. It first checks if the plugin is already registered in the `_plugins` map.
|
|
455
|
+
* If not, it attempts to resolve the plugin's `package.json` file to retrieve its name and enable it.
|
|
456
|
+
*
|
|
457
|
+
* @param {string} nameOrPath - The name or path of the plugin to enable.
|
|
458
|
+
* @returns {Promise<RegisteredPlugin | null>} A promise that resolves to the enabled plugin object, or null if the plugin could not be enabled.
|
|
459
|
+
*/
|
|
268
460
|
async disable(nameOrPath) {
|
|
269
461
|
const { promises } = await import('node:fs');
|
|
270
462
|
if (!nameOrPath || nameOrPath === '')
|
|
@@ -298,6 +490,16 @@ export class PluginManager {
|
|
|
298
490
|
return null;
|
|
299
491
|
}
|
|
300
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* Removes a plugin by its name or path.
|
|
495
|
+
*
|
|
496
|
+
* This method removes a plugin from the `_plugins` map and saves the updated plugin information to storage.
|
|
497
|
+
* It first checks if the plugin is already registered in the `_plugins` map. If not, it attempts to resolve
|
|
498
|
+
* the plugin's `package.json` file to retrieve its name and remove it.
|
|
499
|
+
*
|
|
500
|
+
* @param {string} nameOrPath - The name or path of the plugin to remove.
|
|
501
|
+
* @returns {Promise<RegisteredPlugin | null>} A promise that resolves to the removed plugin object, or null if the plugin could not be removed.
|
|
502
|
+
*/
|
|
301
503
|
async remove(nameOrPath) {
|
|
302
504
|
const { promises } = await import('node:fs');
|
|
303
505
|
if (!nameOrPath || nameOrPath === '')
|
|
@@ -331,6 +533,17 @@ export class PluginManager {
|
|
|
331
533
|
return null;
|
|
332
534
|
}
|
|
333
535
|
}
|
|
536
|
+
/**
|
|
537
|
+
* Adds a plugin by its name or path.
|
|
538
|
+
*
|
|
539
|
+
* This method adds a plugin to the `_plugins` map and saves the updated plugin information to storage.
|
|
540
|
+
* It first resolves the plugin's `package.json` file to retrieve its details. If the plugin is already
|
|
541
|
+
* registered, it logs an info message and returns null. Otherwise, it registers the plugin, enables it,
|
|
542
|
+
* and saves the updated plugin information to storage.
|
|
543
|
+
*
|
|
544
|
+
* @param {string} nameOrPath - The name or path of the plugin to add.
|
|
545
|
+
* @returns {Promise<RegisteredPlugin | null>} A promise that resolves to the added plugin object, or null if the plugin could not be added.
|
|
546
|
+
*/
|
|
334
547
|
async add(nameOrPath) {
|
|
335
548
|
const { promises } = await import('node:fs');
|
|
336
549
|
if (!nameOrPath || nameOrPath === '')
|
|
@@ -346,7 +559,15 @@ export class PluginManager {
|
|
|
346
559
|
this.log.info(`Plugin ${plg}${nameOrPath}${nf} already registered`);
|
|
347
560
|
return null;
|
|
348
561
|
}
|
|
349
|
-
this._plugins.set(packageJson.name, {
|
|
562
|
+
this._plugins.set(packageJson.name, {
|
|
563
|
+
name: packageJson.name,
|
|
564
|
+
enabled: true,
|
|
565
|
+
path: packageJsonPath,
|
|
566
|
+
type: 'AnyPlatform',
|
|
567
|
+
version: packageJson.version,
|
|
568
|
+
description: packageJson.description,
|
|
569
|
+
author: this.getAuthor(packageJson),
|
|
570
|
+
});
|
|
350
571
|
this.log.info(`Added plugin ${plg}${packageJson.name}${nf}`);
|
|
351
572
|
await this.saveToStorage();
|
|
352
573
|
const plugin = this._plugins.get(packageJson.name);
|
|
@@ -357,6 +578,15 @@ export class PluginManager {
|
|
|
357
578
|
return null;
|
|
358
579
|
}
|
|
359
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Installs a plugin by its name.
|
|
583
|
+
*
|
|
584
|
+
* This method first uninstalls any existing version of the plugin, then installs the plugin globally using npm.
|
|
585
|
+
* It logs the installation process and retrieves the installed version of the plugin.
|
|
586
|
+
*
|
|
587
|
+
* @param {string} name - The name of the plugin to install.
|
|
588
|
+
* @returns {Promise<string | undefined>} A promise that resolves to the installed version of the plugin, or undefined if the installation failed.
|
|
589
|
+
*/
|
|
360
590
|
async install(name) {
|
|
361
591
|
const { exec } = await import('node:child_process');
|
|
362
592
|
await this.uninstall(name);
|
|
@@ -371,11 +601,14 @@ export class PluginManager {
|
|
|
371
601
|
else {
|
|
372
602
|
this.log.info(`Installed plugin ${plg}${name}${nf}`);
|
|
373
603
|
this.log.debug(`Installed plugin ${plg}${name}${db}: ${stdout}`);
|
|
604
|
+
// Get the installed version
|
|
605
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
374
606
|
exec(`npm list -g ${name} --depth=0`, (listError, listStdout, listStderr) => {
|
|
375
607
|
if (listError) {
|
|
376
608
|
this.log.error(`List error: ${listError}`);
|
|
377
609
|
resolve(undefined);
|
|
378
610
|
}
|
|
611
|
+
// Clean the output to get only the package name and version
|
|
379
612
|
const lines = listStdout.split('\n');
|
|
380
613
|
const versionLine = lines.find((line) => line.includes(`${name}@`));
|
|
381
614
|
if (versionLine) {
|
|
@@ -391,6 +624,15 @@ export class PluginManager {
|
|
|
391
624
|
});
|
|
392
625
|
});
|
|
393
626
|
}
|
|
627
|
+
/**
|
|
628
|
+
* Uninstalls a plugin by its name.
|
|
629
|
+
*
|
|
630
|
+
* This method uninstalls a globally installed plugin using npm. It logs the uninstallation process
|
|
631
|
+
* and returns the name of the uninstalled plugin if successful, or undefined if the uninstallation failed.
|
|
632
|
+
*
|
|
633
|
+
* @param {string} name - The name of the plugin to uninstall.
|
|
634
|
+
* @returns {Promise<string | undefined>} A promise that resolves to the name of the uninstalled plugin, or undefined if the uninstallation failed.
|
|
635
|
+
*/
|
|
394
636
|
async uninstall(name) {
|
|
395
637
|
const { exec } = await import('node:child_process');
|
|
396
638
|
this.log.info(`Uninstalling plugin ${plg}${name}${nf}`);
|
|
@@ -409,6 +651,14 @@ export class PluginManager {
|
|
|
409
651
|
});
|
|
410
652
|
});
|
|
411
653
|
}
|
|
654
|
+
/**
|
|
655
|
+
* Loads a plugin and returns the corresponding MatterbridgePlatform instance.
|
|
656
|
+
* @param plugin - The plugin to load.
|
|
657
|
+
* @param start - Optional flag indicating whether to start the plugin after loading. Default is false.
|
|
658
|
+
* @param message - Optional message to pass to the plugin when starting.
|
|
659
|
+
* @returns A Promise that resolves to the loaded MatterbridgePlatform instance.
|
|
660
|
+
* @throws An error if the plugin is not enabled, already loaded, or fails to load.
|
|
661
|
+
*/
|
|
412
662
|
async load(plugin, start = false, message = '', configure = false) {
|
|
413
663
|
const { promises } = await import('node:fs');
|
|
414
664
|
const { default: path } = await import('node:path');
|
|
@@ -422,24 +672,29 @@ export class PluginManager {
|
|
|
422
672
|
}
|
|
423
673
|
this.log.info(`Loading plugin ${plg}${plugin.name}${nf} type ${typ}${plugin.type}${nf}`);
|
|
424
674
|
try {
|
|
675
|
+
// Load the package.json of the plugin
|
|
425
676
|
const packageJson = JSON.parse(await promises.readFile(plugin.path, 'utf8'));
|
|
677
|
+
// Resolve the main module path relative to package.json
|
|
426
678
|
const pluginEntry = path.resolve(path.dirname(plugin.path), packageJson.main);
|
|
679
|
+
// Dynamically import the plugin
|
|
427
680
|
const { pathToFileURL } = await import('node:url');
|
|
428
681
|
const pluginUrl = pathToFileURL(pluginEntry);
|
|
429
682
|
this.log.debug(`Importing plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
|
|
430
683
|
const pluginInstance = await import(pluginUrl.href);
|
|
431
684
|
this.log.debug(`Imported plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
|
|
685
|
+
// Call the default export function of the plugin, passing this MatterBridge instance, the log and the config
|
|
432
686
|
if (pluginInstance.default) {
|
|
433
687
|
const config = await this.loadConfig(plugin);
|
|
688
|
+
// Preset the plugin properties here in case the plugin throws an error during loading. In this case the user can change the config and restart the plugin.
|
|
434
689
|
plugin.name = packageJson.name;
|
|
435
690
|
plugin.description = packageJson.description ?? 'No description';
|
|
436
691
|
plugin.version = packageJson.version;
|
|
437
|
-
plugin.author = packageJson
|
|
692
|
+
plugin.author = this.getAuthor(packageJson);
|
|
438
693
|
plugin.configJson = config;
|
|
439
694
|
plugin.schemaJson = await this.loadSchema(plugin);
|
|
440
695
|
config.name = plugin.name;
|
|
441
696
|
config.version = packageJson.version;
|
|
442
|
-
const log = new AnsiLogger({ logName: plugin.description ?? 'No description', logTimestampFormat: 4
|
|
697
|
+
const log = new AnsiLogger({ logName: plugin.description ?? 'No description', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: config.debug ? "debug" /* LogLevel.DEBUG */ : this.matterbridge.log.logLevel });
|
|
443
698
|
const platform = pluginInstance.default(this.matterbridge, log, config);
|
|
444
699
|
config.type = platform.type;
|
|
445
700
|
platform.name = packageJson.name;
|
|
@@ -448,13 +703,13 @@ export class PluginManager {
|
|
|
448
703
|
plugin.name = packageJson.name;
|
|
449
704
|
plugin.description = packageJson.description ?? 'No description';
|
|
450
705
|
plugin.version = packageJson.version;
|
|
451
|
-
plugin.author = packageJson
|
|
706
|
+
plugin.author = this.getAuthor(packageJson);
|
|
452
707
|
plugin.type = platform.type;
|
|
453
708
|
plugin.platform = platform;
|
|
454
709
|
plugin.loaded = true;
|
|
455
710
|
plugin.registeredDevices = 0;
|
|
456
711
|
plugin.addedDevices = 0;
|
|
457
|
-
await this.saveToStorage();
|
|
712
|
+
await this.saveToStorage(); // Save the plugin to storage
|
|
458
713
|
this.log.notice(`Loaded plugin ${plg}${plugin.name}${nt} type ${typ}${platform.type}${nt} (entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
|
|
459
714
|
if (start)
|
|
460
715
|
await this.start(plugin, message, false);
|
|
@@ -473,6 +728,14 @@ export class PluginManager {
|
|
|
473
728
|
}
|
|
474
729
|
return undefined;
|
|
475
730
|
}
|
|
731
|
+
/**
|
|
732
|
+
* Starts a plugin.
|
|
733
|
+
*
|
|
734
|
+
* @param {RegisteredPlugin} plugin - The plugin to start.
|
|
735
|
+
* @param {string} [message] - Optional message to pass to the plugin's onStart method.
|
|
736
|
+
* @param {boolean} [configure] - Indicates whether to configure the plugin after starting (default false).
|
|
737
|
+
* @returns {Promise<RegisteredPlugin | undefined>} A promise that resolves when the plugin is started successfully, or rejects with an error if starting the plugin fails.
|
|
738
|
+
*/
|
|
476
739
|
async start(plugin, message, configure = false) {
|
|
477
740
|
if (!plugin.loaded) {
|
|
478
741
|
this.log.error(`Plugin ${plg}${plugin.name}${er} not loaded`);
|
|
@@ -502,6 +765,12 @@ export class PluginManager {
|
|
|
502
765
|
}
|
|
503
766
|
return undefined;
|
|
504
767
|
}
|
|
768
|
+
/**
|
|
769
|
+
* Configures a plugin.
|
|
770
|
+
*
|
|
771
|
+
* @param {RegisteredPlugin} plugin - The plugin to configure.
|
|
772
|
+
* @returns {Promise<void>} A promise that resolves when the plugin is configured successfully, or rejects with an error if configuration fails.
|
|
773
|
+
*/
|
|
505
774
|
async configure(plugin) {
|
|
506
775
|
if (!plugin.loaded) {
|
|
507
776
|
this.log.error(`Plugin ${plg}${plugin.name}${er} not loaded`);
|
|
@@ -532,6 +801,18 @@ export class PluginManager {
|
|
|
532
801
|
}
|
|
533
802
|
return undefined;
|
|
534
803
|
}
|
|
804
|
+
/**
|
|
805
|
+
* Shuts down a plugin.
|
|
806
|
+
*
|
|
807
|
+
* This method shuts down a plugin by calling its `onShutdown` method and resetting its state.
|
|
808
|
+
* It logs the shutdown process and optionally removes all devices associated with the plugin.
|
|
809
|
+
*
|
|
810
|
+
* @param {RegisteredPlugin} plugin - The plugin to shut down.
|
|
811
|
+
* @param {string} [reason] - The reason for shutting down the plugin.
|
|
812
|
+
* @param {boolean} [removeAllDevices=false] - Whether to remove all devices associated with the plugin.
|
|
813
|
+
* @param {boolean} [force=false] - Whether to force the shutdown even if the plugin is not loaded or started.
|
|
814
|
+
* @returns {Promise<RegisteredPlugin | undefined>} A promise that resolves to the shut down plugin object, or undefined if the shutdown failed.
|
|
815
|
+
*/
|
|
535
816
|
async shutdown(plugin, reason, removeAllDevices = false, force = false) {
|
|
536
817
|
this.log.debug(`Shutting down plugin ${plg}${plugin.name}${db}`);
|
|
537
818
|
if (!plugin.loaded) {
|
|
@@ -574,6 +855,15 @@ export class PluginManager {
|
|
|
574
855
|
}
|
|
575
856
|
return undefined;
|
|
576
857
|
}
|
|
858
|
+
/**
|
|
859
|
+
* Loads the configuration for a plugin.
|
|
860
|
+
* If the configuration file exists, it reads the file and returns the parsed JSON data.
|
|
861
|
+
* If the configuration file does not exist, it creates a new file with default configuration and returns it.
|
|
862
|
+
* If any error occurs during file access or creation, it logs an error and return un empty config.
|
|
863
|
+
*
|
|
864
|
+
* @param plugin - The plugin for which to load the configuration.
|
|
865
|
+
* @returns A promise that resolves to the loaded or created configuration.
|
|
866
|
+
*/
|
|
577
867
|
async loadConfig(plugin) {
|
|
578
868
|
const { default: path } = await import('node:path');
|
|
579
869
|
const { promises } = await import('node:fs');
|
|
@@ -584,6 +874,8 @@ export class PluginManager {
|
|
|
584
874
|
const data = await promises.readFile(configFile, 'utf8');
|
|
585
875
|
const config = JSON.parse(data);
|
|
586
876
|
this.log.debug(`Loaded config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
|
|
877
|
+
// this.log.debug(`Loaded config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
|
|
878
|
+
// The first time a plugin is added to the system, the config file is created with the plugin name and type "AnyPlatform".
|
|
587
879
|
config.name = plugin.name;
|
|
588
880
|
config.type = plugin.type;
|
|
589
881
|
if (config.debug === undefined)
|
|
@@ -607,6 +899,7 @@ export class PluginManager {
|
|
|
607
899
|
try {
|
|
608
900
|
await promises.writeFile(configFile, JSON.stringify(config, null, 2), 'utf8');
|
|
609
901
|
this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.`);
|
|
902
|
+
// this.log.debug(`Created config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
|
|
610
903
|
return config;
|
|
611
904
|
}
|
|
612
905
|
catch (err) {
|
|
@@ -620,6 +913,18 @@ export class PluginManager {
|
|
|
620
913
|
}
|
|
621
914
|
}
|
|
622
915
|
}
|
|
916
|
+
/**
|
|
917
|
+
* Saves the configuration of a plugin to a file.
|
|
918
|
+
*
|
|
919
|
+
* This method saves the configuration of the specified plugin to a JSON file in the matterbridge directory.
|
|
920
|
+
* If the plugin's configuration is not found, it logs an error and rejects the promise. If the configuration
|
|
921
|
+
* is successfully saved, it logs a debug message. If an error occurs during the file write operation, it logs
|
|
922
|
+
* the error and rejects the promise.
|
|
923
|
+
*
|
|
924
|
+
* @param {RegisteredPlugin} plugin - The plugin whose configuration is to be saved.
|
|
925
|
+
* @returns {Promise<void>} A promise that resolves when the configuration is successfully saved, or rejects if an error occurs.
|
|
926
|
+
* @throws {Error} If the plugin's configuration is not found.
|
|
927
|
+
*/
|
|
623
928
|
async saveConfigFromPlugin(plugin) {
|
|
624
929
|
const { default: path } = await import('node:path');
|
|
625
930
|
const { promises } = await import('node:fs');
|
|
@@ -632,6 +937,7 @@ export class PluginManager {
|
|
|
632
937
|
await promises.writeFile(configFile, JSON.stringify(plugin.platform.config, null, 2), 'utf8');
|
|
633
938
|
plugin.configJson = plugin.platform.config;
|
|
634
939
|
this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
|
|
940
|
+
// this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, plugin.platform.config);
|
|
635
941
|
return Promise.resolve();
|
|
636
942
|
}
|
|
637
943
|
catch (err) {
|
|
@@ -639,6 +945,19 @@ export class PluginManager {
|
|
|
639
945
|
return Promise.reject(err);
|
|
640
946
|
}
|
|
641
947
|
}
|
|
948
|
+
/**
|
|
949
|
+
* Saves the configuration of a plugin from a JSON object to a file.
|
|
950
|
+
*
|
|
951
|
+
* This method saves the provided configuration of the specified plugin to a JSON file in the matterbridge directory.
|
|
952
|
+
* It first checks if the configuration data is valid by ensuring it contains the correct name and type, and matches
|
|
953
|
+
* the plugin's name. If the configuration data is invalid, it logs an error and returns. If the configuration is
|
|
954
|
+
* successfully saved, it updates the plugin's `configJson` property and logs a debug message. If an error occurs
|
|
955
|
+
* during the file write operation, it logs the error and returns.
|
|
956
|
+
*
|
|
957
|
+
* @param {RegisteredPlugin} plugin - The plugin whose configuration is to be saved.
|
|
958
|
+
* @param {PlatformConfig} config - The configuration data to be saved.
|
|
959
|
+
* @returns {Promise<void>} A promise that resolves when the configuration is successfully saved, or returns if an error occurs.
|
|
960
|
+
*/
|
|
642
961
|
async saveConfigFromJson(plugin, config) {
|
|
643
962
|
const { default: path } = await import('node:path');
|
|
644
963
|
const { promises } = await import('node:fs');
|
|
@@ -656,12 +975,23 @@ export class PluginManager {
|
|
|
656
975
|
plugin.platform.onConfigChanged(config).catch((err) => this.log.error(`Error calling onConfigChanged for plugin ${plg}${plugin.name}${er}: ${err}`));
|
|
657
976
|
}
|
|
658
977
|
this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}`);
|
|
978
|
+
// this.log.debug(`Saved config file ${configFile} for plugin ${plg}${plugin.name}${db}.\nConfig:${rs}\n`, config);
|
|
659
979
|
}
|
|
660
980
|
catch (err) {
|
|
661
981
|
this.log.error(`Error saving config file ${configFile} for plugin ${plg}${plugin.name}${er}: ${err}`);
|
|
662
982
|
return;
|
|
663
983
|
}
|
|
664
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
* Loads the schema for a plugin.
|
|
987
|
+
*
|
|
988
|
+
* This method attempts to load the schema file for the specified plugin. If the schema file is found,
|
|
989
|
+
* it reads and parses the file, updates the schema's title and description, and logs the process.
|
|
990
|
+
* If the schema file is not found, it logs the event and loads a default schema for the plugin.
|
|
991
|
+
*
|
|
992
|
+
* @param {RegisteredPlugin} plugin - The plugin whose schema is to be loaded.
|
|
993
|
+
* @returns {Promise<PlatformSchema>} A promise that resolves to the loaded schema object, or the default schema if the schema file is not found.
|
|
994
|
+
*/
|
|
665
995
|
async loadSchema(plugin) {
|
|
666
996
|
const { promises } = await import('node:fs');
|
|
667
997
|
const schemaFile = plugin.path.replace('package.json', `${plugin.name}.schema.json`);
|
|
@@ -672,6 +1002,7 @@ export class PluginManager {
|
|
|
672
1002
|
schema.title = plugin.description;
|
|
673
1003
|
schema.description = plugin.name + ' v. ' + plugin.version + ' by ' + plugin.author;
|
|
674
1004
|
this.log.debug(`Loaded schema file ${schemaFile} for plugin ${plg}${plugin.name}${db}.`);
|
|
1005
|
+
// this.log.debug(`Loaded schema file ${schemaFile} for plugin ${plg}${plugin.name}${db}.\nSchema:${rs}\n`, schema);
|
|
675
1006
|
return schema;
|
|
676
1007
|
}
|
|
677
1008
|
catch (error) {
|
|
@@ -679,6 +1010,16 @@ export class PluginManager {
|
|
|
679
1010
|
return this.getDefaultSchema(plugin);
|
|
680
1011
|
}
|
|
681
1012
|
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Returns the default schema for a plugin.
|
|
1015
|
+
*
|
|
1016
|
+
* This method generates a default schema object for the specified plugin. The schema includes
|
|
1017
|
+
* metadata such as the plugin's title, description, version, and author. It also defines the
|
|
1018
|
+
* properties of the schema, including the plugin's name, type, debug flag, and unregisterOnShutdown flag.
|
|
1019
|
+
*
|
|
1020
|
+
* @param {RegisteredPlugin} plugin - The plugin for which the default schema is to be generated.
|
|
1021
|
+
* @returns {PlatformSchema} The default schema object for the plugin.
|
|
1022
|
+
*/
|
|
682
1023
|
getDefaultSchema(plugin) {
|
|
683
1024
|
return {
|
|
684
1025
|
title: plugin.description,
|
|
@@ -709,3 +1050,4 @@ export class PluginManager {
|
|
|
709
1050
|
};
|
|
710
1051
|
}
|
|
711
1052
|
}
|
|
1053
|
+
//# sourceMappingURL=pluginManager.js.map
|