@stoar/cli
Version:
CLI tool for STOAR - decentralized file storage on Arweave
188 lines • 7.09 kB
JavaScript
import { Command } from 'commander';
import { execSync } from 'node:child_process';
import { readFileSync, existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import chalk from 'chalk';
import ora from 'ora';
import updateNotifier from 'update-notifier';
import { output, success } from '../utils/output.js';
import { wrapCommand } from '../utils/error.js';
import { compareVersions } from '../utils/version.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export const updateCommand = new Command('update')
.description('Update STOAR CLI to the latest version')
.option('--check', 'Only check for updates without installing')
.option('--force', 'Force update even if already on latest version')
.action(wrapCommand(async (options) => {
const spinner = ora('Checking for updates...').start();
try {
// Always clear cache for update command to ensure fresh results
try {
// Clear update-notifier cache for @stoar/cli package
const cacheDir = join(process.env.HOME || process.env.USERPROFILE || '', '.config', 'update-notifier');
const cacheFiles = ['@stoar-cli.json', 'stoar-cli.json', '@stoar_cli.json'];
for (const cacheFile of cacheFiles) {
const cachePath = join(cacheDir, cacheFile);
if (existsSync(cachePath)) {
const { unlinkSync } = await import('node:fs');
unlinkSync(cachePath);
}
}
}
catch {
// Ignore cache clear errors
}
// Get current version
const packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
const currentVersion = packageJson.version;
// Force fresh check from npm registry
let latestVersion;
let hasUpdate = false;
try {
// Get latest version from npm registry directly
const npmInfo = execSync('npm view @stoar/cli version', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe']
}).trim();
latestVersion = npmInfo;
hasUpdate = compareVersions(currentVersion, latestVersion) < 0;
// Also try update-notifier as fallback
const notifier = updateNotifier({
pkg: packageJson,
updateCheckInterval: 0 // Force check now
});
await notifier.fetchInfo();
// Use update-notifier result if npm view failed
if (!latestVersion && notifier.update) {
latestVersion = notifier.update.latest;
hasUpdate = true;
}
}
catch (error) {
// Fallback to current version if check fails
latestVersion = currentVersion;
hasUpdate = false;
}
spinner.stop();
if (options.check) {
// Just check, don't update
const result = {
current: currentVersion,
latest: latestVersion,
updateAvailable: hasUpdate
};
if (options.json || process.argv.includes('--json')) {
output(result);
}
else {
if (hasUpdate) {
console.log(chalk.yellow(`\nUpdate available: ${currentVersion} → ${latestVersion}`));
console.log(chalk.gray('Run `stoar update` to install the latest version'));
}
else {
success('You are on the latest version!');
}
}
return;
}
// Perform update
if (!hasUpdate && !options.force) {
success(`Already on the latest version (${currentVersion})`);
return;
}
const updateSpinner = ora(`Updating to version ${latestVersion}...`).start();
try {
// Detect package manager
const isGloballyInstalled = checkIfGloballyInstalled();
const packageManager = detectPackageManager();
let updateCmd;
if (isGloballyInstalled) {
switch (packageManager) {
case 'bun':
updateCmd = 'bun add -g @stoar/cli@latest';
break;
case 'yarn':
updateCmd = 'yarn global add @stoar/cli@latest';
break;
case 'pnpm':
updateCmd = 'pnpm add -g @stoar/cli@latest';
break;
default:
updateCmd = 'npm install -g @stoar/cli@latest';
}
}
else {
// Local installation
switch (packageManager) {
case 'bun':
updateCmd = 'bun add @stoar/cli@latest';
break;
case 'yarn':
updateCmd = 'yarn add @stoar/cli@latest';
break;
case 'pnpm':
updateCmd = 'pnpm add @stoar/cli@latest';
break;
default:
updateCmd = 'npm install @stoar/cli@latest';
}
}
updateSpinner.text = `Running: ${updateCmd}`;
execSync(updateCmd, {
encoding: 'utf-8',
stdio: 'inherit'
});
updateSpinner.stop();
success(`Successfully updated to version ${latestVersion}`);
// Show changelog if available
try {
const changelogUrl = `https://github.com/stoar/cli/releases/tag/v${latestVersion}`;
console.log(chalk.gray(`\nView changelog: ${changelogUrl}`));
}
catch { }
}
catch (error) {
updateSpinner.stop();
throw new Error(`Failed to update: ${error.message}`);
}
}
catch (error) {
spinner.stop();
throw error;
}
}));
function checkIfGloballyInstalled() {
try {
const npmList = execSync('npm list -g @stoar/cli', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe']
});
return npmList.includes('@stoar/cli');
}
catch {
return false;
}
}
function detectPackageManager() {
// Check for lock files
try {
const cwd = process.cwd();
if (existsSync(join(cwd, 'bun.lockb')))
return 'bun';
if (existsSync(join(cwd, 'yarn.lock')))
return 'yarn';
if (existsSync(join(cwd, 'pnpm-lock.yaml')))
return 'pnpm';
// Check if running via bun
if (process.versions.bun)
return 'bun';
// Default to npm
return 'npm';
}
catch {
return 'npm';
}
}
//# sourceMappingURL=update.js.map