Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 43 additions & 54 deletions backend/Input_validators/ValidateResume.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
const { z } = require("zod");
const mongoose = require("mongoose");
const { handleValidationError } = require('./ValidateQuestions')
const { handleValidationError } = require("./ValidateQuestions");

const objectId = (label) =>
z
.string()
.min(1, `${label} is required`)
.refine((v) => mongoose.isValidObjectId(v), "Invalid ObjectId format");
// ==========================================
// Schemas
// ==========================================

// Schema for compileResume request
const compileResumeSchema = z.object({
code: z.string().min(1, "LaTeX code is required"),
code: z
.string({
required_error: "LaTeX code is required",
invalid_type_error: "LaTeX code must be a string",
})
Comment on lines +10 to +13

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟑 Minor | ⚑ Quick win

🧩 Analysis chain

🌐 Web query:

Zod 4 migration guide required_error invalid_type_error unified error parameter

πŸ’‘ Result:

In Zod 4, error customization has been standardized under a single, unified error parameter, replacing the previously fragmented API [1][2]. Key migration points: 1. Unified Error Parameter: The legacy message parameter (often used for simple string overrides) has been deprecated in favor of the error parameter [1][2]. This new parameter accepts an error map function, allowing for consistent error handling across the library [3][4]. 2. Deprecation of Fragmented APIs: Previous approaches to customizing errorsβ€”such as passing separate error messages or using inconsistent configuration objectsβ€”have been cleaned up to improve cohesion [1][2]. 3. Error Maps: Error customization is now centrally managed through error maps. These functions receive an issue object (iss), which is a discriminated union of all possible issue types, allowing you to handle specific codes like invalid_type or too_small precisely [3][4]. 4. Migration Assistance: An unofficial community-maintained codemod (zod-v3-to-v4) is available to automate many of these breaking changes [1]. Official documentation suggests reading the Zod 4 migration guide thoroughly as it lists changes in order of impact [1][2]. To upgrade to Zod 4, install the latest version: npm install zod@^4.0.0 [5][6] For detailed customization examples, including per-parse and global configurations using the unified error approach, refer to the Zod 4 error customization documentation [3][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- candidate files ---'
git ls-files | grep -E '(^|/)(ValidateResume\.js|package\.json|package-lock\.json|yarn\.lock|pnpm-lock\.yaml)$' || true

printf '%s\n' '--- validator source ---'
file=$(git ls-files | grep 'backend/Input_validators/ValidateResume\.js$' | head -n 1)
if [ -n "${file:-}" ]; then
  cat -n "$file"
fi

printf '%s\n' '--- Zod dependency declarations ---'
while IFS= read -r f; do
  case "$f" in
    *package.json|*package-lock.json|*yarn.lock|*pnpm-lock.yaml)
      grep -nE '"zod"|(^|[[:space:]])zod([@[:space:]:]|$)' "$f" || true
      ;;
  esac
done < <(git ls-files | grep -E '(^|/)(package\.json|package-lock\.json|yarn\.lock|pnpm-lock\.yaml)$')

printf '%s\n' '--- validator usages ---'
rg -n --glob '!node_modules' 'ValidateResume|resumeSchema|latexCode|title: z\.string' backend . || true

Repository: Canopus-Labs/PrepPilot

Length of output: 3460


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import json
from pathlib import Path

for name in ["package.json", "backend/package.json", "frontend/package.json"]:
    p = Path(name)
    if not p.exists():
        continue
    data = json.loads(p.read_text())
    deps = {}
    deps.update(data.get("dependencies", {}))
    deps.update(data.get("devDependencies", {}))
    print(f"{name}: zod declaration = {deps.get('zod', '<absent>')}")

for name in ["package-lock.json", "backend/package-lock.json", "frontend/package-lock.json"]:
    p = Path(name)
    if not p.exists():
        continue
    data = json.loads(p.read_text())
    versions = set()
    packages = data.get("packages", {})
    for key, value in packages.items():
        if key.endswith("/node_modules/zod") or key == "node_modules/zod":
            if "version" in value:
                versions.add(value["version"])
    if not versions:
        root = data.get("dependencies", {}).get("zod", {})
        if root.get("version"):
            versions.add(root["version"])
    print(f"{name}: locked zod versions = {sorted(versions) or '<absent>'}")
PY

printf '%s\n' '--- all Zod declarations/usages ---'
rg -n --glob '!node_modules' --glob '*package*.json' --glob '*lock*' '"zod"|node_modules/zod' . || true

Repository: Canopus-Labs/PrepPilot

Length of output: 662


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- validation error handling ---'
file=$(git ls-files | grep 'backend/Input_validators/ValidateQuestions\.js$' | head -n 1)
if [ -n "${file:-}" ]; then
  cat -n "$file"
fi

printf '%s\n' '--- validation message consumers and tests ---'
rg -n --glob '!node_modules' 'LaTeX code is required|LaTeX code must be a string|Title is required|Title must be a string|required_error|invalid_type_error|validateCompileResume|validateSaveResume|handleValidationError' backend . || true

printf '%s\n' '--- Zod lockfile package metadata ---'
python3 - <<'PY'
import json
from pathlib import Path
p = Path("backend/package-lock.json")
data = json.loads(p.read_text())
for key, value in data.get("packages", {}).items():
    if key.endswith("/node_modules/zod"):
        print(key, value)
PY

Repository: Canopus-Labs/PrepPilot

Length of output: 16477


🌐 Web query:

site:zod.dev/v4/changelog required_error invalid_type_error removed Zod 4

πŸ’‘ Result:

In Zod 4, the previously used invalid_type_error and required_error parameters have been removed to standardize error customization [1]. These parameters were removed because they were inconsistent, conflicted with errorMap usage, and did not align with Zod's internal issue codes (as there is no native 'required' issue code) [1]. To replace this functionality, Zod 4 introduces a unified error parameter that accepts a function [1]. This function receives the ZodIssue object and allows for logic-based error message customization [1]. For example, to replicate the behavior of a required field error: z.string({ error: (issue) => issue.input === undefined? "This field is required": "Not a string" }); By returning undefined from this function, you can also signal Zod to fall back to the next error map in the chain [1].

Citations:


Replace the removed Zod 4 error options.

Use error customization for code, title, and latexCode. Zod 4 removed required_error and invalid_type_error, so these fields currently use default messages for missing and non-string inputs.

πŸ“ Affects 1 file
  • backend/Input_validators/ValidateResume.js#L10-L13 (this comment)
  • backend/Input_validators/ValidateResume.js#L27-L34

.min(1, "LaTeX code is required"),
});

