diff --git a/CLAUDE.md b/CLAUDE.md index 605324c..c9acd38 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -163,6 +163,13 @@ GitHub Actions with two workflows: **Docker**: Multi-stage Dockerfile (node:22-slim), exposes port 3000, persists data to `/data` volume. +## Database schema changes + +When adding or modifying tables in `src/lib/server/db/schema.ts`: + +- **If the table has a foreign key to `users`**: update `deleteUser()` in `src/lib/server/auth.ts` to delete from the new table before the user row is removed. Order matters — delete child rows before parent rows. +- **If the table has a foreign key to `notes`**: either add `onDelete: 'cascade'` in the schema definition, or add explicit cleanup in the note deletion logic. + ## Testing philosophy: BDD/TDD Write tests first or alongside features. Tests serve as living documentation of expected behavior. diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts index ff48340..9afb1bd 100644 --- a/src/lib/server/auth.ts +++ b/src/lib/server/auth.ts @@ -228,6 +228,12 @@ export function getUser(userId: number): User | null { export async function deleteUser(userId: number): Promise { // Cascade: delete user's data in dependency order + sqlite.prepare('DELETE FROM user_preferences WHERE user_id = ?').run(userId); + sqlite.prepare('DELETE FROM api_keys WHERE user_id = ?').run(userId); + sqlite.prepare('DELETE FROM note_user_state WHERE user_id = ?').run(userId); + sqlite + .prepare('DELETE FROM note_collaborators WHERE user_id = ? OR added_by = ?') + .run(userId, userId); sqlite.prepare('DELETE FROM sync_log WHERE user_id = ?').run(userId); sqlite.prepare('DELETE FROM attachments WHERE user_id = ?').run(userId); sqlite