@re-shell/cli
Version:
Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja
254 lines (253 loc) • 11.2 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkForUpdates = checkForUpdates;
exports.runUpdateCommand = runUpdateCommand;
const https = __importStar(require("https"));
const semver = __importStar(require("semver"));
const chalk_1 = __importDefault(require("chalk"));
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const child_process_1 = require("child_process");
async function checkForUpdates(currentVersion) {
try {
// Check if we should skip the update check (e.g., in CI environments)
if (process.env.CI || process.env.RE_SHELL_SKIP_UPDATE_CHECK) {
return;
}
// Check if we've recently checked for updates (within last 24 hours)
const cacheFile = path.join(process.env.HOME || process.env.USERPROFILE || '', '.re-shell-update-check');
if (await fs.pathExists(cacheFile)) {
const lastCheck = await fs.readJson(cacheFile).catch(() => null);
if (lastCheck && Date.now() - lastCheck.timestamp < 86400000) { // 24 hours
// If there was a cached update notification, show it
if (lastCheck.hasUpdate) {
showUpdateNotification(currentVersion, lastCheck.latestVersion);
}
return;
}
}
// Fetch latest version from npm registry
const latestVersion = await fetchLatestVersion('@re-shell/cli');
if (latestVersion && semver.gt(latestVersion, currentVersion)) {
// Cache the update check result
await fs.writeJson(cacheFile, {
timestamp: Date.now(),
hasUpdate: true,
latestVersion
}).catch(() => { });
showUpdateNotification(currentVersion, latestVersion);
}
else {
// Cache that no update is needed
await fs.writeJson(cacheFile, {
timestamp: Date.now(),
hasUpdate: false,
latestVersion
}).catch(() => { });
}
}
catch (error) {
// Silently ignore update check errors to not disrupt the CLI usage
}
}
function fetchLatestVersion(packageName) {
return new Promise((resolve) => {
const options = {
hostname: 'registry.npmjs.org',
path: `/${packageName}`,
method: 'GET',
timeout: 3000 // 3 second timeout
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const packageInfo = JSON.parse(data);
resolve(packageInfo['dist-tags'].latest);
}
catch {
resolve(null);
}
});
});
req.on('error', () => resolve(null));
req.on('timeout', () => {
req.destroy();
resolve(null);
});
req.end();
});
}
function showUpdateNotification(currentVersion, latestVersion) {
console.log();
console.log(chalk_1.default.yellow('╔════════════════════════════════════════════════════════════════╗'));
console.log(chalk_1.default.yellow('║') + ' ' + chalk_1.default.yellow('║'));
console.log(chalk_1.default.yellow('║') + chalk_1.default.bold.white(' Update available! ') + chalk_1.default.gray(`${currentVersion} → `) + chalk_1.default.green.bold(latestVersion) + ' ' + chalk_1.default.yellow('║'));
console.log(chalk_1.default.yellow('║') + ' ' + chalk_1.default.yellow('║'));
console.log(chalk_1.default.yellow('║') + ' Run ' + chalk_1.default.cyan.bold('npm install -g @re-shell/cli@latest') + ' to update ' + chalk_1.default.yellow('║'));
console.log(chalk_1.default.yellow('║') + ' ' + chalk_1.default.yellow('║'));
console.log(chalk_1.default.yellow('║') + chalk_1.default.gray(' Changelog: https://github.com/Re-Shell/cli/releases') + ' ' + chalk_1.default.yellow('║'));
console.log(chalk_1.default.yellow('║') + ' ' + chalk_1.default.yellow('║'));
console.log(chalk_1.default.yellow('╚════════════════════════════════════════════════════════════════╝'));
console.log();
// Force flush output
process.stdout.write('');
process.stderr.write('');
}
async function runUpdateCommand() {
const { createSpinner, flushOutput } = await Promise.resolve().then(() => __importStar(require('./spinner')));
const prompts = await Promise.resolve().then(() => __importStar(require('prompts')));
const spinner = createSpinner('Checking for updates...').start();
flushOutput();
try {
const packageJsonPath = path.resolve(__dirname, '../../package.json');
const packageJson = await fs.readJson(packageJsonPath);
const currentVersion = packageJson.version;
const latestVersion = await fetchLatestVersion('@re-shell/cli');
if (!latestVersion) {
spinner.fail(chalk_1.default.red('Unable to check for updates. Please check your internet connection.'));
return;
}
if (semver.gt(latestVersion, currentVersion)) {
spinner.succeed(chalk_1.default.green(`Update available: ${currentVersion} → ${latestVersion}`));
console.log();
// Ask user if they want to update automatically
const response = await prompts.default({
type: 'confirm',
name: 'shouldUpdate',
message: `Do you want to update to version ${latestVersion} now?`,
initial: true
});
if (response.shouldUpdate) {
// Detect package manager
const packageManager = detectPackageManager();
const updateSpinner = createSpinner(`Updating @re-shell/cli using ${packageManager}...`).start();
try {
await performUpdate(packageManager);
updateSpinner.succeed(chalk_1.default.green(`Successfully updated to @re-shell/cli@${latestVersion}!`));
console.log();
console.log(chalk_1.default.green('🎉 Update completed! You can now use the latest features.'));
}
catch (error) {
updateSpinner.fail(chalk_1.default.red('Update failed'));
console.log();
console.log(chalk_1.default.yellow('Please update manually using one of these commands:'));
console.log(chalk_1.default.bold(' npm install -g @re-shell/cli@latest'));
console.log(' yarn global add @re-shell/cli@latest');
console.log(' pnpm add -g @re-shell/cli@latest');
}
}
else {
console.log();
console.log(chalk_1.default.yellow('Update skipped. To update later, run:'));
console.log(chalk_1.default.bold(' re-shell update'));
}
}
else {
spinner.succeed(chalk_1.default.green(`You're using the latest version (${currentVersion})`));
}
}
catch (error) {
spinner.fail(chalk_1.default.red('Error checking for updates'));
console.error(error);
}
}
function detectPackageManager() {
// Try to detect which package manager was used to install re-shell
const execPath = process.env._ || '';
if (execPath.includes('pnpm'))
return 'pnpm';
if (execPath.includes('yarn'))
return 'yarn';
// Check if pnpm is available
try {
require('child_process').execSync('pnpm --version', { stdio: 'ignore' });
return 'pnpm';
}
catch {
// pnpm not available
}
// Check if yarn is available
try {
require('child_process').execSync('yarn --version', { stdio: 'ignore' });
return 'yarn';
}
catch {
// yarn not available
}
// Default to npm
return 'npm';
}
function performUpdate(packageManager) {
return new Promise((resolve, reject) => {
let command;
let args;
switch (packageManager) {
case 'pnpm':
command = 'pnpm';
args = ['add', '-g', '@re-shell/cli@latest'];
break;
case 'yarn':
command = 'yarn';
args = ['global', 'add', '@re-shell/cli@latest'];
break;
default:
command = 'npm';
args = ['install', '-g', '@re-shell/cli@latest'];
}
const child = (0, child_process_1.spawn)(command, args, {
stdio: 'pipe',
shell: true
});
child.on('close', (code) => {
if (code === 0) {
resolve();
}
else {
reject(new Error(`Update process exited with code ${code}`));
}
});
child.on('error', (error) => {
reject(error);
});
});
}