"""Rehearsal library REST API — backed by SQLite via core.database. Mirrors the IndexedDB API in rehearser.js: GET /api/rehearsals → { rehearsals: [...] } GET /api/rehearsals/{id} → record | 404 PUT /api/rehearsals/{id} → full replace (id must exist) POST /api/rehearsals → insert (no id), returns { id } DELETE /api/rehearsals/{id} → { ok: true } POST /api/rehearsals/migrate → bulk import from JS IndexedDB dump """ from __future__ import annotations from fastapi import APIRouter, HTTPException, Request from core.database import reh_get_all, reh_get, reh_put, reh_delete, reh_compact_titles router = APIRouter() @router.get("/api/rehearsals") async def rehearsals_list(): reh_compact_titles() return {"rehearsals": reh_get_all()} @router.get("/api/rehearsals/{reh_id:int}") async def rehearsals_get(reh_id: int): rec = reh_get(reh_id) if rec is None: raise HTTPException(404, "Rehearsal not found") return rec @router.post("/api/rehearsals") async def rehearsals_add(request: Request): try: body = await request.json() except Exception: raise HTTPException(400, "Invalid JSON") body.pop("id", None) saved = reh_put(body) return {"id": saved["id"]} @router.put("/api/rehearsals/{reh_id:int}") async def rehearsals_put(reh_id: int, request: Request): if reh_get(reh_id) is None: raise HTTPException(404, "Rehearsal not found") try: body = await request.json() except Exception: raise HTTPException(400, "Invalid JSON") body["id"] = reh_id reh_put(body) return {"ok": True} @router.delete("/api/rehearsals/{reh_id:int}") async def rehearsals_delete(reh_id: int): reh_delete(reh_id) return {"ok": True} @router.post("/api/rehearsals/migrate") async def rehearsals_migrate(request: Request): """Accept a batch of rehearsal records from the browser's IndexedDB dump.""" try: body = await request.json() except Exception: raise HTTPException(400, "Invalid JSON") records = body if isinstance(body, list) else body.get("rehearsals", []) ids = [] for rec in records: saved = reh_put(rec) ids.append(saved["id"]) return {"imported": len(ids), "ids": ids}