/** * Encode test tracks as the backend's `TrackTable` (#281), so a stub of * `library.Library.GetTrackTable` can be written as a list of tracks. * * Test fixtures are partial tracks; a missing field encodes as the * zero value Go would have sent. The encoding mirrors * `backend/library/tracktable.go` closely enough to exercise the real * decoder: shared string table with "" at 0, genre lists interned. */ import type * as library from '@go/library/models.js'; /** A fixture: any subset of a track's fields, loosely typed as fixtures are. */ type PartialTrack = { FilePath: string } & Record; const STRING_COLS = [ ['trackName', 'TrackName'], ['artistName', 'ArtistName'], ['album', 'Album'], ['composer', 'Composer'], ['fileType', 'FileType'], ['artistMbid', 'ArtistMBID'], ['releaseGroupMbid', 'ReleaseGroupMBID'], ['recordingMbid', 'RecordingMBID'], ['coverArtSmall', 'CoverArtSmall'], ] as const; const INT_COLS = [ ['trackNumber', 'TrackNumber'], ['discNumber', 'DiscNumber'], ['year', 'Year'], ['sampleRate', 'SampleRate'], ['bitDepth', 'BitDepth'], ['channels', 'Channels'], ['bitrate', 'Bitrate'], ['fileSize', 'FileSize'], ['playCount', 'PlayCount'], ] as const; export function trackTable(tracks: readonly PartialTrack[]): library.TrackTable { const strings = ['']; const index = new Map([['', 0]]); const intern = (s: string | undefined): number => { const v = s ?? ''; let i = index.get(v); if (i === undefined) { i = strings.length; strings.push(v); index.set(v, i); } return i; }; const genreSets: number[][] = []; const genreIndex = new Map(); const table: Record = { strings, genreSets, filePath: tracks.map((t) => t.FilePath), lengthMs: tracks.map((t) => Number(t['TrackLength'] ?? 0) || 0), genre: tracks.map((t) => { const genres = (t['Genre'] as string[] | null | undefined) ?? []; const key = genres.join('\u0000'); let i = genreIndex.get(key); if (i === undefined) { i = genreSets.length; genreSets.push(genres.map(intern)); genreIndex.set(key, i); } return i; }), }; for (const [col, field] of STRING_COLS) { table[col] = tracks.map((t) => intern(t[field] as string | undefined)); } for (const [col, field] of INT_COLS) { table[col] = tracks.map((t) => (t[field] as number | undefined) ?? 0); } return table as unknown as library.TrackTable; }