mb-run 0.0.5 → 1.0.0-dev-20260713-cb12854

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 CHANGED
@@ -21,6 +21,16 @@ If you like this project and find it useful, please consider giving it a star on
21
21
 
22
22
  <a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="120"></a>
23
23
 
24
+ ## [1.0.0] - Dev branch
25
+
26
+ ### Added
27
+
28
+ - [bun]: Add Bun version, install, binary, cache, and global module information to `--info`, including the related environment variable values.
29
+ - [self]: Check npm in a background worker for newer mb-run releases and log a warning when an update is available.
30
+ - [install]: Extract dependency installation and Matterbridge plugin linking into `runInstall()`.
31
+
32
+ <a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="80"></a>
33
+
24
34
  ## [0.0.5] - 2026-07-12
25
35
 
26
36
  ### Added
package/README.md CHANGED
@@ -84,7 +84,7 @@ Multiple flags can be combined. They are always executed in this fixed order reg
84
84
  | `--pack [tag] [minify]` | Full pack workflow: back up `package.json`, clean, production build, strip `devDependencies`/`scripts`, empty `node_modules`, `npm install --omit=dev`, `npm shrinkwrap`, `npm pack`, then restore everything. With an optional tag (`dev`, `edge`, `git`, `local`, `next`, `alpha`, `beta`), first bumps the version to `<baseVersion>-<tag>-<yyyymmdd>-<7charSha>`. `minify` compresses the bundle. |
85
85
  | `--publish [tag]` | Full publish workflow: back up all `package.json` files, strip `devDependencies`/`scripts` from root and workspaces, `npm publish` root and every workspace, then restore all files. With an optional tag, first bumps the version to `<baseVersion>-<tag>-<yyyymmdd>-<7charSha>`. |
86
86
  | `--esbuild [minify]` | Bundles the project with esbuild. `minify` compresses output and removes comments. |
87
- | `--info` | Prints system information: platform, hostname, memory, network interfaces, Node.js and npm versions. |
87
+ | `--info` | Prints system information: platform, hostname, memory, network interfaces, Node.js, npm, and Bun versions, plus Bun install, cache, binary, and global module locations with their related environment variables. |
88
88
  | `--dry-run` | Logs every intended action without modifying files or executing commands. |
89
89
  | `--verbose` | Prints each external command before it is executed. |
90
90
  | `--help`, `-h` | Prints usage text. |
package/dist/info.js CHANGED
@@ -1,8 +1,9 @@
1
+ import { execFileSync } from 'node:child_process';
1
2
  import { readFileSync } from 'node:fs';
2
3
  import os from 'node:os';
3
4
  import path from 'node:path';
4
5
  import process from 'node:process';
5
- import { log } from './ansi.js';
6
+ import { brightBlack, log } from './ansi.js';
6
7
  function formatBytes(bytes) {
7
8
  if (bytes >= 1024 * 1024 * 1024)
8
9
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
@@ -70,9 +71,31 @@ function getNpmVersion() {
70
71
  }
71
72
  return 'unavailable';
72
73
  }
