package api import ( "encoding/json" "errors" "net/http" "time" "github.com/google/uuid" "github.com/thepeterstone/claudomator/internal/storage" "github.com/thepeterstone/claudomator/internal/task" ) func (s *Server) handleListTemplates(w http.ResponseWriter, r *http.Request) { templates, err := s.store.ListTemplates() if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } if templates == nil { templates = []*storage.Template{} } writeJSON(w, http.StatusOK, templates) } func (s *Server) handleCreateTemplate(w http.ResponseWriter, r *http.Request) { var input struct { Name string `json:"name"` Description string `json:"description"` Claude task.ClaudeConfig `json:"claude"` Timeout string `json:"timeout"` Priority string `json:"priority"` Tags []string `json:"tags"` } if err := json.NewDecoder(r.Body).Decode(&input); err != nil { writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON: " + err.Error()}) return } if input.Name == "" { writeJSON(w, http.StatusBadRequest, map[string]string{"error": "name is required"}) return } now := time.Now().UTC() tmpl := &storage.Template{ ID: uuid.New().String(), Name: input.Name, Description: input.Description, Claude: input.Claude, Timeout: input.Timeout, Priority: input.Priority, Tags: input.Tags, CreatedAt: now, UpdatedAt: now, } if tmpl.Priority == "" { tmpl.Priority = "normal" } if tmpl.Tags == nil { tmpl.Tags = []string{} } if err := s.store.CreateTemplate(tmpl); err != nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } writeJSON(w, http.StatusCreated, tmpl) } func (s *Server) handleGetTemplate(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") tmpl, err := s.store.GetTemplate(id) if err != nil { if errors.Is(err, storage.ErrTemplateNotFound) { writeJSON(w, http.StatusNotFound, map[string]string{"error": "template not found"}) return } writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } writeJSON(w, http.StatusOK, tmpl) } // handleUpdateTemplate fully replaces all fields of the template identified by {id}. // All fields from the request body overwrite existing values; name is required. func (s *Server) handleUpdateTemplate(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") existing, err := s.store.GetTemplate(id) if err != nil { if errors.Is(err, storage.ErrTemplateNotFound) { writeJSON(w, http.StatusNotFound, map[string]string{"error": "template not found"}) return } writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } var input struct { Name string `json:"name"` Description string `json:"description"` Claude task.ClaudeConfig `json:"claude"` Timeout string `json:"timeout"` Priority string `json:"priority"` Tags []string `json:"tags"` } if err := json.NewDecoder(r.Body).Decode(&input); err != nil { writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON: " + err.Error()}) return } if input.Name == "" { writeJSON(w, http.StatusBadRequest, map[string]string{"error": "name is required"}) return } existing.Name = input.Name existing.Description = input.Description existing.Claude = input.Claude existing.Timeout = input.Timeout existing.Priority = input.Priority if input.Tags != nil { existing.Tags = input.Tags } existing.UpdatedAt = time.Now().UTC() if err := s.store.UpdateTemplate(existing); err != nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } writeJSON(w, http.StatusOK, existing) } func (s *Server) handleDeleteTemplate(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") err := s.store.DeleteTemplate(id) if err != nil { if errors.Is(err, storage.ErrTemplateNotFound) { writeJSON(w, http.StatusNotFound, map[string]string{"error": "template not found"}) return } writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } w.WriteHeader(http.StatusNoContent) }