package cmd import ( "fmt" "os" "path/filepath" "eval/internal/api" "eval/internal/config" "eval/internal/storage" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var ( cfg = config.NewConfig() ) var rootCmd = &cobra.Command{ Use: "eval", Short: "WYSIWYG Markdown Editor Server", Long: `Eval is a markdown editor with preview featuring Go backend and React frontend.`, Run: func(cmd *cobra.Command, args []string) { runServer(cmd) }, } func init() { cfg.AddFlags(rootCmd) rootCmd.PersistentFlags().String("log-level", "info", "Log level (debug, info, warn, error)") } func runServer(cmd *cobra.Command) { // Initialize logger logger := logrus.New() logger.SetFormatter(&logrus.TextFormatter{ FullTimestamp: true, }) logLevel, _ := cmd.Flags().GetString("log-level") if logLevel != "" { level, err := logrus.ParseLevel(logLevel) if err != nil { logger.Warnf("invalid log level: %v, using info", err) level = logrus.InfoLevel } logger.SetLevel(level) } // Validate config if err := cfg.Validate(); err != nil { logger.Fatalf("invalid configuration: %v", err) } // Ensure data directory exists if err := cfg.EnsureDataDir(); err != nil { logger.Fatalf("failed to create data directory: %v", err) } logger.Infof("using data directory: %s", cfg.DataDirPath()) // Initialize storage store := storage.NewStorage(cfg.DataDirPath()) // Initialize API handlers handlers := api.NewHandlers(store, cfg, logger) // Determine build directory (check both build and dist) buildDir := "./frontend/build" distDir := "./frontend/dist" if _, err := os.Stat(buildDir); os.IsNotExist(err) { if _, err := os.Stat(distDir); err == nil { buildDir = distDir } } if rel, err := filepath.Rel(cfg.DataDirPath(), buildDir); err == nil { buildDir = rel } logger.Infof("serving static files from: %s", buildDir) // Setup routes router, err := handlers.SetupRoutes(buildDir) if err != nil { logger.Fatalf("failed to setup routes: %v", err) } // Start server if err := handlers.StartServer(router); err != nil { logger.Fatalf("server error: %v", err) } } // Execute starts the root command // This is called from main.go in the main package func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }