From 9868437f10bb18503ae5421b83b5ba96e45dfaa3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 14 Aug 2025 23:24:37 -0400 Subject: [PATCH] Add update-check command (#423) * Add update-check command * Adding additional information to update-check command and aligning with cli theme * Correct update-check message to exclude global --- tools/installer/bin/bmad.js | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tools/installer/bin/bmad.js b/tools/installer/bin/bmad.js index ff623239..51dff138 100755 --- a/tools/installer/bin/bmad.js +++ b/tools/installer/bin/bmad.js @@ -6,13 +6,17 @@ const fs = require('fs').promises; const yaml = require('js-yaml'); const chalk = require('chalk'); const inquirer = require('inquirer'); +const semver = require('semver'); +const https = require('https'); // Handle both execution contexts (from root via npx or from installer directory) let version; let installer; +let packageName; try { // Try installer context first (when run from tools/installer/) version = require('../package.json').version; + packageName = require('../package.json').name; installer = require('../lib/installer'); } catch (e) { // Fall back to root context (when run via npx from GitHub) @@ -86,6 +90,60 @@ program } }); +// Command to check if updates are available +program + .command('update-check') + .description('Check for BMad Update') + .action(async () => { + console.log('Checking for updates...'); + + // Make HTTP request to npm registry for latest version info + const req = https.get(`https://registry.npmjs.org/${packageName}/latest`, res => { + // Check for HTTP errors (non-200 status codes) + if (res.statusCode !== 200) { + console.error(chalk.red(`Update check failed: Received status code ${res.statusCode}`)); + return; + } + + // Accumulate response data chunks + let data = ''; + res.on('data', chunk => data += chunk); + + // Process complete response + res.on('end', () => { + try { + // Parse npm registry response and extract version + const latest = JSON.parse(data).version; + + // Compare versions using semver + if (semver.gt(latest, version)) { + console.log(chalk.bold.blue(`⚠️ ${packageName} update available: ${version} → ${latest}`)); + console.log(chalk.bold.blue('\nInstall latest by running:')); + console.log(chalk.bold.magenta(` npm install ${packageName}@latest`)); + console.log(chalk.dim(' or')); + console.log(chalk.bold.magenta(` npx ${packageName}@latest`)); + } else { + console.log(chalk.bold.blue(`✨ ${packageName} is up to date`)); + } + } catch (error) { + // Handle JSON parsing errors + console.error(chalk.red('Failed to parse npm registry data:'), error.message); + } + }); + }); + + // Handle network/connection errors + req.on('error', error => { + console.error(chalk.red('Update check failed:'), error.message); + }); + + // Set 30 second timeout to prevent hanging + req.setTimeout(30000, () => { + req.destroy(); + console.error(chalk.red('Update check timed out')); + }); + }); + program .command('list:expansions') .description('List available expansion packs')