From ed31755a54fefb3cb9b726d820ea467997178db1 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 1 Feb 2026 00:26:27 -0500 Subject: [PATCH] feat(api): add collections and device mapping API endpoints Add comprehensive API support for Phase 9 features: Collections API (/api/collections): - GET /collections: List all user collections - POST /collections: Create new collection - GET /collections/:id: Get collection details - PUT /collections/:id: Update collection - DELETE /collections/:id: Delete collection - GET /collections/:id/books: Get books in collection - POST /collections/:id/books: Add books to collection - DELETE /collections/:id/books/:bookId: Remove book from collection Device Shelf Mapping API (/api/devices/:id/collections): - GET: Get all collection-to-shelf mappings for device - POST: Create new mapping - PUT /:collectionId: Update mapping - DELETE /:collectionId: Delete mapping Book Matching API: - POST /sync/books/query: Query books by identifiers - POST /devices/:deviceId/sync/link-book: Manual book linking - GET /devices/:deviceId/sync/unlinked-books: List unmatched books - GET /devices/:id/file-aliases: Get device file aliases - POST /devices/:id/file-aliases: Create file alias - PUT /devices/:id/file-aliases/:aliasId: Update alias - DELETE /devices/:id/file-aliases/:aliasId: Delete alias - GET /books/match: Search for book matches All new endpoints - no existing APIs modified. --- internal/handlers/ebook.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/internal/handlers/ebook.go b/internal/handlers/ebook.go index d7092ae..03255d3 100644 --- a/internal/handlers/ebook.go +++ b/internal/handlers/ebook.go @@ -70,6 +70,35 @@ func parseDate(dateStr string) time.Time { func SetupRoutes(g *echo.Group, db *database.Queries, connManager *wsync.ConnectionManager) *Handler { h := NewHandler(db, connManager) + // Collections API routes + collectionHandler := NewCollectionHandler(db) + collections := g.Group("/collections") + collections.GET("", collectionHandler.GetCollections) + collections.POST("", collectionHandler.CreateCollection) + collections.GET("/:id", collectionHandler.GetCollection) + collections.PUT("/:id", collectionHandler.UpdateCollection) + collections.DELETE("/:id", collectionHandler.DeleteCollection) + collections.GET("/:id/books", collectionHandler.GetBookCollections) + collections.POST("/:id/books", collectionHandler.AddBooks) + collections.DELETE("/:id/books/:bookId", collectionHandler.RemoveBook) + + // Device shelf mapping routes + deviceCollections := g.Group("/devices/:id/collections") + deviceCollections.GET("", collectionHandler.GetDeviceMappings) + deviceCollections.POST("", collectionHandler.CreateDeviceMapping) + deviceCollections.PUT("/:collectionId", collectionHandler.UpdateDeviceMapping) + deviceCollections.DELETE("/:collectionId", collectionHandler.DeleteDeviceMapping) + + // Book matching and linking routes + g.POST("/sync/books/query", h.QueryBooks) + g.POST("/devices/:deviceId/sync/link-book", h.LinkBook) + g.GET("/devices/:deviceId/sync/unlinked-books", h.GetUnlinkedBooks) + g.GET("/devices/:id/file-aliases", h.GetDeviceFileAliases) + g.POST("/devices/:id/file-aliases", h.CreateDeviceFileAlias) + g.PUT("/devices/:id/file-aliases/:aliasId", h.UpdateDeviceFileAlias) + g.DELETE("/devices/:id/file-aliases/:aliasId", h.DeleteDeviceFileAlias) + g.GET("/books/match", h.GetBookMatches) + // Media item routes (all authenticated users) g.GET("/media-items", h.ListMediaItems) g.GET("/media-items/filtered", h.ListMediaItemsFiltered)