feat(api): add DTOs for library reads and search
This commit is contained in:
@@ -24,3 +24,71 @@ type UserView struct {
|
|||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
IsAdmin bool `json:"is_admin"`
|
IsAdmin bool `json:"is_admin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Page is the generic pagination envelope used by list and search endpoints.
|
||||||
|
// Items is always non-nil at JSON encode time — handlers must initialize
|
||||||
|
// empty slices explicitly so absent results render as [] rather than null.
|
||||||
|
type Page[T any] struct {
|
||||||
|
Items []T `json:"items"`
|
||||||
|
Total int `json:"total"`
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
Offset int `json:"offset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArtistRef is the lightweight artist shape used in lists and search results.
|
||||||
|
type ArtistRef struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
AlbumCount int `json:"album_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlbumRef is the lightweight album shape used in lists, artist details,
|
||||||
|
// and search results. CoverURL points to /api/albums/{id}/cover which
|
||||||
|
// Plan 3 implements.
|
||||||
|
type AlbumRef struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
ArtistID string `json:"artist_id"`
|
||||||
|
ArtistName string `json:"artist_name"`
|
||||||
|
Year int `json:"year,omitempty"`
|
||||||
|
TrackCount int `json:"track_count"`
|
||||||
|
DurationSec int `json:"duration_sec"`
|
||||||
|
CoverURL string `json:"cover_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrackRef is the lightweight track shape used in album details and search.
|
||||||
|
// StreamURL points to /api/tracks/{id}/stream which Plan 3 implements.
|
||||||
|
type TrackRef struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
AlbumID string `json:"album_id"`
|
||||||
|
AlbumTitle string `json:"album_title"`
|
||||||
|
ArtistID string `json:"artist_id"`
|
||||||
|
ArtistName string `json:"artist_name"`
|
||||||
|
TrackNumber int `json:"track_number,omitempty"`
|
||||||
|
DiscNumber int `json:"disc_number,omitempty"`
|
||||||
|
DurationSec int `json:"duration_sec"`
|
||||||
|
StreamURL string `json:"stream_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArtistDetail is the response body of GET /api/artists/{id}. Embeds the ref
|
||||||
|
// so callers read id/name/album_count from the same path as list entries.
|
||||||
|
type ArtistDetail struct {
|
||||||
|
ArtistRef
|
||||||
|
Albums []AlbumRef `json:"albums"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlbumDetail is the response body of GET /api/albums/{id}.
|
||||||
|
type AlbumDetail struct {
|
||||||
|
AlbumRef
|
||||||
|
Tracks []TrackRef `json:"tracks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchResponse is the body of GET /api/search. Each facet carries its own
|
||||||
|
// total + limit + offset; the client sends one shared limit/offset and the
|
||||||
|
// server applies it uniformly to each facet's LIMIT/OFFSET query.
|
||||||
|
type SearchResponse struct {
|
||||||
|
Artists Page[ArtistRef] `json:"artists"`
|
||||||
|
Albums Page[AlbumRef] `json:"albums"`
|
||||||
|
Tracks Page[TrackRef] `json:"tracks"`
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user