controller.go
56 lines1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package frontend
import (
"html/template"
"log"
"net/http"
"congo.gg/pkg/application"
)
// Controller returns a named controller that integrates the frontend bundler with the application.
func (f *Frontend) Controller() (string, *Controller) {
return "frontend", &Controller{frontend: f}
}
// Controller is the frontend controller that handles component bundling and serving.
type Controller struct {
frontend *Frontend
}
// Setup is called when the controller is registered with the application.
// It builds the components and registers routes.
func (c *Controller) Setup(app *application.App) {
// Build components
if err := c.frontend.Build(); err != nil {
if !c.frontend.DevMode {
// In production, fail loudly so broken JavaScript is caught early
log.Fatalf("[frontend] Build failed: %v", err)
}
log.Printf("[frontend] Build error: %v", err)
}
// Start file watcher for HMR in dev mode
if c.frontend.DevMode {
if err := c.frontend.Dev(); err != nil {
log.Printf("[frontend] Dev server error: %v", err)
}
}
// Register routes
http.HandleFunc("GET /_frontend/hmr", c.frontend.handleHMR)
http.HandleFunc("GET /_frontend/components.js", c.frontend.handleComponents)
http.HandleFunc("GET /_frontend/components.js.map", c.frontend.handleSourceMap)
// Register template functions
// frontend_script is a placeholder; the real per-request version is injected
// in render() via app.ScriptFunc with the CSP nonce.
app.Func("frontend_script", func() template.HTML { return c.frontend.Script("") })
app.ScriptFunc = c.frontend.Script
app.Func("render", c.frontend.Render)
}
// Handle implements the Controller interface (required but not used for frontend).
func (c *Controller) Handle(r *http.Request) application.Controller {
return c
}