// Schema for analyzeResume request
const analyzeResumeSchema = z.object({
targetRole: z
.string()
Expand All @@ -23,61 +23,50 @@ const analyzeResumeSchema = z.object({
.optional(),
});

// Schema for saveResume request
const saveResumeSchema = z.object({
title: z.string().min(1, "Title is required"),
latexCode: z.string().min(1, "LaTeX code is required"),
resumeId: z
.string()
.optional()
.refine((v) => !v || mongoose.isValidObjectId(v), "Invalid ObjectId format"),
});

// Schema for deleteResume request (params)
const deleteResumeSchema = z.object({
id: objectId("Resume ID"),
title: z.string({
required_error: "Title is required",
invalid_type_error: "Title must be a string",
}).min(1, "Title is required"),
latexCode: z.string({
required_error: "LaTeX code is required",
invalid_type_error: "LaTeX code must be a string",
}).min(1, "LaTeX code is required"),
resumeId: z.string().optional(),
});

// ==========================================
// Middleware Functions
// ==========================================

// Middleware for compileResume
const validateCompileResume = (req, res, next) => {
try {
compileResumeSchema.parse(req.body);
next();
} catch (error) {
return handleValidationError(res, error);
// Generic schema validator runner using Zod's safeParse
const validate = (schema) => (req, res, next) => {
const result = schema.safeParse(req.body || {});
if (!result.success) {
return handleValidationError(res, result.error);
}
next();
};

// Middleware for analyzeResume
const validateAnalyzeResume = async (req, res, next) => {
try {
analyzeResumeSchema.parse(req.body);
// also ensure file is uploaded
if (!req.file) {
return res.status(400).json({ success: false, message: "No resume file uploaded" });
}
next();
} catch (error) {
if (req.file && req.file.path) {
const safePath = require('path').join(require('os').tmpdir(), require('path').basename(req.file.path));
await require('fs').promises.unlink(safePath).catch((err) => {
if (err.code !== 'ENOENT') console.error('Cleanup error:', err);
});
}
return handleValidationError(res, error);
// Middleware for compileResume
const validateCompileResume = validate(compileResumeSchema);

// Middleware for analyzeResume (includes file check)
const validateAnalyzeResume = (req, res, next) => {
const result = analyzeResumeSchema.safeParse(req.body || {});
if (!result.success) {
return handleValidationError(res, result.error);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if (!req.file) {
return res
.status(400)
.json({ success: false, message: "No resume file uploaded" });
}
next();
};

// Middleware for saveResume
const validateSaveResume = (req, res, next) => {
try {
saveResumeSchema.parse(req.body);
next();
} catch (error) {
return handleValidationError(res, error);
}
};
const validateSaveResume = validate(saveResumeSchema);

// Middleware for deleteResume (params)
const validateDeleteResume = (req, res, next) => {
Expand Down
Loading