Files
TermorServer/apps/web/src/lib/api.ts
benya f8880aa9a4 feat: add scan status and cover art endpoints
Track scanner status for the web API and Subsonic-compatible scan endpoints, add authenticated cover art serving, and wire album artwork into the web UI. Keep Subsonic auth limited to legacy password mode for now so behavior stays honest with the current bcrypt-based user storage.
2026-04-02 22:37:10 +03:00

76 lines
1.7 KiB
TypeScript

import { useSessionStore } from '@/stores/session-store'
export type User = {
id: string
username: string
isAdmin: boolean
}
export type HomePayload = {
recentAlbums: Array<{
id: string
artistId: string
artistName: string
title: string
year: number
trackCount: number
coverArtId: string
}>
artists: Array<{
id: string
name: string
albumCount: number
}>
}
export type Track = {
id: string
albumId: string
artistId: string
title: string
artistName: string
albumTitle: string
trackNumber: number
durationSeconds: number
}
const API_BASE = import.meta.env.VITE_API_BASE ?? 'http://localhost:4040'
async function request<T>(path: string, init?: RequestInit): Promise<T> {
const token = useSessionStore.getState().token
const response = await fetch(`${API_BASE}${path}`, {
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(init?.headers ?? {}),
},
...init,
})
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`)
}
return response.json() as Promise<T>
}
export async function login(username: string, password: string) {
return request<{ token: string; user: User }>('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ username, password }),
})
}
export async function fetchHome() {
return request<HomePayload>('/api/home')
}
export async function fetchTracks() {
return request<{ items: Track[] }>('/api/tracks')
}
export function coverArtUrl(id: string) {
const token = useSessionStore.getState().token
return `${API_BASE}/api/cover-art/${id}${token ? `?token=${encodeURIComponent(token)}` : ''}`
}