UNPKG

create-palladium

Version:

A modern CLI tool to create Vite + React + TypeScript projects with various configurations

116 lines (115 loc) 4.45 kB
import fs from "fs-extra"; import path from "path"; import { logger } from "../utils/logger.js"; export class PackageManager { constructor(targetDir, answers) { Object.defineProperty(this, "targetDir", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "answers", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.targetDir = targetDir; this.answers = answers; } async customizePackageJson() { logger.step("package.json 커스터마이징 중..."); const pkgPath = path.resolve(this.targetDir, "package.json"); if (!await fs.pathExists(pkgPath)) { throw new Error("package.json 파일을 찾을 수 없습니다."); } let pkg; try { pkg = await fs.readJson(pkgPath); } catch (error) { throw new Error(`package.json 파싱 실패: ${error instanceof Error ? error.message : 'Unknown error'}`); } // 프로젝트 이름 업데이트 pkg.name = this.answers.projectName; // 기본 의존성 초기화 pkg.dependencies = pkg.dependencies || {}; pkg.devDependencies = pkg.devDependencies || {}; // React Router DOM if (this.answers.useRouter) { pkg.dependencies["react-router-dom"] = "^6.20.0"; } // React Query if (this.answers.useReactQuery) { pkg.dependencies["@tanstack/react-query"] = "^5.8.0"; } // 상태 관리 라이브러리 if (this.answers.stateLibrary === "zustand") { pkg.dependencies["zustand"] = "^4.4.6"; } else if (this.answers.stateLibrary === "redux") { pkg.dependencies["@reduxjs/toolkit"] = "^1.9.7"; pkg.dependencies["react-redux"] = "^8.1.3"; } // CSS 프레임워크 if (this.answers.cssFramework === "Tailwind CSS") { pkg.devDependencies["tailwindcss"] = "^3.3.6"; pkg.devDependencies["postcss"] = "^8.4.32"; pkg.devDependencies["autoprefixer"] = "^10.4.16"; } else if (this.answers.cssFramework === "Styled Components") { pkg.dependencies["styled-components"] = "^6.1.1"; pkg.devDependencies["@types/styled-components"] = "^5.1.34"; } // 유틸리티 if (this.answers.utils.includes("clsx")) { pkg.dependencies["clsx"] = "^2.0.0"; } if (this.answers.utils.includes("eslint + prettier")) { pkg.devDependencies["eslint"] = "^8.54.0"; pkg.devDependencies["prettier"] = "^3.1.0"; pkg.devDependencies["@typescript-eslint/eslint-plugin"] = "^6.12.0"; pkg.devDependencies["@typescript-eslint/parser"] = "^6.12.0"; pkg.devDependencies["eslint-plugin-react"] = "^7.33.2"; pkg.devDependencies["eslint-config-prettier"] = "^9.0.0"; } try { await fs.writeJson(pkgPath, pkg, { spaces: 2 }); logger.success("package.json 커스터마이징 완료"); } catch (error) { throw new Error(`package.json 작성 실패: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async installDependencies() { logger.step("의존성 설치 중..."); try { const { execa } = await import("execa"); await execa("npm", ["install"], { cwd: this.targetDir, stdio: "inherit", timeout: 300000 // 5분 타임아웃 }); logger.success("의존성 설치 완료"); } catch (error) { throw new Error(`의존성 설치 실패: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async runDevServer() { if (!this.answers.runDev) return; logger.step("개발 서버 시작 중..."); try { const { execa } = await import("execa"); await execa("npm", ["run", "dev"], { cwd: this.targetDir, stdio: "inherit" }); } catch (error) { logger.warning("개발 서버 시작 실패 (수동으로 실행해주세요)"); } } }