125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { exec } from "child_process";
|
|
import { promisify } from "util";
|
|
import path from "path";
|
|
import fs from "fs";
|
|
|
|
const execAsync = promisify(exec);
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const { command, layoutData } = await request.json();
|
|
|
|
if (!command || !layoutData) {
|
|
return NextResponse.json({ success: false, message: "명령어와 레이아웃 데이터가 필요합니다." }, { status: 400 });
|
|
}
|
|
|
|
// 프론트엔드 디렉토리 경로
|
|
const frontendDir = path.join(process.cwd());
|
|
|
|
// CLI 명령어 실행
|
|
const fullCommand = `cd ${frontendDir} && node scripts/create-layout.js ${command}`;
|
|
|
|
console.log("실행할 명령어:", fullCommand);
|
|
|
|
const { stdout, stderr } = await execAsync(fullCommand);
|
|
|
|
if (stderr && !stderr.includes("warning")) {
|
|
console.error("CLI 실행 오류:", stderr);
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
message: "레이아웃 생성 중 오류가 발생했습니다.",
|
|
error: stderr,
|
|
},
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
|
|
// 생성된 파일들 확인
|
|
const layoutId = layoutData.name.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
const layoutDir = path.join(frontendDir, "lib/registry/layouts", layoutId);
|
|
|
|
const generatedFiles: string[] = [];
|
|
|
|
if (fs.existsSync(layoutDir)) {
|
|
const files = fs.readdirSync(layoutDir);
|
|
files.forEach((file) => {
|
|
generatedFiles.push(`layouts/${layoutId}/${file}`);
|
|
});
|
|
}
|
|
|
|
// 자동 등록을 위해 index.ts 업데이트
|
|
await updateLayoutIndex(layoutId);
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: "레이아웃이 성공적으로 생성되었습니다.",
|
|
files: generatedFiles,
|
|
output: stdout,
|
|
});
|
|
} catch (error) {
|
|
console.error("레이아웃 생성 API 오류:", error);
|
|
return NextResponse.json(
|
|
{
|
|
success: false,
|
|
message: "서버 오류가 발생했습니다.",
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
},
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* layouts/index.ts에 새 레이아웃 import 추가
|
|
*/
|
|
async function updateLayoutIndex(layoutId: string) {
|
|
try {
|
|
const indexPath = path.join(process.cwd(), "lib/registry/layouts/index.ts");
|
|
|
|
if (!fs.existsSync(indexPath)) {
|
|
console.warn("layouts/index.ts 파일을 찾을 수 없습니다.");
|
|
return;
|
|
}
|
|
|
|
let content = fs.readFileSync(indexPath, "utf8");
|
|
|
|
// 새 import 문 추가
|
|
const newImport = `import "./${layoutId}/${layoutId.charAt(0).toUpperCase() + layoutId.slice(1)}LayoutRenderer";`;
|
|
|
|
// 이미 import되어 있는지 확인
|
|
if (content.includes(newImport)) {
|
|
console.log("이미 import되어 있습니다.");
|
|
return;
|
|
}
|
|
|
|
// 다른 import 문들 찾기
|
|
const importRegex = /import "\.\/.+\/\w+LayoutRenderer";/g;
|
|
const imports = content.match(importRegex) || [];
|
|
|
|
if (imports.length > 0) {
|
|
// 마지막 import 뒤에 추가
|
|
const lastImport = imports[imports.length - 1];
|
|
const lastImportIndex = content.lastIndexOf(lastImport);
|
|
const insertPosition = lastImportIndex + lastImport.length;
|
|
|
|
content = content.slice(0, insertPosition) + "\n" + newImport + content.slice(insertPosition);
|
|
} else {
|
|
// import가 없다면 파일 시작 부분에 추가
|
|
const newStructureComment = "// 새 구조 레이아웃들 (자동 등록)";
|
|
const commentIndex = content.indexOf(newStructureComment);
|
|
|
|
if (commentIndex !== -1) {
|
|
const insertPosition = content.indexOf("\n", commentIndex) + 1;
|
|
content = content.slice(0, insertPosition) + newImport + "\n" + content.slice(insertPosition);
|
|
}
|
|
}
|
|
|
|
fs.writeFileSync(indexPath, content);
|
|
console.log(`layouts/index.ts에 ${layoutId} import 추가 완료`);
|
|
} catch (error) {
|
|
console.error("index.ts 업데이트 오류:", error);
|
|
}
|
|
}
|