import axios from 'axios' import type { Album, Artist, SearchResult, Track, TrackDetail } from './types' const FURUMI_API_BASE = import.meta.env.VITE_FURUMI_API_URL ?? '' export const API_ROOT = `${FURUMI_API_BASE}/api` export const furumiApi = axios.create({ baseURL: API_ROOT, }) function sendTokenToSW(token: string) { try { const req = indexedDB.open('furumi-sw', 1) req.onupgradeneeded = () => req.result.createObjectStore('auth') req.onsuccess = () => { const tx = req.result.transaction('auth', 'readwrite') tx.objectStore('auth').put(token, 'bearer') } } catch { /* ignore */ } } export function setAuthToken(token: string) { furumiApi.defaults.headers.common['Authorization'] = `Bearer ${token}` sendTokenToSW(token) } export function clearAuthToken() { delete furumiApi.defaults.headers.common['Authorization'] } async function refreshToken(): Promise { try { const res = await fetch('/auth/token', { credentials: 'include' }) if (!res.ok) return false const data = await res.json() if (data.access_token) { setAuthToken(data.access_token) return true } } catch { /* ignore */ } return false } let refreshPromise: Promise | null = null furumiApi.interceptors.response.use( (response) => response, async (error) => { const original = error.config if (error.response?.status === 401 && !original._retried) { original._retried = true if (!refreshPromise) { refreshPromise = refreshToken().finally(() => { refreshPromise = null }) } const ok = await refreshPromise if (ok) return furumiApi(original) } return Promise.reject(error) }, ) export async function getArtists(): Promise { const res = await furumiApi.get('/artists').catch(() => null) return res?.data ?? null } export async function getArtistAlbums(artistSlug: string): Promise { const res = await furumiApi.get(`/artists/${artistSlug}/albums`).catch(() => null) return res?.data ?? null } export async function getAlbumTracks(albumSlug: string): Promise { const res = await furumiApi.get(`/albums/${albumSlug}`).catch(() => null) return res?.data ?? null } export async function getArtistTracks(artistSlug: string): Promise { const res = await furumiApi.get(`/artists/${artistSlug}/tracks`).catch(() => null) return res?.data ?? null } export async function searchTracks(query: string): Promise { const res = await furumiApi .get(`/search?q=${encodeURIComponent(query)}`) .catch(() => null) return res?.data ?? null } export async function getTrackInfo(trackSlug: string): Promise { const res = await furumiApi.get(`/tracks/${trackSlug}`).catch(() => null) return res?.data ?? null } export type RecentPlay = { track_slug: string track_title: string artist_name: string album_slug: string | null played_at: string } export async function getRecentPlays(): Promise { const res = await furumiApi.get('/me/recent').catch(() => null) return res?.data ?? null } export async function recordPlay(trackSlug: string): Promise { await furumiApi.post(`/tracks/${trackSlug}/play`).catch(() => null) }