create-palladium
Version:
A modern CLI tool to create Vite + React + TypeScript projects with various configurations
117 lines (116 loc) • 4.62 kB
JavaScript
import fs from "fs-extra";
import path from "path";
import { fileURLToPath } from "url";
import { logger } from "../utils/logger.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export class TemplateManager {
constructor(targetDir, answers) {
Object.defineProperty(this, "templatesDir", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
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.templatesDir = path.resolve(__dirname, "../../src/templates/base");
this.targetDir = targetDir;
this.answers = answers;
}
async copyTemplate() {
logger.step("템플릿 파일 복사 중...");
// 템플릿 디렉토리 존재 확인
if (!await fs.pathExists(this.templatesDir)) {
throw new Error(`템플릿 디렉토리를 찾을 수 없습니다: ${this.templatesDir}`);
}
// 기본 파일 목록
const filesToCopy = [
"postcss.config.js",
"tailwind.config.js",
"vite.config.ts",
"index.html",
"package.json",
"tsconfig.json",
"tsconfig.node.json",
".prettierrc",
".eslintrc.cjs"
];
// 루트 파일 복사
for (const file of filesToCopy) {
const srcPath = path.join(this.templatesDir, file);
if (await fs.pathExists(srcPath)) {
await fs.copy(srcPath, path.join(this.targetDir, file));
}
}
// src 폴더 복사
await fs.copy(path.join(this.templatesDir, "src"), path.join(this.targetDir, "src"));
// public 폴더 복사 (존재하는 경우)
if (await fs.pathExists(path.join(this.templatesDir, "public"))) {
await fs.copy(path.join(this.templatesDir, "public"), path.join(this.targetDir, "public"));
}
logger.success("템플릿 파일 복사 완료");
}
async processConditionals() {
logger.step("조건부 파일 처리 중...");
const conditionals = [
{
file: "src/router.tsx",
condition: (answers) => !answers.useRouter,
action: "remove"
},
{
file: "tailwind.config.js",
condition: (answers) => answers.cssFramework !== "Tailwind CSS",
action: "remove"
},
{
file: "src/main.tsx",
condition: (answers) => !answers.useRouter,
action: "modify",
modifier: (content) => {
return content
.replace(/import.*router.*\n/g, "")
.replace(/<RouterProvider.*\/>/g, "<App />");
}
}
];
for (const conditional of conditionals) {
if (conditional.condition(this.answers)) {
const filePath = path.join(this.targetDir, conditional.file);
if (conditional.action === "remove") {
if (await fs.pathExists(filePath)) {
await fs.remove(filePath);
logger.info(`제거됨: ${conditional.file}`);
}
}
else if (conditional.action === "modify" && conditional.modifier) {
if (await fs.pathExists(filePath)) {
const content = await fs.readFile(filePath, "utf-8");
const modifiedContent = conditional.modifier(content, this.answers);
await fs.writeFile(filePath, modifiedContent);
logger.info(`수정됨: ${conditional.file}`);
}
}
}
}
logger.success("조건부 파일 처리 완료");
}
async validateTargetDirectory() {
// 디렉토리가 비어있는지 확인
const files = await fs.readdir(this.targetDir);
if (files.length > 0) {
throw new Error(`디렉토리 '${path.basename(this.targetDir)}'가 비어있지 않습니다. 다른 이름을 사용하거나 디렉토리를 비워주세요.`);
}
}
}