UNPKG

muggleout

Version:

Transform muggles into terminal wizards / 비개발자를 터미널 마법사로 만들어주는 도구

207 lines (177 loc) 6.39 kB
import { execSync } from 'child_process'; import { createRequire } from 'module'; import chalk from 'chalk'; import boxen from 'boxen'; import semver from 'semver'; import { getConfig, saveConfig } from './config.js'; import { createSpinner, isCI } from './ci-helper.js'; // npm 레지스트리에서 최신 버전 확인 async function getLatestVersion(packageName) { try { const { runCommand } = await import('./runner.js'); const { stdout } = await runCommand(`npm view ${packageName} version`, { silent: true }); return stdout.trim(); } catch (error) { console.debug('Failed to check latest version:', error); return null; } } // 현재 설치된 버전 가져오기 function getCurrentVersion() { // 먼저 환경변수 확인 (muggleout.js에서 설정) if (process.env.MUGGLEOUT_VERSION) { return process.env.MUGGLEOUT_VERSION; } try { // createRequire를 사용하여 package.json 로드 const require = createRequire(import.meta.url); const pkg = require('../../package.json'); return pkg.version; } catch (error) { console.debug('Failed to read local package.json:', error.message); // 글로벌 설치된 경우 간단한 방법으로 확인 try { const output = execSync('npm list -g muggleout --depth=0', { encoding: 'utf8' }); // muggleout@1.1.0 형태에서 버전 추출 const match = output.match(/muggleout@(\d+\.\d+\.\d+)/); if (match && match[1]) { return match[1]; } } catch (npmError) { console.debug('Failed to get version from npm list:', npmError.message); } return '1.0.0'; // fallback } } // 업데이트 확인 (하루에 한 번만) export async function checkForUpdates(options = {}) { const config = await getConfig(); const now = Date.now(); // 강제 체크가 아니면 마지막 체크 시간 확인 if (!options.force) { const lastCheck = config.lastUpdateCheck || 0; const oneDayInMs = 24 * 60 * 60 * 1000; if (now - lastCheck < oneDayInMs) { return null; // 아직 체크할 시간이 아님 } } // 업데이트 체크 비활성화 상태 확인 if (config.disableUpdateCheck && !options.force) { return null; } try { const currentVersion = getCurrentVersion(); const latestVersion = await getLatestVersion('muggleout'); // 마지막 체크 시간 업데이트 config.lastUpdateCheck = now; await saveConfig(config); if (!latestVersion) { return null; } // 버전 비교 if (semver.gt(latestVersion, currentVersion)) { return { current: currentVersion, latest: latestVersion, needsUpdate: true }; } return { current: currentVersion, latest: latestVersion, needsUpdate: false }; } catch (error) { console.debug('Update check failed:', error); return null; } } // 업데이트 알림 표시 export function showUpdateNotification(updateInfo) { if (!updateInfo || !updateInfo.needsUpdate) { return; } const message = chalk.bold(`🎉 새 버전이 출시되었습니다!\n\n`) + chalk.yellow(`현재 버전: ${updateInfo.current}\n`) + chalk.green(`최신 버전: ${updateInfo.latest}\n\n`) + chalk.cyan(`업데이트 방법:\n`) + chalk.gray(` npm update -g muggleout\n`) + chalk.gray(` 또는\n`) + chalk.gray(` npm install -g muggleout@latest`); console.log(boxen(message, { padding: 1, margin: 1, borderStyle: 'round', borderColor: 'green', title: '✨ 업데이트 알림', titleAlignment: 'center' })); } // 자동 업데이트 실행 export async function performUpdate() { console.log(chalk.blue('\n📦 업데이트를 시작합니다...\n')); try { const spinner = await createSpinner('muggleout 최신 버전 설치 중...'); spinner.start(); // npm을 통한 글로벌 업데이트 execSync('npm install -g muggleout@latest', { stdio: 'pipe' }); spinner.succeed('업데이트 완료!'); const newVersion = await getLatestVersion('muggleout'); console.log(chalk.green(`\n✅ muggleout이 ${newVersion} 버전으로 업데이트되었습니다!`)); console.log(chalk.yellow('\n💡 터미널을 재시작하면 새 버전이 적용됩니다.\n')); return true; } catch (error) { console.error(chalk.red('\n❌ 업데이트 실패:'), error.message); console.log(chalk.yellow('\n수동으로 업데이트해주세요:')); console.log(chalk.gray(' npm install -g muggleout@latest\n')); return false; } } // 업데이트 체크 비활성화 export async function disableUpdateCheck() { const config = await getConfig(); config.disableUpdateCheck = true; await saveConfig(config); console.log(chalk.gray('자동 업데이트 체크가 비활성화되었습니다.')); } // 업데이트 체크 활성화 export async function enableUpdateCheck() { const config = await getConfig(); config.disableUpdateCheck = false; await saveConfig(config); console.log(chalk.green('자동 업데이트 체크가 활성화되었습니다.')); } // 사용자에게 업데이트 여부 묻기 export async function promptForUpdate(updateInfo) { if (!updateInfo || !updateInfo.needsUpdate) { return; } const { default: inquirer } = await import('inquirer'); const { shouldUpdate } = await inquirer.prompt([{ type: 'confirm', name: 'shouldUpdate', message: `새 버전 ${updateInfo.latest}이(가) 있습니다. 지금 업데이트하시겠습니까?`, default: true }]); if (shouldUpdate) { await performUpdate(); } else { console.log(chalk.gray('\n나중에 업데이트하려면 다음 명령어를 사용하세요:')); console.log(chalk.cyan(' muggleout update\n')); } } // 시작 시 자동 체크 (백그라운드) export async function checkUpdateOnStart() { // 백그라운드에서 실행 setTimeout(async () => { try { const updateInfo = await checkForUpdates(); if (updateInfo && updateInfo.needsUpdate) { showUpdateNotification(updateInfo); } } catch (error) { // 업데이트 체크 실패는 조용히 처리 console.debug('Update check failed:', error); } }, 1000); // 1초 후 체크 (메인 작업에 방해되지 않도록) }