Files
shelfless/src/api/items.ts
Scarriffle 83d8b7b99d Initial commit: Shelfless – alternative Audiobookshelf frontend
React + Vite + TypeScript SPA covering the full ABS feature set (library
browsing, item detail, metadata/cover editing, podcasts, player with session
sync, admin: users/libraries/scanner/server settings). Dev uses a dynamic
CORS proxy; production is served by server/index.mjs (static + reverse proxy
to ABS_URL). Includes systemd unit and installer under deploy/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 20:23:04 +02:00

60 lines
2.0 KiB
TypeScript

import { api } from './client'
import type { BookMetadata, LibraryItem, PodcastMetadata } from '@/types/abs'
export interface GetItemOptions {
expanded?: boolean
/** e.g. "progress" */
include?: string
}
export async function getItem(id: string, opts: GetItemOptions = {}): Promise<LibraryItem> {
const res = await api.get<LibraryItem>(`/api/items/${id}`, {
params: {
expanded: opts.expanded ? 1 : undefined,
include: opts.include,
},
})
return res.data
}
export async function deleteItem(id: string, hard = false): Promise<void> {
await api.delete(`/api/items/${id}`, { params: hard ? { hard: 1 } : undefined })
}
/** Update book/podcast metadata. ABS: PATCH /api/items/:id/media with { metadata }. */
export async function updateMedia(
id: string,
payload: { metadata?: Partial<BookMetadata> | Partial<PodcastMetadata>; tags?: string[] },
): Promise<LibraryItem> {
const res = await api.patch<LibraryItem>(`/api/items/${id}/media`, payload)
return res.data
}
/** Upload a cover image file (multipart/form-data). */
export async function uploadCover(id: string, file: File): Promise<{ success?: boolean; cover?: string }> {
const form = new FormData()
form.append('cover', file)
const res = await api.post(`/api/items/${id}/cover`, form, {
headers: { 'Content-Type': 'multipart/form-data' },
})
return res.data
}
/** Set a cover from a remote URL (JSON body). */
export async function setCoverByUrl(id: string, url: string): Promise<{ success?: boolean; cover?: string }> {
const res = await api.post(`/api/items/${id}/cover`, { url })
return res.data
}
export async function removeCover(id: string): Promise<void> {
await api.delete(`/api/items/${id}/cover`)
}
export async function batchDelete(libraryItemIds: string[], hard = false): Promise<void> {
await api.post('/api/items/batch/delete', { libraryItemIds }, { params: hard ? { hard: 1 } : undefined })
}
export async function batchUpdate(updates: Array<{ id: string } & Record<string, unknown>>): Promise<void> {
await api.post('/api/items/batch/update', updates)
}