UNPKG

create-viewlogic

Version:

CLI tool to create ViewLogic Vue 3 applications with zero configuration

236 lines (197 loc) 6.89 kB
const fs = require('fs-extra'); const path = require('path'); const chalk = require('chalk'); const ora = require('ora'); const inquirer = require('inquirer'); const { execSync } = require('child_process'); /** * ViewLogic 프로젝트 초기화 (현재 디렉토리 또는 지정된 디렉토리) */ async function init(projectName, options) { const targetDir = projectName ? path.resolve(projectName) : process.cwd(); const isCurrentDir = !projectName; console.log(chalk.cyan.bold('\n🚀 ViewLogic Template 초기화\n')); // 현재 디렉토리가 비어있는지 확인 if (isCurrentDir && fs.readdirSync(targetDir).length > 0) { const { confirm } = await inquirer.prompt([ { type: 'confirm', name: 'confirm', message: '현재 디렉토리가 비어있지 않습니다. 계속하시겠습니까?', default: false } ]); if (!confirm) { console.log(chalk.yellow('취소되었습니다.')); return; } } await installTemplate(targetDir, options); } /** * 새 ViewLogic 프로젝트 생성 */ async function create(projectName, options) { const targetDir = path.resolve(projectName); console.log(chalk.cyan.bold('\n🚀 ViewLogic Template 프로젝트 생성\n')); // 디렉토리가 이미 존재하는지 확인 if (fs.existsSync(targetDir)) { const { overwrite } = await inquirer.prompt([ { type: 'confirm', name: 'overwrite', message: `${projectName} 디렉토리가 이미 존재합니다. 덮어쓰시겠습니까?`, default: false } ]); if (!overwrite) { console.log(chalk.yellow('취소되었습니다.')); return; } await fs.remove(targetDir); } // 디렉토리 생성 await fs.ensureDir(targetDir); await installTemplate(targetDir, options); } /** * 템플릿 설치 공통 로직 */ async function installTemplate(targetDir, options) { const spinner = ora('ViewLogic 템플릿 복사 중...').start(); try { // 템플릿 파일 복사 const templateDir = path.join(__dirname, '../templates'); // templates 폴더가 없으면 GitHub에서 다운로드 if (!fs.existsSync(templateDir)) { spinner.text = 'GitHub에서 ViewLogic 템플릿 다운로드 중...'; await downloadFromGitHub(templateDir); } // 파일 복사 const items = [ 'src', 'js', 'css', 'build.cjs', 'index.html', 'production.html', '.gitignore' ]; for (const item of items) { const source = path.join(templateDir, item); const target = path.join(targetDir, item); if (fs.existsSync(source)) { await fs.copy(source, target); } } // package.json 생성 및 수정 const pkgSource = path.join(templateDir, 'package.json'); const pkgTarget = path.join(targetDir, 'package.json'); let pkgJson; if (fs.existsSync(pkgSource)) { pkgJson = await fs.readJson(pkgSource); } else { // 기본 package.json 생성 pkgJson = { name: path.basename(targetDir), version: "1.0.0", description: "ViewLogic Vue3 SPA Application", main: "index.html", type: "module", scripts: { "dev": "python -m http.server 8000", "build": "node build.cjs build", "build:prod": "node build.cjs build --minify --optimize", "serve": "python -m http.server 8000" }, keywords: ["vue3", "viewlogic", "spa"], author: "", license: "MIT", devDependencies: { "esbuild": "^0.25.9" } }; } // 프로젝트 이름 설정 pkgJson.name = path.basename(targetDir); await fs.writeJson(pkgTarget, pkgJson, { spaces: 2 }); // router.js 설정 수정 const routerPath = path.join(targetDir, 'js/router.js'); if (fs.existsSync(routerPath)) { let routerContent = await fs.readFile(routerPath, 'utf8'); // 인증 설정 if (options.auth) { routerContent = routerContent.replace( 'authEnabled: options.authEnabled || false', 'authEnabled: true' ); if (options.storage) { routerContent = routerContent.replace( `authStorage: options.authStorage || 'localStorage'`, `authStorage: '${options.storage}'` ); } } // i18n 설정 if (options.i18n) { routerContent = routerContent.replace( 'useI18n: options.useI18n !== false', 'useI18n: true' ); } await fs.writeFile(routerPath, routerContent); } spinner.succeed('ViewLogic 템플릿 설치 완료!'); // npm install 실행 if (options.install !== false) { const installSpinner = ora('의존성 패키지 설치 중...').start(); try { execSync('npm install', { cwd: targetDir, stdio: 'ignore' }); installSpinner.succeed('의존성 패키지 설치 완료!'); } catch (error) { installSpinner.warn('npm install을 수동으로 실행해주세요.'); } } // 완료 메시지 console.log('\n' + chalk.green.bold('✨ ViewLogic 프로젝트가 준비되었습니다!\n')); console.log('다음 명령어로 시작하세요:\n'); const isCurrentDir = targetDir === process.cwd(); if (!isCurrentDir) { console.log(chalk.cyan(` cd ${path.relative(process.cwd(), targetDir)}`)); } if (options.install === false) { console.log(chalk.cyan(' npm install')); } console.log(chalk.cyan(' npm run build')); console.log(chalk.cyan(' npm run dev')); console.log('\n' + chalk.gray('자세한 사용법: https://github.com/hopegiver/viewlogic-template')); } catch (error) { spinner.fail('설치 실패'); console.error(chalk.red(error.message)); process.exit(1); } } /** * GitHub에서 템플릿 다운로드 (대체 방법) */ async function downloadFromGitHub(targetDir) { try { // git clone 시도 execSync( 'git clone --depth 1 https://github.com/hopegiver/viewlogic-vue.git temp_viewlogic', { stdio: 'ignore' } ); await fs.ensureDir(targetDir); await fs.copy('./temp_viewlogic', targetDir); await fs.remove('./temp_viewlogic'); } catch (error) { throw new Error('GitHub에서 템플릿을 다운로드할 수 없습니다. 인터넷 연결을 확인해주세요.'); } } module.exports = { init, create };