refac: rethought the complete workflow and deployement flow ; docs etc.

This commit is contained in:
fsylvain committed 2026-09-23 17:36:36 +02:00
1 parent 4a6209a8db
commit 09bd5afa4a
26 files changed
+800 -334

No files matched your search

+12 -2
View File
@@ -86,8 +86,18 @@ func getUseCases(repos *Repositories) *UseCases {
}
}
func InitContainer() *UseCases {
func InitContainer() (*UseCases, func() error) {
db := getDb()
repos := getRepositories(db)
return getUseCases(repos)
return getUseCases(repos), closeDb(db)
}
func closeDb(db *gorm.DB) func() error {
return func() error {
sqlDb, err := db.DB()
if err != nil {
return err
}
return sqlDb.Close()
}
}
+33 -8
View File
@@ -5,13 +5,23 @@ import (
"io"
"io/fs"
"net/http"
"path/filepath"
"path"
"strings"
"time"
"github.com/go-chi/chi/v5"
)
const hashedAssetsPrefix = "assets/"
const (
hashedAssetCacheControl = "public, max-age=31536000, immutable"
staticFileCacheControl = "public, max-age=3600"
indexCacheControl = "no-store, no-cache, must-revalidate"
)
const devNotice = "RenewCMS was built with -tags nofrontend: the SPA is served by the Vite dev server (http://localhost:5173)."
type spaHandler struct {
staticFS fs.FS
modTime time.Time
@@ -20,9 +30,13 @@ type spaHandler struct {
func NewFrontendRouter() http.Handler {
r := chi.NewRouter()
distFS, _ := fs.Sub(assets.DistEmbed, "dist")
if assets.Dist == nil {
r.Get("/*", serveDevNotice)
return r
}
handler := &spaHandler{
staticFS: distFS,
staticFS: assets.Dist,
modTime: time.Now(),
}
@@ -30,6 +44,12 @@ func NewFrontendRouter() http.Handler {
return r
}
func serveDevNotice(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusNotFound)
_, _ = io.WriteString(w, devNotice)
}
func (h *spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path := h.cleanPath(r.URL.Path)
if h.fileExists(path) {
@@ -39,8 +59,8 @@ func (h *spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.serveIndex(w, r)
}
func (h *spaHandler) cleanPath(path string) string {
return strings.TrimPrefix(filepath.Clean(path), "/")
func (h *spaHandler) cleanPath(p string) string {
return strings.TrimPrefix(path.Clean("/"+p), "/")
}
func (h *spaHandler) fileExists(path string) bool {
@@ -52,11 +72,16 @@ func (h *spaHandler) fileExists(path string) bool {
return false
}
defer f.Close()
return true
stat, err := f.Stat()
return err == nil && !stat.IsDir()
}
func (h *spaHandler) serveAsset(w http.ResponseWriter, r *http.Request, path string) {
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
if strings.HasPrefix(path, hashedAssetsPrefix) {
w.Header().Set("Cache-Control", hashedAssetCacheControl)
} else {
w.Header().Set("Cache-Control", staticFileCacheControl)
}
http.FileServer(http.FS(h.staticFS)).ServeHTTP(w, r)
}
@@ -74,6 +99,6 @@ func (h *spaHandler) serveIndex(w http.ResponseWriter, r *http.Request) {
return
}
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate")
w.Header().Set("Cache-Control", indexCacheControl)
http.ServeContent(w, r, "index.html", h.modTime, content)
}
+23 -6
View File
@@ -12,6 +12,7 @@ import (
"github.com/MadAppGang/httplog"
"github.com/go-chi/chi/v5"
chimiddleware "github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"github.com/go-chi/jwtauth/v5"
)
@@ -55,6 +56,7 @@ func InitBackendRoutes(container *UseCases) *chi.Mux {
enableLoggingIfDev(r, "backend")
r.Use(chimiddleware.GetHead)
r.Use(middleware.JsonContentTypeMiddleware)
r.Get("/", GetHelloWorld)
r.Group(func(r chi.Router) {
@@ -77,19 +79,34 @@ func InitFrontendRoutes() *chi.Mux {
return r
}
func InitRoutes(container *UseCases) *chi.Mux {
backend := InitBackendRoutes(container)
frontend := InitFrontendRoutes()
func GetHealth(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
_, _ = w.Write([]byte("ok"))
}
apiRouter := chi.NewRouter()
apiRouter.Use(cors.Handler(cors.Options{
AllowedOrigins: strings.Split(os.Getenv("CORS_ALLOWED_ORIGINS"), ";"),
func enableCorsIfConfigured(r *chi.Mux) {
origins := os.Getenv("CORS_ALLOWED_ORIGINS")
if origins == "" {
return
}
r.Use(cors.Handler(cors.Options{
AllowedOrigins: strings.Split(origins, ";"),
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
ExposedHeaders: []string{"Link"},
AllowCredentials: false,
MaxAge: 300,
}))
}
func InitRoutes(container *UseCases) *chi.Mux {
backend := InitBackendRoutes(container)
frontend := InitFrontendRoutes()
apiRouter := chi.NewRouter()
enableCorsIfConfigured(apiRouter)
apiRouter.Use(chimiddleware.GetHead)
apiRouter.Get("/healthz", GetHealth)
apiRouter.Mount("/v1", backend)
apiRouter.Mount("/", frontend)