62 lines
1.8 KiB
Python
62 lines
1.8 KiB
Python
"""Character library REST API — backed by SQLite via core.database.
|
|
|
|
Mirrors the IndexedDB API in characters-library.js so the JS swap is mechanical:
|
|
GET /api/characters → { characters: [...] }
|
|
GET /api/characters/{id} → record | 404
|
|
PUT /api/characters/{id} → upsert, returns record
|
|
DELETE /api/characters/{id} → { ok: true }
|
|
POST /api/characters/migrate → bulk import from JS (one-time migration)
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, HTTPException, Request
|
|
|
|
from core.database import char_get_all, char_get, char_put, char_delete
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/api/characters")
|
|
async def characters_list():
|
|
return {"characters": char_get_all()}
|
|
|
|
|
|
@router.get("/api/characters/{char_id:path}")
|
|
async def characters_get(char_id: str):
|
|
rec = char_get(char_id)
|
|
if rec is None:
|
|
raise HTTPException(404, "Character not found")
|
|
return rec
|
|
|
|
|
|
@router.put("/api/characters/{char_id:path}")
|
|
async def characters_put(char_id: str, request: Request):
|
|
try:
|
|
body = await request.json()
|
|
except Exception:
|
|
raise HTTPException(400, "Invalid JSON")
|
|
body["id"] = char_id
|
|
return char_put(body)
|
|
|
|
|
|
@router.delete("/api/characters/{char_id:path}")
|
|
async def characters_delete(char_id: str):
|
|
char_delete(char_id)
|
|
return {"ok": True}
|
|
|
|
|
|
@router.post("/api/characters/migrate")
|
|
async def characters_migrate(request: Request):
|
|
"""Accept a batch of character 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("characters", [])
|
|
n = 0
|
|
for rec in records:
|
|
if rec.get("id"):
|
|
char_put(rec)
|
|
n += 1
|
|
return {"imported": n}
|