feat: implement IPC handlers and core management services for Nginx, PHP, and MariaDB processes

This commit is contained in:
Ümit Tunç
2026-03-30 11:13:53 +03:00
parent d15b10a012
commit a952f0d8dd
5 changed files with 184 additions and 8 deletions
+4
View File
@@ -2,6 +2,7 @@ import { app, shell, BrowserWindow, Tray, Menu, nativeImage } from 'electron'
import { join } from 'path' import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils' import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import { registerIpcHandlers } from './ipc' import { registerIpcHandlers } from './ipc'
import { cliAliasService } from './services/CliAliasService'
let tray: Tray | null = null let tray: Tray | null = null
let mainWindow: BrowserWindow | null = null let mainWindow: BrowserWindow | null = null
@@ -80,6 +81,9 @@ app.whenReady().then(() => {
createTray() createTray()
registerIpcHandlers() registerIpcHandlers()
// Generate CLI aliases on start
cliAliasService.generateAliases().catch(console.error)
app.on('activate', function () { app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow() if (BrowserWindow.getAllWindows().length === 0) createWindow()
}) })
+24 -1
View File
@@ -11,6 +11,7 @@ import { phpMyAdminService } from '../services/PhpMyAdminService'
import { portMappingService } from '../services/PortMappingService' import { portMappingService } from '../services/PortMappingService'
import path from 'path' import path from 'path'
import { mariaDbOperationService } from '../services/MariaDbOperationService' import { mariaDbOperationService } from '../services/MariaDbOperationService'
import { cliAliasService } from '../services/CliAliasService'
function findExecutable(dir: string, name: string): string | null { function findExecutable(dir: string, name: string): string | null {
if (!fs.existsSync(dir)) return null if (!fs.existsSync(dir)) return null
@@ -331,6 +332,8 @@ export function registerIpcHandlers(): void {
}) })
phpManagerService.updateProgress(id, 100, 'installed') phpManagerService.updateProgress(id, 100, 'installed')
// Regenerate aliases after install
await cliAliasService.generateAliases()
return { success: true, message: 'İndirme tamamlandı.' } return { success: true, message: 'İndirme tamamlandı.' }
} catch (error: any) { } catch (error: any) {
phpManagerService.updateProgress(id, 0, 'available') phpManagerService.updateProgress(id, 0, 'available')
@@ -358,6 +361,8 @@ export function registerIpcHandlers(): void {
}) })
mariaDbManagerService.updateProgress(id, 100, 'installed') mariaDbManagerService.updateProgress(id, 100, 'installed')
// Regenerate aliases after install
await cliAliasService.generateAliases()
return { success: true, message: 'MariaDB indirme tamamlandı.' } return { success: true, message: 'MariaDB indirme tamamlandı.' }
} catch (error: any) { } catch (error: any) {
mariaDbManagerService.updateProgress(id, 0, 'available') mariaDbManagerService.updateProgress(id, 0, 'available')
@@ -427,10 +432,28 @@ export function registerIpcHandlers(): void {
}) })
ipcMain.handle('binaries:download', async (_event, { name, url }) => { ipcMain.handle('binaries:download', async (_event, { name, url }) => {
return downloadService.downloadAndExtract(url, name, (p) => { const result = await downloadService.downloadAndExtract(url, name, (p) => {
// TODO: Emit progress to renderer via webContents.send // TODO: Emit progress to renderer via webContents.send
console.log(`Download progress for ${name}: ${p}%`) console.log(`Download progress for ${name}: ${p}%`)
}) })
await cliAliasService.generateAliases()
return result
})
ipcMain.handle('cli:generate-aliases', async () => {
try {
await cliAliasService.generateAliases()
return {
success: true,
message: 'CLI aliasları başarıyla oluşturuldu.',
paths: {
powershell: configService.getGeneratedPath('aliases.ps1'),
bash: configService.getGeneratedPath('aliases.sh')
}
}
} catch (error: any) {
return { success: false, message: `Hata: ${error.message}` }
}
}) })
// Project management // Project management
+126
View File
@@ -0,0 +1,126 @@
import fs from 'fs'
import { phpManagerService } from './PhpManagerService'
import { mariaDbManagerService } from './MariaDbManagerService'
import { configService } from './ConfigService'
export class CliAliasService {
async generateAliases() {
const phpVersions = await phpManagerService.getVersions()
const mariaDbVersions = await mariaDbManagerService.getVersions()
const installedPhp = phpVersions.filter(v => v.status === 'installed')
const installedMariaDb = mariaDbVersions.filter(v => v.status === 'installed')
await this.generatePowerShellAliases(installedPhp, installedMariaDb)
await this.generateBashAliases(installedPhp, installedMariaDb)
}
private async generatePowerShellAliases(phpVersions: any[], mariaDbVersions: any[]) {
let content = '# MultiPHP PowerShell Aliases\n\n'
// PHP Aliases
for (const v of phpVersions) {
const binaryPath = await phpManagerService.getPhpBinaryPath(v.version)
if (binaryPath) {
const shortVersion = v.version.split('.').slice(0, 2).join('') // 7.4 -> 74
const majorVersion = v.version.split('.')[0] // 8.1 -> 8
content += `function php${v.version.replace(/\./g, '')} { & "${binaryPath}" @args }\n`
content += `function php${shortVersion} { & "${binaryPath}" @args }\n`
// If it's the latest of its major version (they are sorted descending)
const isLatestMajor = phpVersions.find(pv => pv.version.startsWith(majorVersion)) === v
if (isLatestMajor) {
content += `function php${majorVersion} { & "${binaryPath}" @args }\n`
}
}
}
// Global php (latest installed)
if (phpVersions.length > 0) {
const latestPhp = phpVersions[0]
const latestPath = await phpManagerService.getPhpBinaryPath(latestPhp.version)
if (latestPath) {
content += `function php { & "${latestPath}" @args }\n`
}
}
// MariaDB/MySQL Aliases
for (const v of mariaDbVersions) {
const binaryPath = await mariaDbManagerService.getMariaDbBinaryPath(v.version)
if (binaryPath) {
const shortVersion = v.version.split('.').slice(0, 2).join('') // 10.11 -> 1011
content += `function mysql${shortVersion} { & "${binaryPath}" @args }\n`
content += `function mariadb${shortVersion} { & "${binaryPath}" @args }\n`
}
}
// Global mysql/mariadb (latest installed)
if (mariaDbVersions.length > 0) {
const latestDb = mariaDbVersions[0]
const latestPath = await mariaDbManagerService.getMariaDbBinaryPath(latestDb.version)
if (latestPath) {
content += `function mysql { & "${latestPath}" @args }\n`
content += `function mariadb { & "${latestPath}" @args }\n`
}
}
const targetPath = configService.getGeneratedPath('aliases.ps1')
fs.writeFileSync(targetPath, content)
}
private async generateBashAliases(phpVersions: any[], mariaDbVersions: any[]) {
let content = '# MultiPHP Bash/Zsh Aliases\n\n'
// PHP Aliases
for (const v of phpVersions) {
const binaryPath = await phpManagerService.getPhpBinaryPath(v.version)
if (binaryPath) {
const normalizedPath = binaryPath.replace(/\\/g, '/')
const shortVersion = v.version.split('.').slice(0, 2).join('')
const majorVersion = v.version.split('.')[0]
content += `alias php${v.version.replace(/\./g, '')}='${normalizedPath}'\n`
content += `alias php${shortVersion}='${normalizedPath}'\n`
const isLatestMajor = phpVersions.find(pv => pv.version.startsWith(majorVersion)) === v
if (isLatestMajor) {
content += `alias php${majorVersion}='${normalizedPath}'\n`
}
}
}
if (phpVersions.length > 0) {
const latestPhp = phpVersions[0]
const latestPath = (await phpManagerService.getPhpBinaryPath(latestPhp.version))?.replace(/\\/g, '/')
if (latestPath) {
content += `alias php='${latestPath}'\n`
}
}
// MariaDB Aliases
for (const v of mariaDbVersions) {
const binaryPath = await mariaDbManagerService.getMariaDbBinaryPath(v.version)
if (binaryPath) {
const normalizedPath = binaryPath.replace(/\\/g, '/')
const shortVersion = v.version.split('.').slice(0, 2).join('')
content += `alias mysql${shortVersion}='${normalizedPath}'\n`
content += `alias mariadb${shortVersion}='${normalizedPath}'\n`
}
}
if (mariaDbVersions.length > 0) {
const latestDb = mariaDbVersions[0]
const latestPath = (await mariaDbManagerService.getMariaDbBinaryPath(latestDb.version))?.replace(/\\/g, '/')
if (latestPath) {
content += `alias mysql='${latestPath}'\n`
content += `alias mariadb='${latestPath}'\n`
}
}
const targetPath = configService.getGeneratedPath('aliases.sh')
fs.writeFileSync(targetPath, content)
}
}
export const cliAliasService = new CliAliasService()
@@ -135,6 +135,27 @@ export class MariaDbManagerService {
version.status = status version.status = status
} }
} }
async getMariaDbBinaryPath(version: string): Promise<string | null> {
const isWindows = process.platform === 'win32'
const binaryName = isWindows ? 'mariadbd.exe' : 'mariadbd'
const targetDir = path.join(this.binDir, `mariadb-${version}`)
const possibleBinPaths = [
path.join(targetDir, 'bin', binaryName),
path.join(targetDir, `mariadb-${version}-${isWindows ? 'winx64' : (process.arch === 'arm64' ? 'macosx-arm64' : 'macosx-x86_64')}`, 'bin', binaryName),
path.join(targetDir, `mariadb-${version}-${isWindows ? 'winx64' : 'linux-systemd-x86_64'}`, 'bin', binaryName)
]
for (const p of possibleBinPaths) {
if (fs.existsSync(p)) {
// Return mysql/mariadb client instead of the daemon for CLI usage
const clientName = isWindows ? 'mysql.exe' : 'mysql'
return path.join(path.dirname(p), clientName)
}
}
return null
}
} }
export const mariaDbManagerService = new MariaDbManagerService() export const mariaDbManagerService = new MariaDbManagerService()
+9 -7
View File
@@ -96,13 +96,6 @@ export class PhpManagerService {
}) })
} }
// Also check for supported versions list (e.g. older 8.x)
if (majorEntry.supported_versions) {
for (const branch of majorEntry.supported_versions) {
// This JSON doesn't give specific patch versions for these branches,
// but winData usually covers the latest of each branch anyway.
}
}
} }
// De-duplicate and sort // De-duplicate and sort
@@ -152,6 +145,15 @@ export class PhpManagerService {
version.status = status version.status = status
} }
} }
async getPhpBinaryPath(version: string): Promise<string | null> {
const targetDir = path.join(this.binDir, `php-${version}`)
const phpExe = path.join(targetDir, 'php.exe')
if (fs.existsSync(phpExe)) {
return phpExe
}
return null
}
} }
export const phpManagerService = new PhpManagerService() export const phpManagerService = new PhpManagerService()