Skip to content

Conversation

@jasonpetro
Copy link
Collaborator

@jasonpetro jasonpetro commented Dec 6, 2025

Overview: This PR enhances the project deletion logic to handle cases where related records might be missing and wraps the deletion in a safe transaction.

Changes

  • Updated src/actions/projects/deleteProject/logic.ts to gracefully handle scenarios where dependent records (e.g., members, analytics) might not exist.
  • Implemented a database transaction wrapper to ensure atomicity for project and related data deletion.
  • Ensured changes are localized within logic.ts and remain easily testable.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project deletion reliability: related project members are now removed automatically when a project is deleted.
    • Deletion operations include enhanced error handling and logging so failures return clearer error feedback for troubleshooting.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 6, 2025

Walkthrough

Replaces a direct project delete with a try/catch-wrapped deleteMany call in the action logic and adds error handling/logging; updates Prisma schema to set onDelete: Cascade on the ProjectMember.project relation.

Changes

Cohort / File(s) Change Summary
Project deletion logic
src/actions/projects/deleteProject/logic.ts
Replaced direct delete with deleteMany inside a try/catch; added error logging and returns an error result on failure; imports updated to include result helpers.
Prisma schema relation update
prisma/schema.prisma
Added onDelete: Cascade to ProjectMember.project relation so deleting a Project cascades to its ProjectMember records.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify deleteMany filter targets only the intended project record and that transaction semantics (if used) are correct.
  • Review logging and returned error to avoid leaking internal details.
  • Confirm Prisma migration implications and that cascade behavior matches intended data lifecycle (ensure no unintended deletions).
  • Run/inspect related tests or add tests covering deletion + cascading.

Possibly related PRs

Suggested reviewers

  • fehranbit
  • Stereco-btc

Poem

🐇 In code I nibble bugs away, with gentle hops and care,
A catch to guard the garden path and cascades pruning fair.
Projects fall in order, tidy, not askew—
I thump a drum of tests and log, then hop to something new.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: improving robustness of project deletion through error handling and cascading deletes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/safe-project-deletion

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/actions/projects/deleteProject/logic.ts (2)

10-12: Consider verifying that the project was actually deleted.

Using deleteMany instead of delete won't throw an error if the project doesn't exist—it will return {count: 0}. While this provides idempotency (safe to retry), it also means the function returns success(undefined) even when no project was deleted, potentially masking bugs where invalid IDs are passed.

Consider checking the deletion count:

-    await prisma.$transaction(async (tx) => {
-      await tx.project.deleteMany({
-        where: { id: input.id }
-      });
-    });
+    const result = await prisma.project.deleteMany({
+      where: { id: input.id }
+    });
+    
+    if (result.count === 0) {
+      return err("Project not found.", ErrorCodes.NOT_FOUND);
+    }
+    
     return success(undefined);

Note: This also removes the unnecessary transaction.


15-18: Consider providing more specific error information.

The generic error message and missing error code make it difficult for callers to handle different failure scenarios appropriately. For instance, foreign key constraint violations, permission errors, and network failures would all return the same message.

If distinguishing error types isn't needed here, you could at least pass an error code:

   } catch (error) {
     console.error("Failed to delete project:", error);
-    return err("Failed to delete project due to an unexpected error.");
+    return err("Failed to delete project due to an unexpected error.", ErrorCodes.UNKNOWN_ERROR);
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 348d04f and 0300246.

📒 Files selected for processing (1)
  • src/actions/projects/deleteProject/logic.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/actions/projects/deleteProject/logic.ts (3)
src/actions/projects/deleteProject/schema.ts (1)
  • DeleteProjectInput (7-7)
src/lib/result.ts (3)
  • Result (18-18)
  • success (25-30)
  • error (38-44)
src/lib/prisma.ts (1)
  • prisma (14-18)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0300246 and d428493.

📒 Files selected for processing (2)
  • prisma/schema.prisma (1 hunks)
  • src/actions/projects/deleteProject/logic.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/actions/projects/deleteProject/logic.ts (3)
src/actions/projects/deleteProject/schema.ts (1)
  • DeleteProjectInput (7-7)
src/lib/result.ts (3)
  • Result (18-18)
  • success (25-30)
  • error (38-44)
src/lib/prisma.ts (1)
  • prisma (14-18)
🔇 Additional comments (2)
src/actions/projects/deleteProject/logic.ts (2)

4-4: Import addition looks good.

The addition of err to the imports is correct and necessary for the error handling below.


8-16: Error handling is solid, but PR description claims transaction that isn't present.

The try/catch pattern with error logging is appropriate. Using deleteMany instead of delete is unusual for a single record but acceptable—it won't throw if the project doesn't exist, which aligns with the PR's goal of graceful handling.

However, the PR objectives state: "deletion of a project and its related data is wrapped in a database transaction to ensure atomicity." No transaction wrapper is present in this code. A single deleteMany operation is already atomic, so a transaction isn't technically needed here, but the PR description should be updated to reflect the actual implementation.

With the schema change adding onDelete: Cascade, related ProjectMember records will be automatically deleted by the database when a project is deleted, which is the correct approach.

Minor: Consider whether deleteMany vs delete is intentional.

If the goal is to fail when the project doesn't exist (stricter validation), use delete. If the goal is to succeed silently when the project is already gone (idempotent deletion), deleteMany is appropriate. The current choice seems intentional for robustness.

userId String
role Role @default(USER)
project Project @relation(fields: [projectId], references: [id])
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, check the actual schema.prisma file at line 61 to confirm the change
sed -n '55,65p' prisma/schema.prisma

Repository: Authormaton/authormaton

Length of output: 396


🏁 Script executed:

# Check if prisma/migrations directory exists and list recent migrations
fd -type d -name migrations prisma/ && fd -e sql . prisma/migrations 2>/dev/null | tail -10 || echo "No migrations found"

Repository: Authormaton/authormaton

Length of output: 274


🏁 Script executed:

# Search for any migration containing CASCADE delete
fd -e sql . prisma/migrations 2>/dev/null -x grep -l "ON DELETE CASCADE" {} \; || echo "No migrations with CASCADE found"

Repository: Authormaton/authormaton

Length of output: 99


Migration file is missing for the cascade delete schema change.

The onDelete: Cascade configuration has been added to the ProjectMember.project relation in the schema, but no corresponding Prisma migration file exists in prisma/migrations/. Without generating and applying the migration, the database schema remains unchanged and will not enforce cascade deletes. This means deleting a project will still cause foreign key constraint violations at the database level.

Run prisma migrate dev --name add_cascade_delete_projectmember to generate the migration, then commit both the schema and migration files.

🤖 Prompt for AI Agents
In prisma/schema.prisma around line 61, you added onDelete: Cascade to the
ProjectMember.project relation but did not create/apply the corresponding Prisma
migration; run prisma migrate dev --name add_cascade_delete_projectmember from
the project root to generate and apply the migration, then commit the updated
prisma/schema.prisma plus the new timestamped folder under prisma/migrations
(include migration SQL and schema file) to ensure the DB enforces cascade
deletes.

@fehranbit
Copy link
Member

removing the dependency checks in deletion logic simplifies the process nicely; approved.

@fehranbit fehranbit merged commit b88ddd1 into main Dec 6, 2025
1 of 2 checks passed
@fehranbit fehranbit deleted the fix/safe-project-deletion branch December 6, 2025 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants