package main import ( "database/sql" "embed" "flag" "fmt" "log" "os" "path/filepath" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" ) //go:embed all:frontend/dist var assets embed.FS // examplesDir returns the path to the examples/ directory. // Checks cwd first (wails dev), then next to the executable (production). func examplesDir() string { // 1. examples/ in cwd (wails dev runs from project root) if info, err := os.Stat("examples"); err == nil && info.IsDir() { return "examples" } // 2. examples/ next to the executable (production binary) if exePath, err := os.Executable(); err == nil { dir := filepath.Join(filepath.Dir(exePath), "examples") if info, err := os.Stat(dir); err == nil && info.IsDir() { return dir } } return "" } func firstYAML(dir string) string { entries, err := os.ReadDir(dir) if err != nil { return "" } for _, e := range entries { if !e.IsDir() && (filepath.Ext(e.Name()) == ".yaml" || filepath.Ext(e.Name()) == ".yml") { return filepath.Join(dir, e.Name()) } } return "" } func main() { // File logger for debugging logFile, err := os.OpenFile("rapid_dashboards.log", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) if err == nil { log.SetOutput(logFile) defer logFile.Close() } log.Printf("=== rapid_dashboards starting ===") log.Printf("os.Args: %v", os.Args) log.Printf("DASHBOARD env: %q", os.Getenv("DASHBOARD")) log.Printf("cwd: %s", func() string { d, _ := os.Getwd(); return d }()) dashboardPath := flag.String("dashboard", "", "path to dashboard YAML file") flag.Parse() log.Printf("flag --dashboard: %q", *dashboardPath) // Resolve examples directory — always used for listing/switching dashboards. dashDir := examplesDir() log.Printf("examples dir: %q", dashDir) // Fallback: CLI flag → env var → first YAML in examples/ if *dashboardPath == "" { if envPath := os.Getenv("DASHBOARD"); envPath != "" { *dashboardPath = envPath log.Printf("using DASHBOARD env var: %q", envPath) } else if dashDir != "" { if first := firstYAML(dashDir); first != "" { *dashboardPath = first log.Printf("auto-discovered dashboard: %q", first) } } } var cfg *DashboardConfig var pool map[string]*sql.DB if *dashboardPath == "" { log.Printf("NO dashboard path — using dummy config (bindings mode)") cfg = &DashboardConfig{ Settings: Settings{Title: "rapid-dashboards", Width: 1280, Height: 800, Columns: 12}, Queries: map[string]QueryDef{}, Filters: map[string]FilterDef{}, Sections: []SectionDef{}, Connections: map[string]ConnConfig{}, } } else { log.Printf("loading dashboard from: %q", *dashboardPath) var loadErr error cfg, loadErr = LoadDashboard(*dashboardPath) if loadErr != nil { log.Printf("ERROR loading dashboard: %v", loadErr) fmt.Fprintf(os.Stderr, "error loading dashboard: %v\n", loadErr) os.Exit(1) } log.Printf("dashboard loaded OK — title=%q sections=%d queries=%d", cfg.Settings.Title, len(cfg.Sections), len(cfg.Queries)) yamlDir := filepath.Dir(*dashboardPath) pool, loadErr = OpenConnections(cfg.Connections, yamlDir) if loadErr != nil { log.Printf("ERROR opening connections: %v", loadErr) fmt.Fprintf(os.Stderr, "error opening connections: %v\n", loadErr) os.Exit(1) } defer CloseConnections(pool) log.Printf("connections opened: %d", len(pool)) } engine := NewQueryEngine(cfg, pool) app := NewApp(cfg, engine, pool, dashDir, *dashboardPath) log.Printf("starting wails — title=%q width=%d height=%d layout=%q dashDir=%q", cfg.Settings.Title, cfg.Settings.Width, cfg.Settings.Height, cfg.Settings.Layout, dashDir) wailsOpts := &options.App{ Title: cfg.Settings.Title, Width: cfg.Settings.Width, Height: cfg.Settings.Height, AssetServer: &assetserver.Options{ Assets: assets, }, BackgroundColour: &options.RGBA{R: 10, G: 10, B: 15, A: 1}, OnStartup: app.startup, Bind: []interface{}{ app, }, } if cfg.Settings.Layout == "single_view" { wailsOpts.MaxWidth = cfg.Settings.Width wailsOpts.MaxHeight = cfg.Settings.Height wailsOpts.MinWidth = cfg.Settings.Width wailsOpts.MinHeight = cfg.Settings.Height wailsOpts.DisableResize = true } runErr := wails.Run(wailsOpts) if runErr != nil { log.Printf("ERROR wails.Run: %v", runErr) fmt.Fprintf(os.Stderr, "error: %v\n", runErr) os.Exit(1) } log.Printf("=== rapid_dashboards exited cleanly ===") }