aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-02-12 14:54:18 +0000
committerClaude <noreply@anthropic.com>2026-02-12 14:54:18 +0000
commit1afb825860cd293b8065d51746f4b23e4e8dab5d (patch)
tree1fe3a43f1c7ab469bb0154a1495028cc42b414a0
parent9a52e7ad3b2d46c523caf079794fdb7757375b91 (diff)
downloadkioku-1afb825860cd293b8065d51746f4b23e4e8dab5d.tar.gz
kioku-1afb825860cd293b8065d51746f4b23e4e8dab5d.tar.zst
kioku-1afb825860cd293b8065d51746f4b23e4e8dab5d.zip
feat: 学習カード数の上限を撤廃
REVIEW_CARDS_LIMIT(復習カード80枚制限)とnewCardsPerDay(1日の新規カード制限) を削除し、期日が来たすべてのカードを制限なく返すように変更。 削除した主な要素: - REVIEW_CARDS_LIMIT定数とカード取得時のlimitパラメータ - newCardsPerDayフィールド(DB schema, 型定義, Zod schema, sync, CRDT) - countDueNewCards, countDueReviewCards, findDueNewCardsForStudy, findDueReviewCardsForStudy(CardRepository) - countTodayNewCardReviews(ReviewLogRepository) - デッキルートからのReviewLogRepository依存 https://claude.ai/code/session_018hrEJ9vg3RPoeAPyEc17gS
-rw-r--r--src/client/atoms/decks.ts1
-rw-r--r--src/client/components/CreateDeckModal.test.tsx2
-rw-r--r--src/client/components/EditDeckModal.test.tsx2
-rw-r--r--src/client/components/EditDeckModal.tsx1
-rw-r--r--src/client/db/index.test.ts1
-rw-r--r--src/client/db/index.ts1
-rw-r--r--src/client/db/repositories.test.ts17
-rw-r--r--src/client/db/repositories.ts2
-rw-r--r--src/client/pages/DeckCardsPage.test.tsx1
-rw-r--r--src/client/pages/DeckDetailPage.test.tsx1
-rw-r--r--src/client/pages/HomePage.test.tsx4
-rw-r--r--src/client/sync/conflict.test.ts21
-rw-r--r--src/client/sync/conflict.ts1
-rw-r--r--src/client/sync/crdt/concurrent-edits.test.ts33
-rw-r--r--src/client/sync/crdt/document-manager.test.ts13
-rw-r--r--src/client/sync/crdt/document-manager.ts3
-rw-r--r--src/client/sync/crdt/migration.test.ts1
-rw-r--r--src/client/sync/crdt/repositories.test.ts14
-rw-r--r--src/client/sync/crdt/types.test.ts3
-rw-r--r--src/client/sync/crdt/types.ts1
-rw-r--r--src/client/sync/manager.test.ts2
-rw-r--r--src/client/sync/pull.test.ts22
-rw-r--r--src/client/sync/pull.ts2
-rw-r--r--src/client/sync/push.test.ts17
-rw-r--r--src/client/sync/push.ts2
-rw-r--r--src/client/sync/queue.test.ts12
-rw-r--r--src/server/db/schema.ts1
-rw-r--r--src/server/repositories/card.test.ts4
-rw-r--r--src/server/repositories/card.ts93
-rw-r--r--src/server/repositories/deck.test.ts5
-rw-r--r--src/server/repositories/deck.ts3
-rw-r--r--src/server/repositories/review-log.ts21
-rw-r--r--src/server/repositories/sync.test.ts1
-rw-r--r--src/server/repositories/sync.ts3
-rw-r--r--src/server/repositories/types.ts25
-rw-r--r--src/server/routes/cards.test.ts5
-rw-r--r--src/server/routes/decks.test.ts53
-rw-r--r--src/server/routes/decks.ts43
-rw-r--r--src/server/routes/notes.test.ts1
-rw-r--r--src/server/routes/study.test.ts109
-rw-r--r--src/server/routes/study.ts15
-rw-r--r--src/server/routes/sync.test.ts9
-rw-r--r--src/server/routes/sync.ts1
-rw-r--r--src/server/schemas/index.ts3
-rw-r--r--src/server/types/index.ts1
45 files changed, 40 insertions, 536 deletions
diff --git a/src/client/atoms/decks.ts b/src/client/atoms/decks.ts
index 5a624cf..5a4d44e 100644
--- a/src/client/atoms/decks.ts
+++ b/src/client/atoms/decks.ts
@@ -6,7 +6,6 @@ export interface Deck {
id: string;
name: string;
description: string | null;
- newCardsPerDay: number;
dueCardCount: number;
createdAt: string;
updatedAt: string;
diff --git a/src/client/components/CreateDeckModal.test.tsx b/src/client/components/CreateDeckModal.test.tsx
index cdc5f97..fcaa572 100644
--- a/src/client/components/CreateDeckModal.test.tsx
+++ b/src/client/components/CreateDeckModal.test.tsx
@@ -146,7 +146,6 @@ describe("CreateDeckModal", () => {
id: "deck-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
},
}),
}),
@@ -187,7 +186,6 @@ describe("CreateDeckModal", () => {
id: "deck-1",
name: "Test Deck",
description: "A test description",
- newCardsPerDay: 20,
},
}),
}),
diff --git a/src/client/components/EditDeckModal.test.tsx b/src/client/components/EditDeckModal.test.tsx
index fce17f6..b22cb1d 100644
--- a/src/client/components/EditDeckModal.test.tsx
+++ b/src/client/components/EditDeckModal.test.tsx
@@ -42,7 +42,6 @@ describe("EditDeckModal", () => {
id: "deck-123",
name: "Test Deck",
description: "Test description",
- newCardsPerDay: 20,
};
const defaultProps = {
@@ -60,7 +59,6 @@ describe("EditDeckModal", () => {
id: "deck-123",
name: "Test Deck",
description: "Test description",
- newCardsPerDay: 20,
},
});
});
diff --git a/src/client/components/EditDeckModal.tsx b/src/client/components/EditDeckModal.tsx
index 3babeb5..8e95295 100644
--- a/src/client/components/EditDeckModal.tsx
+++ b/src/client/components/EditDeckModal.tsx
@@ -5,7 +5,6 @@ interface Deck {
id: string;
name: string;
description: string | null;
- newCardsPerDay: number;
}
interface EditDeckModalProps {
diff --git a/src/client/db/index.test.ts b/src/client/db/index.test.ts
index 0a4882d..0dd3758 100644
--- a/src/client/db/index.test.ts
+++ b/src/client/db/index.test.ts
@@ -64,7 +64,6 @@ describe("KiokuDatabase", () => {
userId: "user-1",
name: "Test Deck",
description: "A test deck",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
deletedAt: null,
diff --git a/src/client/db/index.ts b/src/client/db/index.ts
index 59cc526..50d8bbd 100644
--- a/src/client/db/index.ts
+++ b/src/client/db/index.ts
@@ -77,7 +77,6 @@ export interface LocalDeck {
userId: string;
name: string;
description: string | null;
- newCardsPerDay: number;
createdAt: Date;
updatedAt: Date;
deletedAt: Date | null;
diff --git a/src/client/db/repositories.test.ts b/src/client/db/repositories.test.ts
index d591205..b461990 100644
--- a/src/client/db/repositories.test.ts
+++ b/src/client/db/repositories.test.ts
@@ -33,14 +33,12 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Test Deck",
description: "A test deck",
- newCardsPerDay: 20,
});
expect(deck.id).toBeDefined();
expect(deck.userId).toBe("user-1");
expect(deck.name).toBe("Test Deck");
expect(deck.description).toBe("A test deck");
- expect(deck.newCardsPerDay).toBe(20);
expect(deck.createdAt).toBeInstanceOf(Date);
expect(deck.updatedAt).toBeInstanceOf(Date);
expect(deck.deletedAt).toBeNull();
@@ -53,7 +51,6 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 10,
});
const found = await db.decks.get(created.id);
@@ -67,7 +64,6 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const found = await localDeckRepository.findById(created.id);
@@ -86,19 +82,16 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Deck 1",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.create({
userId: "user-1",
name: "Deck 2",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.create({
userId: "user-2",
name: "Other User Deck",
description: null,
- newCardsPerDay: 20,
});
const decks = await localDeckRepository.findByUserId("user-1");
@@ -111,7 +104,6 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Deleted Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.delete(deck.id);
@@ -126,7 +118,6 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Original Name",
description: null,
- newCardsPerDay: 20,
});
const updated = await localDeckRepository.update(deck.id, {
@@ -156,7 +147,6 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const result = await localDeckRepository.delete(deck.id);
@@ -179,13 +169,11 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Unsynced",
description: null,
- newCardsPerDay: 20,
});
const deck2 = await localDeckRepository.create({
userId: "user-1",
name: "Synced",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck2.id, 1);
@@ -201,7 +189,6 @@ describe("localDeckRepository", () => {
userId: "user-1",
name: "Test",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 5);
@@ -225,7 +212,6 @@ describe("localCardRepository", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
deckId = deck.id;
});
@@ -425,7 +411,6 @@ describe("localReviewLogRepository", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
deckId = deck.id;
@@ -950,7 +935,6 @@ describe("localNoteRepository", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
deckId = deck.id;
@@ -1110,7 +1094,6 @@ describe("localNoteFieldValueRepository", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const noteType = await localNoteTypeRepository.create({
diff --git a/src/client/db/repositories.ts b/src/client/db/repositories.ts
index 4c302bf..a0663e1 100644
--- a/src/client/db/repositories.ts
+++ b/src/client/db/repositories.ts
@@ -63,7 +63,7 @@ export const localDeckRepository = {
*/
async update(
id: string,
- data: Partial<Pick<LocalDeck, "name" | "description" | "newCardsPerDay">>,
+ data: Partial<Pick<LocalDeck, "name" | "description">>,
): Promise<LocalDeck | undefined> {
const deck = await db.decks.get(id);
if (!deck) return undefined;
diff --git a/src/client/pages/DeckCardsPage.test.tsx b/src/client/pages/DeckCardsPage.test.tsx
index 7bc97fb..7c3c184 100644
--- a/src/client/pages/DeckCardsPage.test.tsx
+++ b/src/client/pages/DeckCardsPage.test.tsx
@@ -72,7 +72,6 @@ const mockDeck = {
id: "deck-1",
name: "Japanese Vocabulary",
description: "Common Japanese words",
- newCardsPerDay: 20,
dueCardCount: 0,
createdAt: "2024-01-01T00:00:00Z",
updatedAt: "2024-01-01T00:00:00Z",
diff --git a/src/client/pages/DeckDetailPage.test.tsx b/src/client/pages/DeckDetailPage.test.tsx
index 3c741ad..9dcb152 100644
--- a/src/client/pages/DeckDetailPage.test.tsx
+++ b/src/client/pages/DeckDetailPage.test.tsx
@@ -59,7 +59,6 @@ const mockDeck = {
id: "deck-1",
name: "Japanese Vocabulary",
description: "Common Japanese words",
- newCardsPerDay: 20,
dueCardCount: 0,
createdAt: "2024-01-01T00:00:00Z",
updatedAt: "2024-01-01T00:00:00Z",
diff --git a/src/client/pages/HomePage.test.tsx b/src/client/pages/HomePage.test.tsx
index 8b17506..179c649 100644
--- a/src/client/pages/HomePage.test.tsx
+++ b/src/client/pages/HomePage.test.tsx
@@ -92,7 +92,6 @@ const mockDecks = [
id: "deck-1",
name: "Japanese Vocabulary",
description: "Common Japanese words",
- newCardsPerDay: 20,
dueCardCount: 5,
createdAt: "2024-01-01T00:00:00Z",
updatedAt: "2024-01-01T00:00:00Z",
@@ -101,7 +100,6 @@ const mockDecks = [
id: "deck-2",
name: "Spanish Verbs",
description: null,
- newCardsPerDay: 10,
dueCardCount: 0,
createdAt: "2024-01-02T00:00:00Z",
updatedAt: "2024-01-02T00:00:00Z",
@@ -254,7 +252,6 @@ describe("HomePage", () => {
id: "deck-1",
name: "No Description Deck",
description: null,
- newCardsPerDay: 20,
dueCardCount: 0,
createdAt: "2024-01-01T00:00:00Z",
updatedAt: "2024-01-01T00:00:00Z",
@@ -334,7 +331,6 @@ describe("HomePage", () => {
id: "deck-new",
name: "New Deck",
description: "A new deck",
- newCardsPerDay: 20,
dueCardCount: 0,
createdAt: "2024-01-03T00:00:00Z",
updatedAt: "2024-01-03T00:00:00Z",
diff --git a/src/client/sync/conflict.test.ts b/src/client/sync/conflict.test.ts
index bcd8dae..d11e150 100644
--- a/src/client/sync/conflict.test.ts
+++ b/src/client/sync/conflict.test.ts
@@ -155,7 +155,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Name",
description: "Local description",
- newCardsPerDay: 10,
});
const serverDeck = {
@@ -163,7 +162,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Name",
description: "Server description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-03"),
deletedAt: null,
@@ -178,7 +176,6 @@ describe("ConflictResolver", () => {
const updatedDeck = await localDeckRepository.findById(localDeck.id);
expect(updatedDeck?.name).toBe("Server Name");
expect(updatedDeck?.description).toBe("Server description");
- expect(updatedDeck?.newCardsPerDay).toBe(20);
expect(updatedDeck?._synced).toBe(true);
});
});
@@ -189,7 +186,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const localCard = await localCardRepository.create({
@@ -240,13 +236,11 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Deck 1",
description: null,
- newCardsPerDay: 10,
});
const deck2 = await localDeckRepository.create({
userId: "user-1",
name: "Local Deck 2",
description: null,
- newCardsPerDay: 10,
});
const pushResult: SyncPushResult = {
@@ -273,7 +267,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Deck 1",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -284,7 +277,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Deck 2",
description: null,
- newCardsPerDay: 25,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -314,7 +306,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const card = await localCardRepository.create({
@@ -397,7 +388,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -425,7 +415,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Only Deck",
description: null,
- newCardsPerDay: 10,
});
const pushResult: SyncPushResult = {
@@ -462,7 +451,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Name",
description: null,
- newCardsPerDay: 10,
});
const pushResult: SyncPushResult = {
@@ -483,7 +471,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Name",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -514,7 +501,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Deck Name",
description: "Local description",
- newCardsPerDay: 10,
});
// Store local CRDT document
@@ -532,7 +518,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Deck Name",
description: "Server description",
- newCardsPerDay: 20,
createdAt: localDeck.createdAt,
updatedAt: new Date(Date.now() + 1000),
deletedAt: null,
@@ -590,7 +575,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Name",
description: null,
- newCardsPerDay: 10,
});
const serverDeck = {
@@ -598,7 +582,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Name",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -649,7 +632,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Name",
description: null,
- newCardsPerDay: 10,
});
const serverDeck = {
@@ -657,7 +639,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Name",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -699,7 +680,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Local Name",
description: null,
- newCardsPerDay: 10,
});
const serverDeck = {
@@ -707,7 +687,6 @@ describe("ConflictResolver", () => {
userId: "user-1",
name: "Server Name",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
diff --git a/src/client/sync/conflict.ts b/src/client/sync/conflict.ts
index 7ad0805..64287a1 100644
--- a/src/client/sync/conflict.ts
+++ b/src/client/sync/conflict.ts
@@ -67,7 +67,6 @@ function serverDeckToLocal(deck: ServerDeck): LocalDeck {
userId: deck.userId,
name: deck.name,
description: deck.description,
- newCardsPerDay: deck.newCardsPerDay,
createdAt: new Date(deck.createdAt),
updatedAt: new Date(deck.updatedAt),
deletedAt: deck.deletedAt ? new Date(deck.deletedAt) : null,
diff --git a/src/client/sync/crdt/concurrent-edits.test.ts b/src/client/sync/crdt/concurrent-edits.test.ts
index 2b6f182..d55b233 100644
--- a/src/client/sync/crdt/concurrent-edits.test.ts
+++ b/src/client/sync/crdt/concurrent-edits.test.ts
@@ -34,7 +34,6 @@ function createTestDeck(overrides: Partial<LocalDeck> = {}): LocalDeck {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -89,10 +88,10 @@ describe("Concurrent edit scenarios", () => {
d.meta.lastModified = Date.now();
});
- // Device B: Offline edit - change newCardsPerDay
+ // Device B: Offline edit - change description
const deviceBDoc = Automerge.clone(serverDoc);
const deviceBEdited = updateDocument(deviceBDoc, (d) => {
- d.data.newCardsPerDay = 30;
+ d.data.description = "Updated by Device B";
d.meta.lastModified = Date.now();
});
@@ -101,7 +100,7 @@ describe("Concurrent edit scenarios", () => {
// Both changes should be present
expect(mergeResult.merged.data.name).toBe("Updated by Device A");
- expect(mergeResult.merged.data.newCardsPerDay).toBe(30);
+ expect(mergeResult.merged.data.description).toBe("Updated by Device B");
expect(mergeResult.hasChanges).toBe(true);
});
@@ -120,7 +119,7 @@ describe("Concurrent edit scenarios", () => {
const deviceBDoc = Automerge.clone(serverDoc);
const deviceBEdited = updateDocument(deviceBDoc, (d) => {
- d.data.newCardsPerDay = 50;
+ d.data.userId = "user-updated";
d.meta.lastModified = Date.now();
});
@@ -129,7 +128,7 @@ describe("Concurrent edit scenarios", () => {
expect(mergedDeck.name).toBe("New Name");
expect(mergedDeck.description).toBe("Added by Device A");
- expect(mergedDeck.newCardsPerDay).toBe(50);
+ expect(mergedDeck.userId).toBe("user-updated");
});
});
@@ -342,7 +341,7 @@ describe("Concurrent edit scenarios", () => {
// Device B makes a different edit
const deviceBEdited = updateDocument(deviceBDoc, (d) => {
- d.data.newCardsPerDay = 100;
+ d.data.description = "Description from B";
d.meta.lastModified = Date.now();
});
@@ -354,7 +353,7 @@ describe("Concurrent edit scenarios", () => {
// Both changes should be present
expect(serverWithB.data.name).toBe("Edit 1 from A");
- expect(serverWithB.data.newCardsPerDay).toBe(100);
+ expect(serverWithB.data.description).toBe("Description from B");
});
it("should handle three-way merge correctly", () => {
@@ -377,7 +376,7 @@ describe("Concurrent edit scenarios", () => {
});
const deviceCEdited = updateDocument(deviceCDoc, (d) => {
- d.data.newCardsPerDay = 75;
+ d.data.userId = "user-from-C";
});
// Sequential merge: A + B
@@ -389,7 +388,7 @@ describe("Concurrent edit scenarios", () => {
// All three changes should be present
expect(mergeABC.merged.data.name).toBe("Name from A");
expect(mergeABC.merged.data.description).toBe("Description from B");
- expect(mergeABC.merged.data.newCardsPerDay).toBe(75);
+ expect(mergeABC.merged.data.userId).toBe("user-from-C");
});
});
@@ -575,7 +574,7 @@ describe("Concurrent edit scenarios", () => {
// Edit 3
const beforeEdit3 = Automerge.clone(deviceADoc);
deviceADoc = updateDocument(deviceADoc, (d) => {
- d.data.newCardsPerDay = 42;
+ d.data.userId = "user-offline";
});
offlineEdits.push(getChanges(beforeEdit3, deviceADoc));
@@ -588,7 +587,7 @@ describe("Concurrent edit scenarios", () => {
// Verify all offline edits are applied
expect(currentServer.data.name).toBe("Offline edit 1");
expect(currentServer.data.description).toBe("Offline edit 2");
- expect(currentServer.data.newCardsPerDay).toBe(42);
+ expect(currentServer.data.userId).toBe("user-offline");
});
it("should handle two devices syncing after extended offline periods", () => {
@@ -612,22 +611,22 @@ describe("Concurrent edit scenarios", () => {
// Device B: Different offline edits
let deviceBDoc = Automerge.clone(serverDoc);
deviceBDoc = updateDocument(deviceBDoc, (d) => {
- d.data.newCardsPerDay = 50;
+ d.data.userId = "B: First user";
});
deviceBDoc = updateDocument(deviceBDoc, (d) => {
- d.data.newCardsPerDay = 60;
+ d.data.userId = "B: Second user";
});
deviceBDoc = updateDocument(deviceBDoc, (d) => {
- d.data.newCardsPerDay = 100;
+ d.data.userId = "B: Final user";
});
// Both devices come online and sync
const mergeResult = mergeDocuments(deviceADoc, deviceBDoc);
- // Device A's content edits and Device B's card setting
+ // Device A's content edits and Device B's user edits
expect(mergeResult.merged.data.name).toBe("A: Final name");
expect(mergeResult.merged.data.description).toBe("A: Added description");
- expect(mergeResult.merged.data.newCardsPerDay).toBe(100);
+ expect(mergeResult.merged.data.userId).toBe("B: Final user");
});
});
});
diff --git a/src/client/sync/crdt/document-manager.test.ts b/src/client/sync/crdt/document-manager.test.ts
index 7c0fc00..b578c77 100644
--- a/src/client/sync/crdt/document-manager.test.ts
+++ b/src/client/sync/crdt/document-manager.test.ts
@@ -51,7 +51,6 @@ describe("createDocument", () => {
userId: "user-1",
name: "My Deck",
description: null,
- newCardsPerDay: 20,
createdAt: Date.now(),
deletedAt: null,
},
@@ -154,7 +153,6 @@ describe("saveDocument and loadDocument", () => {
userId: "user-1",
name: "Test Deck",
description: "A test deck",
- newCardsPerDay: 15,
createdAt: 1234567890,
deletedAt: null,
},
@@ -168,7 +166,6 @@ describe("saveDocument and loadDocument", () => {
const loaded = loadDocument<CrdtDeckDocument>(binary);
expect(loaded.meta.entityId).toBe("deck-123");
expect(loaded.data.name).toBe("Test Deck");
- expect(loaded.data.newCardsPerDay).toBe(15);
});
});
@@ -195,7 +192,6 @@ describe("createEmptyDocument", () => {
expect(doc.meta.entityId).toBe("");
expect(doc.meta.deleted).toBe(false);
expect(doc.data.name).toBe("");
- expect(doc.data.newCardsPerDay).toBe(20);
});
it("should create empty card document", () => {
@@ -226,7 +222,6 @@ describe("deckToCrdtDocument and crdtDocumentToDeck", () => {
userId: "user-1",
name: "My Deck",
description: "A deck for testing",
- newCardsPerDay: 25,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -240,7 +235,6 @@ describe("deckToCrdtDocument and crdtDocumentToDeck", () => {
expect(crdtDoc.meta.deleted).toBe(false);
expect(crdtDoc.data.name).toBe("My Deck");
expect(crdtDoc.data.description).toBe("A deck for testing");
- expect(crdtDoc.data.newCardsPerDay).toBe(25);
expect(crdtDoc.data.createdAt).toBe(now.getTime());
});
@@ -252,7 +246,6 @@ describe("deckToCrdtDocument and crdtDocumentToDeck", () => {
userId: "user-1",
name: "Deleted Deck",
description: null,
- newCardsPerDay: 20,
createdAt: now,
updatedAt: deletedAt,
deletedAt: deletedAt,
@@ -278,7 +271,6 @@ describe("deckToCrdtDocument and crdtDocumentToDeck", () => {
userId: "user-2",
name: "Converted Deck",
description: "Converted from CRDT",
- newCardsPerDay: 30,
createdAt: now - 10000,
deletedAt: null,
},
@@ -289,7 +281,6 @@ describe("deckToCrdtDocument and crdtDocumentToDeck", () => {
expect(localDeck.id).toBe("deck-3");
expect(localDeck.userId).toBe("user-2");
expect(localDeck.name).toBe("Converted Deck");
- expect(localDeck.newCardsPerDay).toBe(30);
expect(localDeck.deletedAt).toBeNull();
expect(localDeck.syncVersion).toBe(0); // Set by sync layer
});
@@ -465,7 +456,6 @@ describe("createDocumentFromEntity", () => {
userId: "user-1",
name: "Test",
description: null,
- newCardsPerDay: 20,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -546,7 +536,6 @@ describe("getLastModified", () => {
userId: "user-1",
name: "Test",
description: null,
- newCardsPerDay: 20,
createdAt: timestamp,
deletedAt: null,
},
@@ -569,7 +558,6 @@ describe("isDeleted", () => {
userId: "user-1",
name: "Test",
description: null,
- newCardsPerDay: 20,
createdAt: Date.now(),
deletedAt: null,
},
@@ -590,7 +578,6 @@ describe("isDeleted", () => {
userId: "user-1",
name: "Test",
description: null,
- newCardsPerDay: 20,
createdAt: Date.now(),
deletedAt: Date.now(),
},
diff --git a/src/client/sync/crdt/document-manager.ts b/src/client/sync/crdt/document-manager.ts
index 5c32b67..b753d88 100644
--- a/src/client/sync/crdt/document-manager.ts
+++ b/src/client/sync/crdt/document-manager.ts
@@ -187,7 +187,6 @@ function getEmptyDocumentData(
userId: "",
name: "",
description: null,
- newCardsPerDay: 20,
createdAt: 0,
deletedAt: null,
},
@@ -301,7 +300,6 @@ export function deckToCrdtDocument(deck: LocalDeck): CrdtDeckDocument {
userId: deck.userId,
name: deck.name,
description: deck.description,
- newCardsPerDay: deck.newCardsPerDay,
createdAt: deck.createdAt.getTime(),
deletedAt: deck.deletedAt?.getTime() ?? null,
},
@@ -319,7 +317,6 @@ export function crdtDocumentToDeck(
userId: doc.data.userId,
name: doc.data.name,
description: doc.data.description,
- newCardsPerDay: doc.data.newCardsPerDay,
createdAt: new Date(doc.data.createdAt),
updatedAt: new Date(doc.meta.lastModified),
deletedAt: doc.data.deletedAt ? new Date(doc.data.deletedAt) : null,
diff --git a/src/client/sync/crdt/migration.test.ts b/src/client/sync/crdt/migration.test.ts
index 22f311d..ba90be2 100644
--- a/src/client/sync/crdt/migration.test.ts
+++ b/src/client/sync/crdt/migration.test.ts
@@ -109,7 +109,6 @@ describe("migration", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
diff --git a/src/client/sync/crdt/repositories.test.ts b/src/client/sync/crdt/repositories.test.ts
index f237536..f7b75b3 100644
--- a/src/client/sync/crdt/repositories.test.ts
+++ b/src/client/sync/crdt/repositories.test.ts
@@ -35,7 +35,6 @@ describe("crdtDeckRepository", () => {
userId: "user-1",
name: "Test Deck",
description: "A test deck",
- newCardsPerDay: 20,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -77,14 +76,14 @@ describe("crdtDeckRepository", () => {
d.data.name = "Updated Name";
});
const updated2 = Automerge.change(doc2, (d) => {
- d.data.newCardsPerDay = 30;
+ d.data.description = "Updated Description";
});
const result = crdtDeckRepository.merge(updated1, updated2);
expect(result.hasChanges).toBe(true);
expect(result.merged.data.name).toBe("Updated Name");
- expect(result.merged.data.newCardsPerDay).toBe(30);
+ expect(result.merged.data.description).toBe("Updated Description");
});
it("should convert CRDT document to local entity", () => {
@@ -379,7 +378,6 @@ describe("entitiesToCrdtDocuments", () => {
userId: "user-1",
name: "Deck 1",
description: null,
- newCardsPerDay: 20,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -391,7 +389,6 @@ describe("entitiesToCrdtDocuments", () => {
userId: "user-1",
name: "Deck 2",
description: "Second deck",
- newCardsPerDay: 15,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -418,7 +415,6 @@ describe("mergeAndConvert", () => {
userId: "user-1",
name: "Remote Deck",
description: null,
- newCardsPerDay: 20,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -440,7 +436,6 @@ describe("mergeAndConvert", () => {
userId: "user-1",
name: "Original",
description: null,
- newCardsPerDay: 20,
createdAt: now,
updatedAt: now,
deletedAt: null,
@@ -452,7 +447,7 @@ describe("mergeAndConvert", () => {
// Create remote with different changes
const remoteDoc = Automerge.change(Automerge.clone(localDoc), (d) => {
- d.data.newCardsPerDay = 30;
+ d.data.description = "Remote Description";
});
const remoteBinary = saveDocument(remoteDoc);
@@ -471,7 +466,7 @@ describe("mergeAndConvert", () => {
expect(result.hasChanges).toBe(true);
// Both changes should be merged
expect(result.entity.name).toBe("Updated Local");
- expect(result.entity.newCardsPerDay).toBe(30);
+ expect(result.entity.description).toBe("Remote Description");
});
it("should detect no changes when documents are identical", () => {
@@ -481,7 +476,6 @@ describe("mergeAndConvert", () => {
userId: "user-1",
name: "Same",
description: null,
- newCardsPerDay: 20,
createdAt: now,
updatedAt: now,
deletedAt: null,
diff --git a/src/client/sync/crdt/types.test.ts b/src/client/sync/crdt/types.test.ts
index 15fd79b..07ae0f2 100644
--- a/src/client/sync/crdt/types.test.ts
+++ b/src/client/sync/crdt/types.test.ts
@@ -149,7 +149,6 @@ describe("CRDT Document type structures", () => {
userId: "user-1",
name: "My Deck",
description: "A test deck",
- newCardsPerDay: 20,
createdAt: now,
deletedAt: null,
},
@@ -157,7 +156,6 @@ describe("CRDT Document type structures", () => {
expect(doc.meta.entityId).toBe("deck-1");
expect(doc.data.name).toBe("My Deck");
- expect(doc.data.newCardsPerDay).toBe(20);
});
it("should allow creating a valid CrdtNoteTypeDocument", () => {
@@ -305,7 +303,6 @@ describe("CRDT Document type structures", () => {
userId: "user-1",
name: "Deleted Deck",
description: null,
- newCardsPerDay: 20,
createdAt: now - 86400000,
deletedAt: now,
},
diff --git a/src/client/sync/crdt/types.ts b/src/client/sync/crdt/types.ts
index 1dfae1a..e2f5d4c 100644
--- a/src/client/sync/crdt/types.ts
+++ b/src/client/sync/crdt/types.ts
@@ -36,7 +36,6 @@ export interface CrdtDeckDocument {
userId: string;
name: string;
description: string | null;
- newCardsPerDay: number;
createdAt: number; // Unix timestamp in ms
deletedAt: number | null;
};
diff --git a/src/client/sync/manager.test.ts b/src/client/sync/manager.test.ts
index 8af6e6f..a9be10d 100644
--- a/src/client/sync/manager.test.ts
+++ b/src/client/sync/manager.test.ts
@@ -83,7 +83,6 @@ describe("SyncManager", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
}
@@ -412,7 +411,6 @@ describe("SyncManager", () => {
userId: "user-1",
name: "Server Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
diff --git a/src/client/sync/pull.test.ts b/src/client/sync/pull.test.ts
index 8bbf7cf..0f1b689 100644
--- a/src/client/sync/pull.test.ts
+++ b/src/client/sync/pull.test.ts
@@ -48,7 +48,6 @@ describe("pullResultToLocalData", () => {
userId: "user-1",
name: "Test Deck",
description: "A description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -69,7 +68,6 @@ describe("pullResultToLocalData", () => {
userId: "user-1",
name: "Test Deck",
description: "A description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -85,7 +83,6 @@ describe("pullResultToLocalData", () => {
userId: "user-1",
name: "Deleted Deck",
description: null,
- newCardsPerDay: 10,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-03T12:00:00Z"),
deletedAt: new Date("2024-01-03T12:00:00Z"),
@@ -538,7 +535,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Server Deck",
description: "From server",
- newCardsPerDay: 15,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T10:00:00Z"),
deletedAt: null,
@@ -571,7 +567,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -673,7 +668,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Old Name",
description: null,
- newCardsPerDay: 10,
});
const pullFromServer = vi.fn().mockResolvedValue({
@@ -683,7 +677,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Updated Name",
description: "Updated description",
- newCardsPerDay: 25,
createdAt: existingDeck.createdAt,
updatedAt: new Date(),
deletedAt: null,
@@ -705,7 +698,6 @@ describe("PullService", () => {
const updatedDeck = await localDeckRepository.findById(existingDeck.id);
expect(updatedDeck?.name).toBe("Updated Name");
expect(updatedDeck?.description).toBe("Updated description");
- expect(updatedDeck?.newCardsPerDay).toBe(25);
expect(updatedDeck?._synced).toBe(true);
});
@@ -717,7 +709,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -874,7 +865,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -929,7 +919,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -999,7 +988,6 @@ describe("PullService", () => {
userId: "user-1",
name: "Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -1179,7 +1167,6 @@ describe("applyCrdtChanges", () => {
userId: "user-1",
name: "Test Deck",
description: "A test description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1212,7 +1199,6 @@ describe("applyCrdtChanges", () => {
userId: "user-1",
name: "Local Deck",
description: "Local description",
- newCardsPerDay: 10,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-01T12:00:00Z"),
deletedAt: null,
@@ -1235,7 +1221,6 @@ describe("applyCrdtChanges", () => {
userId: "user-1",
name: "Remote Deck",
description: "Remote description",
- newCardsPerDay: 25,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"), // Later timestamp
deletedAt: null,
@@ -1266,7 +1251,6 @@ describe("applyCrdtChanges", () => {
userId: "user-1",
name: "Deck 1",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1278,7 +1262,6 @@ describe("applyCrdtChanges", () => {
userId: "user-1",
name: "Deck 2",
description: "Second deck",
- newCardsPerDay: 15,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1317,7 +1300,6 @@ describe("applyCrdtChanges", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1372,7 +1354,6 @@ describe("applyCrdtChanges", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1470,7 +1451,6 @@ describe("PullService with CRDT changes", () => {
userId: "user-1",
name: "CRDT Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1521,7 +1501,6 @@ describe("PullService with CRDT changes", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -1598,7 +1577,6 @@ describe("PullService with CRDT changes", () => {
userId: "user-1",
name: "Regular Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
diff --git a/src/client/sync/pull.ts b/src/client/sync/pull.ts
index 4771757..ce4d992 100644
--- a/src/client/sync/pull.ts
+++ b/src/client/sync/pull.ts
@@ -30,7 +30,6 @@ export interface ServerDeck {
userId: string;
name: string;
description: string | null;
- newCardsPerDay: number;
createdAt: Date;
updatedAt: Date;
deletedAt: Date | null;
@@ -168,7 +167,6 @@ function serverDeckToLocal(deck: ServerDeck): LocalDeck {
userId: deck.userId,
name: deck.name,
description: deck.description,
- newCardsPerDay: deck.newCardsPerDay,
createdAt: new Date(deck.createdAt),
updatedAt: new Date(deck.updatedAt),
deletedAt: deck.deletedAt ? new Date(deck.deletedAt) : null,
diff --git a/src/client/sync/push.test.ts b/src/client/sync/push.test.ts
index 19b39da..8605ede 100644
--- a/src/client/sync/push.test.ts
+++ b/src/client/sync/push.test.ts
@@ -81,7 +81,6 @@ describe("pendingChangesToPushData", () => {
userId: "user-1",
name: "Test Deck",
description: "A description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -102,7 +101,6 @@ describe("pendingChangesToPushData", () => {
id: "deck-1",
name: "Test Deck",
description: "A description",
- newCardsPerDay: 20,
createdAt: "2024-01-01T10:00:00.000Z",
updatedAt: "2024-01-02T15:30:00.000Z",
deletedAt: null,
@@ -116,7 +114,6 @@ describe("pendingChangesToPushData", () => {
userId: "user-1",
name: "Deleted Deck",
description: null,
- newCardsPerDay: 10,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-03T12:00:00Z"),
deletedAt: new Date("2024-01-03T12:00:00Z"),
@@ -530,7 +527,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const pushToServer = vi.fn().mockResolvedValue({
@@ -569,7 +565,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -616,7 +611,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -674,7 +668,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const pushToServer = vi.fn().mockResolvedValue({
@@ -702,7 +695,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const pushToServer = vi.fn().mockResolvedValue({
@@ -728,7 +720,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const pushToServer = vi
@@ -748,7 +739,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const card = await localCardRepository.create({
@@ -894,7 +884,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -942,7 +931,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -1006,7 +994,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const noteType = await localNoteTypeRepository.create({
@@ -1093,7 +1080,6 @@ describe("PushService", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const pushService = new PushService({
@@ -1116,7 +1102,6 @@ describe("generateCrdtChanges", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1354,7 +1339,6 @@ describe("generateCrdtChanges", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
@@ -1496,7 +1480,6 @@ describe("pendingChangesToPushData with crdtChanges", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T10:00:00Z"),
updatedAt: new Date("2024-01-02T15:30:00Z"),
deletedAt: null,
diff --git a/src/client/sync/push.ts b/src/client/sync/push.ts
index 61c7f30..e5c5fd4 100644
--- a/src/client/sync/push.ts
+++ b/src/client/sync/push.ts
@@ -39,7 +39,6 @@ export interface SyncDeckData {
id: string;
name: string;
description: string | null;
- newCardsPerDay: number;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
@@ -154,7 +153,6 @@ function deckToSyncData(deck: LocalDeck): SyncDeckData {
id: deck.id,
name: deck.name,
description: deck.description,
- newCardsPerDay: deck.newCardsPerDay,
createdAt: deck.createdAt.toISOString(),
updatedAt: deck.updatedAt.toISOString(),
deletedAt: deck.deletedAt?.toISOString() ?? null,
diff --git a/src/client/sync/queue.test.ts b/src/client/sync/queue.test.ts
index e815282..436046b 100644
--- a/src/client/sync/queue.test.ts
+++ b/src/client/sync/queue.test.ts
@@ -68,7 +68,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const changes = await syncQueue.getPendingChanges();
@@ -81,7 +80,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localCardRepository.create({
deckId: deck.id,
@@ -101,7 +99,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const card = await localCardRepository.create({
deckId: deck.id,
@@ -130,7 +127,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -145,7 +141,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localCardRepository.create({
deckId: deck.id,
@@ -179,7 +174,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const hasPending = await syncQueue.hasPendingChanges();
@@ -304,7 +298,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await syncQueue.markSynced({
@@ -327,7 +320,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const card = await localCardRepository.create({
deckId: deck.id,
@@ -357,7 +349,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const card = await localCardRepository.create({
deckId: deck.id,
@@ -417,7 +408,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Server Deck",
description: null,
- newCardsPerDay: 15,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
@@ -445,7 +435,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
await localDeckRepository.markSynced(deck.id, 1);
@@ -492,7 +481,6 @@ describe("SyncQueue", () => {
userId: "user-1",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
});
const card = await localCardRepository.create({
deckId: deck.id,
diff --git a/src/server/db/schema.ts b/src/server/db/schema.ts
index 50caf85..55be210 100644
--- a/src/server/db/schema.ts
+++ b/src/server/db/schema.ts
@@ -101,7 +101,6 @@ export const decks = pgTable("decks", {
.references(() => users.id),
name: varchar("name", { length: 255 }).notNull(),
description: text("description"),
- newCardsPerDay: integer("new_cards_per_day").notNull().default(20),
createdAt: timestamp("created_at", { withTimezone: true })
.notNull()
.defaultNow(),
diff --git a/src/server/repositories/card.test.ts b/src/server/repositories/card.test.ts
index 21e5485..b492fd7 100644
--- a/src/server/repositories/card.test.ts
+++ b/src/server/repositories/card.test.ts
@@ -112,12 +112,8 @@ function createMockCardRepo(): CardRepository {
softDeleteByNoteId: vi.fn(),
findDueCards: vi.fn(),
countDueCards: vi.fn(),
- countDueNewCards: vi.fn(),
- countDueReviewCards: vi.fn(),
findDueCardsWithNoteData: vi.fn(),
findDueCardsForStudy: vi.fn(),
- findDueNewCardsForStudy: vi.fn(),
- findDueReviewCardsForStudy: vi.fn(),
updateFSRSFields: vi.fn(),
};
}
diff --git a/src/server/repositories/card.ts b/src/server/repositories/card.ts
index d382f4d..0f1ef79 100644
--- a/src/server/repositories/card.ts
+++ b/src/server/repositories/card.ts
@@ -1,4 +1,4 @@
-import { and, eq, isNull, lt, ne, sql } from "drizzle-orm";
+import { and, eq, isNull, lt, sql } from "drizzle-orm";
import { getEndOfStudyDayBoundary } from "../../shared/date.js";
import { db } from "../db/index.js";
import {
@@ -185,11 +185,7 @@ export const cardRepository: CardRepository = {
return result.length > 0;
},
- async findDueCards(
- deckId: string,
- now: Date,
- limit: number,
- ): Promise<Card[]> {
+ async findDueCards(deckId: string, now: Date): Promise<Card[]> {
const boundary = getEndOfStudyDayBoundary(now);
const result = await db
.select()
@@ -201,8 +197,7 @@ export const cardRepository: CardRepository = {
lt(cards.due, boundary),
),
)
- .orderBy(cards.due)
- .limit(limit);
+ .orderBy(cards.due);
return result;
},
@@ -221,44 +216,11 @@ export const cardRepository: CardRepository = {
return result[0]?.count ?? 0;
},
- async countDueNewCards(deckId: string, now: Date): Promise<number> {
- const boundary = getEndOfStudyDayBoundary(now);
- const result = await db
- .select({ count: sql<number>`count(*)::int` })
- .from(cards)
- .where(
- and(
- eq(cards.deckId, deckId),
- isNull(cards.deletedAt),
- lt(cards.due, boundary),
- eq(cards.state, CardState.New),
- ),
- );
- return result[0]?.count ?? 0;
- },
-
- async countDueReviewCards(deckId: string, now: Date): Promise<number> {
- const boundary = getEndOfStudyDayBoundary(now);
- const result = await db
- .select({ count: sql<number>`count(*)::int` })
- .from(cards)
- .where(
- and(
- eq(cards.deckId, deckId),
- isNull(cards.deletedAt),
- lt(cards.due, boundary),
- ne(cards.state, CardState.New),
- ),
- );
- return result[0]?.count ?? 0;
- },
-
async findDueCardsWithNoteData(
deckId: string,
now: Date,
- limit: number,
): Promise<CardWithNoteData[]> {
- const dueCards = await this.findDueCards(deckId, now, limit);
+ const dueCards = await this.findDueCards(deckId, now);
const cardsWithNoteData: CardWithNoteData[] = [];
@@ -292,56 +254,11 @@ export const cardRepository: CardRepository = {
async findDueCardsForStudy(
deckId: string,
now: Date,
- limit: number,
): Promise<CardForStudy[]> {
- const dueCards = await this.findDueCards(deckId, now, limit);
+ const dueCards = await this.findDueCards(deckId, now);
return enrichCardsForStudy(dueCards);
},
- async findDueNewCardsForStudy(
- deckId: string,
- now: Date,
- limit: number,
- ): Promise<CardForStudy[]> {
- const boundary = getEndOfStudyDayBoundary(now);
- const result = await db
- .select()
- .from(cards)
- .where(
- and(
- eq(cards.deckId, deckId),
- isNull(cards.deletedAt),
- lt(cards.due, boundary),
- eq(cards.state, CardState.New),
- ),
- )
- .orderBy(cards.due)
- .limit(limit);
- return enrichCardsForStudy(result);
- },
-
- async findDueReviewCardsForStudy(
- deckId: string,
- now: Date,
- limit: number,
- ): Promise<CardForStudy[]> {
- const boundary = getEndOfStudyDayBoundary(now);
- const result = await db
- .select()
- .from(cards)
- .where(
- and(
- eq(cards.deckId, deckId),
- isNull(cards.deletedAt),
- lt(cards.due, boundary),
- ne(cards.state, CardState.New),
- ),
- )
- .orderBy(cards.due)
- .limit(limit);
- return enrichCardsForStudy(result);
- },
-
async updateFSRSFields(
id: string,
deckId: string,
diff --git a/src/server/repositories/deck.test.ts b/src/server/repositories/deck.test.ts
index 945f844..ab6e2fc 100644
--- a/src/server/repositories/deck.test.ts
+++ b/src/server/repositories/deck.test.ts
@@ -7,7 +7,6 @@ function createMockDeck(overrides: Partial<Deck> = {}): Deck {
userId: "user-uuid-123",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
deletedAt: null,
@@ -35,7 +34,6 @@ describe("DeckRepository mock factory", () => {
expect(deck.userId).toBe("user-uuid-123");
expect(deck.name).toBe("Test Deck");
expect(deck.description).toBeNull();
- expect(deck.newCardsPerDay).toBe(20);
expect(deck.deletedAt).toBeNull();
expect(deck.syncVersion).toBe(0);
});
@@ -45,13 +43,11 @@ describe("DeckRepository mock factory", () => {
id: "custom-id",
name: "Custom Deck",
description: "A description",
- newCardsPerDay: 50,
});
expect(deck.id).toBe("custom-id");
expect(deck.name).toBe("Custom Deck");
expect(deck.description).toBe("A description");
- expect(deck.newCardsPerDay).toBe(50);
});
});
@@ -130,7 +126,6 @@ describe("Deck interface contracts", () => {
expect(deck).toHaveProperty("name");
expect(deck).toHaveProperty("description");
- expect(deck).toHaveProperty("newCardsPerDay");
});
});
diff --git a/src/server/repositories/deck.ts b/src/server/repositories/deck.ts
index 647c5cb..97af5f7 100644
--- a/src/server/repositories/deck.ts
+++ b/src/server/repositories/deck.ts
@@ -31,7 +31,6 @@ export const deckRepository: DeckRepository = {
userId: string;
name: string;
description?: string | null;
- newCardsPerDay?: number;
}): Promise<Deck> {
const [deck] = await db
.insert(decks)
@@ -39,7 +38,6 @@ export const deckRepository: DeckRepository = {
userId: data.userId,
name: data.name,
description: data.description ?? null,
- newCardsPerDay: data.newCardsPerDay ?? 20,
})
.returning();
if (!deck) {
@@ -54,7 +52,6 @@ export const deckRepository: DeckRepository = {
data: {
name?: string;
description?: string | null;
- newCardsPerDay?: number;
},
): Promise<Deck | undefined> {
const result = await db
diff --git a/src/server/repositories/review-log.ts b/src/server/repositories/review-log.ts
index 97488d2..c8950d6 100644
--- a/src/server/repositories/review-log.ts
+++ b/src/server/repositories/review-log.ts
@@ -1,7 +1,5 @@
-import { and, eq, gte, sql } from "drizzle-orm";
-import { getStartOfStudyDayBoundary } from "../../shared/date.js";
import { db } from "../db/index.js";
-import { CardState, cards, reviewLogs } from "../db/schema.js";
+import { reviewLogs } from "../db/schema.js";
import type { ReviewLog, ReviewLogRepository } from "./types.js";
export const reviewLogRepository: ReviewLogRepository = {
@@ -31,21 +29,4 @@ export const reviewLogRepository: ReviewLogRepository = {
}
return reviewLog;
},
-
- async countTodayNewCardReviews(deckId: string, now: Date): Promise<number> {
- const startOfDay = getStartOfStudyDayBoundary(now);
-
- const result = await db
- .select({ count: sql<number>`count(distinct ${reviewLogs.cardId})::int` })
- .from(reviewLogs)
- .innerJoin(cards, eq(reviewLogs.cardId, cards.id))
- .where(
- and(
- eq(cards.deckId, deckId),
- eq(reviewLogs.state, CardState.New),
- gte(reviewLogs.reviewedAt, startOfDay),
- ),
- );
- return result[0]?.count ?? 0;
- },
};
diff --git a/src/server/repositories/sync.test.ts b/src/server/repositories/sync.test.ts
index ce59cb5..8425839 100644
--- a/src/server/repositories/sync.test.ts
+++ b/src/server/repositories/sync.test.ts
@@ -16,7 +16,6 @@ function createMockDeck(overrides: Partial<Deck> = {}): Deck {
userId: "user-uuid-123",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
deletedAt: null,
diff --git a/src/server/repositories/sync.ts b/src/server/repositories/sync.ts
index ca4c208..e197d37 100644
--- a/src/server/repositories/sync.ts
+++ b/src/server/repositories/sync.ts
@@ -53,7 +53,6 @@ export interface SyncDeckData {
id: string;
name: string;
description: string | null;
- newCardsPerDay: number;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
@@ -224,7 +223,6 @@ export const syncRepository: SyncRepository = {
userId,
name: deckData.name,
description: deckData.description,
- newCardsPerDay: deckData.newCardsPerDay,
createdAt: new Date(deckData.createdAt),
updatedAt: clientUpdatedAt,
deletedAt: deckData.deletedAt ? new Date(deckData.deletedAt) : null,
@@ -248,7 +246,6 @@ export const syncRepository: SyncRepository = {
.set({
name: deckData.name,
description: deckData.description,
- newCardsPerDay: deckData.newCardsPerDay,
updatedAt: clientUpdatedAt,
deletedAt: deckData.deletedAt
? new Date(deckData.deletedAt)
diff --git a/src/server/repositories/types.ts b/src/server/repositories/types.ts
index 4042daf..71cb811 100644
--- a/src/server/repositories/types.ts
+++ b/src/server/repositories/types.ts
@@ -50,7 +50,6 @@ export interface Deck {
userId: string;
name: string;
description: string | null;
- newCardsPerDay: number;
createdAt: Date;
updatedAt: Date;
deletedAt: Date | null;
@@ -64,7 +63,6 @@ export interface DeckRepository {
userId: string;
name: string;
description?: string | null;
- newCardsPerDay?: number;
}): Promise<Deck>;
update(
id: string,
@@ -72,7 +70,6 @@ export interface DeckRepository {
data: {
name?: string;
description?: string | null;
- newCardsPerDay?: number;
},
): Promise<Deck | undefined>;
softDelete(id: string, userId: string): Promise<boolean>;
@@ -146,30 +143,13 @@ export interface CardRepository {
): Promise<Card | undefined>;
softDelete(id: string, deckId: string): Promise<boolean>;
softDeleteByNoteId(noteId: string): Promise<boolean>;
- findDueCards(deckId: string, now: Date, limit: number): Promise<Card[]>;
+ findDueCards(deckId: string, now: Date): Promise<Card[]>;
countDueCards(deckId: string, now: Date): Promise<number>;
findDueCardsWithNoteData(
deckId: string,
now: Date,
- limit: number,
): Promise<CardWithNoteData[]>;
- findDueCardsForStudy(
- deckId: string,
- now: Date,
- limit: number,
- ): Promise<CardForStudy[]>;
- findDueNewCardsForStudy(
- deckId: string,
- now: Date,
- limit: number,
- ): Promise<CardForStudy[]>;
- findDueReviewCardsForStudy(
- deckId: string,
- now: Date,
- limit: number,
- ): Promise<CardForStudy[]>;
- countDueNewCards(deckId: string, now: Date): Promise<number>;
- countDueReviewCards(deckId: string, now: Date): Promise<number>;
+ findDueCardsForStudy(deckId: string, now: Date): Promise<CardForStudy[]>;
updateFSRSFields(
id: string,
deckId: string,
@@ -210,7 +190,6 @@ export interface ReviewLogRepository {
elapsedDays: number;
durationMs?: number | null;
}): Promise<ReviewLog>;
- countTodayNewCardReviews(deckId: string, now: Date): Promise<number>;
}
export interface NoteType {
diff --git a/src/server/routes/cards.test.ts b/src/server/routes/cards.test.ts
index 4595e28..a063c95 100644
--- a/src/server/routes/cards.test.ts
+++ b/src/server/routes/cards.test.ts
@@ -26,12 +26,8 @@ function createMockCardRepo(): CardRepository {
softDeleteByNoteId: vi.fn(),
findDueCards: vi.fn(),
countDueCards: vi.fn(),
- countDueNewCards: vi.fn(),
- countDueReviewCards: vi.fn(),
findDueCardsWithNoteData: vi.fn(),
findDueCardsForStudy: vi.fn(),
- findDueNewCardsForStudy: vi.fn(),
- findDueReviewCardsForStudy: vi.fn(),
updateFSRSFields: vi.fn(),
};
}
@@ -66,7 +62,6 @@ function createMockDeck(overrides: Partial<Deck> = {}): Deck {
userId: "user-uuid-123",
name: "Test Deck",
description: "Test description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
deletedAt: null,
diff --git a/src/server/routes/decks.test.ts b/src/server/routes/decks.test.ts
index d0854c1..f686024 100644
--- a/src/server/routes/decks.test.ts
+++ b/src/server/routes/decks.test.ts
@@ -6,7 +6,6 @@ import type {
CardRepository,
Deck,
DeckRepository,
- ReviewLogRepository,
} from "../repositories/index.js";
import { createDecksRouter } from "./decks.js";
@@ -32,23 +31,12 @@ function createMockCardRepo(): CardRepository {
softDeleteByNoteId: vi.fn(),
findDueCards: vi.fn(),
countDueCards: vi.fn().mockResolvedValue(0),
- countDueNewCards: vi.fn().mockResolvedValue(0),
- countDueReviewCards: vi.fn().mockResolvedValue(0),
findDueCardsWithNoteData: vi.fn(),
findDueCardsForStudy: vi.fn(),
- findDueNewCardsForStudy: vi.fn(),
- findDueReviewCardsForStudy: vi.fn(),
updateFSRSFields: vi.fn(),
};
}
-function createMockReviewLogRepo(): ReviewLogRepository {
- return {
- create: vi.fn(),
- countTodayNewCardReviews: vi.fn().mockResolvedValue(0),
- };
-}
-
const JWT_SECRET = process.env.JWT_SECRET || "test-secret";
async function createTestToken(userId: string): Promise<string> {
@@ -69,7 +57,6 @@ function createMockDeck(overrides: Partial<Deck> = {}): Deck {
userId: "user-uuid-123",
name: "Test Deck",
description: "Test description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
deletedAt: null,
@@ -92,18 +79,15 @@ describe("GET /api/decks", () => {
let app: Hono;
let mockDeckRepo: ReturnType<typeof createMockDeckRepo>;
let mockCardRepo: ReturnType<typeof createMockCardRepo>;
- let mockReviewLogRepo: ReturnType<typeof createMockReviewLogRepo>;
let authToken: string;
beforeEach(async () => {
vi.clearAllMocks();
mockDeckRepo = createMockDeckRepo();
mockCardRepo = createMockCardRepo();
- mockReviewLogRepo = createMockReviewLogRepo();
const decksRouter = createDecksRouter({
deckRepo: mockDeckRepo,
cardRepo: mockCardRepo,
- reviewLogRepo: mockReviewLogRepo,
});
app = new Hono();
app.onError(errorHandler);
@@ -155,18 +139,15 @@ describe("POST /api/decks", () => {
let app: Hono;
let mockDeckRepo: ReturnType<typeof createMockDeckRepo>;
let mockCardRepo: ReturnType<typeof createMockCardRepo>;
- let mockReviewLogRepo: ReturnType<typeof createMockReviewLogRepo>;
let authToken: string;
beforeEach(async () => {
vi.clearAllMocks();
mockDeckRepo = createMockDeckRepo();
mockCardRepo = createMockCardRepo();
- mockReviewLogRepo = createMockReviewLogRepo();
const decksRouter = createDecksRouter({
deckRepo: mockDeckRepo,
cardRepo: mockCardRepo,
- reviewLogRepo: mockReviewLogRepo,
});
app = new Hono();
app.onError(errorHandler);
@@ -194,7 +175,6 @@ describe("POST /api/decks", () => {
userId: "user-uuid-123",
name: "New Deck",
description: undefined,
- newCardsPerDay: 20,
});
});
@@ -202,7 +182,6 @@ describe("POST /api/decks", () => {
const newDeck = createMockDeck({
name: "Full Deck",
description: "Full description",
- newCardsPerDay: 30,
});
vi.mocked(mockDeckRepo.create).mockResolvedValue(newDeck);
@@ -215,7 +194,6 @@ describe("POST /api/decks", () => {
body: JSON.stringify({
name: "Full Deck",
description: "Full description",
- newCardsPerDay: 30,
}),
});
@@ -226,7 +204,6 @@ describe("POST /api/decks", () => {
userId: "user-uuid-123",
name: "Full Deck",
description: "Full description",
- newCardsPerDay: 30,
});
});
@@ -271,18 +248,15 @@ describe("GET /api/decks/:id", () => {
let app: Hono;
let mockDeckRepo: ReturnType<typeof createMockDeckRepo>;
let mockCardRepo: ReturnType<typeof createMockCardRepo>;
- let mockReviewLogRepo: ReturnType<typeof createMockReviewLogRepo>;
let authToken: string;
beforeEach(async () => {
vi.clearAllMocks();
mockDeckRepo = createMockDeckRepo();
mockCardRepo = createMockCardRepo();
- mockReviewLogRepo = createMockReviewLogRepo();
const decksRouter = createDecksRouter({
deckRepo: mockDeckRepo,
cardRepo: mockCardRepo,
- reviewLogRepo: mockReviewLogRepo,
});
app = new Hono();
app.onError(errorHandler);
@@ -344,18 +318,15 @@ describe("PUT /api/decks/:id", () => {
let app: Hono;
let mockDeckRepo: ReturnType<typeof createMockDeckRepo>;
let mockCardRepo: ReturnType<typeof createMockCardRepo>;
- let mockReviewLogRepo: ReturnType<typeof createMockReviewLogRepo>;
let authToken: string;
beforeEach(async () => {
vi.clearAllMocks();
mockDeckRepo = createMockDeckRepo();
mockCardRepo = createMockCardRepo();
- mockReviewLogRepo = createMockReviewLogRepo();
const decksRouter = createDecksRouter({
deckRepo: mockDeckRepo,
cardRepo: mockCardRepo,
- reviewLogRepo: mockReviewLogRepo,
});
app = new Hono();
app.onError(errorHandler);
@@ -405,27 +376,6 @@ describe("PUT /api/decks/:id", () => {
expect(body.deck?.description).toBe("New description");
});
- it("updates newCardsPerDay", async () => {
- const updatedDeck = createMockDeck({ newCardsPerDay: 50 });
- vi.mocked(mockDeckRepo.update).mockResolvedValue(updatedDeck);
-
- const res = await app.request(
- "/api/decks/00000000-0000-0000-0000-000000000000",
- {
- method: "PUT",
- headers: {
- Authorization: `Bearer ${authToken}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ newCardsPerDay: 50 }),
- },
- );
-
- expect(res.status).toBe(200);
- const body = (await res.json()) as DeckResponse;
- expect(body.deck?.newCardsPerDay).toBe(50);
- });
-
it("returns 404 for non-existent deck", async () => {
vi.mocked(mockDeckRepo.update).mockResolvedValue(undefined);
@@ -477,18 +427,15 @@ describe("DELETE /api/decks/:id", () => {
let app: Hono;
let mockDeckRepo: ReturnType<typeof createMockDeckRepo>;
let mockCardRepo: ReturnType<typeof createMockCardRepo>;
- let mockReviewLogRepo: ReturnType<typeof createMockReviewLogRepo>;
let authToken: string;
beforeEach(async () => {
vi.clearAllMocks();
mockDeckRepo = createMockDeckRepo();
mockCardRepo = createMockCardRepo();
- mockReviewLogRepo = createMockReviewLogRepo();
const decksRouter = createDecksRouter({
deckRepo: mockDeckRepo,
cardRepo: mockCardRepo,
- reviewLogRepo: mockReviewLogRepo,
});
app = new Hono();
app.onError(errorHandler);
diff --git a/src/server/routes/decks.ts b/src/server/routes/decks.ts
index d73aa0c..ed7077e 100644
--- a/src/server/routes/decks.ts
+++ b/src/server/routes/decks.ts
@@ -7,25 +7,20 @@ import {
cardRepository,
type DeckRepository,
deckRepository,
- type ReviewLogRepository,
- reviewLogRepository,
} from "../repositories/index.js";
import { createDeckSchema, updateDeckSchema } from "../schemas/index.js";
export interface DeckDependencies {
deckRepo: DeckRepository;
cardRepo: CardRepository;
- reviewLogRepo: ReviewLogRepository;
}
const deckIdParamSchema = z.object({
id: z.uuid(),
});
-const REVIEW_CARDS_LIMIT = 80;
-
export function createDecksRouter(deps: DeckDependencies) {
- const { deckRepo, cardRepo, reviewLogRepo } = deps;
+ const { deckRepo, cardRepo } = deps;
return new Hono()
.use("*", authMiddleware)
@@ -35,26 +30,7 @@ export function createDecksRouter(deps: DeckDependencies) {
const now = new Date();
const decksWithDueCount = await Promise.all(
decks.map(async (deck) => {
- const [dueNewCards, dueReviewCards, reviewedNewCards] =
- await Promise.all([
- cardRepo.countDueNewCards(deck.id, now),
- cardRepo.countDueReviewCards(deck.id, now),
- reviewLogRepo.countTodayNewCardReviews(deck.id, now),
- ]);
-
- // Apply the same limits as the study screen
- const newCardBudget = Math.max(
- 0,
- deck.newCardsPerDay - reviewedNewCards,
- );
- const newCardsToStudy = Math.min(dueNewCards, newCardBudget);
- const reviewCardsToStudy = Math.min(
- dueReviewCards,
- REVIEW_CARDS_LIMIT,
- );
-
- const dueCardCount = newCardsToStudy + reviewCardsToStudy;
-
+ const dueCardCount = await cardRepo.countDueCards(deck.id, now);
return { ...deck, dueCardCount };
}),
);
@@ -68,7 +44,6 @@ export function createDecksRouter(deps: DeckDependencies) {
userId: user.id,
name: data.name,
description: data.description,
- newCardsPerDay: data.newCardsPerDay,
});
return c.json({ deck }, 201);
@@ -83,18 +58,7 @@ export function createDecksRouter(deps: DeckDependencies) {
}
const now = new Date();
- const [dueNewCards, dueReviewCards, reviewedNewCards] = await Promise.all(
- [
- cardRepo.countDueNewCards(deck.id, now),
- cardRepo.countDueReviewCards(deck.id, now),
- reviewLogRepo.countTodayNewCardReviews(deck.id, now),
- ],
- );
-
- const newCardBudget = Math.max(0, deck.newCardsPerDay - reviewedNewCards);
- const newCardsToStudy = Math.min(dueNewCards, newCardBudget);
- const reviewCardsToStudy = Math.min(dueReviewCards, REVIEW_CARDS_LIMIT);
- const dueCardCount = newCardsToStudy + reviewCardsToStudy;
+ const dueCardCount = await cardRepo.countDueCards(deck.id, now);
return c.json({ deck: { ...deck, dueCardCount } }, 200);
})
@@ -131,5 +95,4 @@ export function createDecksRouter(deps: DeckDependencies) {
export const decks = createDecksRouter({
deckRepo: deckRepository,
cardRepo: cardRepository,
- reviewLogRepo: reviewLogRepository,
});
diff --git a/src/server/routes/notes.test.ts b/src/server/routes/notes.test.ts
index e354fa6..116a57f 100644
--- a/src/server/routes/notes.test.ts
+++ b/src/server/routes/notes.test.ts
@@ -57,7 +57,6 @@ function createMockDeck(overrides: Partial<Deck> = {}): Deck {
userId: "user-uuid-123",
name: "Test Deck",
description: "Test description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
deletedAt: null,
diff --git a/src/server/routes/study.test.ts b/src/server/routes/study.test.ts
index 514d966..119b25d 100644
--- a/src/server/routes/study.test.ts
+++ b/src/server/routes/study.test.ts
@@ -26,12 +26,8 @@ function createMockCardRepo(): CardRepository {
softDeleteByNoteId: vi.fn(),
findDueCards: vi.fn(),
countDueCards: vi.fn(),
- countDueNewCards: vi.fn(),
- countDueReviewCards: vi.fn(),
findDueCardsWithNoteData: vi.fn(),
findDueCardsForStudy: vi.fn(),
- findDueNewCardsForStudy: vi.fn(),
- findDueReviewCardsForStudy: vi.fn(),
updateFSRSFields: vi.fn(),
};
}
@@ -49,7 +45,6 @@ function createMockDeckRepo(): DeckRepository {
function createMockReviewLogRepo(): ReviewLogRepository {
return {
create: vi.fn(),
- countTodayNewCardReviews: vi.fn().mockResolvedValue(0),
};
}
@@ -73,7 +68,6 @@ function createMockDeck(overrides: Partial<Deck> = {}): Deck {
userId: "user-uuid-123",
name: "Test Deck",
description: "Test description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
deletedAt: null,
@@ -152,14 +146,13 @@ describe("GET /api/decks/:deckId/study", () => {
let app: Hono;
let mockCardRepo: ReturnType<typeof createMockCardRepo>;
let mockDeckRepo: ReturnType<typeof createMockDeckRepo>;
- let mockReviewLogRepo: ReturnType<typeof createMockReviewLogRepo>;
let authToken: string;
beforeEach(async () => {
vi.clearAllMocks();
mockCardRepo = createMockCardRepo();
mockDeckRepo = createMockDeckRepo();
- mockReviewLogRepo = createMockReviewLogRepo();
+ const mockReviewLogRepo = createMockReviewLogRepo();
const studyRouter = createStudyRouter({
cardRepo: mockCardRepo,
deckRepo: mockDeckRepo,
@@ -175,8 +168,7 @@ describe("GET /api/decks/:deckId/study", () => {
vi.mocked(mockDeckRepo.findById).mockResolvedValue(
createMockDeck({ id: DECK_ID }),
);
- vi.mocked(mockCardRepo.findDueNewCardsForStudy).mockResolvedValue([]);
- vi.mocked(mockCardRepo.findDueReviewCardsForStudy).mockResolvedValue([]);
+ vi.mocked(mockCardRepo.findDueCardsForStudy).mockResolvedValue([]);
const res = await app.request(`/api/decks/${DECK_ID}/study`, {
method: "GET",
@@ -190,20 +182,14 @@ describe("GET /api/decks/:deckId/study", () => {
DECK_ID,
"user-uuid-123",
);
- expect(mockCardRepo.findDueNewCardsForStudy).toHaveBeenCalledWith(
- DECK_ID,
- expect.any(Date),
- 20,
- );
- expect(mockCardRepo.findDueReviewCardsForStudy).toHaveBeenCalledWith(
+ expect(mockCardRepo.findDueCardsForStudy).toHaveBeenCalledWith(
DECK_ID,
expect.any(Date),
- 80,
);
});
it("returns due cards", async () => {
- const newCards = [
+ const mockCards = [
createMockCardForStudy({
id: "card-1",
front: "Q1",
@@ -211,8 +197,6 @@ describe("GET /api/decks/:deckId/study", () => {
state: CardState.New,
fieldValuesMap: {},
}),
- ];
- const reviewCards = [
createMockCardForStudy({
id: "card-2",
front: "Q2",
@@ -224,10 +208,7 @@ describe("GET /api/decks/:deckId/study", () => {
vi.mocked(mockDeckRepo.findById).mockResolvedValue(
createMockDeck({ id: DECK_ID }),
);
- vi.mocked(mockCardRepo.findDueNewCardsForStudy).mockResolvedValue(newCards);
- vi.mocked(mockCardRepo.findDueReviewCardsForStudy).mockResolvedValue(
- reviewCards,
- );
+ vi.mocked(mockCardRepo.findDueCardsForStudy).mockResolvedValue(mockCards);
const res = await app.request(`/api/decks/${DECK_ID}/study`, {
method: "GET",
@@ -259,10 +240,7 @@ describe("GET /api/decks/:deckId/study", () => {
vi.mocked(mockDeckRepo.findById).mockResolvedValue(
createMockDeck({ id: DECK_ID }),
);
- vi.mocked(mockCardRepo.findDueNewCardsForStudy).mockResolvedValue(
- mockCards,
- );
- vi.mocked(mockCardRepo.findDueReviewCardsForStudy).mockResolvedValue([]);
+ vi.mocked(mockCardRepo.findDueCardsForStudy).mockResolvedValue(mockCards);
const res = await app.request(`/api/decks/${DECK_ID}/study`, {
method: "GET",
@@ -276,81 +254,6 @@ describe("GET /api/decks/:deckId/study", () => {
expect(body.cards?.[0]?.fieldValuesMap?.Front).toBe("Question");
});
- it("limits new cards based on newCardsPerDay", async () => {
- vi.mocked(mockDeckRepo.findById).mockResolvedValue(
- createMockDeck({ id: DECK_ID, newCardsPerDay: 5 }),
- );
- vi.mocked(mockReviewLogRepo.countTodayNewCardReviews).mockResolvedValue(3);
- vi.mocked(mockCardRepo.findDueNewCardsForStudy).mockResolvedValue([]);
- vi.mocked(mockCardRepo.findDueReviewCardsForStudy).mockResolvedValue([]);
-
- await app.request(`/api/decks/${DECK_ID}/study`, {
- method: "GET",
- headers: { Authorization: `Bearer ${authToken}` },
- });
-
- expect(mockCardRepo.findDueNewCardsForStudy).toHaveBeenCalledWith(
- DECK_ID,
- expect.any(Date),
- 2,
- );
- });
-
- it("returns 0 new cards when daily limit is reached", async () => {
- vi.mocked(mockDeckRepo.findById).mockResolvedValue(
- createMockDeck({ id: DECK_ID, newCardsPerDay: 5 }),
- );
- vi.mocked(mockReviewLogRepo.countTodayNewCardReviews).mockResolvedValue(5);
- vi.mocked(mockCardRepo.findDueNewCardsForStudy).mockResolvedValue([]);
- vi.mocked(mockCardRepo.findDueReviewCardsForStudy).mockResolvedValue([]);
-
- await app.request(`/api/decks/${DECK_ID}/study`, {
- method: "GET",
- headers: { Authorization: `Bearer ${authToken}` },
- });
-
- expect(mockCardRepo.findDueNewCardsForStudy).toHaveBeenCalledWith(
- DECK_ID,
- expect.any(Date),
- 0,
- );
- });
-
- it("places new cards before review cards in response", async () => {
- const newCards = [
- createMockCardForStudy({
- id: "new-1",
- state: CardState.New,
- fieldValuesMap: {},
- }),
- ];
- const reviewCards = [
- createMockCardForStudy({
- id: "review-1",
- state: CardState.Review,
- fieldValuesMap: {},
- }),
- ];
- vi.mocked(mockDeckRepo.findById).mockResolvedValue(
- createMockDeck({ id: DECK_ID }),
- );
- vi.mocked(mockCardRepo.findDueNewCardsForStudy).mockResolvedValue(newCards);
- vi.mocked(mockCardRepo.findDueReviewCardsForStudy).mockResolvedValue(
- reviewCards,
- );
-
- const res = await app.request(`/api/decks/${DECK_ID}/study`, {
- method: "GET",
- headers: { Authorization: `Bearer ${authToken}` },
- });
-
- expect(res.status).toBe(200);
- const body = (await res.json()) as StudyResponse;
- expect(body.cards).toHaveLength(2);
- expect(body.cards?.[0]?.id).toBe("new-1");
- expect(body.cards?.[1]?.id).toBe("review-1");
- });
-
it("returns 404 for non-existent deck", async () => {
vi.mocked(mockDeckRepo.findById).mockResolvedValue(undefined);
diff --git a/src/server/routes/study.ts b/src/server/routes/study.ts
index d05f3ca..0f42f93 100644
--- a/src/server/routes/study.ts
+++ b/src/server/routes/study.ts
@@ -52,20 +52,9 @@ export function createStudyRouter(deps: StudyDependencies) {
const now = new Date();
- // Calculate new card budget based on today's already-reviewed new cards
- const reviewedNewCards = await reviewLogRepo.countTodayNewCardReviews(
- deckId,
- now,
- );
- const newCardBudget = Math.max(0, deck.newCardsPerDay - reviewedNewCards);
+ const cards = await cardRepo.findDueCardsForStudy(deckId, now);
- // Fetch new cards (limited) and review cards separately
- const [newCards, reviewCards] = await Promise.all([
- cardRepo.findDueNewCardsForStudy(deckId, now, newCardBudget),
- cardRepo.findDueReviewCardsForStudy(deckId, now, 80),
- ]);
-
- return c.json({ cards: [...newCards, ...reviewCards] }, 200);
+ return c.json({ cards }, 200);
})
.post(
"/:cardId",
diff --git a/src/server/routes/sync.test.ts b/src/server/routes/sync.test.ts
index 8ea2ce3..4c0d8d8 100644
--- a/src/server/routes/sync.test.ts
+++ b/src/server/routes/sync.test.ts
@@ -143,7 +143,6 @@ describe("POST /api/sync/push", () => {
id: "550e8400-e29b-41d4-a716-446655440000",
name: "Test Deck",
description: "A test deck",
- newCardsPerDay: 20,
createdAt: "2024-01-01T00:00:00.000Z",
updatedAt: "2024-01-02T00:00:00.000Z",
deletedAt: null,
@@ -302,7 +301,6 @@ describe("POST /api/sync/push", () => {
id: "550e8400-e29b-41d4-a716-446655440003",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: "2024-01-01T00:00:00.000Z",
updatedAt: "2024-01-02T00:00:00.000Z",
deletedAt: null,
@@ -349,7 +347,6 @@ describe("POST /api/sync/push", () => {
id: "not-a-uuid",
name: "",
description: null,
- newCardsPerDay: -1,
createdAt: "invalid-date",
updatedAt: "2024-01-01T00:00:00.000Z",
deletedAt: null,
@@ -432,7 +429,6 @@ describe("POST /api/sync/push", () => {
id: "550e8400-e29b-41d4-a716-446655440004",
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: "2024-01-01T00:00:00.000Z",
updatedAt: "2024-01-01T00:00:00.000Z",
deletedAt: null,
@@ -634,7 +630,6 @@ describe("POST /api/sync/push", () => {
id: "550e8400-e29b-41d4-a716-446655440007",
name: "Deleted Deck",
description: null,
- newCardsPerDay: 20,
createdAt: "2024-01-01T00:00:00.000Z",
updatedAt: "2024-01-02T00:00:00.000Z",
deletedAt: "2024-01-02T00:00:00.000Z",
@@ -830,7 +825,6 @@ describe("GET /api/sync/pull", () => {
userId,
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T00:00:00.000Z"),
updatedAt: new Date("2024-01-02T00:00:00.000Z"),
deletedAt: null,
@@ -906,7 +900,6 @@ describe("GET /api/sync/pull", () => {
userId,
name: "Test Deck",
description: "A test description",
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T00:00:00.000Z"),
updatedAt: new Date("2024-01-02T00:00:00.000Z"),
deletedAt: null,
@@ -1041,7 +1034,6 @@ describe("GET /api/sync/pull", () => {
userId,
name: "Test Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T00:00:00.000Z"),
updatedAt: new Date("2024-01-01T00:00:00.000Z"),
deletedAt: null,
@@ -1215,7 +1207,6 @@ describe("GET /api/sync/pull", () => {
userId,
name: "Deleted Deck",
description: null,
- newCardsPerDay: 20,
createdAt: new Date("2024-01-01T00:00:00.000Z"),
updatedAt: new Date("2024-01-02T00:00:00.000Z"),
deletedAt: new Date("2024-01-02T00:00:00.000Z"),
diff --git a/src/server/routes/sync.ts b/src/server/routes/sync.ts
index c571f8a..a9ea3b3 100644
--- a/src/server/routes/sync.ts
+++ b/src/server/routes/sync.ts
@@ -18,7 +18,6 @@ const syncDeckSchema = z.object({
id: z.uuid(),
name: z.string().min(1).max(255),
description: z.string().nullable(),
- newCardsPerDay: z.number().int().min(0).max(1000),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
deletedAt: z.string().datetime().nullable(),
diff --git a/src/server/schemas/index.ts b/src/server/schemas/index.ts
index fc1bd77..aa9ceea 100644
--- a/src/server/schemas/index.ts
+++ b/src/server/schemas/index.ts
@@ -48,7 +48,6 @@ export const deckSchema = z.object({
userId: z.uuid(),
name: z.string().min(1).max(255),
description: z.string().max(1000).nullable(),
- newCardsPerDay: z.number().int().min(0).default(20),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
deletedAt: z.coerce.date().nullable(),
@@ -59,14 +58,12 @@ export const deckSchema = z.object({
export const createDeckSchema = z.object({
name: z.string().min(1).max(255),
description: z.string().max(1000).nullable().optional(),
- newCardsPerDay: z.number().int().min(0).default(20),
});
// Deck update input schema
export const updateDeckSchema = z.object({
name: z.string().min(1).max(255).optional(),
description: z.string().max(1000).nullable().optional(),
- newCardsPerDay: z.number().int().min(0).optional(),
});
// Card schema
diff --git a/src/server/types/index.ts b/src/server/types/index.ts
index bfba06f..08f8379 100644
--- a/src/server/types/index.ts
+++ b/src/server/types/index.ts
@@ -33,7 +33,6 @@ export interface Deck {
userId: string;
name: string;
description: string | null;
- newCardsPerDay: number;
createdAt: Date;
updatedAt: Date;
deletedAt: Date | null;