Files
Bike-Tinder/app/serve.py
Torres 5df2a20bac app: FastAPI API + serve CLI (Phase 2)
- create_app(db_path, img_dir, state_dir) factory; every route + payload
  from app.state — selfcheck runs the real router on a temp DB copy
- /api/health (ok/db/counts), /api/stats (live/new/likes/maybes/nopes/
  last_import), /api/deck (undecided semantics, score/first_seen/id DESC,
  opaque '<score>|<first_seen>|<id>' cursor, strictly-after tuple page,
  remaining count), /api/swipe upsert + DELETE (idempotent), /api/list
  (decision/sort/q/limit/offset, total), /api/listing/{id}, /api/import
  (importer, HTTP 200 even when gates fail), /api/badge/seen, /img/{id}
  (cached file -> 302 img_url -> 404), static routes (/, manifest, sw.js,
  icons, apple-touch; no-cache on index + sw.js)
- frozen payload contract incl. img=/img/{id} when img_url or cached file
- serve.py: argparse (--db/--img-dir/--state-dir/--host/--port, defaults
  127.0.0.1:9453) -> uvicorn.run
- verified: 560-deep deck walks clean with zero page overlap, swipe ->
  list -> edit -> delete -> back on deck, badge roundtrip (new 560 -> 0);
  real uvicorn returns true 302 for the img fallback (TestClient in this
  fastapi/httpx pair mangles RedirectResponse into a 404 — framework
  artifact, not app behavior)
2026-11-10 21:17:57 -04:00

39 lines
1.2 KiB
Python

"""Serve the Bike-Tinder app (FastAPI + uvicorn).
.venv/bin/python -m app.serve --db data/bike-tinder.sqlite3 --port 9453
Defaults per the task brief: host 127.0.0.1, port 9453, DB data/bike-tinder.sqlite3,
images data/img. The import endpoint points at the hunt state dir
(~/.hermes/scripts/motorcycle-hunt.d) unless --state-dir overrides it.
"""
import argparse
import os
import sys
from .api import create_app
def default_state_dir():
return os.path.expanduser('~/.hermes/scripts/motorcycle-hunt.d')
def main(argv=None):
ap = argparse.ArgumentParser(description='Bike-Tinder server')
ap.add_argument('--db', default='data/bike-tinder.sqlite3')
ap.add_argument('--img-dir', default='data/img')
ap.add_argument('--state-dir', default=None,
help='hunt state dir for POST /api/import'
' (default: ~/.hermes/scripts/motorcycle-hunt.d)')
ap.add_argument('--host', default='127.0.0.1')
ap.add_argument('--port', type=int, default=9453)
args = ap.parse_args(argv)
import uvicorn
app = create_app(args.db, args.img_dir,
args.state_dir or default_state_dir())
uvicorn.run(app, host=args.host, port=args.port)
if __name__ == '__main__':
sys.exit(main())