feat: implement CLI binary service and add Turkish localization support
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
"allowRemoteAccess": false,
|
"allowRemoteAccess": false,
|
||||||
"language": "tr",
|
"language": "tr",
|
||||||
"cliEnvEnabled": true,
|
"cliEnvEnabled": true,
|
||||||
"defaultPhpVersion": "7.4.33",
|
"defaultPhpVersion": "php-7.4.33",
|
||||||
"defaultMariaDbVersion": "mariadb-11.4.2",
|
"defaultMariaDbVersion": "mariadb-11.4.2",
|
||||||
"mysqlPort": "3306",
|
"mysqlPort": "3306",
|
||||||
"mysqlPorts": {}
|
"mysqlPorts": {}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const execAsync = promisify(exec)
|
|||||||
|
|
||||||
export class CliBinService {
|
export class CliBinService {
|
||||||
private _binDir: string | null = null
|
private _binDir: string | null = null
|
||||||
private aliases: { command: string, target: string }[] = []
|
private aliases: { command: string, target: string, version: string }[] = []
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ export class CliBinService {
|
|||||||
for (const v of installedPhp) {
|
for (const v of installedPhp) {
|
||||||
const binaryPath = await phpManagerService.getPhpBinaryPath(v.version)
|
const binaryPath = await phpManagerService.getPhpBinaryPath(v.version)
|
||||||
if (binaryPath) {
|
if (binaryPath) {
|
||||||
|
const versionName = `PHP ${v.version}`
|
||||||
// version: 8.1.2 -> php812, php81, php8, php8.1
|
// version: 8.1.2 -> php812, php81, php8, php8.1
|
||||||
const vParts = v.version.split('.')
|
const vParts = v.version.split('.')
|
||||||
const aliases = [
|
const aliases = [
|
||||||
@@ -54,12 +55,13 @@ export class CliBinService {
|
|||||||
]
|
]
|
||||||
|
|
||||||
for (const alias of aliases) {
|
for (const alias of aliases) {
|
||||||
this.createWindowsShim(alias, binaryPath)
|
this.createWindowsShim(alias, binaryPath, versionName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the chosen default binary for general 'php'
|
// If this is the chosen default binary for general 'php'
|
||||||
if (settings.defaultPhpVersion === v.version) {
|
// Use v.id for more robust comparison if available, or fallback to version
|
||||||
this.createWindowsShim('php', binaryPath)
|
if (settings.defaultPhpVersion === v.id || settings.defaultPhpVersion === v.version) {
|
||||||
|
this.createWindowsShim('php', binaryPath, versionName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,13 +70,14 @@ export class CliBinService {
|
|||||||
if (!settings.defaultPhpVersion && installedPhp.length > 0) {
|
if (!settings.defaultPhpVersion && installedPhp.length > 0) {
|
||||||
const latest = installedPhp[0]
|
const latest = installedPhp[0]
|
||||||
const path = await phpManagerService.getPhpBinaryPath(latest.version)
|
const path = await phpManagerService.getPhpBinaryPath(latest.version)
|
||||||
if (path) this.createWindowsShim('php', path)
|
if (path) this.createWindowsShim('php', path, `PHP ${latest.version}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate MariaDB shims
|
// Generate MariaDB shims
|
||||||
for (const v of installedMariaDb) {
|
for (const v of installedMariaDb) {
|
||||||
const binaryPath = await mariaDbManagerService.getMariaDbBinaryPath(v.version)
|
const binaryPath = await mariaDbManagerService.getMariaDbBinaryPath(v.version)
|
||||||
if (binaryPath) {
|
if (binaryPath) {
|
||||||
|
const versionName = `MariaDB ${v.version}`
|
||||||
const vParts = v.version.split('.')
|
const vParts = v.version.split('.')
|
||||||
const aliases = [
|
const aliases = [
|
||||||
`mysql${vParts[0]}${vParts[1]}`,
|
`mysql${vParts[0]}${vParts[1]}`,
|
||||||
@@ -84,12 +87,12 @@ export class CliBinService {
|
|||||||
]
|
]
|
||||||
|
|
||||||
for (const alias of aliases) {
|
for (const alias of aliases) {
|
||||||
this.createWindowsShim(alias, binaryPath)
|
this.createWindowsShim(alias, binaryPath, versionName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.defaultMariaDbVersion === v.id) {
|
if (settings.defaultMariaDbVersion === v.id) {
|
||||||
this.createWindowsShim('mysql', binaryPath)
|
this.createWindowsShim('mysql', binaryPath, versionName)
|
||||||
this.createWindowsShim('mariadb', binaryPath)
|
this.createWindowsShim('mariadb', binaryPath, versionName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,8 +102,9 @@ export class CliBinService {
|
|||||||
const latest = installedMariaDb[0]
|
const latest = installedMariaDb[0]
|
||||||
const path = await mariaDbManagerService.getMariaDbBinaryPath(latest.version)
|
const path = await mariaDbManagerService.getMariaDbBinaryPath(latest.version)
|
||||||
if (path) {
|
if (path) {
|
||||||
this.createWindowsShim('mysql', path)
|
const vName = `MariaDB ${latest.version}`
|
||||||
this.createWindowsShim('mariadb', path)
|
this.createWindowsShim('mysql', path, vName)
|
||||||
|
this.createWindowsShim('mariadb', path, vName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,25 +114,19 @@ export class CliBinService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createWindowsShim(name: string, targetPath: string) {
|
private createWindowsShim(name: string, targetPath: string, version: string) {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
// For Unix we could use symlinks, but Multi-PHP target is mainly Windows for now
|
|
||||||
// Symlinks are also fine: fs.symlinkSync(targetPath, path.join(this.binDir, name))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a small .cmd proxy for each command
|
|
||||||
// Using "@%* " to pass all arguments correctly
|
|
||||||
const content = `@echo off\n"${targetPath}" %*\n`
|
const content = `@echo off\n"${targetPath}" %*\n`
|
||||||
const binDir = this.getBinDirInternal()
|
const binDir = this.getBinDirInternal()
|
||||||
fs.writeFileSync(path.join(binDir, `${name}.cmd`), content)
|
fs.writeFileSync(path.join(binDir, `${name}.cmd`), content)
|
||||||
|
|
||||||
// Also create a .bat just in case
|
|
||||||
fs.writeFileSync(path.join(binDir, `${name}.bat`), content)
|
fs.writeFileSync(path.join(binDir, `${name}.bat`), content)
|
||||||
|
|
||||||
// Track alias
|
// Track alias
|
||||||
if (!this.aliases.some(a => a.command === name)) {
|
if (!this.aliases.some(a => a.command === name)) {
|
||||||
this.aliases.push({ command: name, target: targetPath })
|
this.aliases.push({ command: name, target: targetPath, version })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useRef, useMemo } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import logo from './assets/logo.svg'
|
import logo from './assets/logo.svg'
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -1280,7 +1280,7 @@ function App(): JSX.Element {
|
|||||||
>
|
>
|
||||||
<MenuItem value=""><em>{t('common.ready')}</em></MenuItem>
|
<MenuItem value=""><em>{t('common.ready')}</em></MenuItem>
|
||||||
{phpVersions.filter(v => v.status === 'installed').map(v => (
|
{phpVersions.filter(v => v.status === 'installed').map(v => (
|
||||||
<MenuItem key={v.id} value={v.version}>PHP {v.version}</MenuItem>
|
<MenuItem key={v.id} value={v.id}>PHP {v.version}</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
<Typography variant="caption" color="text.secondary" sx={{ mt: 0.5 }}>{t('settings.cli_default_php_desc')}</Typography>
|
<Typography variant="caption" color="text.secondary" sx={{ mt: 0.5 }}>{t('settings.cli_default_php_desc')}</Typography>
|
||||||
@@ -1330,6 +1330,12 @@ function App(): JSX.Element {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{cliConfig.enabled && (
|
||||||
|
<Alert severity="info" sx={{ bgcolor: 'rgba(2, 136, 209, 0.1)', color: '#91d5ff', '& .MuiAlert-icon': { color: '#91d5ff' } }}>
|
||||||
|
{t('settings.cli_restart_warning')}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{cliConfig.aliases && cliConfig.aliases.length > 0 && (
|
{cliConfig.aliases && cliConfig.aliases.length > 0 && (
|
||||||
<Box sx={{ mt: 2 }}>
|
<Box sx={{ mt: 2 }}>
|
||||||
<Typography variant="subtitle2" sx={{ mb: 1, fontWeight: 600, color: 'primary.main' }}>
|
<Typography variant="subtitle2" sx={{ mb: 1, fontWeight: 600, color: 'primary.main' }}>
|
||||||
@@ -1340,10 +1346,17 @@ function App(): JSX.Element {
|
|||||||
{cliConfig.aliases.map((a: any) => (
|
{cliConfig.aliases.map((a: any) => (
|
||||||
<ListItem key={a.command} divider sx={{ py: 0.5, borderColor: 'rgba(255,255,255,0.05)' }}>
|
<ListItem key={a.command} divider sx={{ py: 0.5, borderColor: 'rgba(255,255,255,0.05)' }}>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={<code>{a.command}</code>}
|
primary={
|
||||||
|
<Box component="span" sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
<code>{a.command}</code>
|
||||||
|
<Typography variant="caption" sx={{ opacity: 0.5, fontWeight: 'normal' }}>
|
||||||
|
({a.version})
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
secondary={a.target}
|
secondary={a.target}
|
||||||
primaryTypographyProps={{ variant: 'body2', fontWeight: 'bold' }}
|
primaryTypographyProps={{ variant: 'body2', fontWeight: 'bold' }}
|
||||||
secondaryTypographyProps={{ variant: 'caption', sx: { opacity: 0.5 } }}
|
secondaryTypographyProps={{ variant: 'caption', sx: { opacity: 0.5, fontStyle: 'italic' } }}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -114,6 +114,7 @@
|
|||||||
"cli_path_not_found": "PATH Not Set Yet",
|
"cli_path_not_found": "PATH Not Set Yet",
|
||||||
"cli_sync_success": "CLI commands updated successfully.",
|
"cli_sync_success": "CLI commands updated successfully.",
|
||||||
"cli_aliases_title": "Generated Commands (Aliases)",
|
"cli_aliases_title": "Generated Commands (Aliases)",
|
||||||
|
"cli_restart_warning": "Notice: You must restart your terminal/CMD windows for PATH changes to take effect.",
|
||||||
"server_settings": "Server Settings"
|
"server_settings": "Server Settings"
|
||||||
},
|
},
|
||||||
"server": {
|
"server": {
|
||||||
|
|||||||
@@ -114,7 +114,8 @@
|
|||||||
"cli_path_found": "PATH Ayarı Bulundu:",
|
"cli_path_found": "PATH Ayarı Bulundu:",
|
||||||
"cli_path_not_found": "PATH Ayarı Henüz Yapılmamış",
|
"cli_path_not_found": "PATH Ayarı Henüz Yapılmamış",
|
||||||
"cli_sync_success": "CLI komutları başarıyla güncellendi.",
|
"cli_sync_success": "CLI komutları başarıyla güncellendi.",
|
||||||
"cli_aliases_title": "Oluşturulan Komutlar (Takma Adlar)"
|
"cli_aliases_title": "Oluşturulan Komutlar (Takma Adlar)",
|
||||||
|
"cli_restart_warning": "Dikkat: PATH değişikliklerinin geçerli olması için açık olan terminal/CMD pencerelerinizi kapatıp yeniden açmalısınız."
|
||||||
},
|
},
|
||||||
"server": {
|
"server": {
|
||||||
"nginx": {
|
"nginx": {
|
||||||
|
|||||||
Reference in New Issue
Block a user