diff options
Diffstat (limited to 'src/client/sync')
| -rw-r--r-- | src/client/sync/index.ts | 2 | ||||
| -rw-r--r-- | src/client/sync/scheduler.test.ts | 75 | ||||
| -rw-r--r-- | src/client/sync/scheduler.ts | 65 |
3 files changed, 1 insertions, 141 deletions
diff --git a/src/client/sync/index.ts b/src/client/sync/index.ts index d565569..59ae15a 100644 --- a/src/client/sync/index.ts +++ b/src/client/sync/index.ts @@ -44,8 +44,6 @@ export { syncQueue, } from "./queue"; export { - cacheStudyCards, - type ServerStudyCard, type SubmitReviewResult, submitReviewLocal, undoReviewLocal, diff --git a/src/client/sync/scheduler.test.ts b/src/client/sync/scheduler.test.ts index adee34e..d14b5ae 100644 --- a/src/client/sync/scheduler.test.ts +++ b/src/client/sync/scheduler.test.ts @@ -10,12 +10,7 @@ import { localReviewLogRepository, } from "../db/repositories"; import { syncQueue } from "./queue"; -import { - cacheStudyCards, - type ServerStudyCard, - submitReviewLocal, - undoReviewLocal, -} from "./scheduler"; +import { submitReviewLocal, undoReviewLocal } from "./scheduler"; async function clearDb() { await db.decks.clear(); @@ -182,71 +177,3 @@ describe("undoReviewLocal", () => { expect(logs).toHaveLength(0); }); }); - -describe("cacheStudyCards", () => { - beforeEach(async () => { - await clearDb(); - localStorage.clear(); - }); - - afterEach(async () => { - await clearDb(); - localStorage.clear(); - }); - - function makeServerCard(id: string): ServerStudyCard { - return { - id, - deckId: "deck-1", - noteId: `note-${id}`, - isReversed: false, - front: "front", - back: "back", - state: 0, - due: "2026-05-02T00:00:00.000Z", - stability: 0, - difficulty: 0, - elapsedDays: 0, - scheduledDays: 0, - reps: 0, - lapses: 0, - lastReview: null, - createdAt: "2026-05-01T00:00:00.000Z", - updatedAt: "2026-05-01T00:00:00.000Z", - deletedAt: null, - syncVersion: 1, - }; - } - - it("upserts new cards into IndexedDB as synced", async () => { - await cacheStudyCards([makeServerCard("card-1"), makeServerCard("card-2")]); - - const card1 = await localCardRepository.findById("card-1"); - expect(card1?._synced).toBe(true); - expect(card1?.due).toBeInstanceOf(Date); - expect(card1?.syncVersion).toBe(1); - - const card2 = await localCardRepository.findById("card-2"); - expect(card2).toBeDefined(); - }); - - it("does not clobber unsynced local edits", async () => { - const deck = await seedDeck(); - const card = await seedSyncedCard(deck.id); - await submitReviewLocal({ - cardId: card.id, - rating: Rating.Good, - durationMs: 1000, - }); - - const before = await localCardRepository.findById(card.id); - expect(before?._synced).toBe(false); - - // Simulate the server returning a stale view of this card. - await cacheStudyCards([{ ...makeServerCard(card.id), reps: 0, state: 0 }]); - - const after = await localCardRepository.findById(card.id); - expect(after?._synced).toBe(false); - expect(after?.reps).toBe(1); - }); -}); diff --git a/src/client/sync/scheduler.ts b/src/client/sync/scheduler.ts index 72a6e25..9c8572a 100644 --- a/src/client/sync/scheduler.ts +++ b/src/client/sync/scheduler.ts @@ -88,68 +88,3 @@ export async function undoReviewLocal(params: { await localReviewLogRepository.delete(params.reviewLogId); await syncQueue.notifyChanged(); } - -/** - * Server-shaped study card. Includes all FSRS fields needed to reconstruct - * a LocalCard so we can submit reviews offline. - */ -export interface ServerStudyCard { - id: string; - deckId: string; - noteId: string; - isReversed: boolean; - front: string; - back: string; - state: number; - due: string; - stability: number; - difficulty: number; - elapsedDays: number; - scheduledDays: number; - reps: number; - lapses: number; - lastReview: string | null; - createdAt: string; - updatedAt: string; - deletedAt: string | null; - syncVersion: number; -} - -/** - * Cache study cards into IndexedDB so the scheduler can submit reviews - * even when the network drops mid-session. Only cards are cached here — - * note types / fields / values come through the regular sync pull. - */ -export async function cacheStudyCards(cards: ServerStudyCard[]): Promise<void> { - for (const c of cards) { - const local: LocalCard = { - id: c.id, - deckId: c.deckId, - noteId: c.noteId, - isReversed: c.isReversed, - front: c.front, - back: c.back, - state: c.state as LocalCard["state"], - due: new Date(c.due), - stability: c.stability, - difficulty: c.difficulty, - elapsedDays: c.elapsedDays, - scheduledDays: c.scheduledDays, - reps: c.reps, - lapses: c.lapses, - lastReview: c.lastReview ? new Date(c.lastReview) : null, - createdAt: new Date(c.createdAt), - updatedAt: new Date(c.updatedAt), - deletedAt: c.deletedAt ? new Date(c.deletedAt) : null, - syncVersion: c.syncVersion, - _synced: true, - }; - - // Don't clobber pending local edits (e.g., a review that hasn't - // been pushed yet). If the local copy has unsynced changes, skip. - const existing = await localCardRepository.findById(c.id); - if (existing && !existing._synced) continue; - - await localCardRepository.upsertFromServer(local); - } -} |
