2 Commits

Author SHA1 Message Date
Ryan Hamamura
303c45cab1 feat: add downloader binary for client-side dependencies
All checks were successful
CI / Deploy / test (pull_request) Successful in 14s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
Replace the curl-based Taskfile download task with a Go binary that
concurrently fetches datastar.js, datastar.js.map, daisyui.mjs, and
daisyui-theme.mjs. Update vendored libs to latest versions.
2026-03-02 14:34:53 -10:00
Ryan Hamamura
587f392b8b fix: serve datastar locally and clean up session/route config
Replace CDN-hosted datastar beta.11 with local v1.0.0-RC.7 to fix
client-side expression incompatibilities with the Go SDK. Also fix
quoted CSS class keys in data-class expressions, harden session cookie
settings (named cookie, Secure flag), simplify SetupRoutes to not
return an error, and regenerate templ output.
2026-03-02 14:34:39 -10:00
18 changed files with 174 additions and 2175 deletions

View File

@@ -1,6 +1,11 @@
version: "3" version: "3"
tasks: tasks:
download:
desc: Download latest client-side libs
cmds:
- go run cmd/downloader/main.go
build:styles: build:styles:
desc: Build TailwindCSS styles desc: Build TailwindCSS styles
cmds: cmds:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

9
assets/js/datastar.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

100
cmd/downloader/main.go Normal file
View File

@@ -0,0 +1,100 @@
package main
import (
"errors"
"fmt"
"io"
"log/slog"
"net/http"
"os"
"path/filepath"
"sync"
)
// Asset directories, relative to project root.
const (
jsDir = "assets/js"
cssDir = "assets/css"
)
// files maps download URLs to local destination paths.
var files = map[string]string{
"https://raw.githubusercontent.com/starfederation/datastar/main/bundles/datastar.js": jsDir + "/datastar.js",
"https://raw.githubusercontent.com/starfederation/datastar/main/bundles/datastar.js.map": jsDir + "/datastar.js.map",
"https://github.com/saadeghi/daisyui/releases/latest/download/daisyui.mjs": cssDir + "/daisyui.mjs",
"https://github.com/saadeghi/daisyui/releases/latest/download/daisyui-theme.mjs": cssDir + "/daisyui-theme.mjs",
}
func main() {
if err := run(); err != nil {
slog.Error("failure", "error", err)
os.Exit(1)
}
}
func run() error {
dirs := []string{jsDir, cssDir}
for _, dir := range dirs {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("create directory %s: %w", dir, err)
}
}
return download(files)
}
func download(files map[string]string) error {
var wg sync.WaitGroup
errCh := make(chan error, len(files))
for url, dest := range files {
wg.Go(func() {
base := filepath.Base(dest)
slog.Info("downloading...", "file", base, "url", url)
if err := downloadFile(url, dest); err != nil {
errCh <- fmt.Errorf("download %s: %w", base, err)
} else {
slog.Info("finished", "file", base)
}
})
}
wg.Wait()
close(errCh)
var errs []error
for err := range errCh {
errs = append(errs, err)
}
return errors.Join(errs...)
}
func downloadFile(url, dest string) error {
resp, err := http.Get(url) //nolint:gosec,noctx // static URLs, simple tool
if err != nil {
return fmt.Errorf("GET %s: %w", url, err)
}
defer resp.Body.Close() //nolint:errcheck
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("GET %s: status %s", url, resp.Status)
}
out, err := os.Create(dest) //nolint:gosec // paths are hardcoded constants
if err != nil {
return fmt.Errorf("create %s: %w", dest, err)
}
if _, err := io.Copy(out, resp.Body); err != nil {
out.Close() //nolint:errcheck
return fmt.Errorf("write %s: %w", dest, err)
}
if err := out.Close(); err != nil {
return fmt.Errorf("close %s: %w", dest, err)
}
return nil
}

View File

