From e5ddb30a4a04ab9deeeac2d50e4113806d255849 Mon Sep 17 00:00:00 2001 From: Forbes Date: Sun, 8 Feb 2026 18:37:33 -0600 Subject: [PATCH] feat(api): add GET /api/items/by-uuid/{uuid} endpoint Closes #43 Adds a new read-only endpoint to resolve a Silo item UUID to its full ItemResponse. Used by silo-mod to resolve FreeCAD document SiloUUID properties to part numbers during BOM sync. - Reuses existing ItemRepository.GetByID() (items.id is the stable UUID) - Returns 404 for archived items - Registered in viewer-accessible route group (no editor role required) --- docs/BOM_MERGE.md | 0 internal/api/handlers.go | 20 ++++++++++++++++++++ internal/api/routes.go | 1 + 3 files changed, 21 insertions(+) create mode 100644 docs/BOM_MERGE.md diff --git a/docs/BOM_MERGE.md b/docs/BOM_MERGE.md new file mode 100644 index 0000000..e69de29 diff --git a/internal/api/handlers.go b/internal/api/handlers.go index aaef469..1c6a6d5 100644 --- a/internal/api/handlers.go +++ b/internal/api/handlers.go @@ -465,6 +465,26 @@ func (s *Server) HandleCreateItem(w http.ResponseWriter, r *http.Request) { s.broker.Publish("item.created", mustMarshal(resp)) } +// HandleGetItemByUUID retrieves an item by its stable UUID (the items.id column). +// Used by silo-mod to resolve FreeCAD document SiloUUID properties to part numbers. +func (s *Server) HandleGetItemByUUID(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + uuid := chi.URLParam(r, "uuid") + + item, err := s.items.GetByID(ctx, uuid) + if err != nil { + s.logger.Error().Err(err).Msg("failed to get item by UUID") + writeError(w, http.StatusInternalServerError, "internal_error", "Failed to get item") + return + } + if item == nil || item.ArchivedAt != nil { + writeError(w, http.StatusNotFound, "not_found", "Item not found") + return + } + + writeJSON(w, http.StatusOK, itemToResponse(item)) +} + // HandleGetItem retrieves an item by part number. // Supports query param: ?include=properties to include current revision properties. func (s *Server) HandleGetItem(w http.ResponseWriter, r *http.Request) { diff --git a/internal/api/routes.go b/internal/api/routes.go index 32d760a..4992f1f 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -119,6 +119,7 @@ func NewRouter(server *Server, logger zerolog.Logger) http.Handler { r.Route("/items", func(r chi.Router) { r.Get("/", server.HandleListItems) r.Get("/search", server.HandleFuzzySearch) + r.Get("/by-uuid/{uuid}", server.HandleGetItemByUUID) r.Get("/export.csv", server.HandleExportCSV) r.Get("/template.csv", server.HandleCSVTemplate) r.Get("/export.ods", server.HandleExportODS)