aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/server/repositories
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/repositories')
-rw-r--r--src/server/repositories/card.test.ts69
-rw-r--r--src/server/repositories/card.ts56
-rw-r--r--src/server/repositories/note.test.ts4
-rw-r--r--src/server/repositories/sync.ts4
-rw-r--r--src/server/repositories/types.ts14
5 files changed, 56 insertions, 91 deletions
diff --git a/src/server/repositories/card.test.ts b/src/server/repositories/card.test.ts
index 9d7ffa6..98913e9 100644
--- a/src/server/repositories/card.test.ts
+++ b/src/server/repositories/card.test.ts
@@ -12,8 +12,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: "Front text",
back: "Back text",
state: 0,
@@ -89,15 +89,14 @@ function createMockCardWithNoteData(
function createMockCardForStudy(
overrides: Partial<CardForStudy> = {},
): CardForStudy {
- const card = createMockCard({
- noteId: overrides.noteType ? "note-uuid-123" : null,
- isReversed: overrides.noteType ? false : null,
- ...overrides,
- });
+ const card = createMockCard(overrides);
return {
...card,
- noteType: overrides.noteType ?? null,
- fieldValuesMap: overrides.fieldValuesMap ?? {},
+ noteType: overrides.noteType ?? {
+ frontTemplate: "{{Front}}",
+ backTemplate: "{{Back}}",
+ },
+ fieldValuesMap: overrides.fieldValuesMap ?? { Front: "Q", Back: "A" },
};
}
@@ -125,8 +124,8 @@ describe("CardRepository mock factory", () => {
expect(card.id).toBe("card-uuid-123");
expect(card.deckId).toBe("deck-uuid-123");
- expect(card.noteId).toBeNull();
- expect(card.isReversed).toBeNull();
+ expect(card.noteId).toBe("note-uuid-123");
+ expect(card.isReversed).toBe(false);
expect(card.front).toBe("Front text");
expect(card.back).toBe("Back text");
expect(card.state).toBe(0);
@@ -205,17 +204,13 @@ describe("CardRepository mock factory", () => {
expect(cardWithNote.fieldValues[0]?.value).toBe("日本語");
});
- it("can represent legacy card with null note", () => {
- // For legacy cards without notes, we explicitly construct the type
- const legacyCard: CardWithNoteData = {
- ...createMockCard({ noteId: null, isReversed: null }),
- note: null,
- fieldValues: [],
- };
-
- expect(legacyCard.noteId).toBeNull();
- expect(legacyCard.note).toBeNull();
- expect(legacyCard.fieldValues).toHaveLength(0);
+ it("card always has note association", () => {
+ // All cards now require note association
+ const cardWithNote = createMockCardWithNoteData();
+
+ expect(cardWithNote.noteId).toBe("note-uuid-123");
+ expect(cardWithNote.note).not.toBeNull();
+ expect(cardWithNote.fieldValues).toHaveLength(2);
});
});
@@ -392,41 +387,39 @@ describe("Card interface contracts", () => {
expect(cardForStudy.fieldValuesMap.Front).toBe("Question");
});
- it("CardForStudy can represent legacy card with null noteType", () => {
- const legacyCard = createMockCardForStudy({
- front: "Legacy Question",
- back: "Legacy Answer",
+ it("CardForStudy has required note data", () => {
+ const cardForStudy = createMockCardForStudy({
+ front: "Question",
+ back: "Answer",
});
- expect(legacyCard.noteId).toBeNull();
- expect(legacyCard.noteType).toBeNull();
- expect(legacyCard.fieldValuesMap).toEqual({});
- expect(legacyCard.front).toBe("Legacy Question");
- expect(legacyCard.back).toBe("Legacy Answer");
+ expect(cardForStudy.noteId).toBe("note-uuid-123");
+ expect(cardForStudy.noteType).not.toBeNull();
+ expect(cardForStudy.noteType.frontTemplate).toBe("{{Front}}");
+ expect(cardForStudy.fieldValuesMap).toEqual({ Front: "Q", Back: "A" });
});
});
describe("Card and Note relationship", () => {
- it("legacy card has null noteId and isReversed", () => {
+ it("card has required noteId and isReversed", () => {
const card = createMockCard();
- expect(card.noteId).toBeNull();
- expect(card.isReversed).toBeNull();
+ expect(card.noteId).toBe("note-uuid-123");
+ expect(card.isReversed).toBe(false);
});
- it("note-based card has noteId and isReversed set", () => {
+ it("card with explicit note data", () => {
const card = createMockCard({
- noteId: "note-uuid-123",
+ noteId: "different-note-id",
isReversed: false,
});
- expect(card.noteId).toBe("note-uuid-123");
+ expect(card.noteId).toBe("different-note-id");
expect(card.isReversed).toBe(false);
});
it("reversed card has isReversed true", () => {
const card = createMockCard({
- noteId: "note-uuid-123",
isReversed: true,
});
diff --git a/src/server/repositories/card.ts b/src/server/repositories/card.ts
index 7116642..4c4fc81 100644
--- a/src/server/repositories/card.ts
+++ b/src/server/repositories/card.ts
@@ -47,20 +47,15 @@ export const cardRepository: CardRepository = {
return undefined;
}
- if (!card.noteId) {
- return {
- ...card,
- note: null,
- fieldValues: [],
- };
- }
-
const noteResult = await db
.select()
.from(notes)
.where(and(eq(notes.id, card.noteId), isNull(notes.deletedAt)));
- const note = noteResult[0] ?? null;
+ const note = noteResult[0];
+ if (!note) {
+ return undefined;
+ }
const fieldValuesResult = await db
.select()
@@ -85,6 +80,8 @@ export const cardRepository: CardRepository = {
async create(
deckId: string,
data: {
+ noteId: string;
+ isReversed: boolean;
front: string;
back: string;
},
@@ -93,6 +90,8 @@ export const cardRepository: CardRepository = {
.insert(cards)
.values({
deckId,
+ noteId: data.noteId,
+ isReversed: data.isReversed,
front: data.front,
back: data.back,
state: CardState.New,
@@ -200,21 +199,16 @@ export const cardRepository: CardRepository = {
const cardsWithNoteData: CardWithNoteData[] = [];
for (const card of dueCards) {
- if (!card.noteId) {
- cardsWithNoteData.push({
- ...card,
- note: null,
- fieldValues: [],
- });
- continue;
- }
-
const noteResult = await db
.select()
.from(notes)
.where(and(eq(notes.id, card.noteId), isNull(notes.deletedAt)));
- const note = noteResult[0] ?? null;
+ const note = noteResult[0];
+ if (!note) {
+ // Note was deleted, skip this card
+ continue;
+ }
const fieldValuesResult = await db
.select()
@@ -241,16 +235,6 @@ export const cardRepository: CardRepository = {
const cardsForStudy: CardForStudy[] = [];
for (const card of dueCards) {
- // Legacy card (no note association)
- if (!card.noteId) {
- cardsForStudy.push({
- ...card,
- noteType: null,
- fieldValuesMap: {},
- });
- continue;
- }
-
// Fetch note to get noteTypeId
const noteResult = await db
.select()
@@ -259,12 +243,7 @@ export const cardRepository: CardRepository = {
const note = noteResult[0];
if (!note) {
- // Note was deleted, treat as legacy card
- cardsForStudy.push({
- ...card,
- noteType: null,
- fieldValuesMap: {},
- });
+ // Note was deleted, skip this card
continue;
}
@@ -281,12 +260,7 @@ export const cardRepository: CardRepository = {
const noteType = noteTypeResult[0];
if (!noteType) {
- // Note type was deleted, treat as legacy card
- cardsForStudy.push({
- ...card,
- noteType: null,
- fieldValuesMap: {},
- });
+ // Note type was deleted, skip this card
continue;
}
diff --git a/src/server/repositories/note.test.ts b/src/server/repositories/note.test.ts
index 70dcb4a..cc1a9ae 100644
--- a/src/server/repositories/note.test.ts
+++ b/src/server/repositories/note.test.ts
@@ -40,8 +40,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: "Front text",
back: "Back text",
state: 0,
diff --git a/src/server/repositories/sync.ts b/src/server/repositories/sync.ts
index 8c4fd25..59a195a 100644
--- a/src/server/repositories/sync.ts
+++ b/src/server/repositories/sync.ts
@@ -45,8 +45,8 @@ export interface SyncDeckData {
export interface SyncCardData {
id: string;
deckId: string;
- noteId: string | null;
- isReversed: boolean | null;
+ noteId: string;
+ isReversed: boolean;
front: string;
back: string;
state: number;
diff --git a/src/server/repositories/types.ts b/src/server/repositories/types.ts
index c864be0..a986cad 100644
--- a/src/server/repositories/types.ts
+++ b/src/server/repositories/types.ts
@@ -81,8 +81,8 @@ export interface DeckRepository {
export interface Card {
id: string;
deckId: string;
- noteId: string | null;
- isReversed: boolean | null;
+ noteId: string;
+ isReversed: boolean;
front: string;
back: string;
@@ -104,22 +104,20 @@ export interface Card {
}
export interface CardWithNoteData extends Card {
- note: Note | null;
+ note: Note;
fieldValues: NoteFieldValue[];
}
/**
* Card data prepared for study, including all necessary template rendering info.
- * For note-based cards, includes templates and field values as a name-value map.
- * For legacy cards, note and templates are null.
*/
export interface CardForStudy extends Card {
- /** Note type templates for rendering (null for legacy cards) */
+ /** Note type templates for rendering */
noteType: {
frontTemplate: string;
backTemplate: string;
- } | null;
- /** Field values as a name-value map for template rendering (empty for legacy cards) */
+ };
+ /** Field values as a name-value map for template rendering */
fieldValuesMap: Record<string, string>;
}