"""tarot-lab FastAPI app — /api/tarot/* 6 endpoints.""" from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from .config import CORS_ALLOW_ORIGINS from .models import ( TarotInterpretRequest, TarotInterpretResponse, TarotSaveRequest, TarotPatchRequest, ) from . import pipeline, db as db_module app = FastAPI(title="tarot-lab") _origins = [o.strip() for o in CORS_ALLOW_ORIGINS.split(",") if o.strip()] app.add_middleware( CORSMiddleware, allow_origins=_origins, allow_credentials=False, allow_methods=["GET", "POST", "PATCH", "DELETE", "OPTIONS"], allow_headers=["Content-Type"], ) @app.on_event("startup") def _init(): db_module.init_db() @app.get("/health") def health(): return {"ok": True} @app.post("/api/tarot/interpret", response_model=TarotInterpretResponse) async def interpret_endpoint(req: TarotInterpretRequest): try: result = await pipeline.interpret(req) except pipeline.TarotError as e: raise HTTPException(status_code=500, detail=str(e)) from e return result @app.post("/api/tarot/readings") async def save_reading(req: TarotSaveRequest): rid = db_module.save_tarot_reading(req.model_dump()) row = db_module.get_tarot_reading(rid) return {"id": rid, "created_at": row["created_at"]} @app.get("/api/tarot/readings") async def list_readings( page: int = 1, size: int = 20, favorite: bool | None = None, spread_type: str | None = None, category: str | None = None, ): return db_module.list_tarot_readings( page=page, size=size, favorite=favorite, spread_type=spread_type, category=category, ) @app.get("/api/tarot/readings/{reading_id}") async def get_reading(reading_id: int): row = db_module.get_tarot_reading(reading_id) if not row: raise HTTPException(status_code=404, detail="reading not found") return row @app.patch("/api/tarot/readings/{reading_id}") async def patch_reading(reading_id: int, req: TarotPatchRequest): row = db_module.get_tarot_reading(reading_id) if not row: raise HTTPException(status_code=404, detail="reading not found") db_module.update_tarot_reading(reading_id, **req.model_dump(exclude_none=True)) return {"ok": True} @app.delete("/api/tarot/readings/{reading_id}") async def delete_reading(reading_id: int): row = db_module.get_tarot_reading(reading_id) if not row: raise HTTPException(status_code=404, detail="reading not found") db_module.delete_tarot_reading(reading_id) return {"ok": True}