HTTP analytics API via query engine (aggregate, messages, search)#188
HTTP analytics API via query engine (aggregate, messages, search)#188
Conversation
… routes - Add engine field and WithEngine() method to Server struct - Register GET /api/v1/aggregate, /engine/messages, /engine/search - Add api_key query param fallback in authMiddleware for browser access
…rch handlers - GET /api/v1/aggregate: grouped stats by sender/domain/label/time with drill-down support via from/subject/domain/account filter params - GET /api/v1/engine/messages: paginated list with sort, period/date range, account, attachment and MIME category (file_type=) filters - GET /api/v1/engine/search: full-text search with Gmail-style query syntax - All endpoints return HTTP 503 when no engine is configured
roborev: Combined Review (
|
roborev: Combined Review (
|
roborev: Combined Review (
|
roborev: Combined Review (
|
roborev: Combined Review (
|
|
Would you like me to work on getting this PR in? |
Summary
Adds three new HTTP endpoints backed by the query engine (SQLite/DuckDB), enabling the web UI to power its analytics views, message listing, and full-text search without coupling directly to SQLite queries.
Changes
New endpoints
GET /api/v1/aggregate— Returns grouped statistics by sender, sender name, recipient, domain, label, or time granularity (year/month/day). Supports drill-down viafrom,subject,domain, andaccountfilter params.GET /api/v1/engine/messages— Paginated message list with sort (date/size/subject),period=orafter=/before=date range,account,has_attachment, andfile_type=MIME category filters (Images, PDFs, Calendar invites, Documents, etc.).GET /api/v1/engine/search— Full-text search with Gmail-style query syntax (from:,subject:, etc.). Returns HTTP 400 ifqis missing.All three endpoints return HTTP 503 when no engine is configured, allowing graceful degradation.
Server wiring (
internal/api/server.go)engine query.Enginefield andWithEngine(e query.Engine) *Servermethod.api_keyquery param fallback inauthMiddlewarefor direct browser navigation.Query package (
internal/query/)MimeCategory stringfield toMessageFilterfor MIME-type-based filtering.MimeCategoryPatterns()andMimeCategoryExistsSQL()helpers that map category names to SQLLIKEpatterns and buildEXISTSsubqueries (used by both engines).CountMessages(ctx, filter) (int64, error)to theEngineinterface with implementations in bothSQLiteEngineandDuckDBEngine(DuckDB delegates to SQLite when available, falls back to Parquet COUNT).Testing
internal/apiandinternal/querytests continue to pass.