feat(api): GET /api/artists with alpha/newest sort and paging

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 08:06:03 -04:00
parent f37fd782af
commit 8fb2f4e184
3 changed files with 268 additions and 2 deletions
+42
View File
@@ -1,11 +1,18 @@
package api
import (
"errors"
"net/url"
"strconv"
"strings"
"github.com/jackc/pgx/v5/pgtype"
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
)
var errBadPaging = errors.New("invalid limit or offset")
// uuidToString renders a pgtype.UUID as a canonical hyphenated string.
// Returns "" when the UUID is invalid (unset). Duplicated from the subsonic
// package intentionally — the two packages must not depend on each other.
@@ -115,3 +122,38 @@ func trackRefFrom(t dbq.Track, albumTitle, artistName string) TrackRef {
}
return ref
}
// parsePaging reads limit/offset from the query string, applying defaults
// and clamping. Returns a 400-worthy error when the values are non-numeric
// or negative; out-of-range values silently clamp (deliberate — UX).
func parsePaging(raw url.Values) (limit, offset int, err error) {
const (
defLimit = 50
maxLimit = 200
)
limit = defLimit
if s := strings.TrimSpace(raw.Get("limit")); s != "" {
n, perr := strconv.Atoi(s)
if perr != nil {
return 0, 0, errBadPaging
}
if n < 1 {
n = 1
}
if n > maxLimit {
n = maxLimit
}
limit = n
}
if s := strings.TrimSpace(raw.Get("offset")); s != "" {
n, perr := strconv.Atoi(s)
if perr != nil {
return 0, 0, errBadPaging
}
if n < 0 {
return 0, 0, errBadPaging
}
offset = n
}
return limit, offset, nil
}