UNPKG

muggleout

Version:

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

72 lines (63 loc) 2.23 kB
import { execa } from 'execa'; import chalk from 'chalk'; // 명령어 실행 래퍼 export async function runCommand(command, options = {}) { const { interactive = false, silent = false, stdio } = options; // ~ 를 홈 디렉토리로 확장 const expandedCommand = command.replace(/~/g, process.env.HOME || ''); if (!silent) { console.log(chalk.gray(`$ ${command}`)); } try { if (interactive || stdio === 'inherit') { // 대화형 명령어 (사용자 입력 필요) // shell: true 제거 - bash -c와 충돌 const result = await execa('bash', ['-c', expandedCommand], { stdio: stdio || 'inherit' }); return { stdout: '', stderr: '', exitCode: result.exitCode || 0 }; } else { // 일반 명령어 - shell: true 제거하여 정확한 exit code 얻기 const result = await execa('bash', ['-c', expandedCommand]); if (result.stdout && !silent) { console.log(result.stdout); } if (result.stderr && !silent) { console.error(chalk.yellow(result.stderr)); } return { stdout: result.stdout || '', stderr: result.stderr || '', exitCode: 0 }; } } catch (error) { if (!silent) { console.error(chalk.red(`명령어 실행 실패: ${error.message}`)); } // silent 모드에서는 에러를 던지지 않고 exitCode 반환 if (silent && error.exitCode !== undefined) { return { stdout: error.stdout || '', stderr: error.stderr || '', exitCode: error.exitCode }; } throw error; } } // 명령어 존재 확인 export async function commandExists(command) { try { // which로 먼저 경로 확인 const { stdout: path } = await execa('which', [command]); // 실제로 실행 가능한지 확인 (--version 또는 --help 시도) try { await execa(command, ['--version'], { timeout: 3000 }); return true; } catch { // --version이 실패하면 --help 시도 try { await execa(command, ['--help'], { timeout: 3000 }); return true; } catch { // 둘 다 실패하면 설치되지 않은 것으로 간주 return false; } } } catch { return false; } }