const express = require('express'); const { exec } = require('child_process'); const fs = require('fs'); const path = require('path'); const { v4: uuidv4 } = require('uuid'); const app = express(); const PORT = 7860; // CORS middleware app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { return res.sendStatus(200); } next(); }); // JSON body parser app.use(express.json()); // Job storage const jobs = {}; // Web arayüzü app.get('/', (req, res) => { res.send(`
POST /build - Build başlat (appName, packageId, repoUrl)
GET /status/:jobId - Durum sorgula
GET /download/:jobId - APK indir
`); }); // Build endpoint app.post('/build', (req, res) => { const { appName, packageId, repoUrl } = req.body; if (!appName || !packageId || !repoUrl) { return res.status(400).json({ success: false, message: 'appName, packageId ve repoUrl gerekli' }); } const jobId = uuidv4(); jobs[jobId] = { status: 'pending', appName, packageId, repoUrl, createdAt: new Date(), apkPath: null }; // Build işlemini arka planda başlat buildAPK(jobId); res.json({ success: true, jobId, message: 'Build başlatıldı' }); }); // Durum sorgulama app.get('/status/:jobId', (req, res) => { const { jobId } = req.params; const job = jobs[jobId]; if (!job) { return res.status(404).json({ success: false, message: 'Job bulunamadı' }); } res.json({ success: true, jobId, status: job.status, appName: job.appName, createdAt: job.createdAt }); }); // APK indirme app.get('/download/:jobId', (req, res) => { const { jobId } = req.params; const job = jobs[jobId]; if (!job) { return res.status(404).json({ success: false, message: 'Job bulunamadı' }); } if (job.status !== 'completed') { return res.status(400).json({ success: false, message: 'APK henüz hazır değil' }); } if (job.apkPath && fs.existsSync(job.apkPath)) { res.download(job.apkPath, `${job.appName}-debug.apk`); } else { res.status(404).json({ success: false, message: 'APK dosyası bulunamadı' }); } }); // Tüm job'ları listele app.get('/jobs', (req, res) => { const jobList = Object.entries(jobs).map(([jobId, job]) => ({ jobId, status: job.status, appName: job.appName, packageId: job.packageId, repoUrl: job.repoUrl, createdAt: job.createdAt, error: job.error })); // Tarihe göre sırala (en yeni önce) jobList.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); res.json({ success: true, jobs: jobList }); }); // Build fonksiyonu function buildAPK(jobId) { const job = jobs[jobId]; job.status = 'building'; const buildDir = `/tmp/build-${jobId}`; // Temizle if (fs.existsSync(buildDir)) { fs.rmSync(buildDir, { recursive: true }); } // Klonla (with token if available) const token = process.env.GITHUB_TOKEN; let cloneUrl = job.repoUrl; if (token && job.repoUrl.startsWith('https://github.com/')) { cloneUrl = job.repoUrl.replace('https://github.com/', `https://git:${token}@github.com/`); } exec(`git clone ${cloneUrl} ${buildDir}`, (error, stdout, stderr) => { if (error) { console.error('Klonlama hatası:', error); job.status = 'failed'; job.error = error.message; return; } // Build işlemi (step by step) - WebView Android App const steps = [ 'npm install', // Android projesi oluştur `mkdir -p android-project/app/src/main/java/com/example/webview`, `mkdir -p android-project/app/src/main/res/values`, `mkdir -p android-project/app/src/main/res/layout`, // AndroidManifest.xml oluştur `cat > android-project/app/src/main/AndroidManifest.xml << 'EOF'