Skip to content

feat: add FormDefinition validation to update controller and export Z… - #78

Merged
Basharkhan7776 merged 2 commits into
Openlabsops:mainfrom
yashraj639:feature/edit-id-apis
Jun 30, 2026
Merged

Basharkhan7776 merged 2 commits into
Openlabsops:mainfrom
yashraj639:feature/edit-id-apis

Conversation

@yashraj639

@yashraj639 yashraj639 commented Jun 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Implements the [Block] Edit/[id] APIs by refining existing endpoints and adding explicit defensive validation.

Changes Made

  • Verified GET /api/v1/forms/:id handles drafts correctly (returns form data by userId regardless of published state).
  • Verified PATCH /api/v1/forms/:id properly accepts updates to the Form.definition JSON.
  • Exported formatZodErrors helper from validation middleware for reuse.
  • Added explicit FormDefinitionSchema.safeParse() validation inside the updateForm controller as defense-in-depth before touching the database.
  • Fixed a TOCTOU race condition in updateForm by properly trapping the Prisma P2025 error if the form is deleted between the ownership check and the update.

Testing

  • bun turbo lint passes (0 errors, 0 warnings).
  • Manual validation completed.
  • No regressions introduced.

Related Issues

Checklist

  • Code follows project conventions
  • Tests pass
  • Documentation updated
  • No linting errors
  • Form editing now supports loading the draft form data for a user even when the form has already been published.
  • Updating a form now accepts changes to the saved form layout/definition, helping editors refine drafts safely.
  • Form updates are now validated before saving, so invalid form definitions are rejected early with clear feedback.
  • The update flow also handles forms being removed during edit, reducing the chance of confusing edit failures.
  • Validation error formatting is now reusable across the API, which should make future form-related validation more consistent.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yashraj639, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 18 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cd612373-fe12-4c80-a8c1-a68b0011f4f7

📥 Commits

Reviewing files that changed from the base of the PR and between e8a2acc and 3527e22.

📒 Files selected for processing (1)
  • apps/api/src/controllers/form.controller.ts
📝 Walkthrough

Walkthrough

formatZodErrors is exported from validate.ts and imported into form.controller.ts. The updateForm handler now validates the definition payload via FormDefinitionSchema.safeParse, returning HTTP 400 with formatted Zod errors on failure. Prisma error handling is updated to explicitly return 409 for duplicate slug (P2002) and 404 for missing record (P2025).

updateForm Validation and Error Handling

Layer / File(s) Summary
Export formatZodErrors + import
apps/api/src/middleware/validate.ts, apps/api/src/controllers/form.controller.ts
formatZodErrors gains the export keyword in validate.ts and is imported into the form controller.
definition validation and Prisma error mapping
apps/api/src/controllers/form.controller.ts
updateForm runs FormDefinitionSchema.safeParse(definition) before the Prisma update, returning 400 on failure; catch block maps P2002 → 409 and P2025 → 404.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • Openlabsops/Snap-form#62: Modifies the same updateForm path in form.controller.ts around definition handling and Prisma error behavior.

Suggested reviewers

  • Basharkhan7776

🐇 A schema check here, a 400 there,
Zod errors formatted with flair!
P2002 says "slug's taken, friend,"
P2025 brings a 404 end.
The form stays safe, hip-hip-hooray! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR covers update validation and Prisma error handling, but it doesn't show the required GET draft fetch or PATCH definition-saving work from #44. Implement the missing edit/[id] API behavior, including GET draft data retrieval and PATCH persistence of Form.definition, then revalidate against #44.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change by highlighting FormDefinition validation in the update controller and the exported Zod error helper.
Out of Scope Changes check ✅ Passed The changes stay within the edit form flow: validation, error mapping, and helper export, with no clearly unrelated edits.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/api/src/controllers/form.controller.ts (1)

178-201: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Persist the parsed result, not the raw definition.

FormDefinitionSchema.safeParse(definition) normalizes the payload (notably version via .default("1.0")), but parsed.data is discarded and the raw definition is written to fields on Line 201. As a result, Zod-applied defaults are never persisted — this is the same reason the validate middleware reassigns req.body = result.data. A client omitting version would store an un-versioned definition, defeating the schema-versioning intent.

🛠️ Proposed fix to persist normalized data
     if (definition !== undefined) {
       const parsed = FormDefinitionSchema.safeParse(definition);
       if (!parsed.success) {
         res.status(400).json({
           success: false,
           message: "Validation failed",
           errors: formatZodErrors(parsed.error),
         });
         return;
       }
+      // use the normalized value so defaults (e.g. version) are persisted
+      definition = parsed.data;
     }

Note: this requires definition to be mutable (e.g. destructure into a let).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/controllers/form.controller.ts` around lines 178 - 201, Persist
the normalized schema result from FormDefinitionSchema.safeParse in
form.controller's update flow instead of writing the raw definition object to
prisma.form.update. After parsing definition, use parsed.data for the fields
assignment so Zod defaults like version are preserved, and make definition
mutable if needed by the existing destructuring in the controller before
building the update payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/api/src/controllers/form.controller.ts`:
- Around line 178-201: Persist the normalized schema result from
FormDefinitionSchema.safeParse in form.controller's update flow instead of
writing the raw definition object to prisma.form.update. After parsing
definition, use parsed.data for the fields assignment so Zod defaults like
version are preserved, and make definition mutable if needed by the existing
destructuring in the controller before building the update payload.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9f6e9b24-353e-4324-9692-902f0862c276

📥 Commits

Reviewing files that changed from the base of the PR and between 2c2e5cd and e8a2acc.

📒 Files selected for processing (2)
  • apps/api/src/controllers/form.controller.ts
  • apps/api/src/middleware/validate.ts
📜 Review details
🔇 Additional comments (2)
apps/api/src/middleware/validate.ts (1)

39-45: LGTM!

apps/api/src/controllers/form.controller.ts (1)

221-232: LGTM!

@Basharkhan7776 Basharkhan7776 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just added controler, merging

@Basharkhan7776
Basharkhan7776 merged commit 91871fa into Openlabsops:main Jun 30, 2026
3 checks passed
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.

[Block] Edit/[id] APIs

2 participants