package main import ( "context" "embed" "fmt" "os" "path/filepath" "time" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" "go.uber.org/zap" "uzdb/internal/app" "uzdb/internal/config" "uzdb/internal/database" "uzdb/internal/handler" "uzdb/internal/services" ) //go:embed all:frontend/dist var assets embed.FS // application holds the global application state type application struct { app *app.App config *config.Config connManager *database.ConnectionManager encryptSvc *services.EncryptionService connectionSvc *services.ConnectionService querySvc *services.QueryService httpServer *handler.HTTPServer } func main() { // Initialize application appState, err := initApplication() if err != nil { fmt.Fprintf(os.Stderr, "Failed to initialize application: %v\n", err) os.Exit(1) } // Create Wails app with options err = wails.Run(&options.App{ Title: "uzdb", Width: 1024, Height: 768, AssetServer: &assetserver.Options{ Assets: assets, }, BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, OnStartup: func(ctx context.Context) { appState.app.OnStartup(ctx) }, OnShutdown: func(ctx context.Context) { appState.app.Shutdown() }, Bind: []interface{}{ appState.app, }, }) if err != nil { fmt.Fprintf(os.Stderr, "Error running application: %v\n", err) os.Exit(1) } } // initApplication initializes all application components func initApplication() (*application, error) { appState := &application{} // Determine data directory dataDir, err := getDataDirectory() if err != nil { return nil, fmt.Errorf("failed to get data directory: %w", err) } // Initialize configuration cfg, err := config.Init(dataDir) if err != nil { return nil, fmt.Errorf("failed to initialize config: %w", err) } appState.config = cfg logger := config.GetLogger() logger.Info("initializing application", zap.String("data_dir", dataDir)) // Initialize encryption service encryptSvc, err := services.InitEncryptionService(&cfg.Encryption) if err != nil { logger.Error("failed to initialize encryption service", zap.Error(err)) return nil, fmt.Errorf("failed to initialize encryption: %w", err) } appState.encryptSvc = encryptSvc // Initialize SQLite database (for app data) sqliteDB, err := database.InitSQLite(cfg.Database.SQLitePath, &cfg.Database) if err != nil { logger.Error("failed to initialize SQLite", zap.Error(err)) return nil, fmt.Errorf("failed to initialize database: %w", err) } // Initialize connection manager appState.connManager = database.NewConnectionManager() // Initialize services appState.connectionSvc = services.NewConnectionService( sqliteDB, appState.connManager, encryptSvc, ) appState.querySvc = services.NewQueryService(sqliteDB) // Initialize HTTP server (for debugging/API access) appState.httpServer = handler.NewHTTPServer( appState.connectionSvc, appState.querySvc, ) // Initialize Wails app wrapper appState.app = app.NewApp() appState.app.Initialize( cfg, appState.connectionSvc, appState.querySvc, appState.httpServer, ) logger.Info("application initialized successfully") return appState, nil } // getDataDirectory returns the appropriate data directory based on platform func getDataDirectory() (string, error) { // Check environment variable first if envDir := os.Getenv("UZDB_DATA_DIR"); envDir != "" { return envDir, nil } var dataDir string // Platform-specific directories switch os.Getenv("GOOS") { case "windows": appData := os.Getenv("APPDATA") if appData == "" { return "", fmt.Errorf("APPDATA environment variable not set") } dataDir = filepath.Join(appData, "uzdb") case "darwin": // macOS homeDir, err := os.UserHomeDir() if err != nil { return "", err } dataDir = filepath.Join(homeDir, "Library", "Application Support", "uzdb") default: // Linux and others // Try XDG data directory xdgData := os.Getenv("XDG_DATA_HOME") if xdgData != "" { dataDir = filepath.Join(xdgData, "uzdb") } else { homeDir, err := os.UserHomeDir() if err != nil { return "", err } dataDir = filepath.Join(homeDir, ".local", "share", "uzdb") } } // For development, use local directory if _, err := os.Stat("frontend"); err == nil { dataDir = "./data" } // Ensure directory exists if err := os.MkdirAll(dataDir, 0755); err != nil { return "", fmt.Errorf("failed to create data directory: %w", err) } return dataDir, nil } // Helper functions exposed for testing func GetVersion() string { return "1.0.0" } func GetBuildTime() string { return time.Now().Format(time.RFC3339) }