matterbridge 3.4.7-dev-20260104-6b10cee → 3.4.7-dev-20260112-bd9e311
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 +11 -4
- package/README.md +5 -1
- package/dist/broadcastServer.d.ts +29 -0
- package/dist/broadcastServerTypes.d.ts +798 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cliEmitter.d.ts +14 -0
- package/dist/cliHistory.d.ts +6 -0
- package/dist/clusters/export.d.ts +1 -0
- package/dist/deviceManager.d.ts +27 -0
- package/dist/devices/airConditioner.d.ts +23 -0
- package/dist/devices/batteryStorage.d.ts +5 -0
- package/dist/devices/cooktop.d.ts +6 -0
- package/dist/devices/dishwasher.d.ts +16 -0
- package/dist/devices/evse.d.ts +19 -0
- package/dist/devices/export.d.ts +16 -0
- package/dist/devices/extractorHood.d.ts +5 -0
- package/dist/devices/heatPump.d.ts +4 -0
- package/dist/devices/laundryDryer.d.ts +9 -0
- package/dist/devices/laundryWasher.d.ts +17 -0
- package/dist/devices/microwaveOven.d.ts +92 -0
- package/dist/devices/oven.d.ts +23 -0
- package/dist/devices/refrigerator.d.ts +18 -0
- package/dist/devices/roboticVacuumCleaner.d.ts +29 -0
- package/dist/devices/solarPower.d.ts +4 -0
- package/dist/devices/speaker.d.ts +8 -0
- package/dist/devices/temperatureControl.d.ts +145 -0
- package/dist/devices/waterHeater.d.ts +37 -0
- package/dist/dgram/coap.d.ts +34 -0
- package/dist/dgram/dgram.d.ts +45 -0
- package/dist/dgram/dgram.js +5 -2
- package/dist/dgram/mb_coap.d.ts +1 -0
- package/dist/dgram/mb_coap.js +1 -2
- package/dist/dgram/mb_mdns.d.ts +1 -0
- package/dist/dgram/mb_mdns.js +39 -50
- package/dist/dgram/mdns.d.ts +188 -0
- package/dist/dgram/multicast.d.ts +18 -0
- package/dist/dgram/unicast.d.ts +11 -0
- package/dist/frontend.d.ts +58 -0
- package/dist/frontendTypes.d.ts +472 -0
- package/dist/helpers.d.ts +5 -0
- package/dist/index.d.ts +11 -0
- package/dist/jestutils/export.d.ts +1 -0
- package/dist/jestutils/jestHelpers.d.ts +90 -0
- package/dist/logger/export.d.ts +1 -0
- package/dist/matter/behaviors.d.ts +1 -0
- package/dist/matter/clusters.d.ts +1 -0
- package/dist/matter/devices.d.ts +1 -0
- package/dist/matter/endpoints.d.ts +1 -0
- package/dist/matter/export.d.ts +4 -0
- package/dist/matter/types.d.ts +2 -0
- package/dist/matterNode.d.ts +84 -0
- package/dist/matterbridge.d.ts +152 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts +5 -0
- package/dist/matterbridgeBehaviors.d.ts +2380 -0
- package/dist/matterbridgeDeviceTypes.d.ts +95 -0
- package/dist/matterbridgeDynamicPlatform.d.ts +5 -0
- package/dist/matterbridgeEndpoint.d.ts +175 -0
- package/dist/matterbridgeEndpointHelpers.d.ts +362 -0
- package/dist/matterbridgeEndpointTypes.d.ts +96 -0
- package/dist/matterbridgePlatform.d.ts +114 -0
- package/dist/matterbridgeTypes.d.ts +206 -0
- package/dist/pluginManager.d.ts +67 -0
- package/dist/shelly.d.ts +24 -0
- package/dist/storage/export.d.ts +1 -0
- package/dist/update.d.ts +9 -0
- package/dist/utils/colorUtils.d.ts +24 -0
- package/dist/utils/commandLine.d.ts +6 -0
- package/dist/utils/copyDirectory.d.ts +2 -0
- package/dist/utils/createDirectory.d.ts +2 -0
- package/dist/utils/createZip.d.ts +1 -0
- package/dist/utils/deepCopy.d.ts +1 -0
- package/dist/utils/deepEqual.d.ts +1 -0
- package/dist/utils/error.d.ts +3 -0
- package/dist/utils/export.d.ts +12 -0
- package/dist/utils/format.d.ts +4 -0
- package/dist/utils/hex.d.ts +4 -0
- package/dist/utils/inspector.d.ts +24 -0
- package/dist/utils/isValid.d.ts +10 -0
- package/dist/utils/network.d.ts +25 -0
- package/dist/utils/spawn.d.ts +1 -0
- package/dist/utils/tracker.d.ts +52 -0
- package/dist/utils/wait.d.ts +3 -0
- package/dist/workerGlobalPrefix.d.ts +1 -0
- package/dist/workerTypes.d.ts +27 -0
- package/dist/workers.d.ts +8 -0
- package/npm-shrinkwrap.json +1109 -330
- package/package.json +9 -2
- package/packages/dgram/dist/coap.d.ts +34 -0
- package/packages/dgram/dist/coap.js +252 -0
- package/packages/dgram/dist/dgram.d.ts +45 -0
- package/packages/dgram/dist/dgram.js +255 -0
- package/packages/dgram/dist/export.d.ts +5 -0
- package/packages/dgram/dist/export.js +5 -0
- package/packages/dgram/dist/mdns.d.ts +188 -0
- package/packages/dgram/dist/mdns.js +702 -0
- package/packages/dgram/dist/multicast.d.ts +18 -0
- package/packages/dgram/dist/multicast.js +119 -0
- package/packages/dgram/dist/unicast.d.ts +11 -0
- package/packages/dgram/dist/unicast.js +40 -0
- package/packages/dgram/package.json +110 -0
- package/packages/jest-utils/LICENSE +202 -0
- package/packages/jest-utils/bmc-button.svg +22 -0
- package/packages/jest-utils/dist/export.d.ts +1 -0
- package/packages/jest-utils/dist/export.js +1 -0
- package/packages/jest-utils/matterbridge.svg +50 -0
- package/packages/{mb-lib-test → jest-utils}/package.json +18 -15
- package/packages/utils/LICENSE +202 -0
- package/packages/utils/bmc-button.svg +22 -0
- package/packages/utils/dist/colorUtils.d.ts +24 -0
- package/packages/utils/dist/colorUtils.js +187 -0
- package/packages/utils/dist/commandLine.d.ts +6 -0
- package/packages/utils/dist/commandLine.js +63 -0
- package/packages/utils/dist/copyDirectory.d.ts +2 -0
- package/packages/utils/dist/copyDirectory.js +39 -0
- package/packages/utils/dist/createDirectory.d.ts +2 -0
- package/packages/utils/dist/createDirectory.js +21 -0
- package/packages/utils/dist/createZip.d.ts +1 -0
- package/packages/utils/dist/createZip.js +69 -0
- package/packages/utils/dist/deepCopy.d.ts +1 -0
- package/packages/utils/dist/deepCopy.js +40 -0
- package/packages/utils/dist/deepEqual.d.ts +1 -0
- package/packages/utils/dist/deepEqual.js +58 -0
- package/packages/utils/dist/error.d.ts +3 -0
- package/packages/utils/dist/error.js +12 -0
- package/packages/utils/dist/export.d.ts +15 -0
- package/packages/utils/dist/export.js +15 -0
- package/packages/utils/dist/format.d.ts +4 -0
- package/packages/utils/dist/format.js +29 -0
- package/packages/utils/dist/githubVersion.d.ts +11 -0
- package/packages/utils/dist/githubVersion.js +37 -0
- package/packages/utils/dist/hex.d.ts +4 -0
- package/packages/utils/dist/hex.js +118 -0
- package/packages/utils/dist/inspector.d.ts +24 -0
- package/packages/utils/dist/inspector.js +200 -0
- package/packages/utils/dist/isValid.d.ts +10 -0
- package/packages/utils/dist/isValid.js +69 -0
- package/packages/utils/dist/network.d.ts +12 -0
- package/packages/utils/dist/network.js +105 -0
- package/packages/utils/dist/npmRoot.d.ts +1 -0
- package/packages/utils/dist/npmRoot.js +13 -0
- package/packages/utils/dist/npmVersion.d.ts +1 -0
- package/packages/utils/dist/npmVersion.js +43 -0
- package/packages/utils/dist/tracker.d.ts +52 -0
- package/packages/utils/dist/tracker.js +201 -0
- package/packages/utils/dist/wait.d.ts +3 -0
- package/packages/utils/dist/wait.js +73 -0
- package/packages/utils/matterbridge.svg +50 -0
- package/packages/utils/package.json +110 -0
- package/packages/vitest-utils/LICENSE +202 -0
- package/packages/vitest-utils/bmc-button.svg +22 -0
- package/packages/vitest-utils/dist/export.d.ts +1 -0
- package/packages/vitest-utils/dist/export.js +1 -0
- package/packages/vitest-utils/matterbridge.svg +50 -0
- package/packages/vitest-utils/package.json +109 -0
- package/dist/dgram/mdnsReflectorClient.js +0 -176
- package/dist/dgram/mdnsReflectorServer.js +0 -301
- package/dist/dgram/mdnsReflectorTypes.js +0 -5
- package/packages/mb-lib-test/dist/module.d.ts +0 -2
- package/packages/mb-lib-test/dist/module.js +0 -2
- package/reflector/DockerDesktopSetup.png +0 -0
- package/reflector/Reflector.md +0 -158
- package/reflector/ReflectorClient.png +0 -0
- package/reflector/ReflectorServer.png +0 -0
- package/reflector/docker-compose.yml +0 -32
- package/reflector/mDnsPacket.png +0 -0
- /package/packages/{mb-lib-test → dgram}/LICENSE +0 -0
- /package/packages/{mb-lib-test → dgram}/bmc-button.svg +0 -0
- /package/packages/{mb-lib-test → dgram}/matterbridge.svg +0 -0
- /package/packages/{mb-lib-test/dist/jestutils → jest-utils/dist}/jestHelpers.d.ts +0 -0
- /package/packages/{mb-lib-test/dist/jestutils → jest-utils/dist}/jestHelpers.js +0 -0
- /package/packages/{mb-lib-test/dist/vitestutils → vitest-utils/dist}/vitestHelpers.d.ts +0 -0
- /package/packages/{mb-lib-test/dist/vitestutils → vitest-utils/dist}/vitestHelpers.js +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { isValidNumber } from './isValid.js';
|
|
2
|
+
export function hasParameter(name) {
|
|
3
|
+
const commandArguments = process.argv.slice(2);
|
|
4
|
+
let markerIncluded = commandArguments.includes(`-${name}`);
|
|
5
|
+
if (!markerIncluded)
|
|
6
|
+
markerIncluded = commandArguments.includes(`--${name}`);
|
|
7
|
+
return markerIncluded;
|
|
8
|
+
}
|
|
9
|
+
export function hasAnyParameter(...params) {
|
|
10
|
+
return params.some((param) => {
|
|
11
|
+
return hasParameter(param);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function getParameter(name) {
|
|
15
|
+
const commandArguments = process.argv.slice(2);
|
|
16
|
+
let markerIndex = commandArguments.indexOf(`-${name}`);
|
|
17
|
+
if (markerIndex === -1)
|
|
18
|
+
markerIndex = commandArguments.indexOf(`--${name}`);
|
|
19
|
+
if (markerIndex === -1 || markerIndex + 1 === commandArguments.length || commandArguments[markerIndex + 1].startsWith('-'))
|
|
20
|
+
return undefined;
|
|
21
|
+
return commandArguments[markerIndex + 1];
|
|
22
|
+
}
|
|
23
|
+
export function getIntParameter(name) {
|
|
24
|
+
const value = getParameter(name);
|
|
25
|
+
if (value === undefined)
|
|
26
|
+
return undefined;
|
|
27
|
+
const intValue = parseInt(value, 10);
|
|
28
|
+
if (!isValidNumber(intValue))
|
|
29
|
+
return undefined;
|
|
30
|
+
return intValue;
|
|
31
|
+
}
|
|
32
|
+
export function getIntArrayParameter(name) {
|
|
33
|
+
const commandArguments = process.argv.slice(2);
|
|
34
|
+
let markerIndex = commandArguments.indexOf(`--${name}`);
|
|
35
|
+
if (markerIndex < 0)
|
|
36
|
+
markerIndex = commandArguments.indexOf(`-${name}`);
|
|
37
|
+
if (markerIndex < 0)
|
|
38
|
+
return undefined;
|
|
39
|
+
const intValues = [];
|
|
40
|
+
for (let i = markerIndex + 1; i < commandArguments.length && !commandArguments[i].startsWith('-'); i++) {
|
|
41
|
+
const intValue = parseInt(commandArguments[i], 10);
|
|
42
|
+
if (isValidNumber(intValue))
|
|
43
|
+
intValues.push(intValue);
|
|
44
|
+
}
|
|
45
|
+
if (intValues.length === 0)
|
|
46
|
+
return undefined;
|
|
47
|
+
return intValues;
|
|
48
|
+
}
|
|
49
|
+
export function getStringArrayParameter(name) {
|
|
50
|
+
const commandArguments = process.argv.slice(2);
|
|
51
|
+
let markerIndex = commandArguments.indexOf(`--${name}`);
|
|
52
|
+
if (markerIndex < 0)
|
|
53
|
+
markerIndex = commandArguments.indexOf(`-${name}`);
|
|
54
|
+
if (markerIndex < 0)
|
|
55
|
+
return undefined;
|
|
56
|
+
const values = [];
|
|
57
|
+
for (let i = markerIndex + 1; i < commandArguments.length && !commandArguments[i].startsWith('-'); i++) {
|
|
58
|
+
values.push(commandArguments[i]);
|
|
59
|
+
}
|
|
60
|
+
if (values.length === 0)
|
|
61
|
+
return undefined;
|
|
62
|
+
return values;
|
|
63
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export async function copyDirectory(srcDir, destDir, log) {
|
|
2
|
+
if (srcDir === '') {
|
|
3
|
+
throw new Error('Source directory must be specified.');
|
|
4
|
+
}
|
|
5
|
+
if (destDir === '') {
|
|
6
|
+
throw new Error('Destination directory must be specified.');
|
|
7
|
+
}
|
|
8
|
+
if (!srcDir) {
|
|
9
|
+
throw new Error('Source directory must be specified.');
|
|
10
|
+
}
|
|
11
|
+
if (!destDir) {
|
|
12
|
+
throw new Error('Destination directory must be specified.');
|
|
13
|
+
}
|
|
14
|
+
if (srcDir === destDir) {
|
|
15
|
+
throw new Error('Source and destination directories must be different.');
|
|
16
|
+
}
|
|
17
|
+
const fs = await import('node:fs').then((mod) => mod.promises);
|
|
18
|
+
const path = await import('node:path');
|
|
19
|
+
log?.debug(`copyDirectory: copying directory from ${srcDir} to ${destDir}`);
|
|
20
|
+
try {
|
|
21
|
+
await fs.mkdir(destDir, { recursive: true });
|
|
22
|
+
const entries = await fs.readdir(srcDir, { withFileTypes: true });
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
25
|
+
const destPath = path.join(destDir, entry.name);
|
|
26
|
+
if (entry.isDirectory()) {
|
|
27
|
+
await copyDirectory(srcPath, destPath);
|
|
28
|
+
}
|
|
29
|
+
else if (entry.isFile()) {
|
|
30
|
+
await fs.copyFile(srcPath, destPath);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
log?.error(`copyDirectory error copying from ${srcDir} to ${destDir}: ${error instanceof Error ? error.message : error}`);
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
export async function createDirectory(path, name, log) {
|
|
3
|
+
try {
|
|
4
|
+
await fs.access(path);
|
|
5
|
+
log.debug(`Directory ${name} already exists at path: ${path}`);
|
|
6
|
+
}
|
|
7
|
+
catch (err) {
|
|
8
|
+
if (err.code === 'ENOENT') {
|
|
9
|
+
try {
|
|
10
|
+
await fs.mkdir(path, { recursive: true });
|
|
11
|
+
log.info(`Created ${name}: ${path}`);
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
log.error(`Error creating dir ${name} path ${path}: ${err}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
log.error(`Error accessing dir ${name} path ${path}: ${err}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createZip(outputPath: string, ...sourcePaths: string[]): Promise<number>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { AnsiLogger } from 'node-ansi-logger';
|
|
2
|
+
export async function createZip(outputPath, ...sourcePaths) {
|
|
3
|
+
const log = new AnsiLogger({ logName: 'Archive', logTimestampFormat: 4, logLevel: "info" });
|
|
4
|
+
const { default: archiver } = await import('archiver');
|
|
5
|
+
const { glob } = await import('glob');
|
|
6
|
+
const { createWriteStream, statSync } = await import('node:fs');
|
|
7
|
+
const path = await import('node:path');
|
|
8
|
+
log.debug(`creating archive ${outputPath} from ${sourcePaths.join(', ')} ...`);
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
const output = createWriteStream(outputPath);
|
|
11
|
+
const archive = archiver('zip', {
|
|
12
|
+
zlib: { level: 9 },
|
|
13
|
+
});
|
|
14
|
+
output.on('close', () => {
|
|
15
|
+
log.debug(`archive ${outputPath} closed with ${archive.pointer()} total bytes`);
|
|
16
|
+
resolve(archive.pointer());
|
|
17
|
+
});
|
|
18
|
+
output.on('end', () => {
|
|
19
|
+
log.debug(`archive ${outputPath} data has been drained ${archive.pointer()} total bytes`);
|
|
20
|
+
});
|
|
21
|
+
archive.on('error', (error) => {
|
|
22
|
+
log.error(`archive error: ${error.message}`);
|
|
23
|
+
reject(error);
|
|
24
|
+
});
|
|
25
|
+
archive.on('warning', (error) => {
|
|
26
|
+
if (error.code === 'ENOENT') {
|
|
27
|
+
log.warn(`archive warning: ${error.message}`);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
log.error(`archive warning: ${error.message}`);
|
|
31
|
+
reject(error);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
archive.on('entry', (entry) => {
|
|
35
|
+
log.debug(`- archive entry: ${entry.name}`);
|
|
36
|
+
});
|
|
37
|
+
archive.pipe(output);
|
|
38
|
+
for (const sourcePath of sourcePaths) {
|
|
39
|
+
let stats;
|
|
40
|
+
try {
|
|
41
|
+
stats = statSync(sourcePath);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (sourcePath.includes('*')) {
|
|
45
|
+
const files = glob.sync(sourcePath.replace(/\\/g, '/'));
|
|
46
|
+
log.debug(`adding files matching glob pattern: ${sourcePath}`);
|
|
47
|
+
for (const file of files) {
|
|
48
|
+
log.debug(`- glob file: ${file}`);
|
|
49
|
+
archive.file(file, { name: file });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
log.error(`no files or directory found for pattern ${sourcePath}: ${error}`);
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (stats.isFile()) {
|
|
58
|
+
log.debug(`adding file: ${sourcePath}`);
|
|
59
|
+
archive.file(sourcePath, { name: path.basename(sourcePath) });
|
|
60
|
+
}
|
|
61
|
+
else if (stats.isDirectory()) {
|
|
62
|
+
log.debug(`adding directory: ${sourcePath}`);
|
|
63
|
+
archive.directory(sourcePath, path.basename(sourcePath));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
log.debug(`finalizing archive ${outputPath}...`);
|
|
67
|
+
archive.finalize().catch(reject);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function deepCopy<T>(value: T): T;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export function deepCopy(value) {
|
|
2
|
+
if (typeof value !== 'object' || value === null) {
|
|
3
|
+
return value;
|
|
4
|
+
}
|
|
5
|
+
else if (Array.isArray(value)) {
|
|
6
|
+
return value.map((item) => deepCopy(item));
|
|
7
|
+
}
|
|
8
|
+
else if (value instanceof Date) {
|
|
9
|
+
return new Date(value.getTime());
|
|
10
|
+
}
|
|
11
|
+
else if (value instanceof RegExp) {
|
|
12
|
+
return new RegExp(value.source, value.flags);
|
|
13
|
+
}
|
|
14
|
+
else if (value instanceof Map) {
|
|
15
|
+
const mapCopy = new Map();
|
|
16
|
+
for (const [origKey, origVal] of value.entries()) {
|
|
17
|
+
const clonedKey = deepCopy(origKey);
|
|
18
|
+
const clonedVal = deepCopy(origVal);
|
|
19
|
+
mapCopy.set(clonedKey, clonedVal);
|
|
20
|
+
}
|
|
21
|
+
return mapCopy;
|
|
22
|
+
}
|
|
23
|
+
else if (value instanceof Set) {
|
|
24
|
+
const setCopy = new Set();
|
|
25
|
+
value.forEach((item) => {
|
|
26
|
+
setCopy.add(deepCopy(item));
|
|
27
|
+
});
|
|
28
|
+
return setCopy;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
const proto = Object.getPrototypeOf(value);
|
|
32
|
+
const copy = Object.create(proto);
|
|
33
|
+
for (const key in value) {
|
|
34
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
35
|
+
copy[key] = deepCopy(value[key]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return copy;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function deepEqual(a: any, b: any, excludeProperties?: string[]): boolean;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export function deepEqual(a, b, excludeProperties = []) {
|
|
2
|
+
const debugLog = (...messages) => {
|
|
3
|
+
};
|
|
4
|
+
if (a === b) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (typeof a !== typeof b) {
|
|
8
|
+
debugLog(`deepEqual false for typeof a: ${typeof a} typeof b: ${typeof b}`);
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (a == null || b == null) {
|
|
12
|
+
debugLog('deepEqual false for == null');
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
if (a instanceof Date && b instanceof Date) {
|
|
16
|
+
return a.getTime() === b.getTime();
|
|
17
|
+
}
|
|
18
|
+
if (a instanceof RegExp && b instanceof RegExp) {
|
|
19
|
+
return a.source === b.source && a.flags === b.flags;
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
22
|
+
if (a.length !== b.length) {
|
|
23
|
+
debugLog(`deepEqual false for array a.length(${a.length}) !== b.length(${b.length})`);
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
for (let i = 0; i < a.length; i++) {
|
|
27
|
+
if (!deepEqual(a[i], b[i], excludeProperties)) {
|
|
28
|
+
debugLog('deepEqual false for array !deepEqual(a[i], b[i])');
|
|
29
|
+
debugLog(`- aProps.length(${a[i]}):`, a[i]);
|
|
30
|
+
debugLog(`- bProps.length(${b[i]}):`, b[i]);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
37
|
+
const aProps = Object.getOwnPropertyNames(a).filter((prop) => !excludeProperties.includes(prop));
|
|
38
|
+
const bProps = Object.getOwnPropertyNames(b).filter((prop) => !excludeProperties.includes(prop));
|
|
39
|
+
if (aProps.length !== bProps.length) {
|
|
40
|
+
debugLog(`deepEqual false for aProps.length(${aProps.length}) !== bProps.length(${bProps.length})`);
|
|
41
|
+
debugLog(`- aProps.length(${aProps.length}):`, aProps);
|
|
42
|
+
debugLog(`- bProps.length(${bProps.length}):`, bProps);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
for (const prop of aProps) {
|
|
46
|
+
if (!Object.prototype.hasOwnProperty.call(b, prop)) {
|
|
47
|
+
debugLog(`deepEqual false for !b.hasOwnProperty(${prop})`);
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (!deepEqual(a[prop], b[prop], excludeProperties)) {
|
|
51
|
+
debugLog(`deepEqual false for !deepEqual(a[${prop}], b[${prop}])`);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { inspect } from 'node:util';
|
|
2
|
+
import { RESET } from 'node-ansi-logger';
|
|
3
|
+
export function logError(log, message, error) {
|
|
4
|
+
log.error(`${message}: ${error instanceof Error ? error.message + ' \nStack: \n' + error.stack : error}`);
|
|
5
|
+
}
|
|
6
|
+
export function inspectError(log, message, error) {
|
|
7
|
+
const errorMessage = error instanceof Error ? `${error.message} \n` : '';
|
|
8
|
+
const inspectedError = inspect(error, { depth: 10, colors: true, showHidden: false });
|
|
9
|
+
const fullMessage = `${message}: ${errorMessage}${RESET}${inspectedError}`;
|
|
10
|
+
log.error(fullMessage);
|
|
11
|
+
return fullMessage;
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './colorUtils.js';
|
|
2
|
+
export * from './commandLine.js';
|
|
3
|
+
export * from './copyDirectory.js';
|
|
4
|
+
export * from './createDirectory.js';
|
|
5
|
+
export * from './createZip.js';
|
|
6
|
+
export * from './deepCopy.js';
|
|
7
|
+
export * from './deepEqual.js';
|
|
8
|
+
export * from './error.js';
|
|
9
|
+
export * from './format.js';
|
|
10
|
+
export * from './hex.js';
|
|
11
|
+
export * from './inspector.js';
|
|
12
|
+
export * from './isValid.js';
|
|
13
|
+
export * from './network.js';
|
|
14
|
+
export * from './tracker.js';
|
|
15
|
+
export * from './wait.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './colorUtils.js';
|
|
2
|
+
export * from './commandLine.js';
|
|
3
|
+
export * from './copyDirectory.js';
|
|
4
|
+
export * from './createDirectory.js';
|
|
5
|
+
export * from './createZip.js';
|
|
6
|
+
export * from './deepCopy.js';
|
|
7
|
+
export * from './deepEqual.js';
|
|
8
|
+
export * from './error.js';
|
|
9
|
+
export * from './format.js';
|
|
10
|
+
export * from './hex.js';
|
|
11
|
+
export * from './inspector.js';
|
|
12
|
+
export * from './isValid.js';
|
|
13
|
+
export * from './network.js';
|
|
14
|
+
export * from './tracker.js';
|
|
15
|
+
export * from './wait.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function formatTimeStamp(timestamp: number): string;
|
|
2
|
+
export declare function formatPercent(percent: number, digits?: number): string;
|
|
3
|
+
export declare function formatBytes(bytes: number, digits?: number): string;
|
|
4
|
+
export declare function formatUptime(seconds: number): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function formatTimeStamp(timestamp) {
|
|
2
|
+
return `${new Date(timestamp).toLocaleString()}`;
|
|
3
|
+
}
|
|
4
|
+
export function formatPercent(percent, digits = 2) {
|
|
5
|
+
return `${percent.toFixed(digits)} %`;
|
|
6
|
+
}
|
|
7
|
+
export function formatBytes(bytes, digits = 2) {
|
|
8
|
+
if (bytes === 0)
|
|
9
|
+
return `${bytes.toFixed(digits)} B`;
|
|
10
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
11
|
+
const idx = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
12
|
+
const value = bytes / Math.pow(1024, idx);
|
|
13
|
+
return `${value.toFixed(digits)} ${units[idx]}`;
|
|
14
|
+
}
|
|
15
|
+
export function formatUptime(seconds) {
|
|
16
|
+
if (seconds >= 86400) {
|
|
17
|
+
const days = Math.floor(seconds / 86400);
|
|
18
|
+
return `${days} day${days !== 1 ? 's' : ''}`;
|
|
19
|
+
}
|
|
20
|
+
if (seconds >= 3600) {
|
|
21
|
+
const hours = Math.floor(seconds / 3600);
|
|
22
|
+
return `${hours} hour${hours !== 1 ? 's' : ''}`;
|
|
23
|
+
}
|
|
24
|
+
if (seconds >= 60) {
|
|
25
|
+
const minutes = Math.floor(seconds / 60);
|
|
26
|
+
return `${minutes} minute${minutes !== 1 ? 's' : ''}`;
|
|
27
|
+
}
|
|
28
|
+
return `${seconds} second${seconds !== 1 ? 's' : ''}`;
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type UpdateJson = {
|
|
2
|
+
latest: string;
|
|
3
|
+
latestDate: string;
|
|
4
|
+
dev: string;
|
|
5
|
+
devDate: string;
|
|
6
|
+
latestMessage: string;
|
|
7
|
+
latestMessageSeverity: 'info' | 'warning' | 'error' | 'success';
|
|
8
|
+
devMessage: string;
|
|
9
|
+
devMessageSeverity: 'info' | 'warning' | 'error' | 'success';
|
|
10
|
+
};
|
|
11
|
+
export declare function getGitHubUpdate(branch: 'main' | 'dev', file: string, timeout?: number): Promise<UpdateJson>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export async function getGitHubUpdate(branch, file, timeout = 10000) {
|
|
2
|
+
const https = await import('node:https');
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const url = `https://matterbridge.io/${branch}_${file}`;
|
|
5
|
+
const controller = new AbortController();
|
|
6
|
+
const timeoutId = setTimeout(() => {
|
|
7
|
+
controller.abort();
|
|
8
|
+
reject(new Error(`Request timed out after ${timeout / 1000} seconds`));
|
|
9
|
+
}, timeout);
|
|
10
|
+
const req = https.get(url, { signal: controller.signal }, (res) => {
|
|
11
|
+
let data = '';
|
|
12
|
+
if (res.statusCode !== 200) {
|
|
13
|
+
clearTimeout(timeoutId);
|
|
14
|
+
res.resume();
|
|
15
|
+
reject(new Error(`Failed to fetch data. Status code: ${res.statusCode}`));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
res.on('data', (chunk) => {
|
|
19
|
+
data += chunk;
|
|
20
|
+
});
|
|
21
|
+
res.on('end', () => {
|
|
22
|
+
clearTimeout(timeoutId);
|
|
23
|
+
try {
|
|
24
|
+
const jsonData = JSON.parse(data);
|
|
25
|
+
resolve(jsonData);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
reject(new Error(`Failed to parse response JSON: ${error instanceof Error ? error.message : error}`));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
req.on('error', (error) => {
|
|
33
|
+
clearTimeout(timeoutId);
|
|
34
|
+
reject(new Error(`Request failed: ${error instanceof Error ? error.message : error}`));
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function bufferToHex(buffer: ArrayBufferLike): string;
|
|
2
|
+
export declare function hexToBuffer(hex: string): Uint8Array;
|
|
3
|
+
export declare function pemToBuffer(pem: string, validate?: boolean): Uint8Array;
|
|
4
|
+
export declare function extractPrivateKeyRaw(pemPrivateKey: string): Uint8Array;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { createPublicKey, createPrivateKey, X509Certificate } from 'node:crypto';
|
|
2
|
+
export function bufferToHex(buffer) {
|
|
3
|
+
if (!(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer))) {
|
|
4
|
+
throw new TypeError('Expected input to be an ArrayBuffer or ArrayBufferView');
|
|
5
|
+
}
|
|
6
|
+
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
7
|
+
return Array.from(bytes)
|
|
8
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
9
|
+
.join('');
|
|
10
|
+
}
|
|
11
|
+
export function hexToBuffer(hex) {
|
|
12
|
+
if (typeof hex !== 'string') {
|
|
13
|
+
throw new TypeError('Expected a string for hex input');
|
|
14
|
+
}
|
|
15
|
+
const cleaned = hex.trim();
|
|
16
|
+
if (cleaned.length % 2 !== 0) {
|
|
17
|
+
throw new Error('Invalid hex string length, must be even');
|
|
18
|
+
}
|
|
19
|
+
if (!/^[0-9a-fA-F]*$/.test(cleaned)) {
|
|
20
|
+
throw new Error('Invalid hex string, contains non-hex characters');
|
|
21
|
+
}
|
|
22
|
+
const length = cleaned.length / 2;
|
|
23
|
+
const result = new Uint8Array(length);
|
|
24
|
+
for (let i = 0; i < length; i++) {
|
|
25
|
+
result[i] = parseInt(cleaned.substr(i * 2, 2), 16);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
export function pemToBuffer(pem, validate = false) {
|
|
30
|
+
if (typeof pem !== 'string') {
|
|
31
|
+
throw new TypeError('Expected a string for PEM input');
|
|
32
|
+
}
|
|
33
|
+
const cleaned = pem.trim();
|
|
34
|
+
if (!cleaned.includes('-----BEGIN') || !cleaned.includes('-----END')) {
|
|
35
|
+
throw new Error('Invalid PEM format: missing BEGIN/END markers');
|
|
36
|
+
}
|
|
37
|
+
const lines = cleaned.split('\n');
|
|
38
|
+
const base64Lines = [];
|
|
39
|
+
let inContent = false;
|
|
40
|
+
for (const line of lines) {
|
|
41
|
+
const trimmedLine = line.trim();
|
|
42
|
+
if (trimmedLine.startsWith('-----BEGIN')) {
|
|
43
|
+
inContent = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (trimmedLine.startsWith('-----END')) {
|
|
47
|
+
inContent = false;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (inContent && trimmedLine.length > 0) {
|
|
51
|
+
base64Lines.push(trimmedLine);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (base64Lines.length === 0) {
|
|
55
|
+
throw new Error('Invalid PEM format: no content found between BEGIN/END markers');
|
|
56
|
+
}
|
|
57
|
+
const base64String = base64Lines.join('');
|
|
58
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(base64String)) {
|
|
59
|
+
throw new Error('Invalid PEM format: contains invalid base64 characters');
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const buffer = Buffer.from(base64String, 'base64');
|
|
63
|
+
const result = new Uint8Array(buffer);
|
|
64
|
+
if (validate) {
|
|
65
|
+
try {
|
|
66
|
+
const pemType = cleaned.match(/-----BEGIN\s+([^-]+)-----/)?.[1]?.trim();
|
|
67
|
+
if (pemType?.includes('CERTIFICATE')) {
|
|
68
|
+
const cert = new X509Certificate(pem);
|
|
69
|
+
if (cert.validFrom && cert.validTo) {
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
const from = Date.parse(cert.validFrom);
|
|
72
|
+
const to = Date.parse(cert.validTo);
|
|
73
|
+
if (now < from || now > to) {
|
|
74
|
+
throw new Error('Certificate is not currently valid');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!cert.subject || !cert.issuer) {
|
|
78
|
+
throw new Error('Certificate missing subject or issuer');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (pemType?.includes('PRIVATE KEY')) {
|
|
82
|
+
createPrivateKey({ key: pem, format: 'pem' });
|
|
83
|
+
}
|
|
84
|
+
else if (pemType?.includes('PUBLIC KEY')) {
|
|
85
|
+
createPublicKey({ key: pem, format: 'pem' });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (validationError) {
|
|
89
|
+
throw new Error(`PEM validation failed: ${validationError instanceof Error ? validationError.message : String(validationError)}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
throw new Error(`Failed to decode base64 content: ${error instanceof Error ? error.message : String(error)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export function extractPrivateKeyRaw(pemPrivateKey) {
|
|
99
|
+
if (typeof pemPrivateKey !== 'string') {
|
|
100
|
+
throw new TypeError('Expected a string for PEM private key input');
|
|
101
|
+
}
|
|
102
|
+
const keyBlock = /-----BEGIN (?:EC )?PRIVATE KEY-----[^-]+-----END (?:EC )?PRIVATE KEY-----/s.exec(pemPrivateKey);
|
|
103
|
+
if (!keyBlock) {
|
|
104
|
+
throw new Error('No EC PRIVATE KEY block found in the supplied PEM');
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
const privateKey = createPrivateKey(keyBlock[0]);
|
|
108
|
+
const pkcs8Der = privateKey.export({ format: 'der', type: 'pkcs8' });
|
|
109
|
+
if (pkcs8Der.length < 32) {
|
|
110
|
+
throw new Error('Invalid private key: DER data too short');
|
|
111
|
+
}
|
|
112
|
+
const rawPrivateKey = pkcs8Der.subarray(pkcs8Der.length - 32);
|
|
113
|
+
return new Uint8Array(rawPrivateKey);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
throw new Error(`Failed to extract private key: ${error instanceof Error ? error.message : String(error)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
|
+
interface InspectorEvents {
|
|
3
|
+
start: [];
|
|
4
|
+
stop: [];
|
|
5
|
+
snapshot: [];
|
|
6
|
+
snapshot_done: [];
|
|
7
|
+
gc: [type?: 'major' | 'minor', execution?: 'sync' | 'async'];
|
|
8
|
+
gc_done: [type: 'major' | 'minor', execution: 'sync' | 'async'];
|
|
9
|
+
}
|
|
10
|
+
export declare class Inspector extends EventEmitter<InspectorEvents> {
|
|
11
|
+
private readonly name;
|
|
12
|
+
private readonly debug;
|
|
13
|
+
private readonly verbose;
|
|
14
|
+
private session;
|
|
15
|
+
private snapshotInterval?;
|
|
16
|
+
private snapshotInProgress;
|
|
17
|
+
private log;
|
|
18
|
+
constructor(name?: string, debug?: boolean, verbose?: boolean);
|
|
19
|
+
start(): Promise<void>;
|
|
20
|
+
stop(): Promise<void>;
|
|
21
|
+
takeHeapSnapshot(): Promise<void>;
|
|
22
|
+
runGarbageCollector(type?: 'major' | 'minor', execution?: 'sync' | 'async'): void;
|
|
23
|
+
}
|
|
24
|
+
export {};
|