261a6294cb
* added dynamic configuration of Port in Desktop app * added dynamic configuration of API_URL to docker deployments. Now it works with editing only .env file.
178 lines
4.9 KiB
Go
178 lines
4.9 KiB
Go
// BaMoRT Desktop application entry point.
|
|
// Uses Wails v2 to wrap the existing Gin HTTP server in a native desktop window.
|
|
// The backend runs on localhost:8185 (SQLite); the WebView loads the bundled frontend.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"embed"
|
|
"io/fs"
|
|
"log"
|
|
"os"
|
|
"time"
|
|
|
|
"bamort/appsystem"
|
|
"bamort/character"
|
|
"bamort/config"
|
|
"bamort/database"
|
|
"bamort/equipment"
|
|
"bamort/gamesystem"
|
|
"bamort/gsmaster"
|
|
"bamort/importer"
|
|
"bamort/logger"
|
|
"bamort/maintenance"
|
|
"bamort/models"
|
|
"bamort/pdfrender"
|
|
"bamort/router"
|
|
"bamort/transfer"
|
|
"bamort/user"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/wailsapp/wails/v2"
|
|
"github.com/wailsapp/wails/v2/pkg/options"
|
|
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
|
)
|
|
|
|
// frontend/dist is populated by `wails build` running the frontend:build command
|
|
// in wails.json (outputs to ../desktop/frontend/dist via DESKTOP_BUILD=1).
|
|
//
|
|
//go:embed all:frontend/dist
|
|
var assets embed.FS
|
|
|
|
// App is the Wails application struct. Lifecycle hooks are attached to it.
|
|
type App struct {
|
|
ctx context.Context
|
|
}
|
|
|
|
// NewApp creates the Wails application instance.
|
|
func NewApp() *App {
|
|
return &App{}
|
|
}
|
|
|
|
// startup is called by Wails just before the WebView window is shown.
|
|
// It starts the Gin HTTP server in the background so the frontend can reach it.
|
|
func (a *App) startup(ctx context.Context) {
|
|
a.ctx = ctx
|
|
startGinServer()
|
|
}
|
|
|
|
// GetAPIBaseURL returns the HTTP server address for the frontend to connect to.
|
|
// This allows the API port to be configured at runtime via .env without rebuilding.
|
|
func (a *App) GetAPIBaseURL() string {
|
|
// GetServerAddress returns ":port", so we need to add localhost
|
|
return "http://localhost" + config.Cfg.GetServerAddress()
|
|
}
|
|
|
|
// startGinServer initialises the database, runs migrations, and starts the
|
|
// Gin HTTP server on the configured port (default 8185) in a goroutine.
|
|
func startGinServer() {
|
|
cfg := config.Cfg
|
|
|
|
logger.Info("BaMoRT Desktop Server wird gestartet...")
|
|
logger.Info("Environment: %s", cfg.Environment)
|
|
logger.Info("Database: %s @ %s", cfg.DatabaseType, cfg.DatabaseURL)
|
|
|
|
gin.SetMode(gin.ReleaseMode)
|
|
|
|
// Connect to SQLite database.
|
|
database.ConnectDatabase()
|
|
|
|
// Auto-migrate all modules so a fresh SQLite file gets a complete schema.
|
|
if err := models.MigrateStructure(); err != nil {
|
|
logger.Warn("models migration: %s", err.Error())
|
|
}
|
|
if err := user.MigrateStructure(); err != nil {
|
|
logger.Warn("user migration: %s", err.Error())
|
|
}
|
|
if err := gamesystem.MigrateStructure(); err != nil {
|
|
logger.Warn("gamesystem migration: %s", err.Error())
|
|
}
|
|
if err := database.MigrateStructure(); err != nil {
|
|
logger.Warn("database migration: %s", err.Error())
|
|
}
|
|
|
|
// Initialise PDF templates (source from ./default_templates if present).
|
|
if err := pdfrender.InitializeTemplates("./default_templates", cfg.TemplatesDir); err != nil {
|
|
logger.Warn("template init: %s", err.Error())
|
|
}
|
|
|
|
r := gin.Default()
|
|
router.SetupGin(r)
|
|
|
|
protected := router.BaseRouterGrp(r)
|
|
user.RegisterRoutes(protected)
|
|
gsmaster.RegisterRoutes(protected)
|
|
character.RegisterRoutes(protected)
|
|
equipment.RegisterRoutes(protected)
|
|
maintenance.RegisterRoutes(protected)
|
|
importer.RegisterRoutes(protected)
|
|
pdfrender.RegisterRoutes(protected)
|
|
transfer.RegisterRoutes(protected)
|
|
appsystem.RegisterRoutes(protected)
|
|
|
|
pdfrender.RegisterPublicRoutes(r)
|
|
appsystem.RegisterPublicRoutes(r)
|
|
|
|
logger.Info("Desktop API server starting on %s", cfg.GetServerAddress())
|
|
go func() {
|
|
if err := r.Run(cfg.GetServerAddress()); err != nil {
|
|
log.Printf("Gin server error: %v", err)
|
|
}
|
|
}()
|
|
|
|
// Brief pause to let the HTTP server bind before the WebView starts loading.
|
|
time.Sleep(150 * time.Millisecond)
|
|
}
|
|
|
|
func main() {
|
|
// Apply desktop defaults BEFORE anything uses config.Cfg.
|
|
// config.init() already ran (at import time) and may have picked up .env;
|
|
// here we ensure the critical SQLite settings exist even without a .env file.
|
|
if os.Getenv("DATABASE_TYPE") == "" {
|
|
_ = os.Setenv("DATABASE_TYPE", "sqlite")
|
|
}
|
|
if os.Getenv("DATABASE_URL") == "" {
|
|
_ = os.Setenv("DATABASE_URL", "./bamort-desktop.db")
|
|
}
|
|
if os.Getenv("ENVIRONMENT") == "" {
|
|
_ = os.Setenv("ENVIRONMENT", "desktop")
|
|
}
|
|
if os.Getenv("API_PORT") == "" {
|
|
_ = os.Setenv("API_PORT", "8185")
|
|
}
|
|
if os.Getenv("TEMPLATES_DIR") == "" {
|
|
_ = os.Setenv("TEMPLATES_DIR", "./templates")
|
|
}
|
|
if os.Getenv("EXPORT_TEMP_DIR") == "" {
|
|
_ = os.Setenv("EXPORT_TEMP_DIR", "./export_temp")
|
|
}
|
|
|
|
// Reload config so the above env vars take effect (init() may have run first).
|
|
config.Cfg = config.LoadConfig()
|
|
|
|
// Sub-FS rooted at frontend/dist so Wails serves it from /.
|
|
frontendFS, err := fs.Sub(assets, "frontend/dist")
|
|
if err != nil {
|
|
log.Fatal("frontend/dist embed error:", err)
|
|
}
|
|
|
|
app := NewApp()
|
|
|
|
if err := wails.Run(&options.App{
|
|
Title: "BaMoRT",
|
|
Width: 1400,
|
|
Height: 900,
|
|
MinWidth: 1024,
|
|
MinHeight: 768,
|
|
OnStartup: app.startup,
|
|
Bind: []interface{}{
|
|
app,
|
|
},
|
|
AssetServer: &assetserver.Options{
|
|
Assets: frontendFS,
|
|
},
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|