feat: implement IPC handlers for Nginx, PHP, and MySQL service management
This commit is contained in:
@@ -38,3 +38,4 @@ logs/
|
|||||||
bin/
|
bin/
|
||||||
*.exe
|
*.exe
|
||||||
*.dll
|
*.dll
|
||||||
|
projects.json
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
39708
|
23324
|
||||||
|
|||||||
+48
-5
@@ -60,13 +60,12 @@ export function registerIpcHandlers(): void {
|
|||||||
const phpPort = portMappingService.getPhpPort(p.phpVersion)
|
const phpPort = portMappingService.getPhpPort(p.phpVersion)
|
||||||
const normalizedPath = p.path.replace(/\\/g, '/')
|
const normalizedPath = p.path.replace(/\\/g, '/')
|
||||||
return `
|
return `
|
||||||
location /${p.host} {
|
location /${p.host}/ {
|
||||||
alias "${normalizedPath}";
|
alias "${normalizedPath}/";
|
||||||
index index.php index.html;
|
index index.php index.html;
|
||||||
try_files $uri $uri/ /${p.host}/index.php?$query_string;
|
try_files $uri $uri/ /${p.host}/index.php?$query_string;
|
||||||
|
|
||||||
location ~ ^/${p.host}/(.+\\.php)$ {
|
location ~ \.php$ {
|
||||||
alias "${normalizedPath}/$1";
|
|
||||||
fastcgi_pass 127.0.0.1:${phpPort};
|
fastcgi_pass 127.0.0.1:${phpPort};
|
||||||
fastcgi_index index.php;
|
fastcgi_index index.php;
|
||||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
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.readdirSync(dataDir).length === 0) {
|
||||||
if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true })
|
if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true })
|
||||||
console.log(`Initializing MySQL data directory for ${serviceName}...`)
|
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
|
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)
|
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ı.` }
|
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)
|
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}` }
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ import {
|
|||||||
Storage as MySQLIcon,
|
Storage as MySQLIcon,
|
||||||
Language as HostIcon,
|
Language as HostIcon,
|
||||||
Launch as LaunchIcon,
|
Launch as LaunchIcon,
|
||||||
Handyman as ToolsIcon
|
Handyman as ToolsIcon,
|
||||||
|
Restore as ResetIcon
|
||||||
} from '@mui/icons-material'
|
} from '@mui/icons-material'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
@@ -314,6 +315,13 @@ function App(): JSX.Element {
|
|||||||
await fetchLogs(service)
|
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 () => {
|
const handleSaveSettings = async () => {
|
||||||
if (window.api && window.api.saveSettings) {
|
if (window.api && window.api.saveSettings) {
|
||||||
const result = await window.api.saveSettings(settings)
|
const result = await window.api.saveSettings(settings)
|
||||||
@@ -819,9 +827,14 @@ function App(): JSX.Element {
|
|||||||
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>MySQL {v.version}</Typography>
|
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>MySQL {v.version}</Typography>
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>Port: {settings.mysqlPorts?.[v.id] || v.port}</Typography>
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>Port: {settings.mysqlPorts?.[v.id] || v.port}</Typography>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
<IconButton onClick={() => handleOpenLogs(`mysql:${v.version}`)} size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}>
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||||
<TerminalIcon fontSize="small" />
|
<IconButton onClick={() => handleOpenLogs(`mysql:${v.version}`)} title="Hata Logları" size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)' }}>
|
||||||
</IconButton>
|
<TerminalIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={() => handleResetData(`mysql:${v.version}`)} title="Verileri Sıfırla" size="small" sx={{ bgcolor: 'rgba(255,255,255,0.05)', '&:hover': { color: 'error.main' } }}>
|
||||||
|
<ResetIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
<Switch
|
<Switch
|
||||||
checked={(status[`mysql:${v.version}`] || 'stopped') === 'running' || status[`mysql:${v.version}`] === 'starting'}
|
checked={(status[`mysql:${v.version}`] || 'stopped') === 'running' || status[`mysql:${v.version}`] === 'starting'}
|
||||||
onChange={() => handleToggleService(`mysql:${v.version}`)}
|
onChange={() => handleToggleService(`mysql:${v.version}`)}
|
||||||
|
|||||||
Reference in New Issue
Block a user