diff --git a/app.go b/app.go index d2d6bb4..6a37606 100644 --- a/app.go +++ b/app.go @@ -1,7 +1,7 @@ package main import ( - "LocalValet/internal/platform" + configprovider "LocalValet/internal/config_provider" "LocalValet/internal/platform/domain" servicemonitor "LocalValet/internal/service_monitor" "context" @@ -18,6 +18,7 @@ type App struct { monitoringActive bool servicesToMonitor []string + configProvider configprovider.ConfigProvider serviceManager domain.ServiceManager monitor *servicemonitor.ServiceMonitor emitter servicemonitor.EventEmitter @@ -31,9 +32,10 @@ type LogMessage struct { } // NewApp creates a new App application struct -func NewApp() *App { +func NewApp(sm domain.ServiceManager, cf configprovider.ConfigProvider) *App { return &App{ - serviceManager: platform.NewServiceManager(), + serviceManager: sm, + configProvider: cf, } } @@ -44,11 +46,11 @@ func (a *App) startup(ctx context.Context) { a.ctx = ctx a.monitoringActive = true - configs := GetServiceConfigs() + configs := a.configProvider.GetServiceConfigs() a.servicesToMonitor = make([]string, 0, len(configs)) for _, config := range configs { - serviceName := GetServiceName(config.DisplayName) + serviceName := a.configProvider.GetServiceName(config.DisplayName) a.servicesToMonitor = append(a.servicesToMonitor, serviceName) } @@ -149,7 +151,7 @@ func (a *App) ToggleService(serviceName string, shouldStart bool) LogMessage { go func() { // Kita beri batas waktu maksimal 5 detik untuk status berubah. // Jika lebih dari 5 detik, kita menyerah (mencegah infinite loop). - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(a.ctx, 5*time.Second) defer cancel() // Cek setiap 200 milidetik @@ -195,18 +197,16 @@ func (a *App) GetAllServicesStatus() []domain.ServiceStatus { } // GetBinarySourceInfo returns information about where binaries are executed from -func (a *App) GetBinarySourceInfo() map[string]interface{} { - info := make(map[string]interface{}) - - info["os"] = runtime.GOOS - info["using_system_binaries"] = IsUsingSystemBinaries() +func (a *App) GetBinarySourceInfo() domain.BinarySourceInfo { + info := domain.BinarySourceInfo{ + OS: runtime.GOOS, + UsingSystemBinaries: IsUsingSystemBinaries(), + BinaryLocation: "system", + } if runtime.GOOS == "windows" { - info["binary_location"] = "bin/windows/" - info["binary_validation"] = ValidateWindowsBinaries() - } else { - info["binary_location"] = "system" - info["binary_validation"] = nil + info.BinaryLocation = "bin/windows/" + info.BinaryValidation = ValidateWindowsBinaries() } return info diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 2bfe3fc..ad327b9 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -7,9 +7,7 @@ export function CheckSudoAccess():Promise; export function GetAllServicesStatus():Promise>; -export function GetAvailableServices():Promise>; - -export function GetBinarySourceInfo():Promise>; +export function GetBinarySourceInfo():Promise; export function GetServiceStatus(arg1:string):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index c8b6c62..189fd55 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -10,10 +10,6 @@ export function GetAllServicesStatus() { return window['go']['main']['App']['GetAllServicesStatus'](); } -export function GetAvailableServices() { - return window['go']['main']['App']['GetAvailableServices'](); -} - export function GetBinarySourceInfo() { return window['go']['main']['App']['GetBinarySourceInfo'](); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index 1f952b6..4c53547 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -1,5 +1,23 @@ export namespace domain { + export class BinarySourceInfo { + os: string; + using_system_binaries: boolean; + binary_location: string; + binary_validation: any; + + static createFrom(source: any = {}) { + return new BinarySourceInfo(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.os = source["os"]; + this.using_system_binaries = source["using_system_binaries"]; + this.binary_location = source["binary_location"]; + this.binary_validation = source["binary_validation"]; + } + } export class ServiceStatus { name: string; isRunning: boolean; @@ -37,24 +55,6 @@ export namespace main { this.message = source["message"]; } } - export class ServiceConfig { - DisplayName: string; - Linux: string; - Darwin: string; - Windows: string; - - static createFrom(source: any = {}) { - return new ServiceConfig(source); - } - - constructor(source: any = {}) { - if ('string' === typeof source) source = JSON.parse(source); - this.DisplayName = source["DisplayName"]; - this.Linux = source["Linux"]; - this.Darwin = source["Darwin"]; - this.Windows = source["Windows"]; - } - } } diff --git a/internal/config_provider/provider.go b/internal/config_provider/provider.go new file mode 100644 index 0000000..92e9292 --- /dev/null +++ b/internal/config_provider/provider.go @@ -0,0 +1,87 @@ +package configprovider + +import "runtime" + +// 1. Definisikan Interface +type ConfigProvider interface { + GetServiceConfigs() []ServiceConfig + GetServiceName(displayName string) string +} + +// 2. Definisikan Struct Konkret (Implementasi Nyata) +type DefaultConfigProvider struct{} + +// 3. Buat Constructor +func NewConfigProvider() *DefaultConfigProvider { + return &DefaultConfigProvider{} +} + +// 4. Definisikan Struktur Data Config +type ServiceConfig struct { + DisplayName string + Linux string + Darwin string + Windows string +} + +// GetServiceConfigs returns all available service configurations +func (p *DefaultConfigProvider) GetServiceConfigs() []ServiceConfig { + return []ServiceConfig{ + { + DisplayName: "Apache", + Linux: "apache2", + Darwin: "httpd", + Windows: "Apache2.4", + }, + { + DisplayName: "MySQL", + Linux: "mysql", + Darwin: "mysql", + Windows: "MySQL80", + }, + { + DisplayName: "PostgreSQL", + Linux: "postgresql", + Darwin: "postgresql", + Windows: "PostgreSQL", + }, + { + DisplayName: "Redis", + Linux: "redis-server", + Darwin: "redis", + Windows: "Redis", + }, + { + DisplayName: "Nginx", + Linux: "nginx", + Darwin: "nginx", + Windows: "nginx", + }, + { + DisplayName: "PHP-FPM", + Linux: "php8.1-fpm", // or php7.4-fpm, adjust version + Darwin: "php", + Windows: "php-cgi", + }, + } +} + +// 6. Implementasi Method Interface: GetServiceName +// Logika ini dipindah ke sini agar App.go tidak pusing mikirin OS logic +func (p *DefaultConfigProvider) GetServiceName(displayName string) string { + configs := p.GetServiceConfigs() + + for _, config := range configs { + if config.DisplayName == displayName { + switch runtime.GOOS { + case "linux": + return config.Linux + case "darwin": + return config.Darwin + case "windows": + return config.Windows + } + } + } + return displayName +} diff --git a/internal/platform/domain/domain.go b/internal/platform/domain/domain.go index 833060d..9039563 100644 --- a/internal/platform/domain/domain.go +++ b/internal/platform/domain/domain.go @@ -12,3 +12,10 @@ type ServiceStatus struct { IsRunning bool `json:"isRunning"` Message string `json:"message"` } + +type BinarySourceInfo struct { + OS string `json:"os"` + UsingSystemBinaries bool `json:"using_system_binaries"` + BinaryLocation string `json:"binary_location"` + BinaryValidation interface{} `json:"binary_validation"` // Bisa dispesifikkan lagi jika strukturnya jelas +} diff --git a/main.go b/main.go index b8d8dc0..b6da540 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,8 @@ package main import ( + configprovider "LocalValet/internal/config_provider" + "LocalValet/internal/platform" "embed" "github.com/wailsapp/wails/v2" @@ -14,7 +16,10 @@ var assets embed.FS func main() { // Create an instance of the app structure - app := NewApp() + serviceManager := platform.NewServiceManager() + configProvider := configprovider.NewConfigProvider() + + app := NewApp(serviceManager, configProvider) // Create application with options err := wails.Run(&options.App{ diff --git a/service_config.go b/service_config.go deleted file mode 100644 index c268f35..0000000 --- a/service_config.go +++ /dev/null @@ -1,79 +0,0 @@ -package main - -import "runtime" - -// ServiceConfig holds service configuration for different platforms -type ServiceConfig struct { - DisplayName string - Linux string // systemctl service name - Darwin string // brew service name - Windows string // Windows service name -} - -// GetServiceConfigs returns all available service configurations -func GetServiceConfigs() []ServiceConfig { - return []ServiceConfig{ - { - DisplayName: "Apache", - Linux: "apache2", - Darwin: "httpd", - Windows: "Apache2.4", - }, - { - DisplayName: "MySQL", - Linux: "mysql", - Darwin: "mysql", - Windows: "MySQL80", - }, - { - DisplayName: "PostgreSQL", - Linux: "postgresql", - Darwin: "postgresql", - Windows: "PostgreSQL", - }, - { - DisplayName: "Redis", - Linux: "redis-server", - Darwin: "redis", - Windows: "Redis", - }, - { - DisplayName: "Nginx", - Linux: "nginx", - Darwin: "nginx", - Windows: "nginx", - }, - { - DisplayName: "PHP-FPM", - Linux: "php8.1-fpm", // or php7.4-fpm, adjust version - Darwin: "php", - Windows: "php-cgi", - }, - } -} - -// GetServiceName returns the appropriate service name for current OS -func GetServiceName(displayName string) string { - configs := GetServiceConfigs() - - for _, config := range configs { - if config.DisplayName == displayName { - switch runtime.GOOS { - case "linux": - return config.Linux - case "darwin": - return config.Darwin - case "windows": - return config.Windows - } - } - } - - // Return display name as fallback - return displayName -} - -// GetAvailableServices returns list of services for frontend -func (a *App) GetAvailableServices() []ServiceConfig { - return GetServiceConfigs() -} diff --git a/service_path.go b/service_path.go index a56f205..08fa630 100644 --- a/service_path.go +++ b/service_path.go @@ -1,6 +1,9 @@ package main +// ini masih kode sementara yaww + import ( + configprovider "LocalValet/internal/config_provider" "os" "path/filepath" "runtime" @@ -58,7 +61,7 @@ func GetExecutablePath(displayName string) string { } // For Linux/macOS, return the service name (system will find it) - return GetServiceName(displayName) + return configprovider.NewConfigProvider().GetServiceName(displayName) } // getWindowsExecutablePath constructs the full path to Windows binary @@ -68,13 +71,13 @@ func getWindowsExecutablePath(displayName string) string { if !exists { // Fallback to service name if config not found - return GetServiceName(displayName) + return configprovider.NewConfigProvider().GetServiceName(displayName) } // Get the executable directory (where the compiled binary is) exePath, err := os.Executable() if err != nil { - return GetServiceName(displayName) + return configprovider.NewConfigProvider().GetServiceName(displayName) } exeDir := filepath.Dir(exePath) @@ -93,7 +96,7 @@ func getWindowsExecutablePath(displayName string) string { } // Fallback to service name if binary not found - return GetServiceName(displayName) + return configprovider.NewConfigProvider().GetServiceName(displayName) } // GetServiceWorkingDirectory returns the working directory for the service