feat(stats): add stats server, API endpoints, config, and Anki integration

- Hono HTTP server with 20+ REST endpoints for stats data
- Stats overlay BrowserWindow with toggle keybinding
- IPC channel definitions and preload bridge
- Stats config section (toggleKey, serverPort, autoStartServer, autoOpenBrowser)
- Config resolver for stats section
- AnkiConnect proxy endpoints (guiBrowse, notesInfo)
- Note ID passthrough in card mining callback chain
- Stats CLI command with autoOpenBrowser respect
This commit is contained in:
2026-03-14 22:14:09 -07:00
parent fe8bb167c4
commit ffe5c6e1c6
36 changed files with 2273 additions and 86 deletions

View File

@@ -0,0 +1,35 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { PollingRunner } from './polling';
test('polling runner records newly added cards after initialization', async () => {
const recordedCards: number[] = [];
let tracked = new Set<number>();
const responses = [[10, 11], [10, 11, 12, 13]];
const runner = new PollingRunner({
getDeck: () => 'Mining',
getPollingRate: () => 250,
findNotes: async () => responses.shift() ?? [],
shouldAutoUpdateNewCards: () => true,
processNewCard: async () => undefined,
recordCardsAdded: (count) => {
recordedCards.push(count);
},
isUpdateInProgress: () => false,
setUpdateInProgress: () => undefined,
getTrackedNoteIds: () => tracked,
setTrackedNoteIds: (noteIds) => {
tracked = noteIds;
},
showStatusNotification: () => undefined,
logDebug: () => undefined,
logInfo: () => undefined,
logWarn: () => undefined,
});
await runner.pollOnce();
await runner.pollOnce();
assert.deepEqual(recordedCards, [2]);
});