129 lines
3 KiB
Go
129 lines
3 KiB
Go
package spahandler
|
|
|
|
import (
|
|
"fmt"
|
|
"io/fs"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"text/template"
|
|
|
|
"github.com/olivere/vite"
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"xtablo-backend/internal/frontend"
|
|
)
|
|
|
|
type handler struct {
|
|
distFS fs.FS
|
|
}
|
|
|
|
func NewHandler() *handler {
|
|
distFS, err := fs.Sub(frontend.DistFS, "dist")
|
|
if err != nil {
|
|
panic(fmt.Errorf("creating sub-filesystem for 'dist' directory: %w", err))
|
|
}
|
|
return &handler{
|
|
distFS: distFS,
|
|
}
|
|
}
|
|
|
|
func (h *handler) GetAssets() http.HandlerFunc {
|
|
return http.FileServerFS(h.distFS).ServeHTTP
|
|
}
|
|
|
|
func (h *handler) GetSpa() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
var err error
|
|
defer func() {
|
|
if err != nil {
|
|
log.Err(err).Msg(err.Error())
|
|
}
|
|
}()
|
|
|
|
if r.URL.Path == "/" || r.URL.Path == "/index.html" {
|
|
viteFragment, err := vite.HTMLFragment(vite.Config{
|
|
FS: h.distFS,
|
|
IsDev: false,
|
|
})
|
|
if err != nil {
|
|
log.Err(err).Msg(err.Error())
|
|
http.Error(w, "Error instantiating vite fragment", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
tmpl, err := template.New("index").Parse(indexTmpl)
|
|
if err != nil {
|
|
http.Error(w, "Error parsing template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if err = tmpl.Execute(w, map[string]interface{}{
|
|
"Vite": viteFragment,
|
|
}); err != nil {
|
|
http.Error(w, "Error executing template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// Serve the public files generated by Vite. By default, these files are
|
|
// referenced in the DOM with a root-relative URL format (e.g. '/file.ext').
|
|
http.ServeFileFS(w, r, h.distFS, filepath.Base(r.URL.Path))
|
|
}
|
|
}
|
|
|
|
func (h *handler) GetDevSpa() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
var err error
|
|
defer func() {
|
|
if err != nil {
|
|
log.Err(err).Msg(err.Error())
|
|
}
|
|
}()
|
|
if r.URL.Path == "/" || r.URL.Path == "/index.html" {
|
|
viteFragment, err := vite.HTMLFragment(vite.Config{
|
|
FS: os.DirFS("ui"),
|
|
IsDev: true,
|
|
ViteURL: "http://localhost:5173",
|
|
ViteTemplate: vite.SvelteTs,
|
|
ViteEntry: "/src/main.ts",
|
|
})
|
|
|
|
if err != nil {
|
|
http.Error(w, "Error instantiating vite fragment", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
tmpl, err := template.New("index").Parse(indexTmpl)
|
|
if err != nil {
|
|
http.Error(w, "Error parsing template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if err = tmpl.Execute(w, map[string]interface{}{
|
|
"Vite": viteFragment,
|
|
}); err != nil {
|
|
http.Error(w, "Error executing template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// Serve files in the public directory. By default, these files are
|
|
// referenced in the DOM with a root-relative URL format (e.g. '/file.ext').
|
|
http.ServeFileFS(w, r, os.DirFS("./public"), filepath.Base(r.URL.Path))
|
|
}
|
|
}
|
|
|
|
var indexTmpl = `<!doctype html>
|
|
<html lang="en" class="h-full scroll-smooth">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
{{ .Vite.Tags }}
|
|
</head>
|
|
<body class="w-100">
|
|
<div id="app"></div>
|
|
</body>
|
|
</html>
|
|
`
|