package main import ( "context" "embed" "fmt" "io/fs" "log" "net/http" "os" "path/filepath" "strings" originclient "git.warky.dev/wdevs/origin_client/go" "wedding-server/internal/api" "wedding-server/internal/config" "wedding-server/internal/mail" "wedding-server/internal/store" "wedding-server/internal/webhook" ) //go:embed all:web/dist var embeddedWeb embed.FS func main() { cfgPath := config.Path() cfg, err := config.Load(cfgPath) if err != nil { log.Fatalf("config: %v", err) } if err := os.MkdirAll(cfg.Storage.DataDir, 0o755); err != nil { log.Fatalf("data dir: %v", err) } st, err := store.Open(cfg.Storage.DataDir) if err != nil { log.Fatalf("store: %v", err) } defer st.Close() mailer := mail.New(cfg.Email) wh := webhook.New(cfg.Webhook) if cfg.Origin.ServiceKey == "" { log.Printf("origin registration disabled: origin.service_key is not configured") } else { origin, err := originclient.New(originclient.Config{ URL: cfg.Origin.URL, ServiceKey: cfg.Origin.ServiceKey, Type: "generic", Version: cfg.Origin.Version, Name: "ZoeShaldon", AppType: "go", Port: cfg.Server.Port, BaseURL: cfg.Site.URL, Description: "CronoCraft App - ZoeShaldon wedding site", }) if err != nil { log.Fatalf("origin client: %v", err) } go origin.Run(context.Background()) } mux := http.NewServeMux() api.New(cfg, st, mailer, wh).Routes(mux) uploadsDir := filepath.Join(cfg.Storage.DataDir, "photos") mux.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir(uploadsDir)))) webFS, err := fs.Sub(embeddedWeb, "web/dist") if err != nil { log.Fatalf("embedded web assets: %v", err) } mux.Handle("/", staticHandler(webFS)) addr := fmt.Sprintf(":%d", cfg.Server.Port) log.Printf("listening on %s", addr) if err := http.ListenAndServe(addr, mux); err != nil { log.Fatal(err) } } // staticHandler serves the prerendered SvelteKit build, where routes are // written as flat files (e.g. "rsvp.html") rather than "rsvp/index.html". func staticHandler(fsys fs.FS) http.Handler { fileServer := http.FileServer(http.FS(fsys)) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { p := strings.TrimPrefix(r.URL.Path, "/") if p == "" { p = "index.html" } if _, err := fs.Stat(fsys, p); err != nil { if _, err := fs.Stat(fsys, p+".html"); err == nil { r2 := *r r2.URL.Path = "/" + p + ".html" fileServer.ServeHTTP(w, &r2) return } } fileServer.ServeHTTP(w, r) }) }