Conversation
- Implemented a checks workflow to run linting, type-checking, tests, and build on pull requests and main branch pushes. - Created a deploy workflow to automate deployment to Vercel on pushes to the main branch. - Added VSCode settings for GitHub Actions schema validation. - Introduced a CONTRIBUTING.md file with guidelines for contributing to the project. - Consolidated project documentation into a single README.md for easier access. - Added new logo assets for branding.
…turtle into working-branch
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR encompasses documentation updates, workspace configuration, widespread type safety enhancements, refactoring of dashboard and profile components to use server components with Suspense, new authentication middleware, and creation of shared form management utilities and validation helpers. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In @.github/workflows/checks.yml:
- Around line 21-23: Remove the unused id-token permission from the workflow
permissions block: delete the line "id-token: write" under the permissions
mapping (the "permissions" block with "contents: read"), leaving only the
required scopes to follow least-privilege; if OIDC is needed later, re-add
"id-token: write" with a comment explaining its purpose.
In `@CONTRIBUTING.md`:
- Around line 49-50: Update the "Reporting Security Issues" section to
explicitly discourage opening public issues for vulnerabilities: replace the
current line under the "Reporting Security Issues" header with wording that
instructs reporters not to open public issues, and instead to use private
channels such as GitHub Security Advisories or direct contact to the maintainer;
reference the "Reporting Security Issues" header to locate the text and ensure
the new text clearly states "do not open public issues" and provides the
preferred private reporting options.
In `@docs/README.md`:
- Around line 43-51: Update the fenced code block in docs/README.md that shows
the project tree to specify a language (e.g., "text") after the opening
backticks; locate the block containing "src/" and the directory lines and change
the opening fence from ``` to ```text so the linter rule MD040 is satisfied.
In `@README.md`:
- Around line 177-179: Update the contributors image tag to include meaningful
alt text for accessibility (MD045); locate the HTML anchor/img snippet
containing <img src="https://contrib.rocks/image?repo=Ansh-dhanani/codeturtle"
/> and add an alt attribute such as alt="Contributors to
Ansh-dhanani/codeturtle" (or similar descriptive text) so the <img> element has
accessible alternative text.
🧹 Nitpick comments (1)
.github/workflows/deploy.yml (1)
28-62: Remove error masking in Vercel CLI install and pin tool versions.Using
latestfor Bun and|| truewhen installing Vercel CLI makes deployments nondeterministic and hides install failures. Remove the error suppression to fail fast on install errors. Since no toolchain files (.bun-version,.node-version,.tool-versions) exist in the repository, pin versions directly in the workflow or create a toolchain file:Suggested fix (fail fast)
- npm install -g vercel@latest || true + npm install -g vercel@latest- bun-version: 'latest' + bun-version: '1.x' # or pin to specific version
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
README.md (1)
115-117: Misleading description fordb:seedscript.Line 116 describes
db:seedas "Clear all data" but seeding typically means populating data. The comment in parentheses also seems incomplete or misplaced. Consider clarifying:✏️ Suggested fix
- `bun run db:clear` - Clear all data from database -- `bun run db:seed` - Clear all data (users are created automatically via GitHub OAuth on first login) +- `bun run db:seed` - Seed database with initial data (users are created automatically via GitHub OAuth on first login) - `bun run db:reset` - Clear database (runs db:clear and db:seed)
🤖 Fix all issues with AI agents
In @.github/workflows/deploy.yml:
- Line 62: Replace the deprecated --confirm flag in the Vercel deploy command
with --yes: locate the npx vercel invocation (the line containing npx vercel
--prod --token "$VERCEL_TOKEN" --confirm) and change the flag to --yes so the
command becomes npx vercel --prod --token "$VERCEL_TOKEN" --yes.
- Around line 29-31: The workflow pins Bun to an outdated version; update the
bun-version value in the GitHub Actions step using uses: oven-sh/setup-bun@v1
(the block containing bun-version) to a recent stable release instead of '1.0.0'
— e.g., set bun-version to '1.3.6' (or a tight range like '>=1.3.6 <1.4.0') to
retain determinism while using a current stable Bun.
In `@docs/README.md`:
- Line 76: Remove the conversational placeholder sentence "If you'd like, I can
add a small sidebar or split docs later, but this keeps everything in one place
for now." from README.md and replace it with a concise, professional closing or
summary line (e.g., a brief next-steps sentence or an invitation to contribute)
so the documentation reads like final content rather than AI-generated chat.
In `@README.md`:
- Line 13: The README heading <h1> currently says "Turtie AI" which conflicts
with the rest of the repo (e.g., "CodeTurtle" usage and logo alt text); update
the heading text to the canonical product name used across the project (replace
"Turtie AI" with "CodeTurtle" or vice versa to match logo/repo), and ensure any
related occurrences in README (title, intro, alt text) are made consistent with
the chosen name.
.github/workflows/deploy.yml
Outdated
| uses: oven-sh/setup-bun@v1 | ||
| with: | ||
| bun-version: '1.0.0' |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
latest stable version of Bun runtime 2025 2026
💡 Result:
As of January 23, 2026, the latest stable Bun runtime release is v1.3.6 (released January 13, 2026). [1][2]
Update Bun version to a recent stable release.
Version 1.0.0 (October 2023) is significantly outdated; the current stable version is 1.3.6 (January 2026). Rather than using latest in CI/CD (which creates non-determinism), pin to a recent stable version or use a version range.
♻️ Suggested fix
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
- bun-version: '1.0.0'
+ bun-version: '1.3'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| uses: oven-sh/setup-bun@v1 | |
| with: | |
| bun-version: '1.0.0' | |
| uses: oven-sh/setup-bun@v1 | |
| with: | |
| bun-version: '1.3' |
🤖 Prompt for AI Agents
In @.github/workflows/deploy.yml around lines 29 - 31, The workflow pins Bun to
an outdated version; update the bun-version value in the GitHub Actions step
using uses: oven-sh/setup-bun@v1 (the block containing bun-version) to a recent
stable release instead of '1.0.0' — e.g., set bun-version to '1.3.6' (or a tight
range like '>=1.3.6 <1.4.0') to retain determinism while using a current stable
Bun.
.github/workflows/deploy.yml
Outdated
| echo "Installing Vercel CLI..." | ||
| npm install -g vercel@latest | ||
| echo "Deploying to Vercel..." | ||
| npx vercel --prod --token "$VERCEL_TOKEN" --confirm |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Vercel CLI --confirm flag deprecated --yes flag
💡 Result:
Vercel CLI’s --confirm flag was deprecated in v27.4.0 in favor of --yes, which is now the recommended way to skip interactive prompts across the CLI. [1]
So, replace:
vercel ... --confirm
with:
vercel ... --yes(for example:vercel dev --yes) [1][2]
Sources: [1][2]
Replace deprecated --confirm flag with --yes.
The --confirm flag is deprecated in Vercel CLI (since v27.4.0). Use --yes instead.
♻️ Suggested fix
- npx vercel --prod --token "$VERCEL_TOKEN" --confirm
+ npx vercel --prod --token "$VERCEL_TOKEN" --yes🤖 Prompt for AI Agents
In @.github/workflows/deploy.yml at line 62, Replace the deprecated --confirm
flag in the Vercel deploy command with --yes: locate the npx vercel invocation
(the line containing npx vercel --prod --token "$VERCEL_TOKEN" --confirm) and
change the flag to --yes so the command becomes npx vercel --prod --token
"$VERCEL_TOKEN" --yes.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/components/pages/profile-form.tsx`:
- Line 2: The component initializes name via useState(data?.name || '') which
only runs on first render so when the profile query resolves the input stays
blank; update the ProfileForm component to run a useEffect that watches
data?.name (or data) and calls setName(data.name ?? '') when it changes, and
change the initial useState to useState('') (or keep data?.name fallback but
still sync in useEffect) so the input always reflects the loaded profile;
reference the useState for name, the setName setter, and add a useEffect
import/useEffect hook in profile-form.tsx.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/module/dashboard/actions/index.ts (1)
145-147: Outdated JSDoc: function no longer returns null.The JSDoc states "Returns null if an error occurs" but the catch block (lines 240-258) now returns a default data array, not null.
Proposed fix
* `@returns` A promise that resolves to an array of objects, each containing the month name - * (e.g., "Jan 2023"), and the counts for commits, PRs, and reviews. Returns null if an error occurs. + * (e.g., "Jan 2023"), and the counts for commits, PRs, and reviews. Returns default empty data during prerendering or on error. - * `@throws` {Error} If the user is unauthorized or no GitHub token is found.
🤖 Fix all issues with AI agents
In `@src/app/`(dashboard)/dashboard/page.tsx:
- Around line 121-133: MonthlyActivitySkeleton renders a Card but
MonthlyActivity currently returns MonthlyActivityChart directly, causing a
layout jump; make the two consistent by wrapping MonthlyActivity's output in the
same Card structure as the skeleton (i.e., update the MonthlyActivity function
to return a Card containing a CardHeader/optional header and CardContent that
renders MonthlyActivityChart), or alternatively remove the Card wrapper from
MonthlyActivitySkeleton—use the MonthlyActivity and MonthlyActivitySkeleton
function names and the MonthlyActivityChart component to locate the spots to
change and ensure both render the same outer container.
🧹 Nitpick comments (11)
src/app/api/user/github-account/route.ts (1)
24-29: Suppressing all errors loses valuable debugging context.While the comment mentions "expected PPR behavior," catching and discarding all errors—including unexpected ones like database connection failures—makes production debugging difficult. Consider logging unexpected errors while handling the expected PPR case specifically, or at minimum use a structured approach:
♻️ Suggested improvement
- } catch { - // Suppress logging for expected PPR behavior + } catch (error) { + // Only suppress logging for expected PPR/prerender errors + if (!(error instanceof Error && error.message.includes('Dynamic server usage'))) { + console.error("Error checking GitHub account:", error); + } return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); }src/middleware.ts (2)
31-33: Consider preserving the return URL for post-login redirect.When redirecting unauthenticated users, capturing the original URL allows redirecting back after successful login, improving UX.
♻️ Optional enhancement
if (!session) { - return NextResponse.redirect(new URL('/login', request.url)) + const loginUrl = new URL('/login', request.url) + loginUrl.searchParams.set('callbackUrl', pathname) + return NextResponse.redirect(loginUrl) }
21-23: Route matching uses prefix matching—verify no unintended matches.Using
startsWithmeans/dashboardwould also match/dashboardXYZ. While this is likely fine if no such routes exist, an exact match or trailing slash check is more precise.♻️ More precise matching
const isProtectedRoute = protectedRoutes.some(route => - pathname.startsWith(route) + pathname === route || pathname.startsWith(`${route}/`) )src/app/(dashboard)/settings/page.tsx (1)
11-52: Consider adding error handling for the async component.If the database query fails, the error will propagate and potentially break the page. Consider wrapping with an error boundary or adding try-catch:
♻️ Add error handling
async function GithubStatus() { - const session = await auth.api.getSession({ headers: await headers() }); - let githubConnected = false; - if (session) { - const account = await prisma.account.findFirst({ - where: { - userId: session.user.id, - providerId: "github", - }, - }); - githubConnected = !!account; + try { + const session = await auth.api.getSession({ headers: await headers() }); + let githubConnected = false; + if (session) { + const account = await prisma.account.findFirst({ + where: { + userId: session.user.id, + providerId: "github", + }, + }); + githubConnected = !!account; + } + // ... rest of return statement + } catch { + // Fallback to showing not connected state on error + return ( + <Card> + {/* ... fallback UI ... */} + </Card> + ); }Alternatively, wrap the
<GithubStatus />component with an Error Boundary at the call site.src/app/(dashboard)/repositories/page.tsx (1)
24-39: Export types from the actions module and import them in the repositories page to avoid duplication.The
GithubRepositoryandRepositorytypes are duplicated in bothsrc/module/repository/actions/index.tsandsrc/app/(dashboard)/repositories/page.tsx. Currently, the types in the actions module are not exported. Export them fromsrc/module/repository/actions/index.tsand import them insrc/app/(dashboard)/repositories/page.tsxto maintain a single source of truth and prevent type drift.src/app/(dashboard)/dashboard/page.tsx (1)
83-100: Contribution data fetched but not displayed.The component fetches
contributionData.contributionsarray but only renderstotalContributionsand a static color legend. The actual contribution grid/heatmap visualization is missing, making the API call partially wasteful.Consider either:
- Rendering the contribution grid using the
contributionsarray- Or simplifying the fetch to only retrieve
totalContributionsif the grid isn't needed yetWould you like me to help implement the contribution grid visualization, or should this be tracked as a follow-up task?
src/module/dashboard/actions/index.ts (5)
40-46: Unreachable code:getGithubToken()throws on failure, never returns null.Looking at
getGithubTokeninsrc/module/github/github.ts, it throws errors for unauthorized, unlinked account, or null token cases—it never returns a falsy value. Thisif (!token)block is unreachable; errors will be caught by the outercatchinstead.Proposed cleanup
const token = await getGithubToken(); - if (!token) { - return { - contributions: [], - totalContributions: 0, - }; - } const { data: user } = await new Octokit({This is a minor cleanup—the current code works correctly due to the outer catch block.
92-100: Same unreachable code pattern.Similar to
getContributionGraph, thisif (!token)block is unreachable sincegetGithubToken()throws rather than returning null.
112-114: Minor: Trailing space in search query.The query string has a trailing space after
${user.login}. While likely harmless, it's cleaner to remove it.Proposed fix
const { data: prs } = await octokit.rest.search.issuesAndPullRequests({ - q: `is:pr author:${user.login} `, + q: `is:pr author:${user.login}`, });
150-158: Inconsistent error handling pattern across actions.
getContributionGraphandgetDashboardStatsreturn default values when session/token is missing (early return pattern), whilegetMonthlyActivitythrows errors that are then caught. Both approaches work, but the inconsistency can confuse maintainers.Consider aligning
getMonthlyActivitywith the other functions:Proposed fix for consistency
export async function getMonthlyActivity() { try { const session = await auth.api.getSession({ headers: await headers() }); if (!session) { - throw new Error("Unauthorized"); + // During prerendering, return default values + return getDefaultMonthlyData(); } const token = await getGithubToken(); - if (!token) { - throw new Error("No GitHub token found"); - }Where
getDefaultMonthlyData()extracts the default data generation logic from the catch block.
240-258: Consider extracting default data generation to reduce duplication.The catch block duplicates the month name array and 6-month iteration logic from lines 171-191. Extracting this to a helper function would improve maintainability.
Example helper extraction
function getDefaultMonthlyData() { const monthsNames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; const now = new Date(); const data = []; for (let i = 5; i >= 0; i--) { const date = new Date(now.getFullYear(), now.getMonth() - i, 1); data.push({ name: `${monthsNames[date.getMonth()]} ${date.getFullYear()}`, commits: 0, prs: 0, reviews: 0, }); } return data; }This helper could be reused in both the catch block and the initialization section.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.github/workflows/checks.yml:
- Around line 3-4: The workflow comment and job name in
.github/workflows/checks.yml claim it runs "type-check" and "tests" but no such
steps exist; either add concrete "Typecheck" and "Test" steps to the job
declared under jobs (the job referenced on line ~19) and ensure package.json
includes "typecheck" and "test" scripts, or update the top-of-file description
and the job name to accurately reflect the actual steps currently present (lint,
build, etc.); make the change inside .github/workflows/checks.yml by either
adding steps with names "Typecheck" and "Test" that run npm/yarn run typecheck
and test, or by editing the comment and the job name string to remove references
to type-check/tests.
🧹 Nitpick comments (2)
.github/workflows/checks.yml (2)
34-37: Consider pinning Bun version for reproducible builds.Using
bun-version: 'latest'could cause inconsistent behavior across workflow runs if Bun releases a breaking update. Consider pinning to a specific version.📌 Suggested fix
- name: Setup Bun uses: oven-sh/setup-bun@v1 with: - bun-version: 'latest' + bun-version: '1.2.4' # or your preferred stable version
23-24: Remove redundantstrategyblock.
fail-fastonly applies to matrix builds. Without a matrix, this block has no effect and can be removed.🧹 Suggested cleanup
permissions: contents: read - strategy: - fail-fast: true steps:
.github/workflows/checks.yml
Outdated
| # Runs lint, type-check, tests and build for pull requests and main branch pushes. | ||
| # This workflow is focused on verification (no deploys). |
There was a problem hiding this comment.
Workflow description and job name are misleading.
The comment on lines 3-4 and job name on line 19 claim this workflow runs "type-check" and "tests," but no such steps exist. This could mislead contributors into thinking type safety and tests are verified in CI.
Either add the missing steps or update the descriptions to reflect what actually runs.
🔧 Option 1: Update descriptions to match actual behavior
-# Runs lint, type-check, tests and build for pull requests and main branch pushes.
+# Runs lint and build for pull requests and main branch pushes.
# This workflow is focused on verification (no deploys). jobs:
checks:
- name: Checks (lint, typecheck, test, build)
+ name: Checks (lint, build)🔧 Option 2: Add missing typecheck and test steps
- name: Lint
run: bun run lint
+ - name: Type Check
+ run: bun run tsc --noEmit
+
+ - name: Test
+ run: bun run test
+
- id: build-step
name: Build
run: bun run buildNote: This requires adding typecheck and test scripts to package.json.
Also applies to: 19-19
🤖 Prompt for AI Agents
In @.github/workflows/checks.yml around lines 3 - 4, The workflow comment and
job name in .github/workflows/checks.yml claim it runs "type-check" and "tests"
but no such steps exist; either add concrete "Typecheck" and "Test" steps to the
job declared under jobs (the job referenced on line ~19) and ensure package.json
includes "typecheck" and "test" scripts, or update the top-of-file description
and the job name to accurately reflect the actual steps currently present (lint,
build, etc.); make the change inside .github/workflows/checks.yml by either
adding steps with names "Typecheck" and "Test" that run npm/yarn run typecheck
and test, or by editing the comment and the job name string to remove references
to type-check/tests.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@src/app/`(dashboard)/dashboard/page.tsx:
- Around line 82-86: The CardDescription text ("Your coding activity over the
last 12 months") is inaccurate because getMonthlyActivity() returns 6 months of
data; update the UI copy to match the dataset (e.g., change to "Your coding
activity over the last 6 months") in the component that renders CardDescription
(near CardTitle/CardDescription) or alternatively modify getMonthlyActivity() to
return 12 months—pick one approach and ensure CardDescription and the data
returned by getMonthlyActivity() stay consistent.
In `@src/hooks/useProfile.ts`:
- Around line 46-50: The effect is re-running because the whole form object is
in the dependency array; replace form with stable references (use form.setData
and form.data.name) so React won't see a new object each render and avoid the
loop: update the useEffect dependency array to [data?.name, form.data.name,
form.setData] and keep the guard that only calls form.setData({ name: data.name
}) when data?.name exists and form.data.name === '' so you don't overwrite an
intentional user change; reference the existing useEffect, form.data.name, and
form.setData when making this change.
In `@src/lib/validation.ts`:
- Around line 32-34: The custom validator is being invoked with { fieldName }
instead of the full form data, preventing cross-field checks; update
validateField to call rules.custom(value, { fieldName, data }) or
rules.custom(value, data) (matching the custom signature used elsewhere) and
ensure validateData passes the complete data object into validateField so
rules.custom receives the full form data for cross-field validation; adjust any
call sites of validateField/validateData to propagate the data parameter
accordingly.
🧹 Nitpick comments (1)
src/hooks/useForm.ts (1)
38-44: Stale closure risk insetValuedue toerrorsdependency.The
setValuecallback depends onerrors, which means it gets recreated whenever errors change. More importantly, clearing an error sets it to an empty string ('') rather than removing the key, which can cause subtle issues if code checks for key existence vs truthiness.Suggested improvement
const setValue = useCallback(<K extends keyof T>(key: K, value: T[K]) => { setFormData(prev => ({ ...prev, [key]: value })) // Clear error when user starts typing - if (errors[key as string]) { - setErrors(prev => ({ ...prev, [key as string]: '' })) - } + setErrors(prev => { + if (prev[key as string]) { + const { [key as string]: _, ...rest } = prev + return rest + } + return prev + }) -}, [errors]) +}, [])This removes the dependency on
errorsand properly deletes the key instead of setting it to an empty string.
| <CardHeader> | ||
| <CardTitle>Monthly Activity</CardTitle> | ||
| <CardDescription> | ||
| Your coding activity over the last 12 months | ||
| </CardDescription> |
There was a problem hiding this comment.
UI copy doesn’t match the data window.
getMonthlyActivity() returns 6 months of data (per module docs), but the copy says 12 months. Please align the label with the actual dataset.
✏️ Suggested fix
- Your coding activity over the last 12 months
+ Your coding activity over the last 6 months🤖 Prompt for AI Agents
In `@src/app/`(dashboard)/dashboard/page.tsx around lines 82 - 86, The
CardDescription text ("Your coding activity over the last 12 months") is
inaccurate because getMonthlyActivity() returns 6 months of data; update the UI
copy to match the dataset (e.g., change to "Your coding activity over the last 6
months") in the component that renders CardDescription (near
CardTitle/CardDescription) or alternatively modify getMonthlyActivity() to
return 12 months—pick one approach and ensure CardDescription and the data
returned by getMonthlyActivity() stay consistent.
| React.useEffect(() => { | ||
| if (data?.name && form.data.name === '') { | ||
| form.setData({ name: data.name }) | ||
| } | ||
| }, [data?.name, form]) |
There was a problem hiding this comment.
Potential infinite loop: form object in useEffect dependencies.
The form object changes on every render (since it contains data and errors which are state values), which can cause this effect to fire repeatedly. Additionally, the condition form.data.name === '' may not handle all edge cases (e.g., user intentionally clearing the field).
Suggested fix
Use stable references in the dependency array:
// Update form data when profile data loads
React.useEffect(() => {
- if (data?.name && form.data.name === '') {
+ if (data?.name !== undefined) {
form.setData({ name: data.name })
}
-}, [data?.name, form])
+}, [data?.name, form.setData])Since form.setData is wrapped in useCallback with no dependencies, it's stable and won't cause re-renders.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| React.useEffect(() => { | |
| if (data?.name && form.data.name === '') { | |
| form.setData({ name: data.name }) | |
| } | |
| }, [data?.name, form]) | |
| React.useEffect(() => { | |
| if (data?.name !== undefined) { | |
| form.setData({ name: data.name }) | |
| } | |
| }, [data?.name, form.setData]) |
🤖 Prompt for AI Agents
In `@src/hooks/useProfile.ts` around lines 46 - 50, The effect is re-running
because the whole form object is in the dependency array; replace form with
stable references (use form.setData and form.data.name) so React won't see a new
object each render and avoid the loop: update the useEffect dependency array to
[data?.name, form.data.name, form.setData] and keep the guard that only calls
form.setData({ name: data.name }) when data?.name exists and form.data.name ===
'' so you don't overwrite an intentional user change; reference the existing
useEffect, form.data.name, and form.setData when making this change.
| if (rules.custom) { | ||
| return rules.custom(value, { fieldName }) | ||
| } |
There was a problem hiding this comment.
Custom validator receives { fieldName } instead of full form data.
The custom function signature suggests it receives the form data (data?: Record<string, unknown>), but you're passing { fieldName } instead. This prevents cross-field validation (e.g., password confirmation).
Suggested fix
If cross-field validation is needed, pass the actual data through validateField:
-export function validateField(value: unknown, rules: ValidationRule, fieldName: string): string | null {
+export function validateField(value: unknown, rules: ValidationRule, fieldName: string, data?: Record<string, unknown>): string | null {
// ... existing checks ...
if (rules.custom) {
- return rules.custom(value, { fieldName })
+ return rules.custom(value, data)
}Then update validateData to pass the full data object:
- const error = validateField(data[field], rules, field.charAt(0).toUpperCase() + field.slice(1))
+ const error = validateField(data[field], rules, field.charAt(0).toUpperCase() + field.slice(1), data)🤖 Prompt for AI Agents
In `@src/lib/validation.ts` around lines 32 - 34, The custom validator is being
invoked with { fieldName } instead of the full form data, preventing cross-field
checks; update validateField to call rules.custom(value, { fieldName, data }) or
rules.custom(value, data) (matching the custom signature used elsewhere) and
ensure validateData passes the complete data object into validateField so
rules.custom receives the full form data for cross-field validation; adjust any
call sites of validateField/validateData to propagate the data parameter
accordingly.
|
messed up |
Summary by CodeRabbit
New Features
Documentation
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.