// web/frontend/src/utils/validators.ts import { TracklistEntry } from '../types' import { parseTracklistWithFormat } from './parser' export const validateTracklist = ( entries: TracklistEntry[] ): { isValid: boolean; errors: { line: number; message: string }[] } => { const errors: { line: number; message: string }[] = [] entries.forEach((entry, index) => { const lineNum = index + 1 if (!entry.ts || !entry.ts.trim()) { errors.push({ line: lineNum, message: 'Missing timestamp (%ts)' }) } else { // Validate timestamp format const ts = entry.ts.trim() if (!/^\d{1,2}:\d{2}(:\d{2})?$/.test(ts) && !/^\d{1,2}:\d{2}-\d{1,2}:\d{2}$/.test(ts)) { errors.push({ line: lineNum, message: 'Invalid timestamp format. Expected mm:ss or mm:ss-HH:MM:SS' }) } } if (!entry.tn || !entry.tn.trim()) { errors.push({ line: lineNum, message: 'Missing track name (%tn)' }) } }) return { isValid: errors.length === 0, errors, } } // New function that parses and validates using the format export function parseAndValidateTracklist(text: string, format: string): { entries: TracklistEntry[] errors: { line: number; message: string }[] isValid: boolean } { // We need to handle parsing errors gracefully. // parseTracklistWithFormat will throw on some errors, but we can catch and mark as invalid. try { const entries = parseTracklistWithFormat(text, format) const validation = validateTracklist(entries) return { entries, errors: validation.errors, isValid: validation.isValid, } } catch (error) { // If parsing fails (e.g., invalid format), treat all lines as errors const lines = text.split('\n').filter(line => line.trim() !== '') const errors = lines.map((_, index) => ({ line: index + 1, message: error instanceof Error ? error.message : 'Parse error', })) return { entries: [], errors, isValid: false, } } }