/** * Validates a single feed object shape (pure function). * @param {unknown} item * @returns {boolean} True if item has id, name, lat, lng with correct types. */ export function isValidFeed(item) { if (!item || typeof item !== 'object') return false const o = /** @type {Record} */ (item) return ( typeof o.id === 'string' && typeof o.name === 'string' && typeof o.lat === 'number' && typeof o.lng === 'number' ) } /** * Returns a safe stream URL (http/https only) or empty string. Prevents javascript:, data:, etc. * @param {unknown} url * @returns {string} Safe http(s) URL or empty string. */ export function sanitizeStreamUrl(url) { if (typeof url !== 'string' || !url.trim()) return '' const u = url.trim() if (u.startsWith('https://') || u.startsWith('http://')) return u return '' } /** * Sanitizes a validated feed for API response: safe streamUrl and sourceType only. * @param {{ id: string, name: string, lat: number, lng: number, [key: string]: unknown }} feed * @returns {{ id: string, name: string, lat: number, lng: number, streamUrl: string, sourceType: string, description?: string }} Sanitized feed for API. */ export function sanitizeFeedForResponse(feed) { return { id: feed.id, name: feed.name, lat: feed.lat, lng: feed.lng, streamUrl: sanitizeStreamUrl(feed.streamUrl), sourceType: feed.sourceType === 'hls' ? 'hls' : 'mjpeg', ...(typeof feed.description === 'string' ? { description: feed.description } : {}), } } /** * Filters and returns only valid feeds from an array (pure function). * @param {unknown[]} list * @returns {Array<{ id: string, name: string, lat: number, lng: number }>} Array of valid feed objects. */ export function getValidFeeds(list) { if (!Array.isArray(list)) return [] return list.filter(isValidFeed) }