feat(api): add GET /api/artists/{id}/tracks handler

Wires ListArtistTracksForUser (Task 3 SQL) to a new handler that returns
all quarantine-filtered tracks for an artist as a flat TrackRef list.
404 when the artist doesn't exist. Route registered in Mount().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 18:06:15 -04:00
parent fc12532dee
commit 2aecbba2ef
3 changed files with 143 additions and 0 deletions
+40
View File
@@ -143,6 +143,46 @@ func (h *handlers) handleGetArtist(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, detail)
}
// handleGetArtistTracks implements GET /api/artists/{id}/tracks. Returns
// every track the artist has across albums (per-user-quarantine filtered)
// as a flat list. Used by ArtistCard's play affordance, which shuffles
// client-side. 404 when the artist doesn't exist.
func (h *handlers) handleGetArtistTracks(w http.ResponseWriter, r *http.Request) {
id, ok := parseUUID(chi.URLParam(r, "id"))
if !ok {
writeErr(w, http.StatusBadRequest, "bad_request", "invalid artist id")
return
}
user, ok := auth.UserFromContext(r.Context())
if !ok {
writeErr(w, http.StatusUnauthorized, "unauthorized", "authentication required")
return
}
q := dbq.New(h.pool)
if _, err := q.GetArtistByID(r.Context(), id); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
writeErr(w, http.StatusNotFound, "not_found", "artist not found")
return
}
h.logger.Error("api: get artist for tracks", "err", err)
writeErr(w, http.StatusInternalServerError, "server_error", "lookup failed")
return
}
rows, err := q.ListArtistTracksForUser(r.Context(), dbq.ListArtistTracksForUserParams{
ArtistID: id, UserID: user.ID,
})
if err != nil {
h.logger.Error("api: list artist tracks", "err", err)
writeErr(w, http.StatusInternalServerError, "server_error", "lookup failed")
return
}
out := make([]TrackRef, 0, len(rows))
for _, row := range rows {
out = append(out, trackRefFrom(row.Track, row.AlbumTitle, row.ArtistName))
}
writeJSON(w, http.StatusOK, out)
}
// handleListArtists implements GET /api/artists with two sort modes
// (alpha|newest) and enveloped pagination. album_count per artist is
// computed via an N+1 — acceptable at limit=200.