// Package ports defines consumer-side interfaces for the backend services. // Handlers depend on these interfaces, not on concrete implementations. // Main.go wires concrete types (*store.Store, *redispkg.R, etc.) that satisfy them. // // Value types (User, Book, etc.) live in internal/store and are referenced here. package ports import ( "context" "io" "time" "booklib/internal/store" ) // ---------- Store interfaces ---------- type UserStore interface { CountUsers(ctx context.Context) (int, error) CreateUser(ctx context.Context, username, hash, role string) (int64, error) GetUserByName(ctx context.Context, username string) (store.User, error) GetUserByID(ctx context.Context, id int64) (store.User, error) ListUsers(ctx context.Context) ([]store.User, error) DeleteUser(ctx context.Context, id int64) error } type LibraryStore interface { CreateLibrary(ctx context.Context, name, root string) (int64, error) ListLibraries(ctx context.Context) ([]store.Library, error) GetLibrary(ctx context.Context, id int64) (store.Library, error) } type BookStore interface { InsertBook(ctx context.Context, libID int64, path, title, format string, size, modTS int64, pageCount int) (int64, error) GetBook(ctx context.Context, id int64) (store.Book, error) ListBookMeta(ctx context.Context, libID int64) (map[string]store.BookMeta, error) UpdateBookFile(ctx context.Context, id, size, modTS int64, pageCount int) error DeleteBookByPath(ctx context.Context, libID int64, path string) error DeleteBook(ctx context.Context, id int64) error SetBookState(ctx context.Context, id int64, state, msg string) error ListBooks(ctx context.Context, libID int64, q, prefix string, userID int64) ([]store.BookView, error) BookHashes(ctx context.Context) (map[int64][2]int64, error) } type ProgressStore interface { UpsertProgress(ctx context.Context, userID, libID int64, bookPath string, locator []byte, percent float64) error GetProgress(ctx context.Context, userID, libID int64, bookPath string) (store.Progress, error) ListProgress(ctx context.Context, userID int64) ([]store.Progress, error) } type BookmarkStore interface { InsertBookmark(ctx context.Context, userID, libID int64, bookPath string, locator []byte, percent float64, note string) (int64, error) ListBookmarks(ctx context.Context, userID, libID int64, bookPath string) ([]store.Bookmark, error) UpdateBookmarkNote(ctx context.Context, userID, id int64, note string) (bool, error) DeleteBookmark(ctx context.Context, userID, id int64) (bool, error) } // ---------- Redis interfaces ---------- type PageCache interface { Get(ctx context.Context, key string) (string, bool) Set(ctx context.Context, key, val string, ttl time.Duration) } type RateLimiter interface { IncrWindow(ctx context.Context, key string, ttl time.Duration) int } type ScanLocker interface { ScanLock(ctx context.Context, key string, ttl time.Duration) (func(), bool) } // ---------- Service interfaces ---------- type Scanner interface { ScanLibraryByID(ctx context.Context, id int64) } type UploadSessions interface { Init(ctx context.Context, libID int64, name string, size, chunkSize int64) (string, error) Status(ctx context.Context, uploadID string) ([]int64, error) PutPart(ctx context.Context, uploadID string, index int64, body io.Reader, maxSize int64) error Complete(ctx context.Context, uploadID string, root string) (string, error) Sweep(ctx context.Context) error UniquePath(root, name string) (string, error) } type Media interface { EnsureCover(ctx context.Context, bookID int64, format string, size, modTS int64, root, rel string) error ChaptersOf(idx []string) []Chapter PageIndex(ctx context.Context, bookID int64, size, modTS int64, root, rel string) ([]string, error) CacheBuster(size, modTS int64) string } // Chapter represents a CBZ chapter derived from the archive's folder structure. type Chapter struct { Title string `json:"title"` Start int `json:"start"` }