diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-12-31 14:19:22 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-12-31 14:19:22 +0900 |
| commit | b074a4901c630ee5c5f7dcff79fa6ff911a14ded (patch) | |
| tree | a52b738974393e31678c85e37756004d1b547823 /src/server/routes | |
| parent | 29caaa7aaf14a41dad3d345cd29b319fff6e1305 (diff) | |
| download | kioku-b074a4901c630ee5c5f7dcff79fa6ff911a14ded.tar.gz kioku-b074a4901c630ee5c5f7dcff79fa6ff911a14ded.tar.zst kioku-b074a4901c630ee5c5f7dcff79fa6ff911a14ded.zip | |
feat(schema): make note_id and is_reversed NOT NULL
All cards now require note association - legacy card support removed.
This aligns with the note-based card architecture introduced in Phase 8.
- Add database migration for NOT NULL constraints
- Update client Dexie schema to version 3
- Remove LegacyCardItem component and legacy card handling
- Update sync schemas and type definitions
- Update all tests to use note-based cards
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/server/routes')
| -rw-r--r-- | src/server/routes/cards.test.ts | 7 | ||||
| -rw-r--r-- | src/server/routes/study.test.ts | 15 | ||||
| -rw-r--r-- | src/server/routes/sync.test.ts | 16 | ||||
| -rw-r--r-- | src/server/routes/sync.ts | 4 |
4 files changed, 21 insertions, 21 deletions
diff --git a/src/server/routes/cards.test.ts b/src/server/routes/cards.test.ts index 780ea44..66ba601 100644 --- a/src/server/routes/cards.test.ts +++ b/src/server/routes/cards.test.ts @@ -74,8 +74,8 @@ function createMockCard(overrides: Partial<Card> = {}): Card { return { id: "card-uuid-123", deckId: "deck-uuid-123", - noteId: null, - isReversed: null, + noteId: "note-uuid-123", + isReversed: false, front: "Question", back: "Answer", state: CardState.New, @@ -110,7 +110,7 @@ function createMockCardWithNoteData( ): CardWithNoteData { return { ...createMockCard(overrides), - note: overrides.note ?? null, + note: overrides.note ?? createMockNote(), fieldValues: overrides.fieldValues ?? [], }; } @@ -408,7 +408,6 @@ describe("GET /api/decks/:deckId/cards/:cardId", () => { const mockCardWithNote = createMockCardWithNoteData({ id: CARD_ID, deckId: DECK_ID, - note: null, fieldValues: [], }); vi.mocked(mockDeckRepo.findById).mockResolvedValue( diff --git a/src/server/routes/study.test.ts b/src/server/routes/study.test.ts index 41abecd..e2fb457 100644 --- a/src/server/routes/study.test.ts +++ b/src/server/routes/study.test.ts @@ -80,8 +80,8 @@ function createMockCard(overrides: Partial<Card> = {}): Card { return { id: "card-uuid-123", deckId: "deck-uuid-123", - noteId: null, - isReversed: null, + noteId: "note-uuid-123", + isReversed: false, front: "Question", back: "Answer", state: CardState.New, @@ -122,7 +122,10 @@ function createMockCardForStudy( ): CardForStudy { return { ...createMockCard(overrides), - noteType: overrides.noteType ?? null, + noteType: overrides.noteType ?? { + frontTemplate: "{{Front}}", + backTemplate: "{{Back}}", + }, fieldValuesMap: overrides.fieldValuesMap ?? {}, }; } @@ -187,20 +190,18 @@ describe("GET /api/decks/:deckId/study", () => { ); }); - it("returns due cards (legacy cards without note)", async () => { + it("returns due cards", async () => { const mockCards = [ createMockCardForStudy({ id: "card-1", front: "Q1", back: "A1", - noteType: null, fieldValuesMap: {}, }), createMockCardForStudy({ id: "card-2", front: "Q2", back: "A2", - noteType: null, fieldValuesMap: {}, }), ]; @@ -217,7 +218,7 @@ describe("GET /api/decks/:deckId/study", () => { expect(res.status).toBe(200); const body = (await res.json()) as StudyResponse; expect(body.cards).toHaveLength(2); - expect(body.cards?.[0]?.noteType).toBeNull(); + expect(body.cards?.[0]?.noteType).toBeDefined(); }); it("returns due cards with note type and field values when available", async () => { diff --git a/src/server/routes/sync.test.ts b/src/server/routes/sync.test.ts index 1107acd..f340af7 100644 --- a/src/server/routes/sync.test.ts +++ b/src/server/routes/sync.test.ts @@ -186,8 +186,8 @@ describe("POST /api/sync/push", () => { const cardData = { id: "550e8400-e29b-41d4-a716-446655440001", deckId: "550e8400-e29b-41d4-a716-446655440000", - noteId: null, - isReversed: null, + noteId: "550e8400-e29b-41d4-a716-446655440020", + isReversed: false, front: "Question", back: "Answer", state: 0, @@ -435,8 +435,8 @@ describe("POST /api/sync/push", () => { const cardData = { id: "550e8400-e29b-41d4-a716-446655440005", deckId: "550e8400-e29b-41d4-a716-446655440004", - noteId: null, - isReversed: null, + noteId: "550e8400-e29b-41d4-a716-446655440020", + isReversed: false, front: "Q", back: "A", state: 0, @@ -823,8 +823,8 @@ describe("GET /api/sync/pull", () => { const mockCard: Card = { id: "550e8400-e29b-41d4-a716-446655440001", deckId: "550e8400-e29b-41d4-a716-446655440000", - noteId: null, - isReversed: null, + noteId: "550e8400-e29b-41d4-a716-446655440020", + isReversed: false, front: "Question", back: "Answer", state: 2, @@ -928,8 +928,8 @@ describe("GET /api/sync/pull", () => { const mockCard: Card = { id: "550e8400-e29b-41d4-a716-446655440001", deckId: "550e8400-e29b-41d4-a716-446655440000", - noteId: null, - isReversed: null, + noteId: "550e8400-e29b-41d4-a716-446655440020", + isReversed: false, front: "Q", back: "A", state: 0, diff --git a/src/server/routes/sync.ts b/src/server/routes/sync.ts index f05a7ba..fca099b 100644 --- a/src/server/routes/sync.ts +++ b/src/server/routes/sync.ts @@ -26,8 +26,8 @@ const syncDeckSchema = z.object({ const syncCardSchema = z.object({ id: z.uuid(), deckId: z.uuid(), - noteId: z.uuid().nullable(), - isReversed: z.boolean().nullable(), + noteId: z.uuid(), + isReversed: z.boolean(), front: z.string().min(1), back: z.string().min(1), state: z.number().int().min(0).max(3), |
