create-pro-fiori-app-cli
Version:
SAPUI5/Fiori projeleri için akıllı proje oluşturucu ve yönetici. Kod üretimi, deployment ve kalite kontrol otomasyonu sağlar.
195 lines (176 loc) • 6.75 kB
JavaScript
#!/usr/bin/env node
const inquirer = require("inquirer");
const path = require("path");
const fs = require("fs-extra");
const ejs = require("ejs");
const chalk = require("chalk");
const ora = require("ora");
const execa = require("execa");
const commandExists = require("command-exists");
async function checkPrerequisites() {
// Bu fonksiyon doğru, değişiklik yok.
const gitExists = await commandExists("git").catch(() => false);
const npmExists = await commandExists("npm").catch(() => false);
if (!gitExists) {
console.error(
chalk.red.bold(
"Hata: Git sisteminizde kurulu değil. Lütfen önce Git kurun."
)
);
process.exit(1);
}
if (!npmExists) {
console.error(
chalk.red.bold(
"Hata: NPM sisteminizde kurulu değil. Lütfen önce Node.js ve NPM kurun."
)
);
process.exit(1);
}
}
async function initProject(projectName) {
// Bu fonksiyon doğru, değişiklik yok.
console.log(
chalk.cyan.bold("--- Profesyonel Fiori Uygulama Oluşturucu v2.0 ---")
);
await checkPrerequisites();
const answers = await inquirer.prompt([
{
name: "namespace",
message: "Uygulama namespace'ini girin (örn: com.mycompany.app):",
default: "com.example.fiori",
},
{
type: "list",
name: "serviceType",
message: "Projenizin ana veri servisi türü ne olacak?",
choices: [
{ name: "OData V2 (örn: SAP ERP, S/4HANA On-Prem)", value: "ODataV2" },
{ name: "OData V4 (örn: S/4HANA Cloud)", value: "ODataV4" },
{
name: "Standart REST API (Token tabanlı oturum yönetimi ile)",
value: "Rest",
},
{ name: "Hiçbiri (Daha sonra kendim ekleyeceğim)", value: "None" },
],
},
{
name: "backendUrl",
message:
"SAP Gateway veya Backend sistem adresini girin (CORS proxy için):",
default: "http://localhost:8080",
},
]);
const { namespace, serviceType, backendUrl } = answers;
const projectData = { projectName, namespace, serviceType, backendUrl };
const targetDir = path.join(process.cwd(), projectName);
const templateDir = path.join(__dirname, "..", "pro-fiori-template");
if (fs.existsSync(targetDir)) {
console.error(
chalk.red(`\nHata: '${projectName}' adında bir klasör zaten mevcut!`)
);
return;
}
const spinner = ora(chalk.blue("Proje yapısı oluşturuluyor...")).start();
try {
fs.ensureDirSync(targetDir);
await processTemplate(templateDir, targetDir, projectData);
spinner.succeed(chalk.green(" Proje yapısı başarıyla oluşturuldu."));
spinner.start(chalk.blue("Git deposu hazırlanıyor..."));
if (fs.existsSync(path.join(targetDir, "gitignore.template"))) {
fs.renameSync(
path.join(targetDir, "gitignore.template"),
path.join(targetDir, ".gitignore")
);
}
await execa("git", ["init"], { cwd: targetDir });
await execa("git", ["add", "."], { cwd: targetDir });
await execa("git", ["commit", "-m", "Initial commit from fiori-cli"], {
cwd: targetDir,
});
spinner.succeed(chalk.green(" Git deposu başarıyla başlatıldı."));
spinner.start(
chalk.blue("NPM bağımlılıkları kuruluyor (Bu işlem biraz sürebilir)...")
);
await execa("npm", ["install"], { cwd: targetDir });
spinner.succeed(chalk.green(" NPM bağımlılıkları başarıyla kuruldu."));
console.log(chalk.green.bold("\n✨ Kurulum Tamamlandı! ✨"));
console.log(`\nProjeniz '${chalk.cyan(projectName)}' klasöründe hazır.`);
console.log(`\nSıradaki adımlar:`);
console.log(` 1. ${chalk.cyan(`cd ${projectName}`)}`);
console.log(
` 2. ${chalk.cyan("npm start")} komutuyla uygulamayı başlatın.`
);
} catch (error) {
spinner.fail(chalk.red("Bir hata oluştu!"));
fs.removeSync(targetDir);
console.error(chalk.red(error.stack || error.message));
process.exit(1);
}
}
// --- BU FONKSİYON TAMAMEN YENİLENDİ ---
async function processTemplate(templatePath, targetPath, data) {
const entries = fs.readdirSync(templatePath);
for (const entry of entries) {
const sourceFile = path.join(templatePath, entry);
const targetFile = path.join(targetPath, entry);
// --- BİRLEŞTİRİLMİŞ VE DOĞRU ATLAMA MANTIĞI ---
if (data.serviceType !== "Rest") {
const isLoginView = entry === "Login.view.xml";
const isLoginController = entry === "Login.controller.js";
const isRestCss =
templatePath.endsWith("css") &&
(entry === "style.css");
const isRestBackground =
templatePath.endsWith(path.join("img", "backgrounds")) &&
entry === "bg.png";
if (isLoginView || isLoginController || isRestCss || isRestBackground) {
continue; // Bu dosyaları atla
}
}
const stats = fs.lstatSync(sourceFile);
if (stats.isDirectory()) {
fs.ensureDirSync(targetFile);
if (entry === "service") {
const serviceFilesToCopy = [];
if (data.serviceType === "Rest") {
serviceFilesToCopy.push(
"RestService.js",
"UserService.js",
"SessionManager.js"
);
} else if (data.serviceType === "ODataV2") {
serviceFilesToCopy.push("ODataV2Service.js");
} else if (data.serviceType === "ODataV4") {
serviceFilesToCopy.push("ODataV4Service.js");
}
for (const serviceFile of serviceFilesToCopy) {
const sourceServicePath = path.join(sourceFile, serviceFile);
const targetServicePath = path.join(targetFile, serviceFile);
if (fs.existsSync(sourceServicePath)) {
const templateContent = fs.readFileSync(sourceServicePath, "utf-8");
const renderedContent = ejs.render(templateContent, data);
fs.writeFileSync(targetServicePath, renderedContent, "utf-8");
}
}
} else {
await processTemplate(sourceFile, targetFile, data);
}
} else {
if (
entry.endsWith(".css") ||
entry.endsWith(".png") ||
entry.endsWith(".svg") ||
entry.endsWith(".jpg") ||
entry.endsWith(".jpeg")
) {
fs.copyFileSync(sourceFile, targetFile);
} else {
const templateContent = fs.readFileSync(sourceFile, "utf-8");
const renderedContent = ejs.render(templateContent, data);
fs.writeFileSync(targetFile, renderedContent, "utf-8");
}
}
}
}
module.exports = initProject;