diff --git a/.gitignore b/.gitignore index a547bf3..2fdb4d0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ dist dist-ssr *.local +testfiles + # Editor directories and files .vscode/* !.vscode/extensions.json diff --git a/packages/backend/src/services/xmlService.ts b/packages/backend/src/services/xmlService.ts index 5a13228..6a8dcc3 100644 --- a/packages/backend/src/services/xmlService.ts +++ b/packages/backend/src/services/xmlService.ts @@ -30,13 +30,17 @@ const buildXmlNode = (node: any): any => { }; export const streamToXml = async (res: any) => { - // Write XML header - res.write('\n'); - res.write('\n'); + console.log('Starting streamToXml function...'); + + // Write XML header (compact like Rekordbox) + res.write(''); + res.write(''); // Start COLLECTION section + console.log('Counting songs in database...'); const songCount = await Song.countDocuments(); - res.write(` \n`); + console.log(`Found ${songCount} songs in database`); + res.write(''); // Stream songs in batches to avoid memory issues const batchSize = 100; @@ -49,38 +53,66 @@ export const streamToXml = async (res: any) => { .lean(); for (const song of songs) { - res.write(` \n \n \n`); - } else { - res.write('/>\n'); - } + // Only include TrackID, Name, and Artist like Rekordbox + res.write(``); } processedSongs += songs.length; console.log(`Streamed ${processedSongs}/${songCount} songs...`); } - res.write(' \n'); + res.write(''); // Start PLAYLISTS section - res.write(' \n'); - res.write(' \n'); + res.write(''); // Stream playlists + console.log('Fetching playlists from database...'); const playlists = await Playlist.find({}).lean(); + console.log(`Found ${playlists.length} playlists in database`); + + // Write ROOT node with correct Count + res.write(``); + for (const playlist of playlists) { - await streamPlaylistNode(res, playlist, 6); + await streamPlaylistNodeCompact(res, playlist); } - res.write(' \n'); - res.write(' \n'); + res.write(''); + res.write(''); res.write(''); res.end(); }; +const streamPlaylistNodeCompact = async (res: any, node: any) => { + const nodeType = node.type === 'folder' ? '0' : '1'; + + if (node.type === 'folder') { + const childCount = node.children ? node.children.length : 0; + res.write(``); + + if (node.children && node.children.length > 0) { + for (const child of node.children) { + await streamPlaylistNodeCompact(res, child); + } + } + + res.write(''); + } else { + const trackCount = node.tracks ? node.tracks.length : 0; + res.write(``); + + if (node.tracks && node.tracks.length > 0) { + for (const trackId of node.tracks) { + res.write(``); + } + } + + res.write(''); + } +}; + const streamPlaylistNode = async (res: any, node: any, indent: number) => { const spaces = ' '.repeat(indent); const nodeType = node.type === 'folder' ? '0' : '1';