refactor: remove dead code across server, templ pages, and client modules
Deadcode-verified removals (RTA reachability from main, cross-checked with -test and textual xrefs): Go server: - whole files: middleware/transaction.go, middleware/error_handler.go, middleware/password_validator.go (live registration machinery kept), handlers/sync.go, sync/offline.go - unrouted endpoints: auth UpdateUsername/UpdateEmail, timezone settings handler, OPDS RegisterOPDS, Kobo LibrarySync handler, ReaderHandler.ShowReader, JSON-data twins on collections/library - duplicate book-matching handlers (book_matching.go Handler twins, matching.go MatchingHandler twins), superseded helpers (router.parseUUID, handlers.ValidateDeviceToken, normalizePath, userExists, generateLockID) Templ/client: - never-routed pages: api_explorer.templ, queue.templ and their client modules api-explorer.ts, api-explorer-docs.ts, queue.ts - fully orphaned wrapper modules events.ts, dom.ts - broken clearSyncQueue (called a nonexistent endpoint) and the hidden, never-populated sync-queue section on the devices page - 166+ unused exports demoted to private (knip-verified); ~85 truly dead declarations removed via tsc noUnusedLocals fixpoint - stale 'interactive API Explorer' claims dropped from docs The docs drift-gate package (internal/docs), templ-bound modules (dashboard, stats, header, index, login, profile*, bookshelf, collections, toast-error), sqlc-generated code, and web/static are intentionally untouched.
This commit is contained in:
1 parent
8733e83f1f
commit
8631aa00bf
107 files changed
+689
-3443
No files matched your search
@@ -3,7 +3,6 @@ package handlers
|
||||
import (
|
||||
"bookhoard/internal/database"
|
||||
"bookhoard/internal/services"
|
||||
"bookhoard/internal/utils"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -54,91 +53,6 @@ type ReaderMetadata struct {
|
||||
ChapterCount int `json:"chapter_count"`
|
||||
}
|
||||
|
||||
// ShowReader renders the reader page (SSR)
|
||||
func (h *ReaderHandler) ShowReader(c *echo.Context) error {
|
||||
mediaItemID := c.Param("mediaItemId")
|
||||
parsedUUID, err := uuid.Parse(mediaItemID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid media item ID"})
|
||||
}
|
||||
|
||||
// Get media item
|
||||
mediaItem, err := h.db.GetMediaItem(c.Request().Context(), pgtype.UUID{Bytes: parsedUUID, Valid: true})
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "Media item not found"})
|
||||
}
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to fetch media item"})
|
||||
}
|
||||
|
||||
// Get user from context (set by JWT middleware)
|
||||
user := c.Get("user")
|
||||
if user == nil {
|
||||
return c.JSON(http.StatusUnauthorized, map[string]string{"error": "User not authenticated"})
|
||||
}
|
||||
userData := user.(database.Users)
|
||||
|
||||
// Family-lens gate (H4.5 canonical resolver): the media item's
|
||||
// library must be in the requester's visible set — 403, never a
|
||||
// silent pass.
|
||||
visibleSet, _, err := h.libraryService.VisibleLibrarySet(c.Request().Context(), userData.ID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to check library access"})
|
||||
}
|
||||
visible := visibleSet[uuid.UUID(mediaItem.LibraryID.Bytes).String()]
|
||||
if !visible {
|
||||
return c.JSON(http.StatusForbidden, map[string]string{"error": "Access denied to this library"})
|
||||
}
|
||||
|
||||
// Get library with type information for panel detection decision
|
||||
libraryWithType, err := h.db.GetLibraryWithType(c.Request().Context(), mediaItem.LibraryID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to get library info"})
|
||||
}
|
||||
|
||||
// Determine if panel detection should be enabled
|
||||
// Same comic-likeness predicate as treatAsComic below — one function
|
||||
// on purpose (see ShouldTreatAsComic's doc).
|
||||
enablePanelDetection := ShouldTreatAsComic(libraryWithType.TypeName, mediaItem.FormatGroup)
|
||||
treatAsComic := ShouldTreatAsComic(libraryWithType.TypeName, mediaItem.FormatGroup)
|
||||
|
||||
// Get reading progress
|
||||
var progress database.ReadingProgress
|
||||
progress, err = h.db.GetReadingProgress(c.Request().Context(), database.GetReadingProgressParams{
|
||||
MediaItemID: pgtype.UUID{Bytes: parsedUUID, Valid: true},
|
||||
UserID: userData.ID,
|
||||
})
|
||||
if err != nil && !errors.Is(err, pgx.ErrNoRows) {
|
||||
progress = database.ReadingProgress{}
|
||||
}
|
||||
|
||||
// Get bookmarks
|
||||
bookmarks, _ := h.db.GetMediaBookmarks(c.Request().Context(), database.GetMediaBookmarksParams{
|
||||
MediaItemID: pgtype.UUID{Bytes: parsedUUID, Valid: true},
|
||||
UserID: userData.ID,
|
||||
})
|
||||
|
||||
// Return JSON response instead of rendering template
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"media_item_id": mediaItemID,
|
||||
"title": mediaItem.Title,
|
||||
"author": utils.PgTextString(mediaItem.Author),
|
||||
"cover_image_path": utils.PgTextString(mediaItem.CoverImagePath),
|
||||
"library_type": mediaItem.FormatGroup,
|
||||
"mime_type": utils.PgTextString(mediaItem.MimeType),
|
||||
"file_path": mediaItem.FilePath,
|
||||
"total_pages": mediaItem.PageCount,
|
||||
"chapter_count": mediaItem.ChapterCount,
|
||||
"progress": progress,
|
||||
"bookmarks": bookmarks,
|
||||
"enable_panel_detection": enablePanelDetection,
|
||||
"treat_as_comic": treatAsComic,
|
||||
"format_group": mediaItem.FormatGroup,
|
||||
"manga_type": mediaItem.MangaType,
|
||||
"reading_direction": mediaItem.ReadingDirection,
|
||||
})
|
||||
}
|
||||
|
||||
// GetPage returns a specific page for lazy loading
|
||||
func (h *ReaderHandler) GetPage(c *echo.Context) error {
|
||||
mediaItemID := c.Param("mediaItemId")
|
||||
|
||||
Reference in new issue
Block a user