- 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)
39 lines
1.2 KiB
Python
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())
|