// Command server runs the Super Auto Pets board game server: game API, // WebSocket sync, and the built web frontend. package main import ( "context" "errors" "log/slog" "net/http" "os" "os/signal" "strings" "syscall" "time" "github.com/greyson/super-auto-pets-board-game/internal/env" "github.com/greyson/super-auto-pets-board-game/internal/server" "github.com/greyson/super-auto-pets-board-game/internal/store" ) // isTruthy reports whether an env value means "on". func isTruthy(v string) bool { switch strings.ToLower(strings.TrimSpace(v)) { case "1", "true", "yes", "on": return true } return false } func main() { if err := env.Load(".env"); err != nil { slog.Error("failed to read .env", "err", err) os.Exit(1) } dataDir := env.Get("DATA_DIR", "data") port := env.Get("PORT", "8080") staticDir := env.Get("STATIC_DIR", "web/dist") debug := isTruthy(env.Get("DEBUG", "")) if debug { slog.Warn("DEBUG mode on: the buy-any-card panel is enabled") } st, err := store.Open(dataDir) if err != nil { slog.Error("failed to open store", "err", err) os.Exit(1) } defer st.Close() if _, err := os.Stat(staticDir); err != nil { slog.Warn("static dir missing; only the API will be served", "dir", staticDir) staticDir = "" } srv := &http.Server{ Addr: ":" + port, Handler: server.New(st, staticDir, debug).Handler(), } go func() { slog.Info("listening", "addr", "http://localhost:"+port, "dataDir", dataDir) if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { slog.Error("server failed", "err", err) os.Exit(1) } }() stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt, syscall.SIGTERM) <-stop slog.Info("shutting down") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() srv.Shutdown(ctx) }