package api import ( "io/fs" "net/http" "path" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/lerko/nib/internal/db" ) func NewRouter(store *db.Store, devMode bool, webFS ...fs.FS) chi.Router { r := chi.NewRouter() r.Use(middleware.Logger) r.Use(middleware.Recoverer) if devMode { r.Use(corsMiddleware) } r.Route("/api", func(r chi.Router) { r.Use(jsonContentType) r.Get("/entities", listEntities(store)) r.Post("/entities", createEntity(store)) r.Get("/entities/{id}", getEntity(store)) r.Put("/entities/{id}", updateEntity(store)) r.Delete("/entities/{id}", deleteEntity(store)) r.Post("/entities/{id}/promote", promoteEntity(store)) r.Post("/entities/{id}/demote", demoteEntity(store)) r.Post("/entities/{id}/use", useEntity(store)) r.Get("/tags", listTags(store)) }) if len(webFS) > 0 && webFS[0] != nil { r.Get("/*", spaHandler(webFS[0])) } return r } func spaHandler(fsys fs.FS) http.HandlerFunc { fileServer := http.FileServer(http.FS(fsys)) indexHTML, _ := fs.ReadFile(fsys, "index.html") return func(w http.ResponseWriter, r *http.Request) { p := r.URL.Path if p == "/" || path.Ext(p) == "" { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Write(indexHTML) return } fileServer.ServeHTTP(w, r) } } func jsonContentType(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") next.ServeHTTP(w, r) }) } func corsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) return } next.ServeHTTP(w, r) }) }