package api import ( "fmt" "net/http" "git.jnss.me/joakim/opal/internal/api/handlers" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" ) // Server represents the API server type Server struct { router chi.Router addr string } // NewServer creates a new API server func NewServer(addr string) *Server { s := &Server{ router: chi.NewRouter(), addr: addr, } s.setupRoutes() return s } // setupRoutes configures all API routes func (s *Server) setupRoutes() { r := s.router // Global middleware r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(CORSMiddleware()) // Health check (no auth required) r.Get("/health", func(w http.ResponseWriter, r *http.Request) { JSON(w, http.StatusOK, map[string]string{"status": "ok"}) }) // Protected routes r.Group(func(r chi.Router) { r.Use(AuthMiddleware()) // Tasks r.Route("/tasks", func(r chi.Router) { r.Get("/", handlers.ListTasks) r.Post("/", handlers.CreateTask) r.Get("/{uuid}", handlers.GetTask) r.Put("/{uuid}", handlers.UpdateTask) r.Delete("/{uuid}", handlers.DeleteTask) r.Post("/{uuid}/complete", handlers.CompleteTask) r.Post("/{uuid}/start", handlers.StartTask) r.Post("/{uuid}/stop", handlers.StopTask) // Tags r.Get("/{uuid}/tags", handlers.GetTaskTags) r.Post("/{uuid}/tags", handlers.AddTaskTag) r.Delete("/{uuid}/tags/{tag}", handlers.RemoveTaskTag) }) // Metadata r.Get("/tags", handlers.ListAllTags) r.Get("/projects", handlers.ListProjects) // Sync endpoints r.Post("/sync/changes", handlers.GetChanges) r.Post("/sync/push", handlers.PushChanges) // Key management r.Get("/auth/keys", handlers.ListAPIKeys) r.Delete("/auth/keys/{id}", handlers.RevokeAPIKey) }) } // Start starts the HTTP server func (s *Server) Start() error { fmt.Printf("Starting opal API server on %s\n", s.addr) return http.ListenAndServe(s.addr, s.router) }