74
+ function getBunInfo(args) {
75
+ try {
76
+ const output = execFileSync('bun', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
77
+ return output || 'unavailable';
78
+ }
79
+ catch {
80
+ return 'unavailable';
81
+ }
82
+ }
83
+ export function getBunVersion() {
84
+ return getBunInfo(['--version']);
85
+ }
86
+ function getBunGlobalModules(bunBinDir) {
87
+ if (bunBinDir === 'unavailable')
88
+ return 'unavailable';
89
+ return path.join(path.dirname(bunBinDir), 'install', 'global', 'node_modules');
90
+ }
91
+ function formatBunDirectory(directory, environmentVariable) {
92
+ return `${directory} ${brightBlack(`(${environmentVariable}=${process.env[environmentVariable] ?? 'undefined'})`)}`;
93
+ }
73
94
  export function systemInfo() {
74
95
  const total = os.totalmem();
75
96
  const used = total - os.freemem();
97
+ const bunBinDir = getBunInfo(['pm', 'bin', '-g']);
98
+ const bunInstallDir = bunBinDir === 'unavailable' ? 'unavailable' : path.dirname(bunBinDir);
76
99
  let username = 'unavailable';
77
100
  try {
78
101
  username = os.userInfo().username;
@@ -90,4 +113,9 @@ export function systemInfo() {
90
113
  log(`\u{1F310} IPv6: ${getIpv6Addresses()}`);
91
114
  log(`\u{1F7E2} Node.js: ${process.version.replace(/^v/u, '')}`);
92
115
  log(`\u{1F7E3} Npm: ${getNpmVersion()}`);
116
+ log(`\u{1F7E0} Bun: ${getBunVersion()}`);
117
+ log(`\u{1F4C1} Bun install: ${formatBunDirectory(bunInstallDir, 'BUN_INSTALL')}`);
118
+ log(`\u{1F4C2} Bun bin: ${formatBunDirectory(bunBinDir, 'BUN_INSTALL_BIN')}`);
119
+ log(`\u{1F4E6} Bun cache: ${formatBunDirectory(getBunInfo(['pm', 'cache']), 'BUN_INSTALL_CACHE_DIR')}`);
120
+ log(`\u{1F4DA} Bun modules: ${formatBunDirectory(getBunGlobalModules(bunBinDir), 'BUN_INSTALL_GLOBAL_DIR')}`);
93
121
  }
@@ -0,0 +1,8 @@
1
+ import { isPlugin } from './helpers.js';
2
+ import { runCommand } from './spawn.js';
3
+ export async function runInstall(opts) {
4
+ await runCommand('npm', ['install', '--no-fund', '--no-audit', '--silent'], { cwd: opts.rootDir, dryRun: opts.dryRun });
5
+ if (await isPlugin(opts.rootDir)) {
6
+ await runCommand('npm', ['link', 'matterbridge', '--no-fund', '--no-audit', '--silent'], { cwd: opts.rootDir, dryRun: opts.dryRun });
7
+ }
8
+ }
package/dist/module.js CHANGED
@@ -8,10 +8,12 @@ import { runFormatter } from './format.js';
8
8
  import { printPackUsage, printPublishUsage, printUsage, printVersionUsage } from './help.js';
9
9
  import { isPlugin } from './helpers.js';
10
10
  import { systemInfo } from './info.js';
11
+ import { runInstall } from './install.js';
11
12
  import { runLinter } from './lint.js';
12
13
  import { initLogger } from './logger.js';
13
14
  import { runPack } from './pack.js';
14
15
  import { runPublish } from './publish.js';
16
+ import { checkLatestVersion } from './self.js';
15
17
  import { sortAll } from './sort.js';
16
18
  import { ExitError, runCommand } from './spawn.js';
17
19
  import { runTests } from './test.js';
@@ -68,6 +70,7 @@ export async function main() {
68
70
  verbose: verboseCommands,
69
71
  rootDir: repoRoot,
70
72
  });
73
+ checkLatestVersion();
71
74
  const restorePos = (rows = 1) => (rows > 0 && shouldUseAnsi() && !dryRunMode && !verboseCommands ? moveUp(rows) : '');
72
75
  const buildOpts = { rootDir: repoRoot, isWindows, dryRun: dryRunMode, verbose: verboseCommands };
73
76
  const versionIndex = rawArgs.indexOf('--version');
@@ -223,17 +226,13 @@ export async function main() {
223
226
  }
224
227
  if (want.install) {
225
228
  log(`${savePos()}⏳ Installing...`);
226
- await runCommand('npm', ['install', '--no-fund', '--no-audit', '--silent'], { dryRun: dryRunMode });
227
- if (await isPlugin(repoRoot))
228
- await runCommand('npm', ['link', 'matterbridge', '--no-fund', '--no-audit', '--silent'], { cwd: repoRoot, dryRun: dryRunMode });
229
+ await runInstall({ rootDir: repoRoot, dryRun: dryRunMode });
229
230
  log(`${restorePos()}${green('✅')} Install complete in ${getElapsed()}.${clearEnd()}`);
230
231
  }
231
232
  if (want.update) {
232
233
  log(`${savePos()}⏳ Updating dependencies...`);
233
234
  await runUpdate(buildOpts);
234
- await runCommand('npm', ['install', '--no-fund', '--no-audit', '--silent'], { dryRun: dryRunMode });
235
- if (await isPlugin(repoRoot))
236
- await runCommand('npm', ['link', 'matterbridge', '--no-fund', '--no-audit', '--silent'], { cwd: repoRoot, dryRun: dryRunMode });
235
+ await runInstall({ rootDir: repoRoot, dryRun: dryRunMode });
237
236
  log(`${restorePos()}${green('✅')} Update complete in ${getElapsed()}.${clearEnd()}`);
238
237
  }
239
238
  if (want.upgrade) {
package/dist/self.js ADDED
@@ -0,0 +1,42 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ import { brightYellow, log } from './ansi.js';
3
+ function parseVersion(version) {
4
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/u.exec(version);
5
+ if (!match?.[1] || !match[2] || !match[3])
6
+ return undefined;
7
+ return {
8
+ major: Number(match[1]),
9
+ minor: Number(match[2]),
10
+ patch: Number(match[3]),
11
+ prerelease: version.includes('-'),
12
+ };
13
+ }
14
+ export function isNewerVersion(latestVersion, currentVersion) {
15
+ const latest = parseVersion(latestVersion);
16
+ const current = parseVersion(currentVersion);
17
+ if (!latest || !current)
18
+ return false;
19
+ const latestParts = [latest.major, latest.minor, latest.patch];
20
+ const currentParts = [current.major, current.minor, current.patch];
21
+ for (let index = 0; index < latestParts.length; index++) {
22
+ if (latestParts[index] !== currentParts[index])
23
+ return latestParts[index] > currentParts[index];
24
+ }
25
+ return current.prerelease && !latest.prerelease;
26
+ }
27
+ export function checkLatestVersion() {
28
+ try {
29
+ const worker = new Worker(new URL('./self.worker.js', import.meta.url));
30
+ worker.unref();
31
+ worker.once('message', (message) => {
32
+ if (message === null || typeof message !== 'object' || !('currentVersion' in message) || !('latestVersion' in message))
33
+ return;
34
+ if (typeof message.currentVersion !== 'string' || typeof message.latestVersion !== 'string')
35
+ return;
36
+ log(brightYellow(`⚠️ A newer mb-run version is available: ${message.currentVersion} → ${message.latestVersion}. Run npm install --global mb-run@latest to update.`));
37
+ });
38
+ worker.once('error', () => { });
39
+ }
40
+ catch {
41
+ }
42
+ }
@@ -0,0 +1,24 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { parentPort } from 'node:worker_threads';
3
+ import { isNewerVersion } from './self.js';
4
+ const packageJsonUrl = new URL('../package.json', import.meta.url);
5
+ const registryUrl = 'https://registry.npmjs.org/mb-run/latest';
6
+ export async function runSelfUpdateCheck() {
7
+ try {
8
+ const packageJson = JSON.parse(await readFile(packageJsonUrl, 'utf8'));
9
+ if (packageJson === null || typeof packageJson !== 'object' || !('version' in packageJson) || typeof packageJson.version !== 'string')
10
+ return;
11
+ const response = await fetch(registryUrl, { signal: AbortSignal.timeout(1500) });
12
+ if (!response.ok)
13
+ return;
14
+ const registryData = await response.json();
15
+ if (registryData === null || typeof registryData !== 'object' || !('version' in registryData) || typeof registryData.version !== 'string')
16
+ return;
17
+ if (isNewerVersion(registryData.version, packageJson.version)) {
18
+ parentPort?.postMessage({ currentVersion: packageJson.version, latestVersion: registryData.version });
19
+ }
20
+ }
21
+ catch {
22
+ }
23
+ }
24
+ void runSelfUpdateCheck();
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "mb-run",
3
- "version": "0.0.5",
3
+ "version": "1.0.0-dev-20260713-cb12854",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "mb-run",
9
- "version": "0.0.5",
9
+ "version": "1.0.0-dev-20260713-cb12854",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "cross-spawn": "7.0.6",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mb-run",
3
- "version": "0.0.5",
3
+ "version": "1.0.0-dev-20260713-cb12854",
4
4
  "description": "Matterbridge command line executor",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",