mirror of
https://github.com/HexCardGames/HexDeck.git
synced 2025-09-05 03:08:39 +02:00
Merge branch 'dev' into feature/game-view
This commit is contained in:
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
FROM node:23-alpine AS frontend
|
||||||
|
WORKDIR /frontend
|
||||||
|
COPY frontend/package*.json /frontend
|
||||||
|
RUN npm ci
|
||||||
|
RUN npm i @tailwindcss/oxide-linux-x64-musl
|
||||||
|
COPY frontend/ /frontend
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM golang:1.24-alpine AS backend
|
||||||
|
WORKDIR /backend
|
||||||
|
COPY backend/go.* /backend/
|
||||||
|
RUN go mod download
|
||||||
|
COPY backend/ /backend
|
||||||
|
COPY --from=frontend /frontend/dist/client/ /backend/public/
|
||||||
|
RUN go build -o HexDeck
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=backend /backend/HexDeck .
|
||||||
|
CMD ["/app/HexDeck"]
|
1
backend/.dockerignore
Normal file
1
backend/.dockerignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
HexDeck
|
@ -1,16 +1,12 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/HexCardGames/HexDeck/db"
|
"github.com/HexCardGames/HexDeck/db"
|
||||||
"github.com/HexCardGames/HexDeck/game"
|
"github.com/HexCardGames/HexDeck/game"
|
||||||
"github.com/HexCardGames/HexDeck/types"
|
"github.com/HexCardGames/HexDeck/types"
|
||||||
"github.com/HexCardGames/HexDeck/utils"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,10 +33,7 @@ type LeaveRoomRequest struct {
|
|||||||
SessionToken string
|
SessionToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitApi() {
|
func RegisterApi(server *gin.Engine) {
|
||||||
server := gin.Default()
|
|
||||||
server.SetTrustedProxies(nil)
|
|
||||||
|
|
||||||
server.GET("/api/stats", func(c *gin.Context) {
|
server.GET("/api/stats", func(c *gin.Context) {
|
||||||
stats := game.CalculateStats()
|
stats := game.CalculateStats()
|
||||||
c.JSON(http.StatusOK, StatsReply{
|
c.JSON(http.StatusOK, StatsReply{
|
||||||
@ -142,12 +135,4 @@ func InitApi() {
|
|||||||
// Handle WebSocket connections using Socket.io
|
// Handle WebSocket connections using Socket.io
|
||||||
wsHandler := initWS()
|
wsHandler := initWS()
|
||||||
server.Any("/socket.io/", gin.WrapH(wsHandler))
|
server.Any("/socket.io/", gin.WrapH(wsHandler))
|
||||||
|
|
||||||
listenHost := utils.Getenv("LISTEN_HOST", "0.0.0.0")
|
|
||||||
listenPort, err := strconv.Atoi(utils.Getenv("LISTEN_PORT", "3000"))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Value of variable PORT is not a valid integer!")
|
|
||||||
}
|
|
||||||
slog.Info(fmt.Sprintf("HexDeck server listening on http://%s:%d", listenHost, listenPort))
|
|
||||||
server.Run(fmt.Sprintf("%s:%d", listenHost, listenPort))
|
|
||||||
}
|
}
|
||||||
|
26
backend/api/static.go
Normal file
26
backend/api/static.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SPAMiddleware(fs embed.FS, prefix string, notFoundPath string) gin.HandlerFunc {
|
||||||
|
fileServer := http.FileServerFS(fs)
|
||||||
|
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
if strings.HasPrefix(c.Request.URL.Path, "/api/") {
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Request.URL.Path = prefix + c.Request.URL.Path
|
||||||
|
_, err := fs.Open(c.Request.URL.Path)
|
||||||
|
if err != nil {
|
||||||
|
c.Request.URL.Path = prefix + notFoundPath
|
||||||
|
}
|
||||||
|
fileServer.ServeHTTP(c.Writer, c.Request)
|
||||||
|
}
|
||||||
|
}
|
@ -70,13 +70,22 @@ func (conn *DatabaseConnection) QueryGlobalStats() GlobalStatsCollection {
|
|||||||
return stats
|
return stats
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateDBConnection(uri string) DatabaseConnection {
|
func CreateDBConnection(uri string) *DatabaseConnection {
|
||||||
client, _ := mongo.Connect(options.Client().ApplyURI(uri))
|
client, err := mongo.Connect(options.Client().ApplyURI(uri))
|
||||||
return DatabaseConnection{client}
|
if err != nil {
|
||||||
|
slog.Error("MongoDB connection failed", "error", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &DatabaseConnection{client}
|
||||||
}
|
}
|
||||||
|
|
||||||
var Conn DatabaseConnection
|
var Conn DatabaseConnection
|
||||||
|
|
||||||
func InitDB(uri string) {
|
func InitDB(uri string) bool {
|
||||||
Conn = CreateDBConnection(uri)
|
dbConn := CreateDBConnection(uri)
|
||||||
|
if dbConn == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Conn = *dbConn
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/HexCardGames/HexDeck/api"
|
"github.com/HexCardGames/HexDeck/api"
|
||||||
"github.com/HexCardGames/HexDeck/db"
|
"github.com/HexCardGames/HexDeck/db"
|
||||||
"github.com/HexCardGames/HexDeck/game"
|
"github.com/HexCardGames/HexDeck/game"
|
||||||
"github.com/HexCardGames/HexDeck/utils"
|
"github.com/HexCardGames/HexDeck/utils"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed all:public/*
|
||||||
|
var public embed.FS
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
logHandler := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
|
logHandler := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
|
||||||
Level: slog.LevelDebug,
|
Level: slog.LevelDebug,
|
||||||
@ -22,7 +30,11 @@ func main() {
|
|||||||
slog.Error("MONGO_URI environment variable not set!")
|
slog.Error("MONGO_URI environment variable not set!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
db.InitDB(mongoUri)
|
ok := db.InitDB(mongoUri)
|
||||||
|
if !ok {
|
||||||
|
slog.Error("Initializing MongoDB database failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
game.LoadRooms()
|
game.LoadRooms()
|
||||||
|
|
||||||
roomTicker := time.NewTicker(1 * time.Second)
|
roomTicker := time.NewTicker(1 * time.Second)
|
||||||
@ -35,5 +47,17 @@ func main() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
api.InitApi()
|
server := gin.Default()
|
||||||
|
server.SetTrustedProxies(nil)
|
||||||
|
|
||||||
|
api.RegisterApi(server)
|
||||||
|
server.Use(api.SPAMiddleware(public, "public", "/"))
|
||||||
|
|
||||||
|
listenHost := utils.Getenv("LISTEN_HOST", "0.0.0.0")
|
||||||
|
listenPort, err := strconv.Atoi(utils.Getenv("LISTEN_PORT", "3000"))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Value of variable PORT is not a valid integer!")
|
||||||
|
}
|
||||||
|
slog.Info(fmt.Sprintf("HexDeck server listening on http://%s:%d", listenHost, listenPort))
|
||||||
|
server.Run(fmt.Sprintf("%s:%d", listenHost, listenPort))
|
||||||
}
|
}
|
||||||
|
7
backend/public/README.md
Normal file
7
backend/public/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Static Frontend Hosting
|
||||||
|
|
||||||
|
All files in this directory will be merged into the server binary and served as static assets by the HexDeck server.
|
||||||
|
|
||||||
|
When building with docker, the compiled frontend will be copied here automatically.
|
||||||
|
|
||||||
|
If you are building manually, you can copy the contents of the `dist/client/` folder here after building the frontend.
|
16
docker-compose.yml
Normal file
16
docker-compose.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
services:
|
||||||
|
mongodb:
|
||||||
|
user: "1000"
|
||||||
|
volumes:
|
||||||
|
- ./data/mongodb/:/data/db/
|
||||||
|
image: mongodb/mongodb-community-server:latest
|
||||||
|
command: mongod --bind_ip_all
|
||||||
|
hexdeck:
|
||||||
|
user: "1000"
|
||||||
|
ports:
|
||||||
|
- 3000:3000
|
||||||
|
environment:
|
||||||
|
- MONGO_URI=mongodb://mongodb:27017/
|
||||||
|
depends_on:
|
||||||
|
- mongodb
|
||||||
|
build: .
|
26
frontend/.dockerignore
Normal file
26
frontend/.dockerignore
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
.routify/*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
Reference in New Issue
Block a user