diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-12-31 14:27:54 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-12-31 14:27:54 +0900 |
| commit | a490c6dd68470b1be1abac73b00246b07e6bd919 (patch) | |
| tree | 24abecf2556e0fa22887e5d8ff331e6105ff6377 /src/server/repositories/card.ts | |
| parent | a4a03abe7ad5a52df72b538dd206b58d85d912e4 (diff) | |
| download | kioku-a490c6dd68470b1be1abac73b00246b07e6bd919.tar.gz kioku-a490c6dd68470b1be1abac73b00246b07e6bd919.tar.zst kioku-a490c6dd68470b1be1abac73b00246b07e6bd919.zip | |
feat(card): cascade card deletion to note and sibling cards
When a card is deleted, now also soft-deletes its parent Note and all
sibling cards (other cards generated from the same note). This matches
the specified behavior in the roadmap where deleting any card from a
note-based group should remove the entire note and all its cards.
Also adds tests for deletion constraint behaviors:
- NoteType deletion blocked when Notes exist
- NoteFieldType deletion blocked when NoteFieldValues exist
- Note deletion cascades to all related Cards
- Card deletion cascades to Note and sibling 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/repositories/card.ts')
| -rw-r--r-- | src/server/repositories/card.ts | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/src/server/repositories/card.ts b/src/server/repositories/card.ts index 4c4fc81..761b317 100644 --- a/src/server/repositories/card.ts +++ b/src/server/repositories/card.ts @@ -137,22 +137,35 @@ export const cardRepository: CardRepository = { }, async softDelete(id: string, deckId: string): Promise<boolean> { - const result = await db + // First, find the card to get its noteId + const card = await this.findById(id, deckId); + if (!card) { + return false; + } + + const now = new Date(); + + // Soft delete all cards belonging to the same note (including this one and sibling cards) + await db .update(cards) .set({ - deletedAt: new Date(), - updatedAt: new Date(), + deletedAt: now, + updatedAt: now, syncVersion: sql`${cards.syncVersion} + 1`, }) - .where( - and( - eq(cards.id, id), - eq(cards.deckId, deckId), - isNull(cards.deletedAt), - ), - ) - .returning({ id: cards.id }); - return result.length > 0; + .where(and(eq(cards.noteId, card.noteId), isNull(cards.deletedAt))); + + // Soft delete the parent note + await db + .update(notes) + .set({ + deletedAt: now, + updatedAt: now, + syncVersion: sql`${notes.syncVersion} + 1`, + }) + .where(and(eq(notes.id, card.noteId), isNull(notes.deletedAt))); + + return true; }, async softDeleteByNoteId(noteId: string): Promise<boolean> { |
