Add DEBUG-gated panel to buy any card in the shop

When the server's DEBUG env var is on, expose a card catalog endpoint
and a collapsible client panel that drops any pet or food straight into
your deck (free, off-turn). Gated server-side so it is inert in normal
play.
This commit is contained in:
Greyson Parrelli
2026-07-23 01:07:14 -04:00
parent 71fa20493a
commit b2aa7c5ca3
13 changed files with 282 additions and 7 deletions
+14 -4
View File
@@ -22,17 +22,20 @@ import (
type Server struct {
store *store.Store
staticDir string
debug bool // DEBUG mode: unlocks the "buy any card" panel
mu sync.Mutex
rooms map[string]*room // by game ID
}
// New creates a server. staticDir is the built frontend to serve (may be
// empty or missing during backend-only development).
func New(st *store.Store, staticDir string) *Server {
// empty or missing during backend-only development). debug unlocks testing
// aids like the debug card panel.
func New(st *store.Store, staticDir string, debug bool) *Server {
return &Server{
store: st,
staticDir: staticDir,
debug: debug,
rooms: make(map[string]*room),
}
}
@@ -43,15 +46,22 @@ func (s *Server) Handler() http.Handler {
mux.HandleFunc("POST /api/games", s.handleCreate)
mux.HandleFunc("POST /api/join", s.handleJoin)
mux.HandleFunc("GET /api/ws", s.handleWS)
mux.HandleFunc("GET /api/catalog", s.handleCatalog)
mux.HandleFunc("/", s.handleStatic)
return mux
}
// handleCatalog returns every card in the game, for the debug panel.
func (s *Server) handleCatalog(w http.ResponseWriter, _ *http.Request) {
writeJSON(w, game.Catalog())
}
// room is one live game plus its connections.
type room struct {
mu sync.Mutex
game *game.Game
conns map[*client]struct{}
debug bool // mirrors Server.debug, for broadcastLocked
}
// getRoom returns the room for a game ID, loading it from the store if it
@@ -66,7 +76,7 @@ func (s *Server) getRoom(gameID string) (*room, error) {
if err != nil {
return nil, err
}
r := &room{game: g, conns: make(map[*client]struct{})}
r := &room{game: g, conns: make(map[*client]struct{}), debug: s.debug}
s.rooms[gameID] = r
return r, nil
}
@@ -117,7 +127,7 @@ func (s *Server) handleCreate(w http.ResponseWriter, req *http.Request) {
httpError(w, http.StatusBadRequest, err.Error())
return
}
r := &room{game: g, conns: make(map[*client]struct{})}
r := &room{game: g, conns: make(map[*client]struct{}), debug: s.debug}
s.mu.Lock()
s.rooms[g.ID] = r
s.mu.Unlock()