All checks were successful
CI / Windows build (push) Successful in 7m47s
Redesign the optional FastAPI companion around vault files (manifest / PUT/GET/DELETE + OCR jobs) instead of legacy strokes_json notes. Wire a client Server settings panel for health/login. Polish shell UX: l10n for settings/home/board, sticky-board empty state, and a narrow-screen diagnostics FAB. Co-authored-by: Cursor <cursoragent@cursor.com>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""v1 vault sync-assist API — vault files are the source of truth."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
|
|
from fastapi.responses import Response
|
|
|
|
from ..auth import get_current_user
|
|
from .. import vault_store
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/manifest")
|
|
async def get_manifest(user_id: str = Depends(get_current_user)) -> dict:
|
|
"""List all files in the user's vault with size/mtime/sha256."""
|
|
return vault_store.build_manifest(user_id)
|
|
|
|
|
|
@router.get("/files/{file_path:path}")
|
|
async def download_file(
|
|
file_path: str,
|
|
user_id: str = Depends(get_current_user),
|
|
) -> Response:
|
|
try:
|
|
data = vault_store.read_file(user_id, file_path)
|
|
except ValueError as exc:
|
|
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
|
|
except FileNotFoundError:
|
|
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="file not found")
|
|
return Response(
|
|
content=data,
|
|
media_type="application/octet-stream",
|
|
headers={"X-Vault-Path": file_path},
|
|
)
|
|
|
|
|
|
@router.put("/files/{file_path:path}")
|
|
async def upload_file(
|
|
file_path: str,
|
|
upload: UploadFile = File(...),
|
|
user_id: str = Depends(get_current_user),
|
|
) -> dict:
|
|
try:
|
|
data = await upload.read()
|
|
entry = vault_store.write_file(user_id, file_path, data)
|
|
except ValueError as exc:
|
|
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
|
|
return entry.to_dict()
|
|
|
|
|
|
@router.delete("/files/{file_path:path}")
|
|
async def remove_file(
|
|
file_path: str,
|
|
user_id: str = Depends(get_current_user),
|
|
) -> dict:
|
|
try:
|
|
vault_store.delete_file(user_id, file_path, tombstone=True)
|
|
except ValueError as exc:
|
|
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
|
|
except FileNotFoundError:
|
|
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="file not found")
|
|
return {"deleted": file_path, "tombstone": True}
|