Initial project scaffold: FastAPI backend + Svelte 5 frontend

Backend (uv): FastAPI app with routers (foods, log, targets, OFF proxy),
SQLAlchemy models, Pydantic schemas, migration runner + 0001 initial schema,
example pytest suite (7 tests).
Frontend (npm): Vite 7 + Svelte 5 runes, lib/ (api, stores, scanner, format)
per spec §7, placeholder components, example vitest suite (4 tests).
SPEC.md §1: registered uvicorn and Vitest (rule §8.3.3).
This commit is contained in:
Craig
2026-07-26 10:25:59 +01:00
commit e047d884b6
47 changed files with 3994 additions and 0 deletions
View File
+7
View File
@@ -0,0 +1,7 @@
"""Meal business logic: composition, recursion, cycle detection (spec §2.2).
Multi-write operations here own their transactions (spec §8.1 rule 6):
commit once at the end or roll back entirely.
TODO: from-log, unpack, component replacement with cycle checks.
"""
+30
View File
@@ -0,0 +1,30 @@
"""Nutrition math — the ONLY place nutrition is computed (spec §8.1 rule 1).
Routers never compute nutrition; the frontend never re-derives it.
`quantity` is interpreted by context (spec §2.1):
- unit_type "weight": quantity is grams; nutrition = (quantity / 100) × per_unit
- unit_type "count": quantity is item count; nutrition = quantity × per_unit
- meal: quantity is a scaling factor (1.0 = one full meal)
"""
from models import Food
def scale_to_quantity(per_unit: float | None, quantity: float, unit_type: str) -> float:
"""Scale a per-unit nutrition value to a logged quantity. Missing values count as 0."""
if per_unit is None:
return 0.0
if unit_type == "weight":
return per_unit * quantity / 100.0
if unit_type == "count":
return per_unit * quantity
raise ValueError(f"unknown unit_type: {unit_type!r}")
def entry_calories(food: Food, quantity: float) -> float:
"""Calories for a single (non-meal) food at a logged quantity.
TODO: handle is_meal foods by summing scaled component nutrition
(recursively, with cycle detection — spec §2.2).
"""
return scale_to_quantity(food.calories_per_unit, quantity, food.unit_type)