forked from akai/readest
35b02c4efc
Supersedes #3156. Adds a reading-statistics system whose canonical data model is KOReader's own (book + page_stat_data), so stats round-trip losslessly between Readest and KOReader. - Storage: a cross-platform Turso statistics.db in KOReader's exact schema (web/Workers, desktop, iOS, Android) — replacing #3156's Node-only better-sqlite3 + statistics.json. - Tracking: per-page reading events (time-on-page, idle-capped) flushed on page-change/idle/hide/close — the KOReader model — not session aggregates. - Sync: legacy /api/sync extended with a stats type backed by self-contained Supabase tables (stat_books, stat_pages); union/longer-duration-wins merge keyed on book_hash. apps/readest.koplugin syncs through the same endpoint. - Scale & robustness: per-tab singleton connection (avoids OPFS lock conflicts) + explicit WAL checkpoint; transactional bulk apply; chunked resumable push; client-driven paged pull with trailing-ms completion; paginated/scoped server merge. Verified: 5668 unit tests, 155 koplugin busted tests, biome+tsgo + luacheck all green; web OPFS DB verified live. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
1.5 KiB
JSON
51 lines
1.5 KiB
JSON
{
|
|
"base_url": "https://web.readest.com/api",
|
|
"name": "readest-sync-api",
|
|
"methods": {
|
|
"pullChanges": {
|
|
"path": "/sync",
|
|
"method": "GET",
|
|
"required_params": ["since", "type", "book", "meta_hash"],
|
|
"expected_status": [200, 400, 301, 401, 403]
|
|
},
|
|
"pushChanges": {
|
|
"path": "/sync",
|
|
"method": "POST",
|
|
"required_params": ["books", "notes", "configs"],
|
|
"payload": ["books", "notes", "configs", "statBooks", "statPages"],
|
|
"expected_status": [200, 201, 301, 400, 401, 403]
|
|
},
|
|
"pullBooks": {
|
|
"path": "/sync?type=books",
|
|
"method": "GET",
|
|
"required_params": ["since"],
|
|
"expected_status": [200, 400, 301, 401, 403]
|
|
},
|
|
"getDownloadUrl": {
|
|
"path": "/storage/download",
|
|
"method": "GET",
|
|
"required_params": ["fileKey"],
|
|
"expected_status": [200, 400, 301, 401, 403, 404]
|
|
},
|
|
"listFiles": {
|
|
"path": "/storage/list",
|
|
"method": "GET",
|
|
"required_params": ["bookHash"],
|
|
"expected_status": [200, 400, 301, 401, 403]
|
|
},
|
|
"deleteFile": {
|
|
"path": "/storage/delete",
|
|
"method": "DELETE",
|
|
"required_params": ["fileKey"],
|
|
"expected_status": [200, 400, 301, 401, 403, 404]
|
|
},
|
|
"getUploadUrl": {
|
|
"path": "/storage/upload",
|
|
"method": "POST",
|
|
"required_params": ["fileName", "fileSize", "bookHash"],
|
|
"payload": ["fileName", "fileSize", "bookHash"],
|
|
"expected_status": [200, 400, 301, 401, 403]
|
|
}
|
|
}
|
|
}
|