package api import ( "net/http" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/cors" "github.com/rs/zerolog" ) // NewRouter creates a new chi router with all routes registered. func NewRouter(server *Server, logger zerolog.Logger) http.Handler { r := chi.NewRouter() // Middleware stack r.Use(middleware.RequestID) r.Use(middleware.RealIP) r.Use(RequestLogger(logger)) r.Use(Recoverer(logger)) r.Use(cors.Handler(cors.Options{ AllowedOrigins: []string{"*"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-Request-ID"}, ExposedHeaders: []string{"Link", "X-Request-ID"}, AllowCredentials: false, MaxAge: 300, })) // Web handler for HTML pages webHandler, err := NewWebHandler(logger) if err != nil { logger.Fatal().Err(err).Msg("failed to create web handler") } // Health endpoints r.Get("/health", server.HandleHealth) r.Get("/ready", server.HandleReady) // Web UI routes r.Get("/", webHandler.HandleIndex) r.Get("/schemas", webHandler.HandleSchemasPage) // API routes r.Route("/api", func(r chi.Router) { // Schemas r.Route("/schemas", func(r chi.Router) { r.Get("/", server.HandleListSchemas) r.Get("/{name}", server.HandleGetSchema) r.Get("/{name}/properties", server.HandleGetPropertySchema) // Schema segment value management r.Route("/{name}/segments/{segment}/values", func(r chi.Router) { r.Post("/", server.HandleAddSchemaValue) r.Put("/{code}", server.HandleUpdateSchemaValue) r.Delete("/{code}", server.HandleDeleteSchemaValue) }) }) // Projects r.Route("/projects", func(r chi.Router) { r.Get("/", server.HandleListProjects) r.Post("/", server.HandleCreateProject) r.Get("/{code}", server.HandleGetProject) r.Put("/{code}", server.HandleUpdateProject) r.Delete("/{code}", server.HandleDeleteProject) r.Get("/{code}/items", server.HandleGetProjectItems) }) // Items r.Route("/items", func(r chi.Router) { r.Get("/", server.HandleListItems) r.Post("/", server.HandleCreateItem) // CSV Import/Export r.Get("/export.csv", server.HandleExportCSV) r.Post("/import", server.HandleImportCSV) r.Get("/template.csv", server.HandleCSVTemplate) r.Route("/{partNumber}", func(r chi.Router) { r.Get("/", server.HandleGetItem) r.Put("/", server.HandleUpdateItem) r.Delete("/", server.HandleDeleteItem) // Item project tags r.Get("/projects", server.HandleGetItemProjects) r.Post("/projects", server.HandleAddItemProjects) r.Delete("/projects/{code}", server.HandleRemoveItemProject) // Revisions r.Get("/revisions", server.HandleListRevisions) r.Post("/revisions", server.HandleCreateRevision) r.Get("/revisions/compare", server.HandleCompareRevisions) r.Get("/revisions/{revision}", server.HandleGetRevision) r.Patch("/revisions/{revision}", server.HandleUpdateRevision) r.Post("/revisions/{revision}/rollback", server.HandleRollbackRevision) // File upload/download r.Post("/file", server.HandleUploadFile) r.Get("/file", server.HandleDownloadLatestFile) r.Get("/file/{revision}", server.HandleDownloadFile) }) }) // Part number generation r.Post("/generate-part-number", server.HandleGeneratePartNumber) }) return r }