Skip to content

feat: add centralized validate() middleware with 422 structured errors#139

Open
Imole203 wants to merge 1 commit into
Pidoko257:mainfrom
Imole203:feat/centralized-validation-middleware
Open

feat: add centralized validate() middleware with 422 structured errors#139
Imole203 wants to merge 1 commit into
Pidoko257:mainfrom
Imole203:feat/centralized-validation-middleware

Conversation

@Imole203

Copy link
Copy Markdown

feat: centralized validate() middleware with 422 structured errors

Summary

Replaces scattered ad-hoc validation across route handlers with a single validate() middleware
factory powered by Zod. All validation failures now return a consistent HTTP 422 response with
field-level error details.

Changes

New middleware (src/middleware/validation.ts)

  • validate(schema) accepts either a plain ZodSchema (validates req.body) or a { body?, query?,
    params? } shape object to validate any combination of request sources
  • Returns 422 Unprocessable Entity with { errors: [{ field, message }] } on failure
  • Calls next() and writes parsed/coerced values back to req.body, req.query, req.params on
    success
  • Legacy validateRequest, validateQuery, validateParams kept as deprecated wrappers for
    backward compatibility

New schemas (src/middleware/schemas/)

  • Domain-scoped Zod schemas for: auth, transactions, contacts, users, vaults, disputes,
    subscriptions, merchants, webhooks
  • Barrel export via index.ts for clean imports

Migrated routes

  • auth — register and verify endpoints
  • transactions — list (pagination query), notes, metadata, search endpoints
  • contacts — create, get, update, delete (inline schemas removed)
  • users — display name update (inline safeParse removed)
  • vaults — create, update, delete, transfer, get by ID
  • merchants — create merchant (missing-fields check replaced)
  • subscriptions — create, update, get, delete, pause, resume (inline schemas removed)

Before / After

// Before — ad-hoc, 400, no standard shape
const parsed = schema.safeParse(req.body);
if (!parsed.success) return res.status(400).json({ error: "Validation failed", details:
parsed.error.issues });

// After — centralized, 422, consistent shape
router.post("/", validate({ body: CreateContactBodySchema }), handler);
// → 422 { errors: [{ field: "body.nickname", message: "nickname is required" }] }

Testing

The pre-commit hook flagged two pre-existing environment failures unrelated to this PR (spdy
missing http_parser, sharp not installed for linux-x64) and merchant route tests that fail
because they don't mock authenticateToken. No regressions introduced.
closes #4

- Rewrite src/middleware/validation.ts with validate() factory that
  accepts a plain ZodSchema (body-only) or a {body,query,params} shape
- Return HTTP 422 with [{field, message}] array on validation failure
- Keep legacy validateRequest/validateQuery/validateParams as deprecated
  wrappers for backward compatibility
- Add src/middleware/schemas/ with domain schemas for auth, transactions,
  contacts, users, vaults, disputes, subscriptions, merchants, webhooks
- Migrate auth, transactions, contacts, users, vaults, merchants,
  subscriptions routes to use validate()
@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@Imole203 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

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.

Add Input Validation Middleware Using Zod

1 participant