@@ -46,33 +46,33 @@ func LoginPage() templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Login</h1><p class=\"mb-4\">Sign in to your account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Enter your username\" data-bind=\"username\" required autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Enter your password\" data-bind=\"password\" required data-on:keydown.key_enter=\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Login</h1><p class=\"mb-4\">Sign in to your account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><div><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Enter your username\" data-bind=\"username\" autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Enter your password\" data-bind=\"password\" data-on:keydown.key_enter=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var3 string var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login")) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 34, Col: 65} return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 32, Col: 65}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" type=\"button\" data-on:click=\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" data-on:click=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var4 string var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login")) templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/login"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 40, Col: 52} return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/login.templ`, Line: 37, Col: 52}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Login</button></form><p>Don't have an account? <a class=\"link\" href=\"/register\">Register</a></p></main>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Login</button></div><p>Don't have an account? <a class=\"link\" href=\"/register\">Register</a></p></main>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@@ -46,33 +46,33 @@ func RegisterPage() templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', confirm: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Register</h1><p class=\"mb-4\">Create a new account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Choose a username\" data-bind=\"username\" required autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Choose a password (min 8 chars)\" data-bind=\"password\" required> <label class=\"label\" for=\"confirm\">Confirm Password</label> <input class=\"input input-bordered w-full\" id=\"confirm\" type=\"password\" placeholder=\"Confirm your password\" data-bind=\"confirm\" required data-on:keydown.key_enter=\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<main class=\"max-w-sm mx-auto mt-8 text-center\" data-signals=\"{username: '', password: '', confirm: '', error: ''}\"><h1 class=\"text-3xl font-bold\">Register</h1><p class=\"mb-4\">Create a new account</p><div data-show=\"$error != ''\" class=\"alert alert-error mb-4\" data-text=\"$error\"></div><div><fieldset class=\"fieldset\"><label class=\"label\" for=\"username\">Username</label> <input class=\"input input-bordered w-full\" id=\"username\" type=\"text\" placeholder=\"Choose a username\" data-bind=\"username\" autofocus> <label class=\"label\" for=\"password\">Password</label> <input class=\"input input-bordered w-full\" id=\"password\" type=\"password\" placeholder=\"Choose a password (min 8 chars)\" data-bind=\"password\"> <label class=\"label\" for=\"confirm\">Confirm Password</label> <input class=\"input input-bordered w-full\" id=\"confirm\" type=\"password\" placeholder=\"Confirm your password\" data-bind=\"confirm\" data-on:keydown.key_enter=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var3 string var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register")) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 43, Col: 68} return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 40, Col: 68}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" type=\"button\" data-on:click=\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"></fieldset><button class=\"btn btn-primary w-full\" data-on:click=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var4 string var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register")) templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(datastar.PostSSE("/auth/register"))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 49, Col: 55} return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/auth/pages/register.templ`, Line: 45, Col: 55}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Register</button></form><p>Already have an account? <a class=\"link\" href=\"/login\">Login</a></p></main>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">Register</button></div><p>Already have an account? <a class=\"link\" href=\"/login\">Login</a></p></main>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@@ -8,11 +8,9 @@ import (
"github.com/ryanhamamura/c4/db/repository" "github.com/ryanhamamura/c4/db/repository"
) )
func SetupRoutes(router chi.Router, queries *repository.Queries, sessions *scs.SessionManager) error { func SetupRoutes(router chi.Router, queries *repository.Queries, sessions *scs.SessionManager) {
router.Get("/login", HandleLoginPage()) router.Get("/login", HandleLoginPage())
router.Get("/register", HandleRegisterPage()) router.Get("/register", HandleRegisterPage())
router.Post("/auth/login", HandleLogin(queries, sessions)) router.Post("/auth/login", HandleLogin(queries, sessions))
router.Post("/auth/register", HandleRegister(queries, sessions)) router.Post("/auth/register", HandleRegister(queries, sessions))
return nil
} }

View File

@@ -16,7 +16,7 @@ func SetupRoutes(
nc *nats.Conn, nc *nats.Conn,
sessions *scs.SessionManager, sessions *scs.SessionManager,
queries *repository.Queries, queries *repository.Queries,
) error { ) {
router.Route("/games/{id}", func(r chi.Router) { router.Route("/games/{id}", func(r chi.Router) {
r.Get("/", HandleGamePage(store, sessions, queries)) r.Get("/", HandleGamePage(store, sessions, queries))
r.Get("/events", HandleGameEvents(store, nc, sessions, queries)) r.Get("/events", HandleGameEvents(store, nc, sessions, queries))
@@ -25,6 +25,4 @@ func SetupRoutes(
r.Post("/join", HandleSetNickname(store, sessions)) r.Post("/join", HandleSetNickname(store, sessions))
r.Post("/rematch", HandleRematch(store, sessions)) r.Post("/rematch", HandleRematch(store, sessions))
}) })
return nil
} }

