From 59fb813c8507a731aabd3dba0fd6fb12c1410654 Mon Sep 17 00:00:00 2001 From: Simon Martens Date: Thu, 19 Feb 2026 15:09:44 +0100 Subject: [PATCH] Started server --- :wq | 46 +++++++++++++++++++++++++++++++++ app/app.go | 63 +++++++++------------------------------------ app/pages.go | 13 +--------- lenz.go | 30 +++++++-------------- pages/home.go | 10 ------- server/endpoints.go | 11 ++++++++ server/server.go | 36 ++++++++++++++++++++++++++ 7 files changed, 115 insertions(+), 94 deletions(-) create mode 100644 :wq create mode 100644 server/endpoints.go create mode 100644 server/server.go diff --git a/:wq b/:wq new file mode 100644 index 0000000..b3e8b7e --- /dev/null +++ b/:wq @@ -0,0 +1,46 @@ +package main + +import ( + "log/slog" + + "github.com/Theodor-Springmann-Stiftung/lenz-web/app" + "github.com/Theodor-Springmann-Stiftung/lenz-web/server" +) + +func main() { + cfg, err := GetConfig() + if err != nil { + panic(err) + } + + if cfg.Debug { + slog.SetLogLoggerLevel(slog.LevelDebug) + } + + application, err := app.New(cfg) + if err != nil { + panic(err) + } + + err = Serve(application) + if err != nil { + panic(err) + } +} + +func Serve(app *app.App) error { + server, err := server.NewServer(app) + if err != nil { + return err + } + server.Start() + return nil +} + +func GetConfig() (app.Config, error) { + cp := app.NewConfigProvider([]string{"config.dev.json", "config.json"}) + if err := cp.Read(); err != nil { + return app.Config{}, err + } + return *cp.Config, nil +} diff --git a/app/app.go b/app/app.go index de4213f..d997601 100644 --- a/app/app.go +++ b/app/app.go @@ -1,7 +1,6 @@ package app import ( - "fmt" "html/template" "path/filepath" "sync" @@ -12,12 +11,11 @@ import ( ) type App struct { - mu sync.Mutex - lib atomic.Pointer[xmlmodels.Library] - repo atomic.Pointer[git.Repo] - tmpl *template.Template - routes []Route - err error + mu sync.Mutex + lib atomic.Pointer[xmlmodels.Library] + repo atomic.Pointer[git.Repo] + tmpl atomic.Pointer[*template.Template] + cfg Config } func New(cfg Config) (*App, error) { @@ -37,39 +35,15 @@ func (a *App) Repo() *git.Repo { } func (a *App) Templates() *template.Template { - return a.tmpl + return *a.tmpl.Load() } -func (a *App) Routes() []Route { - a.mu.Lock() - defer a.mu.Unlock() - - ret := make([]Route, len(a.routes)) - copy(ret, a.routes) - return ret +func (a *App) Config() Config { + return a.cfg } -func (a *App) RenderPath(path string) ([]byte, error) { - a.mu.Lock() - var route *Route - for i := range a.routes { - if a.routes[i].Path == path { - r := a.routes[i] - route = &r - break - } - } - a.mu.Unlock() - - if route == nil || route.page == nil { - return nil, fmt.Errorf("no route for path: %s", path) - } - - model, err := route.page.Model(a, *route) - if err != nil { - return nil, err - } - return route.page.Render(a, *route, model) +func (a *App) Pages() []Page { + return RegisteredPages() } func (a *App) init(cfg Config) error { @@ -103,15 +77,9 @@ func (a *App) init(cfg Config) error { a.repo.Store(repo) a.lib.Store(lib) - a.tmpl = tmpl + a.tmpl.Store(&tmpl) - routes, err := discoverPages(a) - if err != nil { - return err - } - - a.routes = routes - a.err = nil + a.cfg = cfg return nil } @@ -126,12 +94,5 @@ func (a *App) RefreshLibrary(dir string, commit *git.Commit) (*xmlmodels.Library a.lib.Store(lib) - routes, err := discoverPages(a) - if err != nil { - return nil, err - } - - a.routes = routes - a.err = nil return lib, nil } diff --git a/app/pages.go b/app/pages.go index 6b28fae..8a44924 100644 --- a/app/pages.go +++ b/app/pages.go @@ -1,7 +1,5 @@ package app -import "sync" - type Route struct { Path string Kind string @@ -12,28 +10,19 @@ type Route struct { type Page interface { Discover(app *App) ([]Route, error) Model(app *App, route Route) (map[string]any, error) - Render(app *App, route Route, model map[string]any) ([]byte, error) } -var ( - pagesMu sync.RWMutex - pages []Page -) +var pages []Page func RegisterPage(page Page) { if page == nil { panic("cannot register nil page") } - pagesMu.Lock() - defer pagesMu.Unlock() pages = append(pages, page) } func RegisteredPages() []Page { - pagesMu.RLock() - defer pagesMu.RUnlock() - ret := make([]Page, len(pages)) copy(ret, pages) return ret diff --git a/lenz.go b/lenz.go index e9f6bb1..b3e8b7e 100644 --- a/lenz.go +++ b/lenz.go @@ -1,13 +1,10 @@ package main import ( - "io/fs" "log/slog" "github.com/Theodor-Springmann-Stiftung/lenz-web/app" - _ "github.com/Theodor-Springmann-Stiftung/lenz-web/pages" - "github.com/Theodor-Springmann-Stiftung/lenz-web/templates" - "github.com/labstack/echo/v5" + "github.com/Theodor-Springmann-Stiftung/lenz-web/server" ) func main() { @@ -25,28 +22,19 @@ func main() { panic(err) } - e := echo.New() - publicFS, err := fs.Sub(templates.PublicFS, "public") + err = Serve(application) if err != nil { panic(err) } - e.StaticFS("/public", publicFS) +} - for _, route := range application.Routes() { - routePath := route.Path - e.GET(routePath, func(c *echo.Context) error { - out, err := application.RenderPath(routePath) - if err != nil { - return err - } - return c.HTMLBlob(200, out) - }) - } - - addr := cfg.Address + ":" + cfg.Port - if err := e.Start(addr); err != nil { - panic(err) +func Serve(app *app.App) error { + server, err := server.NewServer(app) + if err != nil { + return err } + server.Start() + return nil } func GetConfig() (app.Config, error) { diff --git a/pages/home.go b/pages/home.go index 749f6a8..bee2394 100644 --- a/pages/home.go +++ b/pages/home.go @@ -1,8 +1,6 @@ package pages import ( - "bytes" - "github.com/Theodor-Springmann-Stiftung/lenz-web/app" ) @@ -23,11 +21,3 @@ func (p HomePage) Model(a *app.App, route app.Route) (map[string]any, error) { "Message": "Template system is working.", }, nil } - -func (p HomePage) Render(a *app.App, route app.Route, model map[string]any) ([]byte, error) { - var buf bytes.Buffer - if err := a.Templates().ExecuteTemplate(&buf, "home", model); err != nil { - return nil, err - } - return buf.Bytes(), nil -} diff --git a/server/endpoints.go b/server/endpoints.go new file mode 100644 index 0000000..f5df9b6 --- /dev/null +++ b/server/endpoints.go @@ -0,0 +1,11 @@ +package server + +import ( + "github.com/Theodor-Springmann-Stiftung/lenz-web/templates" + "github.com/labstack/echo/v5" +) + +func MapStatic(e *echo.Echo) { + // INFO: Static files here: + e.StaticFS("/public", templates.PublicFS) +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..3a73562 --- /dev/null +++ b/server/server.go @@ -0,0 +1,36 @@ +package server + +import ( + "html/template" + + "github.com/Theodor-Springmann-Stiftung/lenz-web/app" + "github.com/labstack/echo/v5" +) + +// WARNING: this is not thread-safe. You can not write and read from the server at the same time! +type Server struct { + server *echo.Echo + cfg app.Config + tmpl *template.Template +} + +func NewServer(app *app.App) (*Server, error) { + s := &Server{ + server: echo.New(), + cfg: app.Config(), + tmpl: app.Templates(), + } + + // INFO: Endpoint mapping here: + MapStatic(s.server) + + return s, nil +} + +func (s *Server) Start() error { + addr := s.cfg.Address + ":" + s.cfg.Port + if err := s.server.Start(addr); err != nil { + return err + } + return nil +}