aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/server/repositories
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-12-07 19:20:04 +0900
committernsfisis <nsfisis@gmail.com>2025-12-07 19:20:04 +0900
commit9632d70ea0d326ac0df4e9bffb7fb669013f0755 (patch)
tree74b29b896b57c16c3bb64e8ade75566f6a8f0e1c /src/server/repositories
parentfe101104cdd50256d4ef5c61e1bf099ed2da68e3 (diff)
downloadkioku-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.ts73
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,
+ };
+ },
};