Files
Work/Backend/internal/httpx/api_project_decode.go
2026-06-29 04:29:05 +01:00

128 lines
3.7 KiB
Go

// Path: Backend/internal/httpx/api_project_decode.go
package httpx
import (
"encoding/json"
"errors"
"io"
"net/http"
"strings"
)
type createProjectFolderRequest struct {
Name string `json:"name"`
ParentFolderPath string `json:"parentFolderId"`
}
type renameProjectFolderRequest struct {
FolderPath string `json:"folderId"`
Name string `json:"name"`
}
type deleteProjectFolderRequest struct {
FolderPath string `json:"folderId"`
}
// Keep the existing JSON contract for the frontend, but use clearer path-vs-stable-ID
// names internally so the move flow is easier to reason about.
type moveProjectFolderRequest struct {
FolderPath string `json:"folderId"`
FolderStableID string `json:"folderNodeId"`
ParentFolderPath string `json:"parentFolderId"`
ParentStableID string `json:"parentNodeId"`
TargetIndex int `json:"targetIndex"`
}
type createProjectItemRequest struct {
Name string `json:"name"`
ParentFolderPath string `json:"parentFolderId"`
ItemType string `json:"itemType"`
}
type deleteProjectItemRequest struct {
ItemPath string `json:"itemId"`
}
type moveProjectItemRequest struct {
ItemPath string `json:"itemId"`
ItemStableID string `json:"itemNodeId"`
ParentFolderPath string `json:"parentFolderId"`
ParentStableID string `json:"parentNodeId"`
TargetIndex int `json:"targetIndex"`
}
func decodeMoveProjectFolderRequest(w http.ResponseWriter, r *http.Request) (moveProjectFolderRequest, bool) {
var payload moveProjectFolderRequest
if !decodeJSONObjectBody(w, r, &payload) {
return payload, false
}
return payload, true
}
func decodeDeleteProjectFolderRequest(r *http.Request) deleteProjectFolderRequest {
return deleteProjectFolderRequest{
FolderPath: strings.TrimSpace(r.URL.Query().Get("folderId")),
}
}
func decodeDeleteProjectItemRequest(r *http.Request) deleteProjectItemRequest {
return deleteProjectItemRequest{
ItemPath: strings.TrimSpace(r.URL.Query().Get("itemId")),
}
}
func decodeRenameProjectFolderRequest(w http.ResponseWriter, r *http.Request) (renameProjectFolderRequest, bool) {
var payload renameProjectFolderRequest
if !decodeJSONObjectBody(w, r, &payload) {
return payload, false
}
return payload, true
}
func decodeProjectFolderRequest(w http.ResponseWriter, r *http.Request) (createProjectFolderRequest, bool) {
var payload createProjectFolderRequest
if !decodeJSONObjectBody(w, r, &payload) {
return payload, false
}
return payload, true
}
func decodeProjectItemRequest(w http.ResponseWriter, r *http.Request) (createProjectItemRequest, bool) {
var payload createProjectItemRequest
if !decodeJSONObjectBody(w, r, &payload) {
return payload, false
}
return payload, true
}
func decodeMoveProjectItemRequest(w http.ResponseWriter, r *http.Request) (moveProjectItemRequest, bool) {
var payload moveProjectItemRequest
if !decodeJSONObjectBody(w, r, &payload) {
return payload, false
}
return payload, true
}
func decodeJSONObjectBody(w http.ResponseWriter, r *http.Request, target any) bool {
decoder := json.NewDecoder(r.Body)
decoder.DisallowUnknownFields()
if err := decoder.Decode(target); err != nil {
if errors.Is(err, io.EOF) {
WriteError(w, http.StatusBadRequest, RequestIDFromContext(r.Context()), "invalid_json", "The request body is required and must be valid JSON.")
return false
}
WriteError(w, http.StatusBadRequest, RequestIDFromContext(r.Context()), "invalid_json", "The request body must be valid JSON.")
return false
}
if err := decoder.Decode(&struct{}{}); !errors.Is(err, io.EOF) {
WriteError(w, http.StatusBadRequest, RequestIDFromContext(r.Context()), "invalid_json", "The request body must contain a single JSON object.")
return false
}
return true
}