const MANAGED_CATALOG_CACHE_PREFIX = 'radioplayer-managed-catalog-'; const MANAGED_CATALOG_SOURCE_HEADER = 'x-radioplayer-managed-source'; export type ManagedCatalogSource = 'remote' | 'cached-remote' | 'bundled' | 'unknown'; let lastManagedCatalogSource: ManagedCatalogSource = 'unknown'; type ManagedCatalogEnvelope = { stations?: unknown; }; async function loadManagedCatalogFromCache(catalogUrl: string): Promise { if (typeof window === 'undefined' || !('caches' in window)) { return null; } try { const cacheKeys = await caches.keys(); const managedCacheName = cacheKeys.find((cacheName) => cacheName.startsWith(MANAGED_CATALOG_CACHE_PREFIX)); if (!managedCacheName) { return null; } const managedCache = await caches.open(managedCacheName); return await managedCache.match(catalogUrl) ?? null; } catch { return null; } } function normalizeManagedStationsPayload(payload: unknown): unknown[] { if (Array.isArray(payload)) { return payload; } if (payload && typeof payload === 'object' && Array.isArray((payload as ManagedCatalogEnvelope).stations)) { return (payload as ManagedCatalogEnvelope).stations as unknown[]; } return []; } function setLastManagedCatalogSource(source: ManagedCatalogSource) { lastManagedCatalogSource = source; } export function getLastManagedCatalogSource(): ManagedCatalogSource { return lastManagedCatalogSource; } export async function loadManagedStations(): Promise { const remoteCatalogUrl = `${import.meta.env.BASE_URL}api/managed-stations.json`; const bundledCatalogUrl = `${import.meta.env.BASE_URL}stations.json`; const hasServiceWorkerController = typeof navigator !== 'undefined' && 'serviceWorker' in navigator && Boolean(navigator.serviceWorker.controller); let response = null; if (hasServiceWorkerController) { response = await loadManagedCatalogFromCache(remoteCatalogUrl); if (response?.ok) { setLastManagedCatalogSource('cached-remote'); } } if (!response?.ok) { try { response = await fetch(remoteCatalogUrl); if (response?.ok) { const responseSource = response.headers.get(MANAGED_CATALOG_SOURCE_HEADER); setLastManagedCatalogSource( responseSource === 'remote' || responseSource === 'cached-remote' || responseSource === 'bundled' ? responseSource : 'remote', ); } } catch { response = null; } } if (!response?.ok) { response = await fetch(bundledCatalogUrl); if (response?.ok) { setLastManagedCatalogSource('bundled'); } } if (!response.ok) { setLastManagedCatalogSource('unknown'); throw new Error(`Failed to load managed stations: ${response.status}`); } const stations = await response.json(); return normalizeManagedStationsPayload(stations); }