@matterbridge/utils 3.9.1-dev-20260614-18d1a2e → 3.9.1-dev-20260617-b1e1b99

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/README.md CHANGED
@@ -6,10 +6,12 @@
6
6
  [![Docker Pulls](https://img.shields.io/docker/pulls/luligu/matterbridge?label=docker%20pulls)](https://hub.docker.com/r/luligu/matterbridge)
7
7
  ![Node.js CI](https://github.com/Luligu/matterbridge/actions/workflows/build.yml/badge.svg)
8
8
  ![CodeQL](https://github.com/Luligu/matterbridge/actions/workflows/codeql.yml/badge.svg)
9
- [![codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
10
- [![styled with prettier](https://img.shields.io/badge/styled_with-Prettier-f8bc45.svg?logo=prettier)](https://prettier.io/)
11
- [![linted with eslint](https://img.shields.io/badge/linted_with-ES_Lint-4B32C3.svg?logo=eslint)](https://eslint.org/)
9
+ [![Codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
10
+ [![tested with Vitest](https://img.shields.io/badge/tested_with-Vitest-6E9F18.svg?logo=vitest&logoColor=white)](https://vitest.dev)
11
+ [![styled with Oxc](https://img.shields.io/badge/styled_with-Oxc-9BE4E0.svg?logo=oxc&logoColor=white)](https://oxc.rs/docs/guide/usage/formatter.html)
12
+ [![linted with Oxc](https://img.shields.io/badge/linted_with-Oxc-9BE4E0.svg?logo=oxc&logoColor=white)](https://oxc.rs/docs/guide/usage/linter.html)
12
13
  [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
14
+ [![TypeScript Native](https://img.shields.io/badge/TypeScript_Native-3178C6?logo=typescript&logoColor=white)](https://github.com/microsoft/typescript-go)
13
15
  [![ESM](https://img.shields.io/badge/ESM-Node.js-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
14
16
  [![matterbridge.io](https://img.shields.io/badge/matterbridge.io-online-brightgreen)](https://matterbridge.io)
15
17
 
@@ -87,13 +87,13 @@ export function xyColorToRgbColor(x, y, brightness = 254) {
87
87
  red = Math.round(red * 255);
88
88
  green = Math.round(green * 255);
89
89
  blue = Math.round(blue * 255);
90
- if (isNaN(red) || red < 0) {
90
+ if (Number.isNaN(red) || red < 0) {
91
91
  red = 0;
92
92
  }
93
- if (isNaN(green) || green < 0) {
93
+ if (Number.isNaN(green) || green < 0) {
94
94
  green = 0;
95
95
  }
96
- if (isNaN(blue) || blue < 0) {
96
+ if (Number.isNaN(blue) || blue < 0) {
97
97
  blue = 0;
98
98
  }
99
99
  return {
@@ -1,2 +1,2 @@
1
- import { type AnsiLogger } from 'node-ansi-logger';
1
+ import type { AnsiLogger } from 'node-ansi-logger';
2
2
  export declare function copyDirectory(srcDir: string, destDir: string, log?: AnsiLogger): Promise<boolean>;
@@ -1,4 +1,6 @@
1
1
  import { getErrorMessage } from './error.js';
2
+ import { logModuleLoaded } from './loader.js';
3
+ logModuleLoaded('CopyDirectory');
2
4
  export async function copyDirectory(srcDir, destDir, log) {
3
5
  if (srcDir === '') {
4
6
  throw new Error('Source directory must be specified.');
@@ -16,7 +18,7 @@ export async function copyDirectory(srcDir, destDir, log) {
16
18
  throw new Error('Source and destination directories must be different.');
17
19
  }
18
20
  const fs = await import('node:fs').then((mod) => mod.promises);
19
- const path = await import('node:path');
21
+ const { default: path } = await import('node:path');
20
22
  log?.debug(`copyDirectory: copying directory from ${srcDir} to ${destDir}`);
21
23
  try {
22
24
  await fs.mkdir(destDir, { recursive: true });
@@ -1,2 +1,2 @@
1
- import { type AnsiLogger } from 'node-ansi-logger';
1
+ import type { AnsiLogger } from 'node-ansi-logger';
2
2
  export declare function createDirectory(path: string, name: string, log: AnsiLogger): Promise<void>;
@@ -1,21 +1,24 @@
1
1
  import { promises as fs } from 'node:fs';
2
+ import { isErrnoException, logError } from './error.js';
3
+ import { logModuleLoaded } from './loader.js';
4
+ logModuleLoaded('CreateDirectory');
2
5
  export async function createDirectory(path, name, log) {
3
6
  try {
4
7
  await fs.access(path);
5
8
  log.debug(`Directory ${name} already exists at path: ${path}`);
6
9
  }
7
10
  catch (err) {
8
- if (err.code === 'ENOENT') {
11
+ if (isErrnoException(err) && err.code === 'ENOENT') {
9
12
  try {
10
13
  await fs.mkdir(path, { recursive: true });
11
14
  log.info(`Created ${name}: ${path}`);
12
15
  }
13
16
  catch (err) {
14
- log.error(`Error creating dir ${name} path ${path}: ${err}`);
17
+ logError(log, `Error creating dir ${name} path ${path}`, err);
15
18
  }
16
19
  }
17
20
  else {
18
- log.error(`Error accessing dir ${name} path ${path}: ${err}`);
21
+ logError(log, `Error accessing dir ${name} path ${path}`, err);
19
22
  }
20
23
  }
21
24
  }
package/dist/deepCopy.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { logModuleLoaded } from './loader.js';
2
+ logModuleLoaded('DeepCopy');
1
3
  export function deepCopy(value) {
2
4
  if (typeof value !== 'object' || value === null) {
3
5
  return value;
package/dist/deepEqual.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { logModuleLoaded } from './loader.js';
2
+ logModuleLoaded('DeepEqual');
1
3
  export function deepEqual(a, b, excludeProperties = []) {
2
4
  const debugLog = (...messages) => {
3
5
  };
@@ -1,15 +1,17 @@
1
- export function getEnumDescription(enumType, value, options = {}) {
2
- const fallback = options.fallback ?? 'Invalid';
3
- if (value === undefined || value === null)
4
- return fallback;
5
- const enumKey = getEnumKey(enumType, value);
6
- return enumKey ?? fallback;
1
+ import { logModuleLoaded } from './loader.js';
2
+ logModuleLoaded('EnumDescription');
3
+ function isNumericEnumReverseKey(key) {
4
+ return /^-?\d+$/.test(key);
7
5
  }
8
6
  function getEnumKey(enumType, value) {
9
7
  return Object.keys(enumType)
10
8
  .filter((key) => !isNumericEnumReverseKey(key))
11
9
  .find((key) => enumType[key] === value);
12
10
  }
13
- function isNumericEnumReverseKey(key) {
14
- return /^-?\d+$/.test(key);
11
+ export function getEnumDescription(enumType, value, options = {}) {
12
+ const fallback = options.fallback ?? 'Invalid';
13
+ if (value === undefined || value === null)
14
+ return fallback;
15
+ const enumKey = getEnumKey(enumType, value);
16
+ return enumKey ?? fallback;
15
17
  }
package/dist/error.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type AnsiLogger } from 'node-ansi-logger';
2
+ export declare function isErrnoException(e: unknown): e is NodeJS.ErrnoException;
2
3
  export declare function getErrorMessage(error: unknown): string;
3
4
  export declare function logError(log: AnsiLogger, message: string, error: unknown): void;
4
5
  export declare function inspectError(log: AnsiLogger, message: string, error: unknown): string;
package/dist/error.js CHANGED
@@ -1,5 +1,10 @@
1
1
  import { inspect } from 'node:util';
2
2
  import { RESET } from 'node-ansi-logger';
3
+ import { logModuleLoaded } from './loader.js';
4
+ logModuleLoaded('Error');
5
+ export function isErrnoException(e) {
6
+ return e instanceof Error && 'code' in e && typeof e.code === 'string';
7
+ }
3
8
  export function getErrorMessage(error) {
4
9
  return error instanceof Error ? error.message : String(error);
5
10
  }
package/dist/export.d.ts CHANGED
@@ -10,6 +10,7 @@ export * from './format.js';
10
10
  export * from './githubVersion.js';
11
11
  export * from './hex.js';
12
12
  export * from './inspector.js';
13
+ export * from './loader.js';
13
14
  export * from './network.js';
14
15
  export * from './npmPrefix.js';
15
16
  export * from './npmVersion.js';
package/dist/export.js CHANGED
@@ -10,6 +10,7 @@ export * from './format.js';
10
10
  export * from './githubVersion.js';
11
11
  export * from './hex.js';
12
12
  export * from './inspector.js';
13
+ export * from './loader.js';
13
14
  export * from './network.js';
14
15
  export * from './npmPrefix.js';
15
16
  export * from './npmVersion.js';
package/dist/format.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { logModuleLoaded } from './loader.js';
2
+ logModuleLoaded('Format');
1
3
  export function formatTimeStamp(timestamp) {
2
4
  return new Date(timestamp).toLocaleString();
3
5
  }
@@ -15,15 +17,15 @@ export function formatBytes(bytes, digits = 2) {
15
17
  export function formatUptime(seconds) {
16
18
  if (seconds >= 86400) {
17
19
  const days = Math.floor(seconds / 86400);
18
- return `${days} day${days !== 1 ? 's' : ''}`;
20
+ return `${days} day${days === 1 ? '' : 's'}`;
19
21
  }
20
22
  if (seconds >= 3600) {
21
23
  const hours = Math.floor(seconds / 3600);
22
- return `${hours} hour${hours !== 1 ? 's' : ''}`;
24
+ return `${hours} hour${hours === 1 ? '' : 's'}`;
23
25
  }
24
26
  if (seconds >= 60) {
25
27
  const minutes = Math.floor(seconds / 60);
26
- return `${minutes} minute${minutes !== 1 ? 's' : ''}`;
28
+ return `${minutes} minute${minutes === 1 ? '' : 's'}`;
27
29
  }
28
- return `${seconds} second${seconds !== 1 ? 's' : ''}`;
30
+ return `${seconds} second${seconds === 1 ? '' : 's'}`;
29
31
  }
package/dist/inspector.js CHANGED
@@ -1,9 +1,9 @@
1
- if (process.argv.includes('--loader'))
2
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] Inspector loaded.\u001B[40;0m');
3
1
  import EventEmitter from 'node:events';
4
2
  import { AnsiLogger, BRIGHT, CYAN, db, RESET, YELLOW } from 'node-ansi-logger';
5
3
  import { getErrorMessage } from './error.js';
4
+ import { logModuleLoaded } from './loader.js';
6
5
  import { fireAndForget } from './wait.js';
6
+ logModuleLoaded('Inspector');
7
7
  export class Inspector extends EventEmitter {
8
8
  name;
9
9
  debug;
@@ -52,7 +52,12 @@ export class Inspector extends EventEmitter {
52
52
  this.session = new Session();
53
53
  this.session.connect();
54
54
  await new Promise((resolve, reject) => {
55
- this.session?.post('HeapProfiler.startSampling', (err) => (err ? reject(err) : resolve()));
55
+ this.session?.post('HeapProfiler.startSampling', (err) => {
56
+ if (err)
57
+ reject(err);
58
+ else
59
+ resolve();
60
+ });
56
61
  });
57
62
  this.log.debug(`Started heap sampling`);
58
63
  const { getIntParameter } = await import('./commandLine.js');
@@ -60,19 +65,14 @@ export class Inspector extends EventEmitter {
60
65
  if (interval && interval >= 30000) {
61
66
  this.log.debug(`Started heap snapshot interval of ${CYAN}${interval}${db} ms`);
62
67
  clearInterval(this.snapshotInterval);
63
- this.snapshotInterval = setInterval(async () => {
64
- try {
65
- if (this.snapshotInProgress) {
66
- if (this.debug)
67
- this.log.debug(`Skip heap snapshot: previous snapshot still in progress`);
68
- return;
69
- }
70
- this.log.debug(`Run heap snapshot interval`);
71
- await this.takeHeapSnapshot();
72
- }
73
- catch (err) {
74
- this.log.error(`Error during scheduled heap snapshot: ${getErrorMessage(err)}`);
68
+ this.snapshotInterval = setInterval(() => {
69
+ if (this.snapshotInProgress) {
70
+ if (this.debug)
71
+ this.log.debug(`Skip heap snapshot: previous snapshot still in progress`);
72
+ return;
75
73
  }
74
+ this.log.debug(`Run heap snapshot interval`);
75
+ fireAndForget(this.takeHeapSnapshot(), this.log, 'Inspector snapshot interval');
76
76
  }, interval).unref();
77
77
  }
78
78
  }
@@ -89,7 +89,7 @@ export class Inspector extends EventEmitter {
89
89
  return;
90
90
  }
91
91
  const { writeFileSync } = await import('node:fs');
92
- const path = await import('node:path');
92
+ const { default: path } = await import('node:path');
93
93
  this.log.debug(`Stopping heap sampling...`);
94
94
  if (this.snapshotInterval) {
95
95
  this.log.debug(`Clearing heap snapshot interval...`);
@@ -98,7 +98,12 @@ export class Inspector extends EventEmitter {
98
98
  }
99
99
  try {
100
100
  const result = await new Promise((resolve, reject) => {
101
- this.session?.post('HeapProfiler.stopSampling', (err, result) => (err ? reject(err) : resolve(result)));
101
+ this.session?.post('HeapProfiler.stopSampling', (err, result) => {
102
+ if (err)
103
+ reject(err);
104
+ else
105
+ resolve(result);
106
+ });
102
107
  });
103
108
  const profile = JSON.stringify(result.profile);
104
109
  const safeTimestamp = new Date().toISOString().replace(/[<>:"/\\|?*]/g, '-');
@@ -127,7 +132,7 @@ export class Inspector extends EventEmitter {
127
132
  }
128
133
  this.snapshotInProgress = true;
129
134
  const { createWriteStream } = await import('node:fs');
130
- const path = await import('node:path');
135
+ const { default: path } = await import('node:path');
131
136
  const safeTimestamp = new Date().toISOString().replace(/[<>:"/\\|?*]/g, '-');
132
137
  const filename = path.join('heap_snapshots', `${safeTimestamp}.heapsnapshot`);
133
138
  this.runGarbageCollector('minor', 'async');
@@ -0,0 +1 @@
1
+ export declare function logModuleLoaded(moduleName: string, color?: string): void;
package/dist/loader.js ADDED
@@ -0,0 +1,7 @@
1
+ export function logModuleLoaded(moduleName, color = '\u001B[32m') {
2
+ if (process.argv.includes('--loader') || process.argv.includes('-loader')) {
3
+ console.log(`${color}[` +
4
+ new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) +
5
+ `] ${moduleName} loaded.\u001B[40;0m`);
6
+ }
7
+ }
package/dist/network.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import os from 'node:os';
2
2
  import { AnsiLogger, BLUE, CYAN, nf } from 'node-ansi-logger';
3
+ import { logModuleLoaded } from './loader.js';
4
+ logModuleLoaded('Network');
3
5
  export const excludedInterfaceNamePattern = /(tailscale|wireguard|openvpn|zerotier|hamachi|\bwg\d+\b|\btun\d+\b|\btap\d+\b|\butun\d+\b|docker|podman|\bveth[a-z0-9]*\b|\bbr-[a-z0-9]+\b|cni|kube|flannel|calico|virbr\d*\b|vmware|vmnet\d*\b|virtualbox|vboxnet\d*\b|teredo|isatap)/i;
4
6
  export function getInterfaceDetails() {
5
7
  const result = {
@@ -11,7 +13,7 @@ export function getInterfaceDetails() {
11
13
  for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
12
14
  if (!interfaceName || excludedInterfaceNamePattern.test(interfaceName))
13
15
  continue;
14
- for (const detail of interfaceDetails || []) {
16
+ for (const detail of interfaceDetails ?? []) {
15
17
  if (detail.internal)
16
18
  continue;
17
19
  if (!result.interfaceName)
@@ -26,32 +28,35 @@ export function getInterfaceDetails() {
26
28
  }
27
29
  if (result.interfaceName)
28
30
  return result;
31
+ return undefined;
29
32
  }
30
33
  export function getInterfaceName() {
31
34
  for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
32
35
  if (!interfaceName || excludedInterfaceNamePattern.test(interfaceName))
33
36
  continue;
34
- for (const detail of interfaceDetails || []) {
37
+ for (const detail of interfaceDetails ?? []) {
35
38
  if (!detail.internal)
36
39
  return interfaceName;
37
40
  }
38
41
  }
42
+ return undefined;
39
43
  }
40
44
  export function getIpv4InterfaceAddress() {
41
45
  for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
42
46
  if (!interfaceName || excludedInterfaceNamePattern.test(interfaceName))
43
47
  continue;
44
- for (const detail of interfaceDetails || []) {
48
+ for (const detail of interfaceDetails ?? []) {
45
49
  if (detail.family === 'IPv4' && !detail.internal)
46
50
  return detail.address;
47
51
  }
48
52
  }
53
+ return undefined;
49
54
  }
50
55
  export function getIpv6InterfaceAddress(scope = false) {
51
56
  for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
52
57
  if (!interfaceName || excludedInterfaceNamePattern.test(interfaceName))
53
58
  continue;
54
- for (const detail of interfaceDetails || []) {
59
+ for (const detail of interfaceDetails ?? []) {
55
60
  if (detail.family === 'IPv6' && !detail.internal) {
56
61
  const address = detail.address;
57
62
  if (!scope)
@@ -67,16 +72,18 @@ export function getIpv6InterfaceAddress(scope = false) {
67
72
  }
68
73
  }
69
74
  }
75
+ return undefined;
70
76
  }
71
77
  export function getMacAddress() {
72
78
  for (const [interfaceName, interfaceDetails] of Object.entries(os.networkInterfaces())) {
73
79
  if (!interfaceName || excludedInterfaceNamePattern.test(interfaceName))
74
80
  continue;
75
- for (const detail of interfaceDetails || []) {
81
+ for (const detail of interfaceDetails ?? []) {
76
82
  if (!detail.internal)
77
83
  return detail.mac;
78
84
  }
79
85
  }
86
+ return undefined;
80
87
  }
81
88
  export function logInterfaces() {
82
89
  const log = new AnsiLogger({ logName: 'MatterbridgeUtils', logTimestampFormat: 4, logLevel: "info" });
package/dist/npmPrefix.js CHANGED
@@ -1,13 +1,13 @@
1
+ import { logModuleLoaded } from './loader.js';
2
+ logModuleLoaded('NpmPrefix');
1
3
  export async function getGlobalNodeModules() {
2
4
  const { exec } = await import('node:child_process');
3
5
  return new Promise((resolve, reject) => {
4
6
  exec('npm root -g', (error, stdout) => {
5
- if (error) {
7
+ if (error)
6
8
  reject(error);
7
- }
8
- else {
9
+ else
9
10
  resolve(stdout.trim());
10
- }
11
11
  });
12
12
  });
13
13
  }
package/dist/tracker.js CHANGED
@@ -1,9 +1,9 @@
1
- if (process.argv.includes('--loader'))
2
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] Tracker loaded.\u001B[40;0m');
3
1
  import EventEmitter from 'node:events';
4
2
  import os from 'node:os';
5
3
  import { AnsiLogger, BRIGHT, CYAN, db, RED, RESET, YELLOW } from 'node-ansi-logger';
6
4
  import { formatBytes, formatPercent, formatTimeStamp } from './format.js';
5
+ import { logModuleLoaded } from './loader.js';
6
+ logModuleLoaded('Tracker');
7
7
  export class Tracker extends EventEmitter {
8
8
  name;
9
9
  debug;
package/dist/validate.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { logModuleLoaded } from './loader.js';
2
+ logModuleLoaded('Validate');
1
3
  export function isValidIpv4Address(ipv4Address) {
2
4
  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
5
  return ipv4Regex.test(ipv4Address);
package/dist/wait.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { AnsiLogger } from 'node-ansi-logger';
2
2
  import { inspectError } from './error.js';
3
+ import { logModuleLoaded } from './loader.js';
4
+ logModuleLoaded('Wait');
3
5
  export async function waiter(name, check, exitWithReject = false, resolveTimeout = 5000, resolveInterval = 500, debug = false) {
6
+ let intervalId;
4
7
  const log = new AnsiLogger({ logName: 'Waiter', logTimestampFormat: 4, logLevel: "debug" });
5
8
  if (check()) {
6
9
  if (debug)
@@ -20,7 +23,7 @@ export async function waiter(name, check, exitWithReject = false, resolveTimeout
20
23
  else
21
24
  resolve(false);
22
25
  }, resolveTimeout).unref();
23
- const intervalId = setInterval(async () => {
26
+ intervalId = setInterval(() => {
24
27
  if (check()) {
25
28
  if (debug)
26
29
  log.debug(`Waiter "${name}" finished for true condition...`);
@@ -28,7 +31,6 @@ export async function waiter(name, check, exitWithReject = false, resolveTimeout
28
31
  clearInterval(intervalId);
29
32
  resolve(true);
30
33
  }
31
- await Promise.resolve();
32
34
  }, resolveInterval).unref();
33
35
  });
34
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/utils",
3
- "version": "3.9.1-dev-20260614-18d1a2e",
3
+ "version": "3.9.1-dev-20260617-b1e1b99",
4
4
  "description": "Matterbridge utils library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -121,6 +121,10 @@
121
121
  "./color-utils": {
122
122
  "types": "./dist/colorUtils.d.ts",
123
123
  "import": "./dist/colorUtils.js"
124
+ },
125
+ "./loader": {
126
+ "types": "./dist/loader.d.ts",
127
+ "import": "./dist/loader.js"
124
128
  }
125
129
  },
126
130
  "engines": {