matterbridge 3.4.7-dev-20260103-3152357 → 3.4.7-dev-20260112-a00b2bf
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 -0
- 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 +7 -0
- 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 +904 -131
- 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 +106 -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/dist/jestHelpers.d.ts +21 -0
- package/packages/jest-utils/matterbridge.svg +50 -0
- package/packages/{mb-lib-test → jest-utils}/package.json +13 -11
- 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 +106 -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/dist/vitestHelpers.d.ts +21 -0
- package/packages/vitest-utils/matterbridge.svg +50 -0
- package/packages/vitest-utils/package.json +108 -0
- package/reflector/DockerDesktopSetup.png +0 -0
- package/reflector/Reflector.md +167 -0
- package/reflector/ReflectorClient.png +0 -0
- package/reflector/ReflectorServer.png +0 -0
- package/reflector/docker-compose.yml +32 -0
- package/reflector/mDnsPacket.png +0 -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.js +0 -2
- /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.js +0 -0
- /package/packages/{mb-lib-test/dist/vitestutils → vitest-utils/dist}/vitestHelpers.js +0 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
if (process.argv.includes('--loader') || process.argv.includes('-loader'))
|
|
2
|
+
console.log('\u001B[32mInspector loaded.\u001B[40;0m');
|
|
3
|
+
import EventEmitter from 'node:events';
|
|
4
|
+
import { AnsiLogger, BRIGHT, CYAN, RESET, YELLOW, db } from 'node-ansi-logger';
|
|
5
|
+
export class Inspector extends EventEmitter {
|
|
6
|
+
name;
|
|
7
|
+
debug;
|
|
8
|
+
verbose;
|
|
9
|
+
session;
|
|
10
|
+
snapshotInterval;
|
|
11
|
+
snapshotInProgress = false;
|
|
12
|
+
log;
|
|
13
|
+
constructor(name = 'Inspector', debug = false, verbose = false) {
|
|
14
|
+
super();
|
|
15
|
+
this.name = name;
|
|
16
|
+
this.debug = debug;
|
|
17
|
+
this.verbose = verbose;
|
|
18
|
+
if (process.argv.includes('--debug') || process.argv.includes('-debug')) {
|
|
19
|
+
this.debug = true;
|
|
20
|
+
}
|
|
21
|
+
if (process.argv.includes('--verbose') || process.argv.includes('-verbose')) {
|
|
22
|
+
this.verbose = true;
|
|
23
|
+
}
|
|
24
|
+
this.log = new AnsiLogger({ logName: this.name, logTimestampFormat: 4, logLevel: this.debug ? "debug" : "info" });
|
|
25
|
+
this.log.logNameColor = YELLOW;
|
|
26
|
+
this.on('start', () => {
|
|
27
|
+
this.start();
|
|
28
|
+
});
|
|
29
|
+
this.on('stop', () => {
|
|
30
|
+
this.stop();
|
|
31
|
+
});
|
|
32
|
+
this.on('snapshot', () => {
|
|
33
|
+
this.takeHeapSnapshot();
|
|
34
|
+
});
|
|
35
|
+
this.on('gc', () => {
|
|
36
|
+
this.runGarbageCollector();
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async start() {
|
|
40
|
+
if (this.session) {
|
|
41
|
+
this.log.warn('Inspector session already active.');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const { Session } = await import('node:inspector');
|
|
45
|
+
const { mkdirSync } = await import('node:fs');
|
|
46
|
+
this.log.debug(`Starting heap sampling...`);
|
|
47
|
+
mkdirSync('heap_profiles', { recursive: true });
|
|
48
|
+
mkdirSync('heap_snapshots', { recursive: true });
|
|
49
|
+
try {
|
|
50
|
+
this.session = new Session();
|
|
51
|
+
this.session.connect();
|
|
52
|
+
await new Promise((resolve, reject) => {
|
|
53
|
+
this.session?.post('HeapProfiler.startSampling', (err) => (err ? reject(err) : resolve()));
|
|
54
|
+
});
|
|
55
|
+
this.log.debug(`Started heap sampling`);
|
|
56
|
+
const { getIntParameter } = await import('./commandLine.js');
|
|
57
|
+
const interval = getIntParameter('snapshotinterval');
|
|
58
|
+
if (interval && interval >= 30000) {
|
|
59
|
+
this.log.debug(`Started heap snapshot interval of ${CYAN}${interval}${db} ms`);
|
|
60
|
+
clearInterval(this.snapshotInterval);
|
|
61
|
+
this.snapshotInterval = setInterval(async () => {
|
|
62
|
+
try {
|
|
63
|
+
if (this.snapshotInProgress) {
|
|
64
|
+
if (this.debug)
|
|
65
|
+
this.log.debug(`Skip heap snapshot: previous snapshot still in progress`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.log.debug(`Run heap snapshot interval`);
|
|
69
|
+
await this.takeHeapSnapshot();
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
this.log.error(`Error during scheduled heap snapshot: ${err instanceof Error ? err.message : err}`);
|
|
73
|
+
}
|
|
74
|
+
}, interval).unref();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
this.log.error(`Failed to start heap sampling: ${err instanceof Error ? err.message : err}`);
|
|
79
|
+
this.session?.disconnect();
|
|
80
|
+
this.session = undefined;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async stop() {
|
|
85
|
+
if (!this.session) {
|
|
86
|
+
this.log.warn('No active inspector session.');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const { writeFileSync } = await import('node:fs');
|
|
90
|
+
const path = await import('node:path');
|
|
91
|
+
this.log.debug(`Stopping heap sampling...`);
|
|
92
|
+
if (this.snapshotInterval) {
|
|
93
|
+
this.log.debug(`Clearing heap snapshot interval...`);
|
|
94
|
+
clearInterval(this.snapshotInterval);
|
|
95
|
+
await this.takeHeapSnapshot();
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const result = await new Promise((resolve, reject) => {
|
|
99
|
+
this.session?.post('HeapProfiler.stopSampling', (err, result) => (err ? reject(err) : resolve(result)));
|
|
100
|
+
});
|
|
101
|
+
const profile = JSON.stringify(result.profile);
|
|
102
|
+
const safeTimestamp = new Date().toISOString().replace(/[<>:"/\\|?*]/g, '-');
|
|
103
|
+
const filename = path.join('heap_profiles', `${safeTimestamp}.heapprofile`);
|
|
104
|
+
writeFileSync(filename, profile);
|
|
105
|
+
this.log.debug(`Heap sampling profile saved to ${CYAN}${filename}${db}`);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
this.log.error(`Failed to stop heap sampling: ${err instanceof Error ? err.message : err}`);
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
this.session.disconnect();
|
|
112
|
+
this.session = undefined;
|
|
113
|
+
this.log.debug(`Stopped heap sampling`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async takeHeapSnapshot() {
|
|
117
|
+
if (!this.session) {
|
|
118
|
+
this.log.warn('No active inspector session.');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (this.snapshotInProgress) {
|
|
122
|
+
if (this.debug)
|
|
123
|
+
this.log.debug('Heap snapshot already in progress, skipping.');
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.snapshotInProgress = true;
|
|
127
|
+
const { createWriteStream } = await import('node:fs');
|
|
128
|
+
const path = await import('node:path');
|
|
129
|
+
const safeTimestamp = new Date().toISOString().replace(/[<>:"/\\|?*]/g, '-');
|
|
130
|
+
const filename = path.join('heap_snapshots', `${safeTimestamp}.heapsnapshot`);
|
|
131
|
+
this.runGarbageCollector('minor', 'async');
|
|
132
|
+
this.runGarbageCollector('major', 'async');
|
|
133
|
+
if (this.debug)
|
|
134
|
+
this.log.debug(`Taking heap snapshot to ${CYAN}${filename}${db}...`);
|
|
135
|
+
const stream = createWriteStream(filename, { flags: 'w' });
|
|
136
|
+
let streamErrored = false;
|
|
137
|
+
const onStreamError = (err) => {
|
|
138
|
+
streamErrored = true;
|
|
139
|
+
this.log.error(`Heap snapshot stream error: ${err instanceof Error ? err.message : err}`);
|
|
140
|
+
};
|
|
141
|
+
stream.once('error', onStreamError);
|
|
142
|
+
const chunksListener = (notification) => {
|
|
143
|
+
if (!stream.write(notification.params.chunk)) {
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
this.session.on('HeapProfiler.addHeapSnapshotChunk', chunksListener);
|
|
147
|
+
try {
|
|
148
|
+
await new Promise((resolve) => {
|
|
149
|
+
this.session?.post('HeapProfiler.takeHeapSnapshot', (err) => {
|
|
150
|
+
this.session?.off('HeapProfiler.addHeapSnapshotChunk', chunksListener);
|
|
151
|
+
const finalize = () => {
|
|
152
|
+
if (!err && !streamErrored) {
|
|
153
|
+
if (this.debug)
|
|
154
|
+
this.log.debug(`Heap sampling snapshot saved to ${CYAN}${filename}${db}`);
|
|
155
|
+
this.runGarbageCollector('minor', 'async');
|
|
156
|
+
this.runGarbageCollector('major', 'async');
|
|
157
|
+
this.emit('snapshot_done');
|
|
158
|
+
}
|
|
159
|
+
else if (err) {
|
|
160
|
+
this.log.error(`Failed to take heap snapshot: ${err instanceof Error ? err.message : err}`);
|
|
161
|
+
this.runGarbageCollector('minor', 'async');
|
|
162
|
+
this.runGarbageCollector('major', 'async');
|
|
163
|
+
}
|
|
164
|
+
resolve();
|
|
165
|
+
};
|
|
166
|
+
try {
|
|
167
|
+
stream.end(() => finalize());
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
this.log.error(`Error finalizing heap snapshot stream: ${e instanceof Error ? e.message : e}`);
|
|
171
|
+
finalize();
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
this.snapshotInProgress = false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
runGarbageCollector(type = 'major', execution = 'async') {
|
|
181
|
+
if (global.gc && typeof global.gc === 'function') {
|
|
182
|
+
try {
|
|
183
|
+
global.gc({ type, execution });
|
|
184
|
+
if (this.debug)
|
|
185
|
+
this.log.debug(`${CYAN}${BRIGHT}Garbage collection (${type}-${execution}) triggered at ${new Date(Date.now()).toLocaleString()}.${RESET}${db}`);
|
|
186
|
+
this.emit('gc_done', type, execution);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
global.gc();
|
|
190
|
+
if (this.debug)
|
|
191
|
+
this.log.debug(`${CYAN}${BRIGHT}Garbage collection (minor-async) triggered at ${new Date(Date.now()).toLocaleString()}.${RESET}${db}`);
|
|
192
|
+
this.emit('gc_done', 'minor', 'async');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
if (this.debug)
|
|
197
|
+
this.log.debug(`${CYAN}${BRIGHT}Garbage collection not exposed. Start Node.js with --expose-gc to enable manual garbage collection.${RESET}${db}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function isValidIpv4Address(ipv4Address: string): boolean;
|
|
2
|
+
export declare function isValidNumber(value: unknown, min?: number, max?: number): value is number;
|
|
3
|
+
export declare function isValidBoolean(value: unknown): value is boolean;
|
|
4
|
+
export declare function isValidString(value: unknown, minLength?: number, maxLength?: number): value is string;
|
|
5
|
+
export declare function isValidRegExp(value: unknown): value is RegExp;
|
|
6
|
+
export declare function isValidObject(value: unknown, minLength?: number, maxLength?: number): value is object;
|
|
7
|
+
export declare function isValidArray(value: unknown, minLength?: number, maxLength?: number): value is unknown[];
|
|
8
|
+
export declare function isValidNull(value: unknown): value is null;
|
|
9
|
+
export declare function isValidUndefined(value: unknown): value is undefined;
|
|
10
|
+
export declare function parseVersionString(versionString: string): number | undefined;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export function isValidIpv4Address(ipv4Address) {
|
|
2
|
+
const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
3
|
+
return ipv4Regex.test(ipv4Address);
|
|
4
|
+
}
|
|
5
|
+
export function isValidNumber(value, min, max) {
|
|
6
|
+
if (value === undefined || value === null || typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value))
|
|
7
|
+
return false;
|
|
8
|
+
if (min !== undefined && value < min)
|
|
9
|
+
return false;
|
|
10
|
+
if (max !== undefined && value > max)
|
|
11
|
+
return false;
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
export function isValidBoolean(value) {
|
|
15
|
+
return value !== undefined && value !== null && typeof value === 'boolean';
|
|
16
|
+
}
|
|
17
|
+
export function isValidString(value, minLength, maxLength) {
|
|
18
|
+
if (value === undefined || value === null || typeof value !== 'string')
|
|
19
|
+
return false;
|
|
20
|
+
if (minLength !== undefined && value.length < minLength)
|
|
21
|
+
return false;
|
|
22
|
+
if (maxLength !== undefined && value.length > maxLength)
|
|
23
|
+
return false;
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
export function isValidRegExp(value) {
|
|
27
|
+
return value !== undefined && value !== null && value instanceof RegExp;
|
|
28
|
+
}
|
|
29
|
+
export function isValidObject(value, minLength, maxLength) {
|
|
30
|
+
if (value === undefined || value === null || typeof value !== 'object' || Array.isArray(value))
|
|
31
|
+
return false;
|
|
32
|
+
const keys = Object.keys(value);
|
|
33
|
+
if (minLength !== undefined && keys.length < minLength)
|
|
34
|
+
return false;
|
|
35
|
+
if (maxLength !== undefined && keys.length > maxLength)
|
|
36
|
+
return false;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
export function isValidArray(value, minLength, maxLength) {
|
|
40
|
+
if (value === undefined || value === null || !Array.isArray(value))
|
|
41
|
+
return false;
|
|
42
|
+
if (minLength !== undefined && value.length < minLength)
|
|
43
|
+
return false;
|
|
44
|
+
if (maxLength !== undefined && value.length > maxLength)
|
|
45
|
+
return false;
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
export function isValidNull(value) {
|
|
49
|
+
return value === null;
|
|
50
|
+
}
|
|
51
|
+
export function isValidUndefined(value) {
|
|
52
|
+
return value === undefined;
|
|
53
|
+
}
|
|
54
|
+
export function parseVersionString(versionString) {
|
|
55
|
+
if (!isValidString(versionString))
|
|
56
|
+
return undefined;
|
|
57
|
+
versionString = versionString.trim();
|
|
58
|
+
const match = versionString.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
59
|
+
if (!match)
|
|
60
|
+
return undefined;
|
|
61
|
+
const [, majorStr, minorStr, patchStr] = match;
|
|
62
|
+
const major = parseInt(majorStr, 10);
|
|
63
|
+
const minor = parseInt(minorStr, 10);
|
|
64
|
+
const patch = parseInt(patchStr, 10);
|
|
65
|
+
if ([major, minor, patch].some((n) => !Number.isFinite(n)) || major > 99 || minor > 99 || patch > 99) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
return major * 10000 + minor * 100 + patch;
|
|
69
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function getInterfaceDetails(): {
|
|
2
|
+
interfaceName: string;
|
|
3
|
+
ipv4Address: string | undefined;
|
|
4
|
+
ipv6Address: string | undefined;
|
|
5
|
+
macAddress: string | undefined;
|
|
6
|
+
} | undefined;
|
|
7
|
+
export declare function getInterfaceName(): string | undefined;
|
|
8
|
+
export declare function getIpv4InterfaceAddress(): string | undefined;
|
|
9
|
+
export declare function getIpv6InterfaceAddress(scope?: boolean): string | undefined;
|
|
10
|
+
export declare function getMacAddress(): string | undefined;
|
|
11
|
+
export declare function logInterfaces(): void;
|
|
12
|
+
export declare function resolveHostname(hostname: string, family?: 0 | 4 | 6): Promise<string | null>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import { AnsiLogger, BLUE, CYAN, nf } from 'node-ansi-logger';
|
|
3
|
+
export function getInterfaceDetails() {
|
|
4
|
+
const result = {
|
|
5
|
+
interfaceName: '',
|
|
6
|
+
ipv4Address: undefined,
|
|
7
|
+
ipv6Address: undefined,
|
|
8
|
+
macAddress: undefined,
|
|
9
|
+
};
|
|
10
|
+
for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
|
|
11
|
+
if (!interfaceName || !interfaceDetails || interfaceDetails.length === 0)
|
|
12
|
+
continue;
|
|
13
|
+
for (const detail of interfaceDetails) {
|
|
14
|
+
if (detail.internal)
|
|
15
|
+
continue;
|
|
16
|
+
if (!result.interfaceName)
|
|
17
|
+
result.interfaceName = interfaceName;
|
|
18
|
+
if (interfaceName === result.interfaceName && !result.ipv4Address && detail.family === 'IPv4')
|
|
19
|
+
result.ipv4Address = detail.address;
|
|
20
|
+
if (interfaceName === result.interfaceName && !result.ipv6Address && detail.family === 'IPv6')
|
|
21
|
+
result.ipv6Address = detail.address;
|
|
22
|
+
if (interfaceName === result.interfaceName && !result.macAddress)
|
|
23
|
+
result.macAddress = detail.mac;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (result.interfaceName)
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
export function getInterfaceName() {
|
|
30
|
+
for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
|
|
31
|
+
if (!interfaceName || !interfaceDetails || interfaceDetails.length === 0)
|
|
32
|
+
continue;
|
|
33
|
+
for (const detail of interfaceDetails) {
|
|
34
|
+
if (!detail.internal)
|
|
35
|
+
return interfaceName;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function getIpv4InterfaceAddress() {
|
|
40
|
+
for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
|
|
41
|
+
if (!interfaceName || !interfaceDetails || interfaceDetails.length === 0)
|
|
42
|
+
continue;
|
|
43
|
+
for (const detail of interfaceDetails) {
|
|
44
|
+
if (detail.family === 'IPv4' && !detail.internal)
|
|
45
|
+
return detail.address;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function getIpv6InterfaceAddress(scope = false) {
|
|
50
|
+
for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
|
|
51
|
+
if (!interfaceName || !interfaceDetails || interfaceDetails.length === 0)
|
|
52
|
+
continue;
|
|
53
|
+
for (const detail of interfaceDetails) {
|
|
54
|
+
if (detail.family === 'IPv6' && !detail.internal) {
|
|
55
|
+
const address = detail.address;
|
|
56
|
+
if (!scope)
|
|
57
|
+
return address;
|
|
58
|
+
if (address.includes('%'))
|
|
59
|
+
return address;
|
|
60
|
+
const isWindows = os.platform() === 'win32';
|
|
61
|
+
const zoneId = isWindows ? detail.scopeid : interfaceName;
|
|
62
|
+
if (zoneId !== undefined && zoneId !== null && `${zoneId}`.length > 0) {
|
|
63
|
+
return `${address}%${zoneId}`;
|
|
64
|
+
}
|
|
65
|
+
return address;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function getMacAddress() {
|
|
71
|
+
for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
|
|
72
|
+
if (!interfaceName || !interfaceDetails || interfaceDetails.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
for (const detail of interfaceDetails) {
|
|
75
|
+
if (!detail.internal)
|
|
76
|
+
return detail.mac;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export function logInterfaces() {
|
|
81
|
+
const log = new AnsiLogger({ logName: 'MatterbridgeUtils', logTimestampFormat: 4, logLevel: "info" });
|
|
82
|
+
log.logLevel = "info";
|
|
83
|
+
log.logName = 'LogInterfaces';
|
|
84
|
+
log.info('Available Network Interfaces:');
|
|
85
|
+
const availableAddresses = Object.entries(os.networkInterfaces());
|
|
86
|
+
for (const [ifaceName, ifaces] of availableAddresses) {
|
|
87
|
+
if (ifaces && ifaces.length > 0) {
|
|
88
|
+
log.info(`Network interface ${BLUE}${ifaceName}${nf}:`);
|
|
89
|
+
ifaces.forEach((iface) => {
|
|
90
|
+
log.info(`- ${CYAN}${iface.family}${nf} address ${CYAN}${iface.address}${nf} netmask ${CYAN}${iface.netmask}${nf} mac ${CYAN}${iface.mac}${nf}` +
|
|
91
|
+
`${iface.scopeid ? ` scopeid ${CYAN}${iface.scopeid}${nf}` : ''}${iface.cidr ? ` cidr ${CYAN}${iface.cidr}${nf}` : ''} ${CYAN}${iface.internal ? 'internal' : 'external'}${nf}`);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export async function resolveHostname(hostname, family = 4) {
|
|
97
|
+
const dns = await import('node:dns');
|
|
98
|
+
try {
|
|
99
|
+
const addresses = await dns.promises.lookup(hostname.toLowerCase(), { family });
|
|
100
|
+
return addresses.address;
|
|
101
|
+
}
|
|
102
|
+
catch (_error) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getGlobalNodeModules(): Promise<string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export async function getGlobalNodeModules() {
|
|
2
|
+
const { exec } = await import('node:child_process');
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
exec('npm root -g', (error, stdout) => {
|
|
5
|
+
if (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
resolve(stdout.trim());
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getNpmPackageVersion(packageName: string, tag?: string, timeout?: number): Promise<string>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export async function getNpmPackageVersion(packageName, tag = 'latest', timeout = 10000) {
|
|
2
|
+
const https = await import('node:https');
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const url = `https://registry.npmjs.org/${packageName}`;
|
|
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
|
+
const version = jsonData['dist-tags']?.[tag];
|
|
26
|
+
if (version) {
|
|
27
|
+
resolve(version);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
reject(new Error(`Tag "${tag}" not found for package "${packageName}"`));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
reject(new Error(`Failed to parse response JSON: ${error instanceof Error ? error.message : error}`));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
req.on('error', (error) => {
|
|
39
|
+
clearTimeout(timeoutId);
|
|
40
|
+
reject(new Error(`Request failed: ${error instanceof Error ? error.message : error}`));
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
|
+
export type TrackerSnapshot = {
|
|
3
|
+
timestamp: number;
|
|
4
|
+
freeMemory: number;
|
|
5
|
+
peakFreeMemory: number;
|
|
6
|
+
totalMemory: number;
|
|
7
|
+
peakTotalMemory: number;
|
|
8
|
+
osCpu: number;
|
|
9
|
+
peakOsCpu: number;
|
|
10
|
+
processCpu: number;
|
|
11
|
+
peakProcessCpu: number;
|
|
12
|
+
rss: number;
|
|
13
|
+
peakRss: number;
|
|
14
|
+
heapUsed: number;
|
|
15
|
+
peakHeapUsed: number;
|
|
16
|
+
heapTotal: number;
|
|
17
|
+
peakHeapTotal: number;
|
|
18
|
+
external: number;
|
|
19
|
+
peakExternal: number;
|
|
20
|
+
arrayBuffers: number;
|
|
21
|
+
peakArrayBuffers: number;
|
|
22
|
+
};
|
|
23
|
+
interface TrackerEvents {
|
|
24
|
+
start: [];
|
|
25
|
+
stop: [];
|
|
26
|
+
uptime: [os: number, process: number];
|
|
27
|
+
cpu: [os: number, process: number];
|
|
28
|
+
memory: [free: number, total: number, rss: number, heapUsed: number, heapTotal: number, external: number, arrayBuffers: number];
|
|
29
|
+
snapshot: [snapshot: TrackerSnapshot];
|
|
30
|
+
reset_peaks: [];
|
|
31
|
+
reset_peaks_done: [];
|
|
32
|
+
gc: [];
|
|
33
|
+
gc_done: [type: 'major' | 'minor', execution: 'sync' | 'async'];
|
|
34
|
+
}
|
|
35
|
+
export declare class Tracker extends EventEmitter<TrackerEvents> {
|
|
36
|
+
private readonly name;
|
|
37
|
+
private readonly debug;
|
|
38
|
+
private readonly verbose;
|
|
39
|
+
private trackerInterval?;
|
|
40
|
+
static historyIndex: number;
|
|
41
|
+
static readonly historySize = 2880;
|
|
42
|
+
static readonly history: TrackerSnapshot[];
|
|
43
|
+
private prevCpus;
|
|
44
|
+
private prevCpuUsage;
|
|
45
|
+
private log;
|
|
46
|
+
constructor(name?: string, debug?: boolean, verbose?: boolean);
|
|
47
|
+
start(sampleIntervalMs?: number): void;
|
|
48
|
+
resetPeaks(): void;
|
|
49
|
+
runGarbageCollector(type?: 'major' | 'minor', execution?: 'sync' | 'async'): void;
|
|
50
|
+
stop(): void;
|
|
51
|
+
}
|
|
52
|
+
export {};
|