Files
Lyra/web/src/app/api/library/route.ts
T
Jonathan 18a22db7fb feat(library): match own-state on artist MBID, not just name
Own-state ("in library") relied on an exact artist-NAME match, so an owned
album whose name differed from the MB canonical (punctuation/locale/feat.)
showed as not-owned even when followed. Capture the MusicBrainz artist MBID
on LibraryItem and prefer it for matching.

- New LibraryItem.artistMbid (migration add_library_artist_mbid). Populated at
  import (pipeline) + scan, both of which already hold the resolved target;
  the pipeline also now stores rgMbid (it previously didn't). COALESCE on
  conflict backfills MBIDs on re-scan without clobbering.
- /api/artists "in library, not followed" matches by artistMbid first, name
  case-insensitively as fallback (rows predating the column). Library route
  prefers the item's own artistMbid over the release join.

Last.fm/discover own-state still use name-match (they work) — a smaller
follow-up. worker 233, web 186 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:55:24 +02:00

37 lines
1.5 KiB
TypeScript

import { prisma } from "@/lib/db";
import { yearFromPath } from "@/lib/library-path";
// Owned albums (LibraryItem) enriched with the release-group MBID + year from the matching
// MonitoredRelease (joined on artist/album), so the Library grid can show cover art + tracks.
export async function GET() {
const [items, releases] = await Promise.all([
prisma.libraryItem.findMany({ orderBy: { importedAt: "desc" } }),
prisma.monitoredRelease.findMany({
select: { id: true, artistName: true, album: true, rgMbid: true, firstReleaseDate: true, primaryType: true, artistMbid: true },
}),
]);
const key = (artist: string, album: string) => `${artist}${album}`;
const byKey = new Map(releases.map((r) => [key(r.artistName, r.album), r]));
return Response.json({
albums: items.map((li) => {
const mr = byKey.get(key(li.artist, li.album));
return {
id: li.id,
artist: li.artist,
album: li.album,
format: li.format,
qualityClass: li.qualityClass,
importedAt: li.importedAt,
rgMbid: li.rgMbid ?? mr?.rgMbid ?? null,
// prefer the resolved release year; fall back to the "(YYYY)" in the folder name so
// manually-imported / metadata-edited albums (no matching release) still show a year
year: mr?.firstReleaseDate?.slice(0, 4) ?? yearFromPath(li.path),
primaryType: mr?.primaryType ?? null,
artistMbid: li.artistMbid ?? mr?.artistMbid ?? null,
monitoredReleaseId: mr?.id ?? null,
trackNames: li.trackNames,
};
}),
});
}