Files
silo-server/internal/api/handlers/recipes.go
T

69 lines
2.2 KiB
Go

package handlers
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/Silo-Server/silo-server/internal/sections/recipes"
)
// RecipeHandler exposes recipe-registry metadata over HTTP.
type RecipeHandler struct{}
// HandleList returns all recipe definitions grouped by category.
// GET /api/sections/recipes
func (h *RecipeHandler) HandleList(w http.ResponseWriter, _ *http.Request) {
groups := map[string][]recipes.RecipeDefinition{}
for _, rec := range recipes.List() {
def := rec.Definition()
if def.Hidden {
continue
}
// Guarantee Presets serialises as `[]` rather than `null` so the UI can
// iterate without a guard. Recipes that take no preset (e.g. custom_filter)
// still need a present-but-empty array.
if def.Presets == nil {
def.Presets = []recipes.GalleryPreset{}
}
key := string(def.Category)
groups[key] = append(groups[key], def)
}
resp := map[string]any{"categories": groups}
writeJSON(w, http.StatusOK, resp)
}
// CandidateSource provides UI-pickable candidates for a parameterized recipe.
// Recipe families register their own sources via RegisterCandidateSource.
type CandidateSource func(r *http.Request) ([]Candidate, error)
// Candidate is a generic shape: the UI shows DisplayName + optional Subtitle and uses Value as the param.
type Candidate struct {
Value string `json:"value"`
DisplayName string `json:"display_name"`
Subtitle string `json:"subtitle,omitempty"`
}
var candidateSources = map[string]CandidateSource{}
// RegisterCandidateSource is called by recipe families that need parameter helpers.
func RegisterCandidateSource(recipeType string, src CandidateSource) {
candidateSources[recipeType] = src
}
// HandleCandidates is GET /api/sections/recipes/{type}/candidates.
func (h *RecipeHandler) HandleCandidates(w http.ResponseWriter, r *http.Request) {
typ := chi.URLParam(r, "type")
src, ok := candidateSources[typ]
if !ok {
writeError(w, http.StatusNotFound, "unknown_recipe", "no candidate source for this recipe type")
return
}
cands, err := src(r)
if err != nil {
writeError(w, http.StatusInternalServerError, "candidate_error", err.Error())
return
}
writeJSON(w, http.StatusOK, map[string]any{"candidates": cands})
}