Files
Bardioc26 261a6294cb Desktop app dynamic config of API Port (#40)
* 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.
2026-02-27 11:55:30 +01:00

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)
}
}