create-palladium
Version:
A modern CLI tool to create Vite + React + TypeScript projects with various configurations
116 lines (115 loc) • 4.45 kB
JavaScript
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("개발 서버 시작 실패 (수동으로 실행해주세요)");
}
}
}