View File

@@ -44,7 +44,7 @@ func Base(title string) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"><script defer type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@starfederation/datastar@1.0.0-beta.11/dist/datastar.min.js\"></script><link href=\"/assets/css/output.css\" rel=\"stylesheet\" type=\"text/css\"></head><body class=\"flex flex-col h-screen\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"><script defer type=\"module\" src=\"/assets/js/datastar.js\"></script><link href=\"/assets/css/output.css\" rel=\"stylesheet\" type=\"text/css\"></head><body class=\"flex flex-col h-screen\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@@ -100,7 +100,7 @@ func LobbyPage(data LobbyData) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</h1><div class=\"tabs tabs-box mb-6 justify-center\"><button class=\"tab\" type=\"button\" data-class=\"{tab-active: $activeTab==='connect4'}\" data-on:click=\"$activeTab='connect4'\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</h1><div class=\"tabs tabs-box mb-6 justify-center\"><button class=\"tab\" type=\"button\" data-class=\"{'tab-active': $activeTab==='connect4'}\" data-on:click=\"$activeTab='connect4'\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@@ -108,7 +108,7 @@ func LobbyPage(data LobbyData) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</button> <button class=\"tab\" type=\"button\" data-class=\"{tab-active: $activeTab==='snake'}\" data-on:click=\"$activeTab='snake'\">~~~~</button></div><div data-show=\"$activeTab==='connect4'\"><p class=\"mb-4\">Start a new session</p><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"nickname\">Your Nickname</label> <input class=\"input input-bordered w-full\" id=\"nickname\" type=\"text\" placeholder=\"Enter your nickname\" data-bind=\"nickname\" required data-on:keydown.enter=\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</button> <button class=\"tab\" type=\"button\" data-class=\"{'tab-active': $activeTab==='snake'}\" data-on:click=\"$activeTab='snake'\">~~~~</button></div><div data-show=\"$activeTab==='connect4'\"><p class=\"mb-4\">Start a new session</p><form><fieldset class=\"fieldset\"><label class=\"label\" for=\"nickname\">Your Nickname</label> <input class=\"input input-bordered w-full\" id=\"nickname\" type=\"text\" placeholder=\"Enter your nickname\" data-bind=\"nickname\" required data-on:keydown.enter=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@@ -152,9 +152,9 @@ func LobbyPage(data LobbyData) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var7 string var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("{btn-active: $selectedSpeed===%d}", i)) templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("{'btn-active': $selectedSpeed===%d}", i))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 113, Col: 72} return templ.Error{Err: templ_7745c5c3_Err, FileName: `features/lobby/pages/lobby.templ`, Line: 113, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {

View File

@@ -16,13 +16,11 @@ func SetupRoutes(
sessions *scs.SessionManager, sessions *scs.SessionManager,
store *game.GameStore, store *game.GameStore,
snakeStore *snake.SnakeStore, snakeStore *snake.SnakeStore,
) error { ) {
router.Get("/", HandleLobbyPage(queries, sessions, snakeStore)) router.Get("/", HandleLobbyPage(queries, sessions, snakeStore))
router.Post("/games", HandleCreateGame(store, sessions)) router.Post("/games", HandleCreateGame(store, sessions))
router.Delete("/games/{id}", HandleDeleteGame(store, sessions)) router.Delete("/games/{id}", HandleDeleteGame(store, sessions))
router.Post("/snake", HandleCreateSnakeGame(snakeStore, sessions)) router.Post("/snake", HandleCreateSnakeGame(snakeStore, sessions))
router.Post("/logout", HandleLogout(sessions)) router.Post("/logout", HandleLogout(sessions))
return nil
} }

View File

