diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-12-07 19:20:04 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-12-07 19:20:04 +0900 |
| commit | 9632d70ea0d326ac0df4e9bffb7fb669013f0755 (patch) | |
| tree | 74b29b896b57c16c3bb64e8ade75566f6a8f0e1c /src/server/repositories | |
| parent | fe101104cdd50256d4ef5c61e1bf099ed2da68e3 (diff) | |
| download | kioku-9632d70ea0d326ac0df4e9bffb7fb669013f0755.tar.gz kioku-9632d70ea0d326ac0df4e9bffb7fb669013f0755.tar.zst kioku-9632d70ea0d326ac0df4e9bffb7fb669013f0755.zip | |
feat(server): add GET /api/sync/pull endpoint
Implement sync pull endpoint to fetch entities updated since a given
syncVersion. Returns decks, cards, and review logs with their current
sync versions for incremental client synchronization.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/server/repositories')
| -rw-r--r-- | src/server/repositories/sync.ts | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/server/repositories/sync.ts b/src/server/repositories/sync.ts index 3051121..87acdb4 100644 --- a/src/server/repositories/sync.ts +++ b/src/server/repositories/sync.ts @@ -62,8 +62,20 @@ export interface SyncPushResult { }; } +export interface SyncPullQuery { + lastSyncVersion: number; +} + +export interface SyncPullResult { + decks: Deck[]; + cards: Card[]; + reviewLogs: ReviewLog[]; + currentSyncVersion: number; +} + export interface SyncRepository { pushChanges(userId: string, data: SyncPushData): Promise<SyncPushResult>; + pullChanges(userId: string, query: SyncPullQuery): Promise<SyncPullResult>; } export const syncRepository: SyncRepository = { @@ -276,4 +288,65 @@ export const syncRepository: SyncRepository = { return result; }, + + async pullChanges(userId: string, query: SyncPullQuery): Promise<SyncPullResult> { + const { lastSyncVersion } = query; + + // Get all decks with syncVersion > lastSyncVersion + const pulledDecks = await db + .select() + .from(decks) + .where(and(eq(decks.userId, userId), gt(decks.syncVersion, lastSyncVersion))); + + // Get all cards from user's decks with syncVersion > lastSyncVersion + const userDeckIds = await db + .select({ id: decks.id }) + .from(decks) + .where(eq(decks.userId, userId)); + + const deckIdList = userDeckIds.map((d) => d.id); + + let pulledCards: Card[] = []; + if (deckIdList.length > 0) { + const cardResults = await db + .select() + .from(cards) + .where(gt(cards.syncVersion, lastSyncVersion)); + + // Filter cards that belong to user's decks + pulledCards = cardResults.filter((c) => deckIdList.includes(c.deckId)); + } + + // Get all review logs for user with syncVersion > lastSyncVersion + const pulledReviewLogs = await db + .select() + .from(reviewLogs) + .where(and(eq(reviewLogs.userId, userId), gt(reviewLogs.syncVersion, lastSyncVersion))); + + // Calculate current max sync version across all entities + let currentSyncVersion = lastSyncVersion; + + for (const deck of pulledDecks) { + if (deck.syncVersion > currentSyncVersion) { + currentSyncVersion = deck.syncVersion; + } + } + for (const card of pulledCards) { + if (card.syncVersion > currentSyncVersion) { + currentSyncVersion = card.syncVersion; + } + } + for (const log of pulledReviewLogs) { + if (log.syncVersion > currentSyncVersion) { + currentSyncVersion = log.syncVersion; + } + } + + return { + decks: pulledDecks, + cards: pulledCards, + reviewLogs: pulledReviewLogs, + currentSyncVersion, + }; + }, }; |
