605 lines
28 KiB
TypeScript
605 lines
28 KiB
TypeScript
import { ipcMain, app, dialog } from 'electron'
|
||
import fs from 'fs'
|
||
import { processManager } from '../services/ProcessManager'
|
||
import { configService } from '../services/ConfigService'
|
||
import { downloadService } from '../services/DownloadService'
|
||
import { projectService } from '../services/ProjectService'
|
||
import { phpManagerService } from '../services/PhpManagerService'
|
||
import { mySqlManagerService } from '../services/MySqlManagerService'
|
||
import { nginxManagerService } from '../services/NginxManagerService'
|
||
import { phpMyAdminService } from '../services/PhpMyAdminService'
|
||
import { portMappingService } from '../services/PortMappingService'
|
||
import path from 'path'
|
||
import { mySqlOperationService } from '../services/MySqlOperationService'
|
||
|
||
function findExecutable(dir: string, name: string): string | null {
|
||
if (!fs.existsSync(dir)) return null
|
||
const files = fs.readdirSync(dir)
|
||
for (const file of files) {
|
||
const fullPath = path.join(dir, file)
|
||
const stat = fs.statSync(fullPath)
|
||
if (stat.isDirectory()) {
|
||
const found = findExecutable(fullPath, name)
|
||
if (found) return found
|
||
} else if (file.toLowerCase() === name.toLowerCase()) {
|
||
return fullPath
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
|
||
async function reloadNginx(): Promise<{ success: boolean; message: string }> {
|
||
try {
|
||
const binDir = path.join(configService.getBasePath(), 'bin')
|
||
const nginxDir = path.join(binDir, 'nginx')
|
||
const nginxVersions = fs.readdirSync(nginxDir).filter(f => fs.statSync(path.join(nginxDir, f)).isDirectory())
|
||
const activeVersion = nginxVersions[0]
|
||
if (!activeVersion) throw new Error('Nginx sürümü bulunamadı.')
|
||
|
||
const nginxPrefix = path.join(nginxDir, activeVersion)
|
||
const binPath = path.join(nginxPrefix, 'nginx.exe')
|
||
const configPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
|
||
|
||
const result = await processManager.runOnce(binPath, ['-p', nginxPrefix, '-c', configPath, '-s', 'reload'], 'nginx')
|
||
if (result.success) {
|
||
console.log('Nginx reload successful')
|
||
return { success: true, message: 'Nginx reloaded' }
|
||
} else {
|
||
console.error('Nginx reload failed:', result.output)
|
||
return { success: false, message: result.output || 'Nginx reload failed' }
|
||
}
|
||
} catch (error: any) {
|
||
return { success: false, message: `Reload hatası: ${error.message}` }
|
||
}
|
||
}
|
||
|
||
export function registerIpcHandlers(): void {
|
||
// Service management
|
||
ipcMain.handle('services:reload', async (_event, serviceName: string) => {
|
||
if (serviceName !== 'nginx') return { success: false, message: 'Yalnızca Nginx için reload desteklenmektedir.' }
|
||
return await reloadNginx()
|
||
})
|
||
|
||
ipcMain.handle('services:start', async (_event, serviceName: string) => {
|
||
try {
|
||
const settings = configService.getSettings()
|
||
const binDir = path.join(configService.getBasePath(), 'bin')
|
||
|
||
if (serviceName === 'nginx') {
|
||
const rootPath = path.join(app.getAppPath(), 'www')
|
||
const nginxDir = path.join(binDir, 'nginx')
|
||
const binPath = findExecutable(nginxDir, 'nginx.exe')
|
||
const logDir = path.join(configService.getBasePath(), 'logs')
|
||
|
||
if (!binPath) return { success: false, message: 'Nginx executable bulunamadı. Lütfen indirin.' }
|
||
|
||
// Nginx prefix = directory containing nginx.exe
|
||
const nginxPrefix = path.dirname(binPath)
|
||
const confDir = path.join(nginxPrefix, 'conf')
|
||
|
||
// Ensure temp directories exist (Nginx needs these)
|
||
const tempDirs = ['temp', 'temp/client_body_temp', 'temp/proxy_temp', 'temp/fastcgi_temp', 'temp/uwsgi_temp', 'temp/scgi_temp', 'logs']
|
||
for (const dir of tempDirs) {
|
||
const fullDir = path.join(nginxPrefix, dir)
|
||
if (!fs.existsSync(fullDir)) {
|
||
fs.mkdirSync(fullDir, { recursive: true })
|
||
}
|
||
}
|
||
|
||
const projects = await projectService.getProjects()
|
||
const projectsConfDir = path.join(configService.getBasePath(), 'generated_configs', 'projects')
|
||
if (!fs.existsSync(projectsConfDir)) fs.mkdirSync(projectsConfDir, { recursive: true })
|
||
|
||
// Clean up old project configs
|
||
const existingFiles = fs.readdirSync(projectsConfDir)
|
||
for (const file of existingFiles) {
|
||
fs.unlinkSync(path.join(projectsConfDir, file))
|
||
}
|
||
|
||
for (const p of projects) {
|
||
const phpPort = portMappingService.getPhpPort(p.phpVersion)
|
||
const normalizedPath = p.path.replace(/\\/g, '/')
|
||
await configService.generateConfig('nginx_project.conf.template', `projects/${p.host}.conf`, {
|
||
HOST: p.host,
|
||
PATH: normalizedPath,
|
||
PHP_PORT: phpPort.toString(),
|
||
CONF_DIR: confDir.replace(/\\/g, '/')
|
||
})
|
||
}
|
||
|
||
const projectsInclusion = projects.length > 0
|
||
? `include "${projectsConfDir.replace(/\\/g, '/')}/*.conf";`
|
||
: ''
|
||
|
||
const configPath = await configService.generateConfig('nginx.conf.template', 'nginx.conf', {
|
||
PORT: settings.nginxPort,
|
||
PHP_PORT: settings.phpPort,
|
||
ROOT: rootPath,
|
||
LOG_DIR: logDir.replace(/\\/g, '/'),
|
||
CONF_DIR: confDir.replace(/\\/g, '/'),
|
||
PHPMYADMIN_DIR: phpMyAdminService.getPath().replace(/\\/g, '/'),
|
||
PROJECTS: projectsInclusion
|
||
})
|
||
|
||
// Test config first with prefix
|
||
const testResult = await processManager.runOnce(binPath, ['-t', '-p', nginxPrefix, '-c', configPath], 'nginx')
|
||
if (!testResult.success) {
|
||
console.error('Nginx config test failed before reload:', testResult.output)
|
||
return { success: false, message: `Nginx config error: ${testResult.output}` }
|
||
}
|
||
|
||
const success = await processManager.startService('nginx', binPath, ['-p', nginxPrefix, '-c', configPath], false)
|
||
|
||
if (!success) {
|
||
const errorLogs = await processManager.getLastErrorLogs('nginx')
|
||
return { success: false, message: `Nginx başlatılamadı.\n\n${errorLogs.join('\n')}` }
|
||
}
|
||
|
||
return { success, message: success ? 'Nginx başlatıldı.' : 'Nginx devreye alınamadı.' }
|
||
}
|
||
|
||
if (serviceName.startsWith('php')) {
|
||
const versionMatch = serviceName.match(/^php:(.+)$/)
|
||
const phpVersion = versionMatch ? versionMatch[1] : null
|
||
const phpId = phpVersion ? `php-${phpVersion}` : null
|
||
|
||
const phpDir = phpId ? path.join(binDir, phpId) : binDir
|
||
const binPath = findExecutable(phpDir, 'php-cgi.exe')
|
||
|
||
if (!binPath) return { success: false, message: `${phpVersion || ''} PHP executable bulunamadı. Lütfen indirin.` }
|
||
|
||
const phpPort = phpVersion ? portMappingService.getPhpPort(phpVersion) : settings.phpPort
|
||
const extDir = path.join(path.dirname(binPath), 'ext').replace(/\\/g, '/')
|
||
const gdExtName = fs.existsSync(path.join(extDir, 'php_gd2.dll')) ? 'gd2' : 'gd'
|
||
|
||
const sessionDir = path.join(configService.getBasePath(), 'data', 'sessions').replace(/\\/g, '/')
|
||
const tempDir = path.join(configService.getBasePath(), 'data', 'temp').replace(/\\/g, '/')
|
||
|
||
if (!fs.existsSync(sessionDir)) fs.mkdirSync(sessionDir, { recursive: true })
|
||
if (!fs.existsSync(tempDir)) fs.mkdirSync(tempDir, { recursive: true })
|
||
|
||
const configPath = await configService.generateConfig('php.ini.template', `php_${phpVersion || 'default'}.ini`, {
|
||
EXT_DIR: extDir,
|
||
GD_EXT: gdExtName,
|
||
SESSION_DIR: sessionDir,
|
||
TEMP_DIR: tempDir
|
||
})
|
||
|
||
const success = await processManager.startService(serviceName, binPath, ['-b', `127.0.0.1:${phpPort}`, '-c', configPath], false)
|
||
|
||
if (!success) {
|
||
const errorLogs = await processManager.getLastErrorLogs(serviceName)
|
||
return { success: false, message: `${phpVersion || ''} PHP başlatılamadı.\n\n${errorLogs.join('\n')}` }
|
||
}
|
||
|
||
return { success, message: success ? `${phpVersion || ''} PHP başlatıldı.` : `${phpVersion || ''} PHP devreye alınamadı.` }
|
||
}
|
||
|
||
if (serviceName.startsWith('mysql')) {
|
||
const versionMatch = serviceName.match(/^mysql:(.+)$/)
|
||
const mysqlVersion = versionMatch ? versionMatch[1] : null
|
||
const mysqlId = mysqlVersion ? `mysql-${mysqlVersion}` : null
|
||
|
||
const dataDir = mysqlId
|
||
? path.join(configService.getBasePath(), 'data', mysqlId)
|
||
: path.join(configService.getBasePath(), 'data', 'default')
|
||
|
||
const mysqlDir = mysqlId ? path.join(binDir, mysqlId) : binDir
|
||
const binPath = findExecutable(mysqlDir, 'mysqld.exe')
|
||
|
||
if (!binPath) return { success: false, message: 'MySQL executable bulunamadı. Lütfen indirin.' }
|
||
|
||
const mysqlVersions = await mySqlManagerService.getVersions()
|
||
const mysqlInfo = mysqlVersions.find(v => v.id === mysqlId)
|
||
const mysqlPort = mysqlInfo?.port || (mysqlId ? '3306' : settings.mysqlPort)
|
||
|
||
// Force kill this specific version if running or generic mysql
|
||
await processManager.forceKillAll(serviceName)
|
||
|
||
// Also kill anything else listening on the same port
|
||
await processManager.killByPort(serviceName, mysqlPort)
|
||
|
||
// Initialize if data directory is empty
|
||
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}...`)
|
||
|
||
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 sanitizedServiceName = serviceName.replace(/:/g, '_')
|
||
const logFile = path.join(configService.getBasePath(), 'logs', `${sanitizedServiceName}_error.log`)
|
||
|
||
const configPath = await configService.generateConfig('my.ini.template', `my_${mysqlId || 'default'}.ini`, {
|
||
PORT: mysqlPort,
|
||
DATADIR: dataDir.replace(/\\/g, '/'),
|
||
SOCKET: `/tmp/${sanitizedServiceName}.sock`,
|
||
LOG_FILE: logFile.replace(/\\/g, '/')
|
||
})
|
||
|
||
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)) {
|
||
const errorLogs = await processManager.getLastErrorLogs(serviceName)
|
||
return { success: false, message: `${mysqlVersion || ''} MySQL başlatıldı ancak çalışma hatası verdi (ExitCode: 1).\n\n${errorLogs.length > 0 ? 'Önemli Hata Logları:\n' + errorLogs.join('\n') : 'Lütfen log sekmesini kontrol edin.'}` }
|
||
}
|
||
} else {
|
||
const errorLogs = await processManager.getLastErrorLogs(serviceName)
|
||
return { success: false, message: `${mysqlVersion || ''} MySQL başlatılamadı.\n\n${errorLogs.join('\n')}` }
|
||
}
|
||
|
||
return { success, message: success ? `${mysqlVersion || ''} MySQL başlatıldı.` : `${mysqlVersion || ''} MySQL devreye alınamadı.` }
|
||
}
|
||
|
||
return { success: false, message: 'Bilinmeyen servis.' }
|
||
} catch (error: any) {
|
||
console.error('Service start error:', error)
|
||
return { success: false, message: `Hata: ${error.message}` }
|
||
}
|
||
})
|
||
|
||
ipcMain.handle('services:stop', async (_event, serviceName: string) => {
|
||
const success = await processManager.stopService(serviceName)
|
||
return { success, message: success ? `${serviceName} durduruldu.` : `${serviceName} zaten durmuş.` }
|
||
})
|
||
|
||
ipcMain.handle('services:status', async () => {
|
||
return processManager.getStatuses()
|
||
})
|
||
|
||
ipcMain.handle('services:logs', async (_event, serviceName: string) => {
|
||
return processManager.getLogs(serviceName)
|
||
})
|
||
|
||
// Binary management
|
||
ipcMain.handle('binaries:list-php', async () => {
|
||
return phpManagerService.getVersions()
|
||
})
|
||
|
||
ipcMain.handle('binaries:download-php', async (event, id: string) => {
|
||
const versions = await phpManagerService.getVersions()
|
||
const version = versions.find(v => v.id === id)
|
||
if (!version) return { success: false, message: 'Geçersiz sürüm.' }
|
||
|
||
try {
|
||
// Signal immediate start
|
||
phpManagerService.updateProgress(id, 0, 'downloading')
|
||
event.sender.send('binaries:progress', { id, progress: 0 })
|
||
|
||
await downloadService.downloadAndExtract(version.url, id, (p) => {
|
||
phpManagerService.updateProgress(id, p)
|
||
event.sender.send('binaries:progress', { id, progress: p })
|
||
})
|
||
|
||
phpManagerService.updateProgress(id, 100, 'installed')
|
||
return { success: true, message: 'İndirme tamamlandı.' }
|
||
} catch (error: any) {
|
||
phpManagerService.updateProgress(id, 0, 'available')
|
||
return { success: false, message: `Hata: ${error.message}` }
|
||
}
|
||
})
|
||
|
||
// MySQL Versions
|
||
ipcMain.handle('mysql:versions', async () => {
|
||
return await mySqlManagerService.getVersions()
|
||
})
|
||
|
||
ipcMain.handle('mysql:download', async (event, id: string) => {
|
||
const versions = await mySqlManagerService.getVersions()
|
||
const version = versions.find(v => v.id === id)
|
||
if (!version) return { success: false, message: 'Geçersiz MySQL sürümü.' }
|
||
|
||
try {
|
||
mySqlManagerService.updateProgress(id, 0, 'downloading')
|
||
event.sender.send('mysql:progress', { id, progress: 0 })
|
||
|
||
await downloadService.downloadAndExtract(version.url, id, (p) => {
|
||
mySqlManagerService.updateProgress(id, p)
|
||
event.sender.send('mysql:progress', { id, progress: p })
|
||
})
|
||
|
||
mySqlManagerService.updateProgress(id, 100, 'installed')
|
||
return { success: true, message: 'MySQL indirme tamamlandı.' }
|
||
} catch (error: any) {
|
||
mySqlManagerService.updateProgress(id, 0, 'available')
|
||
return { success: false, message: `MySQL hatası: ${error.message}` }
|
||
}
|
||
})
|
||
|
||
// Nginx Versions
|
||
ipcMain.handle('nginx:versions', async () => {
|
||
return await nginxManagerService.getVersions()
|
||
})
|
||
|
||
ipcMain.handle('nginx:download', async (event, id: string) => {
|
||
const versions = await nginxManagerService.getVersions()
|
||
const version = versions.find(v => v.id === id)
|
||
if (!version) return { success: false, message: 'Geçersiz Nginx sürümü.' }
|
||
|
||
try {
|
||
nginxManagerService.updateProgress(id, 0, 'downloading')
|
||
event.sender.send('nginx:progress', { id, progress: 0 })
|
||
|
||
await downloadService.downloadAndExtract(version.url, id, (p) => {
|
||
nginxManagerService.updateProgress(id, p)
|
||
event.sender.send('nginx:progress', { id, progress: p })
|
||
})
|
||
|
||
nginxManagerService.updateProgress(id, 100, 'installed')
|
||
return { success: true, message: 'Nginx indirme tamamlandı.' }
|
||
} catch (error: any) {
|
||
nginxManagerService.updateProgress(id, 0, 'available')
|
||
return { success: false, message: `Nginx hatası: ${error.message}` }
|
||
}
|
||
})
|
||
|
||
ipcMain.handle('dialog:select-directory', async () => {
|
||
const result = await dialog.showOpenDialog({
|
||
properties: ['openDirectory']
|
||
})
|
||
if (result.canceled) return null
|
||
return result.filePaths[0]
|
||
})
|
||
|
||
ipcMain.handle('dialog:select-file', async (_event, filters: any[]) => {
|
||
const result = await dialog.showOpenDialog({
|
||
properties: ['openFile'],
|
||
filters: filters || [
|
||
{ name: 'SQL & Archives', extensions: ['sql', 'zip', 'gz', 'tar'] }
|
||
]
|
||
})
|
||
if (result.canceled) return null
|
||
return result.filePaths[0]
|
||
})
|
||
|
||
ipcMain.handle('binaries:download', async (_event, { name, url }) => {
|
||
return downloadService.downloadAndExtract(url, name, (p) => {
|
||
// TODO: Emit progress to renderer via webContents.send
|
||
console.log(`Download progress for ${name}: ${p}%`)
|
||
})
|
||
})
|
||
|
||
// Project management
|
||
ipcMain.handle('projects:list', async () => {
|
||
return projectService.getProjects()
|
||
})
|
||
|
||
ipcMain.handle('projects:add', async (_event, project) => {
|
||
const result = await projectService.addProject(project)
|
||
// Trigger Nginx reload
|
||
await ipcMain.emit('services:reload', null, 'nginx')
|
||
return result
|
||
})
|
||
|
||
ipcMain.handle('projects:remove', async (_event, id) => {
|
||
const result = projectService.removeProject(id)
|
||
// Trigger Nginx reload
|
||
await ipcMain.emit('services:reload', null, 'nginx')
|
||
return result
|
||
})
|
||
ipcMain.handle('projects:update', async (_event, project) => {
|
||
const result = projectService.updateProject(project)
|
||
// Trigger Nginx reload
|
||
await ipcMain.emit('services:reload', null, 'nginx')
|
||
return result
|
||
})
|
||
|
||
// Config management
|
||
ipcMain.handle('config:get', async () => {
|
||
return configService.getSettings()
|
||
})
|
||
|
||
ipcMain.handle('config:save', async (_event, config: any) => {
|
||
const settings = configService.updateSettings(config)
|
||
return { success: true, settings }
|
||
})
|
||
|
||
// Nginx Config Management
|
||
ipcMain.handle('nginx:config:get', async () => {
|
||
const configPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
|
||
if (fs.existsSync(configPath)) {
|
||
return fs.readFileSync(configPath, 'utf8')
|
||
}
|
||
return ''
|
||
})
|
||
|
||
ipcMain.handle('nginx:config:save', async (_event, content) => {
|
||
const configPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
|
||
fs.writeFileSync(configPath, content)
|
||
// Reload Nginx after save
|
||
return await reloadNginx()
|
||
})
|
||
|
||
ipcMain.handle('nginx:config:test', async () => {
|
||
try {
|
||
const binDir = path.join(configService.getBasePath(), 'bin', 'nginx')
|
||
const nginxVersions = fs.readdirSync(binDir).filter(f => fs.statSync(path.join(binDir, f)).isDirectory())
|
||
const activeVersion = nginxVersions[0]
|
||
if (!activeVersion) throw new Error('Nginx not found')
|
||
|
||
const nginxPrefix = path.join(binDir, activeVersion)
|
||
const binPath = path.join(nginxPrefix, 'nginx.exe')
|
||
const configPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
|
||
|
||
const result = await processManager.runOnce(binPath, ['-t', '-p', nginxPrefix, '-c', configPath], 'nginx')
|
||
return { success: result.success, message: result.success ? 'Configuration test successful' : result.output }
|
||
} catch (error: any) {
|
||
return { success: false, message: error.message }
|
||
}
|
||
})
|
||
|
||
// Project Nginx Config
|
||
ipcMain.handle('project:nginx:get', async (_event, host) => {
|
||
const configPath = path.join(configService.getBasePath(), 'generated_configs', 'projects', `${host}.conf`)
|
||
if (fs.existsSync(configPath)) {
|
||
return fs.readFileSync(configPath, 'utf8')
|
||
}
|
||
return ''
|
||
})
|
||
|
||
ipcMain.handle('project:nginx:test', async (_event, host, content) => {
|
||
const configPath = path.join(configService.getBasePath(), 'generated_configs', 'projects', `${host}.conf`)
|
||
let originalContent = ''
|
||
if (fs.existsSync(configPath)) {
|
||
originalContent = fs.readFileSync(configPath, 'utf8')
|
||
}
|
||
|
||
try {
|
||
// 1. Save new content temporarily
|
||
fs.writeFileSync(configPath, content)
|
||
|
||
// 2. Run global test
|
||
const binDir = path.join(configService.getBasePath(), 'bin', 'nginx')
|
||
const nginxVersions = fs.readdirSync(binDir).filter(f => fs.statSync(path.join(binDir, f)).isDirectory())
|
||
const activeVersion = nginxVersions[0]
|
||
if (!activeVersion) throw new Error('Nginx sürümü bulunamadı.')
|
||
|
||
const nginxPrefix = path.join(binDir, activeVersion)
|
||
const binPath = path.join(nginxPrefix, 'nginx.exe')
|
||
const globalConfigPath = path.join(configService.getBasePath(), 'generated_configs', 'nginx.conf')
|
||
|
||
const result = await processManager.runOnce(binPath, ['-t', '-p', nginxPrefix, '-c', globalConfigPath], 'nginx')
|
||
|
||
// 3. Restore original content regardless of test result
|
||
// (The user must click "Save" to keep it)
|
||
if (originalContent) {
|
||
fs.writeFileSync(configPath, originalContent)
|
||
} else {
|
||
fs.unlinkSync(configPath)
|
||
}
|
||
|
||
return { success: result.success, message: result.success ? 'Configuration test successful' : result.output }
|
||
} catch (error: any) {
|
||
// Restore on error too
|
||
if (originalContent) fs.writeFileSync(configPath, originalContent)
|
||
return { success: false, message: error.message }
|
||
}
|
||
})
|
||
|
||
ipcMain.handle('project:nginx:save', async (_event, host, content) => {
|
||
const configPath = path.join(configService.getBasePath(), 'generated_configs', 'projects', `${host}.conf`)
|
||
fs.writeFileSync(configPath, content)
|
||
// Reload Nginx after save
|
||
return await reloadNginx()
|
||
})
|
||
|
||
// phpMyAdmin
|
||
ipcMain.handle('pma:status', async () => {
|
||
return await phpMyAdminService.isInstalled()
|
||
})
|
||
|
||
ipcMain.handle('pma:setup', async (event, mysqlPort: string) => {
|
||
return await phpMyAdminService.setup(mysqlPort, (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}` }
|
||
}
|
||
})
|
||
|
||
ipcMain.handle('mysql:import-wizard:check-db', async (_event, { versionId, dbName, rootPass }) => {
|
||
const versions = await mySqlManagerService.getVersions()
|
||
const v = versions.find(v => v.id === versionId)
|
||
if (!v) return { exists: false, error: 'MySQL version not found' }
|
||
|
||
const binDir = path.join(configService.getBasePath(), 'bin', versionId)
|
||
const binPath = findExecutable(binDir, 'mysql.exe')
|
||
if (!binPath) return { exists: false, error: 'mysql.exe not found' }
|
||
|
||
const exists = await mySqlOperationService.checkDatabaseExists({
|
||
binPath,
|
||
host: '127.0.0.1',
|
||
port: v.port,
|
||
rootUser: 'root',
|
||
rootPass: rootPass || ''
|
||
}, dbName)
|
||
|
||
return { exists }
|
||
})
|
||
|
||
ipcMain.handle('mysql:import-wizard:start', async (event, { versionId, filePath, dbName, user, pass, rootPass, overwrite }) => {
|
||
const versions = await mySqlManagerService.getVersions()
|
||
const v = versions.find(v => v.id === versionId)
|
||
if (!v) return { success: false, message: 'MySQL version not found' }
|
||
|
||
const binDir = path.join(configService.getBasePath(), 'bin', versionId)
|
||
const mysqlBin = findExecutable(binDir, 'mysql.exe')
|
||
if (!mysqlBin) return { success: false, message: 'mysql.exe not found' }
|
||
|
||
const config = {
|
||
binPath: mysqlBin,
|
||
host: '127.0.0.1',
|
||
port: v.port,
|
||
rootUser: 'root',
|
||
rootPass: rootPass || ''
|
||
}
|
||
|
||
const log = (msg: string) => event.sender.send('mysql:import:log', msg)
|
||
|
||
try {
|
||
if (overwrite) {
|
||
log(`Dropping existing database: ${dbName}`)
|
||
await mySqlOperationService.dropDatabase(config, dbName)
|
||
}
|
||
|
||
log(`Creating database and user: ${dbName} / ${user}`)
|
||
const createRes = await mySqlOperationService.createDatabaseAndUser(config, dbName, user, pass)
|
||
if (!createRes.success) return createRes
|
||
|
||
let sqlFiles: string[] = []
|
||
if (filePath.toLowerCase().endsWith('.sql')) {
|
||
sqlFiles = [filePath]
|
||
} else {
|
||
log(`Extracting archive: ${path.basename(filePath)}`)
|
||
const extractDir = path.join(app.getPath('temp'), `mysql_import_${Date.now()}`)
|
||
sqlFiles = await mySqlOperationService.extractArchive(filePath, extractDir)
|
||
if (sqlFiles.length === 0) return { success: false, message: 'No .sql files found in archive.' }
|
||
}
|
||
|
||
for (const sqlFile of sqlFiles) {
|
||
log(`Importing: ${path.basename(sqlFile)}`)
|
||
const importRes = await mySqlOperationService.importSql(config, dbName, sqlFile, (msg) => log(msg))
|
||
if (!importRes.success) return importRes
|
||
}
|
||
|
||
return { success: true, message: 'Import completed successfully.' }
|
||
} catch (error: any) {
|
||
return { success: false, message: `Import error: ${error.message}` }
|
||
}
|
||
})
|
||
}
|