@@ -9,7 +9,7 @@ import (
"github.com/ryanhamamura/c4/snake" "github.com/ryanhamamura/c4/snake"
) )
func SetupRoutes(router chi.Router, snakeStore *snake.SnakeStore, nc *nats.Conn, sessions *scs.SessionManager) error { func SetupRoutes(router chi.Router, snakeStore *snake.SnakeStore, nc *nats.Conn, sessions *scs.SessionManager) {
router.Route("/snake/{id}", func(r chi.Router) { router.Route("/snake/{id}", func(r chi.Router) {
r.Get("/", HandleSnakePage(snakeStore, sessions)) r.Get("/", HandleSnakePage(snakeStore, sessions))
r.Get("/events", HandleSnakeEvents(snakeStore, nc, sessions)) r.Get("/events", HandleSnakeEvents(snakeStore, nc, sessions))
@@ -18,6 +18,4 @@ func SetupRoutes(router chi.Router, snakeStore *snake.SnakeStore, nc *nats.Conn,
r.Post("/join", HandleSetNickname(snakeStore, sessions)) r.Post("/join", HandleSetNickname(snakeStore, sessions))
r.Post("/rematch", HandleRematch(snakeStore, sessions)) r.Post("/rematch", HandleRematch(snakeStore, sessions))
}) })
return nil
} }

View File

@@ -90,9 +90,7 @@ func run(ctx context.Context) error {
sessionManager.LoadAndSave, sessionManager.LoadAndSave,
) )
if err := router.SetupRoutes(r, queries, sessionManager, nc, store, snakeStore, assets); err != nil { router.SetupRoutes(r, queries, sessionManager, nc, store, snakeStore, assets)
return fmt.Errorf("setting up routes: %w", err)
}
// HTTP server // HTTP server
srv := &http.Server{ srv := &http.Server{

View File

@@ -30,7 +30,7 @@ func SetupRoutes(
store *game.GameStore, store *game.GameStore,
snakeStore *snake.SnakeStore, snakeStore *snake.SnakeStore,
assets embed.FS, assets embed.FS,
) error { ) {
// Static assets // Static assets
subFS, _ := fs.Sub(assets, "assets") subFS, _ := fs.Sub(assets, "assets")
router.Handle("/assets/*", http.StripPrefix("/assets/", http.FileServerFS(subFS))) router.Handle("/assets/*", http.StripPrefix("/assets/", http.FileServerFS(subFS)))
@@ -40,20 +40,10 @@ func SetupRoutes(
setupReload(router) setupReload(router)
} }
if err := auth.SetupRoutes(router, queries, sessions); err != nil { auth.SetupRoutes(router, queries, sessions)
return err lobby.SetupRoutes(router, queries, sessions, store, snakeStore)
} c4game.SetupRoutes(router, store, nc, sessions, queries)
if err := lobby.SetupRoutes(router, queries, sessions, store, snakeStore); err != nil { snakegame.SetupRoutes(router, snakeStore, nc, sessions)
return err
}
if err := c4game.SetupRoutes(router, store, nc, sessions, queries); err != nil {
return err
}
if err := snakegame.SetupRoutes(router, snakeStore, nc, sessions); err != nil {
return err
}
return nil
} }
func setupReload(router chi.Router) { func setupReload(router chi.Router) {

View File

@@ -20,9 +20,10 @@ func SetupSessionManager(db *sql.DB) (*scs.SessionManager, func()) {
sessionManager := scs.New() sessionManager := scs.New()
sessionManager.Store = store sessionManager.Store = store
sessionManager.Lifetime = 30 * 24 * time.Hour sessionManager.Lifetime = 30 * 24 * time.Hour
sessionManager.Cookie.Name = "c4_session"
sessionManager.Cookie.Path = "/" sessionManager.Cookie.Path = "/"
sessionManager.Cookie.HttpOnly = true sessionManager.Cookie.HttpOnly = true
sessionManager.Cookie.Secure = false sessionManager.Cookie.Secure = true
sessionManager.Cookie.SameSite = http.SameSiteLaxMode sessionManager.Cookie.SameSite = http.SameSiteLaxMode
slog.Info("session manager configured") slog.Info("session manager configured")