diff --git a/.gitignore b/.gitignore
index ab59bd2..24a8876 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,4 @@ logs/
bin/
*.exe
*.dll
+projects.json
diff --git a/logs/nginx.pid b/logs/nginx.pid
index ebd1b4f..774222b 100644
--- a/logs/nginx.pid
+++ b/logs/nginx.pid
@@ -1 +1 @@
-39708
+23324
diff --git a/src/main/ipc/index.ts b/src/main/ipc/index.ts
index 71a8351..cff5cda 100644
--- a/src/main/ipc/index.ts
+++ b/src/main/ipc/index.ts
@@ -60,13 +60,12 @@ export function registerIpcHandlers(): void {
const phpPort = portMappingService.getPhpPort(p.phpVersion)
const normalizedPath = p.path.replace(/\\/g, '/')
return `
- location /${p.host} {
- alias "${normalizedPath}";
+ location /${p.host}/ {
+ alias "${normalizedPath}/";
index index.php index.html;
try_files $uri $uri/ /${p.host}/index.php?$query_string;
- location ~ ^/${p.host}/(.+\\.php)$ {
- alias "${normalizedPath}/$1";
+ location ~ \.php$ {
fastcgi_pass 127.0.0.1:${phpPort};
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename;
@@ -140,7 +139,22 @@ export function registerIpcHandlers(): void {
if (!fs.existsSync(dataDir) || fs.readdirSync(dataDir).length === 0) {
if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true })
console.log(`Initializing MySQL data directory for ${serviceName}...`)
- await processManager.runOnce(binPath, ['--initialize-insecure', `--datadir=${dataDir.replace(/\\/g, '/')}`])
+
+ try {
+ // Try modern initialization first (5.7+)
+ await processManager.runOnce(binPath, ['--initialize-insecure', `--datadir=${dataDir.replace(/\\/g, '/')}`])
+ } catch (err) {
+ console.log(`Modern init failed, trying template copy for ${serviceName}...`)
+ // Fallback for 5.6: Copy default 'data' folder from binary dir if it exists
+ const templateDataDir = path.join(mysqlDir, 'data')
+ if (fs.existsSync(templateDataDir)) {
+ // Recursively copy template data (mysql, performance_schema, etc.)
+ fs.cpSync(templateDataDir, dataDir, { recursive: true })
+ console.log(`Successfully copied template data for ${serviceName}`)
+ } else {
+ throw new Error(`MySQL initialization failed and no template data found at ${templateDataDir}`)
+ }
+ }
}
const mysqlPort = mysqlId ? (settings.mysqlPorts?.[mysqlId] || '3306') : settings.mysqlPort
@@ -155,6 +169,15 @@ export function registerIpcHandlers(): void {
})
const success = await processManager.startService(serviceName, binPath, ['--defaults-file=' + configPath], false)
+
+ if (success) {
+ // Quick health check for MySQL
+ await new Promise(r => setTimeout(r, 1500))
+ if (!processManager.isServiceRunning(serviceName)) {
+ return { success: false, message: `${mysqlVersion || ''} MySQL başlatıldı ancak çalışma hatası verdi. Lütfen logları ve port çakışmalarını kontrol edin.` }
+ }
+ }
+
return { success, message: success ? `${mysqlVersion || ''} MySQL başlatıldı.` : `${mysqlVersion || ''} MySQL devreye alınamadı.` }
}
@@ -310,4 +333,24 @@ export function registerIpcHandlers(): void {
event.sender.send('pma:progress', p)
})
})
+
+ ipcMain.handle('services:reset-data', async (_event, serviceName: string) => {
+ try {
+ await processManager.forceKillAll(serviceName)
+
+ const versionMatch = serviceName.match(/^mysql:(.+)$/)
+ const mysqlVersion = versionMatch ? versionMatch[1] : null
+ const mysqlId = mysqlVersion ? `mysql-${mysqlVersion}` : null
+
+ if (!mysqlId) return { success: false, message: 'Geçersiz servis adı.' }
+
+ const dataDir = path.join(configService.getBasePath(), 'data', mysqlId)
+ if (fs.existsSync(dataDir)) {
+ fs.rmSync(dataDir, { recursive: true, force: true })
+ }
+ return { success: true, message: `${serviceName} verileri sıfırlandı. Tekrar başlatmayı deneyebilirsiniz.` }
+ } catch (error: any) {
+ return { success: false, message: `Sıfırlama hatası: ${error.message}` }
+ }
+ })
}
diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx
index 3ed4e8e..5d0c74e 100644
--- a/src/renderer/src/App.tsx
+++ b/src/renderer/src/App.tsx
@@ -66,7 +66,8 @@ import {
Storage as MySQLIcon,
Language as HostIcon,
Launch as LaunchIcon,
- Handyman as ToolsIcon
+ Handyman as ToolsIcon,
+ Restore as ResetIcon
} from '@mui/icons-material'
import { useTranslation } from 'react-i18next'
@@ -314,6 +315,13 @@ function App(): JSX.Element {
await fetchLogs(service)
}
+ const handleResetData = async (service: string) => {
+ if (!window.confirm(`${service} verilerini sıfırlamak istiyor musunuz? Bu işlem tüm verileri siler ve temiz kurulum yapar.`)) return
+ const result = await window.api.invoke('services:reset-data', service)
+ alert(result.message)
+ fetchStatus()
+ }
+
const handleSaveSettings = async () => {
if (window.api && window.api.saveSettings) {
const result = await window.api.saveSettings(settings)
@@ -819,9 +827,14 @@ function App(): JSX.Element {
MySQL {v.version}
Port: {settings.mysqlPorts?.[v.id] || v.port}
- handleOpenLogs(`mysql:${v.version}`)} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}>
-
-
+
+ handleOpenLogs(`mysql:${v.version}`)} title="Hata Logları" size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}>
+
+
+ handleResetData(`mysql:${v.version}`)} title="Verileri Sıfırla" size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)', '&:hover': { color: 'error.main' } }}>
+
+
+
handleToggleService(`mysql:${v.version}`)}