ERP-node/frontend/app/api/admin/layouts/generate/route.ts

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);
}
}