Files
cdp/data-layer/api/internal/handler/saved_query_handler.go
2026-05-25 08:38:26 +07:00

126 lines
3.2 KiB
Go

package handler
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"go.uber.org/zap"
"github.com/dbiz/cdp/data-layer/api/internal/apperr"
"github.com/dbiz/cdp/data-layer/api/internal/middleware"
"github.com/dbiz/cdp/data-layer/api/internal/model"
"github.com/dbiz/cdp/data-layer/api/internal/repo"
)
type SavedQueryHandler struct {
repo *repo.SavedQueryRepo
log *zap.Logger
}
func NewSavedQueryHandler(r *repo.SavedQueryRepo, log *zap.Logger) *SavedQueryHandler {
return &SavedQueryHandler{repo: r, log: log}
}
type createSavedQueryRequest struct {
Name string `json:"name" validate:"required,min=1,max=200"`
Kind string `json:"kind" validate:"required,oneof=events sql funnel retention session"`
Spec map[string]any `json:"spec" validate:"required"`
}
type updateSavedQueryRequest struct {
Name string `json:"name" validate:"required,min=1,max=200"`
Spec map[string]any `json:"spec" validate:"required"`
}
func (h *SavedQueryHandler) Create(w http.ResponseWriter, r *http.Request) {
var req createSavedQueryRequest
if err := decodeAndValidate(r, &req); err != nil {
writeError(w, err)
return
}
ws := middleware.WorkspaceFromCtx(r.Context())
q, err := h.repo.Create(r.Context(), model.SavedQuery{
WorkspaceID: ws,
Name: req.Name,
Kind: req.Kind,
Spec: req.Spec,
})
if err != nil {
writeError(w, err)
return
}
writeJSON(w, http.StatusCreated, q)
}
func (h *SavedQueryHandler) List(w http.ResponseWriter, r *http.Request) {
limit, offset := parsePagination(r, 50, 500)
ws := middleware.WorkspaceFromCtx(r.Context())
qs, err := h.repo.List(r.Context(), ws, limit, offset)
if err != nil {
writeError(w, err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"items": qs, "limit": limit, "offset": offset})
}
func (h *SavedQueryHandler) Get(w http.ResponseWriter, r *http.Request) {
id, err := parseSavedQueryID(r)
if err != nil {
writeError(w, err)
return
}
ws := middleware.WorkspaceFromCtx(r.Context())
q, err := h.repo.Get(r.Context(), ws, id)
if err != nil {
writeError(w, err)
return
}
writeJSON(w, http.StatusOK, q)
}
func (h *SavedQueryHandler) Update(w http.ResponseWriter, r *http.Request) {
id, err := parseSavedQueryID(r)
if err != nil {
writeError(w, err)
return
}
var req updateSavedQueryRequest
if err := decodeAndValidate(r, &req); err != nil {
writeError(w, err)
return
}
ws := middleware.WorkspaceFromCtx(r.Context())
q, err := h.repo.Update(r.Context(), ws, id, req.Name, req.Spec)
if err != nil {
writeError(w, err)
return
}
writeJSON(w, http.StatusOK, q)
}
func (h *SavedQueryHandler) Delete(w http.ResponseWriter, r *http.Request) {
id, err := parseSavedQueryID(r)
if err != nil {
writeError(w, err)
return
}
ws := middleware.WorkspaceFromCtx(r.Context())
if err := h.repo.Delete(r.Context(), ws, id); err != nil {
writeError(w, err)
return
}
w.WriteHeader(http.StatusNoContent)
}
func parseSavedQueryID(r *http.Request) (string, error) {
raw := chi.URLParam(r, "id")
if raw == "" {
return "", apperr.BadRequest("missing query id", "id", nil)
}
if _, err := uuid.Parse(raw); err != nil {
return "", apperr.BadRequest("query id must be uuid", "id", err)
}
return raw, nil
}