feat: scaffold work queue API
This commit is contained in:
132
internal/api/handlers_projects.go
Normal file
132
internal/api/handlers_projects.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"work-queue-api/internal/model"
|
||||
)
|
||||
|
||||
type createProjectRequest struct {
|
||||
Name string `json:"name"`
|
||||
ExternalRef *string `json:"external_ref"`
|
||||
}
|
||||
|
||||
type patchProjectRequest struct {
|
||||
Name *string `json:"name"`
|
||||
ExternalRef *string `json:"external_ref"`
|
||||
}
|
||||
|
||||
func (s *Server) handleCreateProject(w http.ResponseWriter, r *http.Request) {
|
||||
var req createProjectRequest
|
||||
if err := decodeJSON(r, &req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid json body")
|
||||
return
|
||||
}
|
||||
if req.Name == "" {
|
||||
writeError(w, http.StatusBadRequest, "name is required")
|
||||
return
|
||||
}
|
||||
|
||||
now := nowUTC()
|
||||
project := model.Project{
|
||||
ID: uuid.NewString(),
|
||||
Name: req.Name,
|
||||
ExternalRef: req.ExternalRef,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
_, err := s.db.Exec(`INSERT INTO projects (id, name, external_ref, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`,
|
||||
project.ID, project.Name, project.ExternalRef, project.CreatedAt.Format(timeLayout), project.UpdatedAt.Format(timeLayout),
|
||||
)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusCreated, project)
|
||||
}
|
||||
|
||||
func (s *Server) handleListProjects(w http.ResponseWriter, r *http.Request) {
|
||||
rows, err := s.db.Query(`SELECT id, name, external_ref, created_at, updated_at FROM projects ORDER BY created_at ASC`)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var projects []model.Project
|
||||
for rows.Next() {
|
||||
project, err := scanProject(rows)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
projects = append(projects, project)
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, projects)
|
||||
}
|
||||
|
||||
func (s *Server) handleGetProject(w http.ResponseWriter, r *http.Request) {
|
||||
project, err := s.fetchProject(chi.URLParam(r, "id"))
|
||||
if err == sql.ErrNoRows {
|
||||
writeError(w, http.StatusNotFound, "project not found")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, project)
|
||||
}
|
||||
|
||||
func (s *Server) handlePatchProject(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
project, err := s.fetchProject(id)
|
||||
if err == sql.ErrNoRows {
|
||||
writeError(w, http.StatusNotFound, "project not found")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req patchProjectRequest
|
||||
if err := decodeJSON(r, &req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid json body")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name != nil {
|
||||
if *req.Name == "" {
|
||||
writeError(w, http.StatusBadRequest, "name cannot be empty")
|
||||
return
|
||||
}
|
||||
project.Name = *req.Name
|
||||
}
|
||||
if req.ExternalRef != nil {
|
||||
project.ExternalRef = req.ExternalRef
|
||||
}
|
||||
project.UpdatedAt = nowUTC()
|
||||
|
||||
_, err = s.db.Exec(`UPDATE projects SET name = ?, external_ref = ?, updated_at = ? WHERE id = ?`,
|
||||
project.Name, project.ExternalRef, project.UpdatedAt.Format(timeLayout), project.ID,
|
||||
)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, project)
|
||||
}
|
||||
|
||||
func (s *Server) fetchProject(id string) (model.Project, error) {
|
||||
row := s.db.QueryRow(`SELECT id, name, external_ref, created_at, updated_at FROM projects WHERE id = ?`, id)
|
||||
return scanProject(row)
|
||||
}
|
||||
Reference in New Issue
Block a user