package api import ( "errors" "net/http" "strings" "github.com/alexei/tinyforge/internal/store" "github.com/go-chi/chi/v5" ) // listApps handles GET /api/apps. func (s *Server) listApps(w http.ResponseWriter, r *http.Request) { out, err := s.store.ListApps() if err != nil { respondError(w, http.StatusInternalServerError, "list apps") return } respondJSON(w, http.StatusOK, out) } // getApp handles GET /api/apps/{id}. func (s *Server) getApp(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") a, err := s.store.GetAppByID(id) if err != nil { if errors.Is(err, store.ErrNotFound) { respondNotFound(w, "app") return } respondError(w, http.StatusInternalServerError, "get app") return } respondJSON(w, http.StatusOK, a) } // createApp handles POST /api/apps. Body: {"name": "...", "description": "..."}. func (s *Server) createApp(w http.ResponseWriter, r *http.Request) { var req struct { Name string `json:"name"` Description string `json:"description"` } if !decodeJSON(w, r, &req) { return } req.Name = strings.TrimSpace(req.Name) if req.Name == "" { respondError(w, http.StatusBadRequest, "name is required") return } a, err := s.store.CreateApp(store.App{ Name: req.Name, Description: req.Description, }) if err != nil { respondError(w, http.StatusBadRequest, err.Error()) return } respondJSON(w, http.StatusCreated, a) } // updateApp handles PUT /api/apps/{id}. func (s *Server) updateApp(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") var req struct { Name string `json:"name"` Description string `json:"description"` } if !decodeJSON(w, r, &req) { return } a, err := s.store.GetAppByID(id) if err != nil { if errors.Is(err, store.ErrNotFound) { respondNotFound(w, "app") return } respondError(w, http.StatusInternalServerError, "get app") return } if name := strings.TrimSpace(req.Name); name != "" { a.Name = name } a.Description = req.Description if err := s.store.UpdateApp(a); err != nil { respondError(w, http.StatusInternalServerError, "update app") return } respondJSON(w, http.StatusOK, a) } // deleteApp handles DELETE /api/apps/{id}. Workloads previously assigned to // this app become unassigned (app_id cleared), they are NOT deleted. func (s *Server) deleteApp(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") if err := s.store.DeleteApp(id); err != nil { if errors.Is(err, store.ErrNotFound) { respondNotFound(w, "app") return } respondError(w, http.StatusInternalServerError, "delete app") return } w.WriteHeader(http.StatusNoContent) }