-
-
Couldn't load subscription status.
- Fork 1.3k
feat: enable async serverFn validation #5583
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe PR adds support for async validators in the server functions framework by making the Changes
Sequence DiagramsequenceDiagram
participant Client as UI Component
participant ServerFn as asyncValidationServerFn
participant ExecValidator as execValidator (async)
participant Schema as asyncValidationSchema
Client->>ServerFn: callServerFn('valid')
ServerFn->>ExecValidator: execValidator(schema, input)
activate ExecValidator
ExecValidator->>Schema: validate('valid')
Schema-->>ExecValidator: { success, value }
ExecValidator->>ExecValidator: Check issues
ExecValidator-->>ServerFn: Promise<'valid'>
deactivate ExecValidator
ServerFn-->>Client: result = 'valid'
Note over Client,ExecValidator: Error Path
Client->>ServerFn: callServerFn('invalid')
ServerFn->>ExecValidator: execValidator(schema, input)
activate ExecValidator
ExecValidator->>Schema: validate('invalid')
Schema-->>ExecValidator: { success: false, issues }
ExecValidator->>ExecValidator: Throw error
ExecValidator-->>ServerFn: Promise rejected
deactivate ExecValidator
ServerFn-->>Client: error.message captured
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (2)**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
packages/{*-start,start-*}/**📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧬 Code graph analysis (1)packages/start-client-core/src/createMiddleware.ts (1)
🔇 Additional comments (1)
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 |
|
interesting! we definitely need e2e tests in e2e/react-start/server-functions |
|
@schiller-manuel I tried to get the type-level test to work with a Standard validator like this: const validator = {
['~standard']: {
validate: (input: { input: string }) => ({ value: { a: input } }),
},
}
EDIT: I got it working without zod using the standard schema validator interface. 🎉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/start-client-core/package.json (1)
89-89: Consider upgrading to Zod 4 for enhanced async validation support.The PR uses Zod 3.24.2, but Zod 4 is available and includes significant improvements for async validation scenarios, including better error handling and more consistent async behavior. Since this PR specifically enables async validation, upgrading to Zod 4 would provide better alignment with the feature's goals.
Apply this diff:
- "zod": "^3.24.2" + "zod": "^4.0.0"e2e/react-start/server-functions/src/routes/async-validation.tsx (1)
10-12: Add a custom error message to the async refine validation.The current
.refine()implementation returns a boolean, which will result in a generic Zod error message. For better user experience and more meaningful test assertions, provide a custom error message.Apply this diff:
const asyncValidationSchema = z .object({ value: z.string() }) - .refine(async (data) => Promise.resolve(data.value !== 'invalid')) + .refine( + async (data) => Promise.resolve(data.value !== 'invalid'), + { message: 'Invalid input' } + )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
e2e/react-start/server-functions/src/routeTree.gen.ts(11 hunks)e2e/react-start/server-functions/src/routes/async-validation.tsx(1 hunks)e2e/react-start/server-functions/src/routes/index.tsx(1 hunks)e2e/react-start/server-functions/tests/server-functions.spec.ts(1 hunks)packages/start-client-core/package.json(1 hunks)packages/start-client-core/src/tests/createServerFn.test-d.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
packages/start-client-core/package.json
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-client-core/package.jsonpackages/start-client-core/src/tests/createServerFn.test-d.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
e2e/react-start/server-functions/src/routes/async-validation.tsxe2e/react-start/server-functions/src/routeTree.gen.tse2e/react-start/server-functions/tests/server-functions.spec.tse2e/react-start/server-functions/src/routes/index.tsxpackages/start-client-core/src/tests/createServerFn.test-d.ts
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
e2e/react-start/server-functions/src/routes/async-validation.tsxe2e/react-start/server-functions/src/routes/index.tsx
e2e/**
📄 CodeRabbit inference engine (AGENTS.md)
Store end-to-end tests under the e2e/ directory
Files:
e2e/react-start/server-functions/src/routes/async-validation.tsxe2e/react-start/server-functions/src/routeTree.gen.tse2e/react-start/server-functions/tests/server-functions.spec.tse2e/react-start/server-functions/src/routes/index.tsx
🧬 Code graph analysis (2)
e2e/react-start/server-functions/src/routes/async-validation.tsx (1)
e2e/react-start/server-functions/src/routes/index.tsx (1)
Route(3-5)
packages/start-client-core/src/tests/createServerFn.test-d.ts (1)
packages/start-client-core/src/createServerFn.ts (1)
createServerFn(49-170)
🔇 Additional comments (9)
e2e/react-start/server-functions/src/routes/index.tsx (2)
66-66: Good catch on the typo fix.
72-76: LGTM! Navigation link properly added.The new async validation test route link follows the existing pattern and is properly integrated into the navigation list.
packages/start-client-core/src/tests/createServerFn.test-d.ts (3)
2-2: LGTM! Zod import added for validator tests.
66-97: Good type-level test coverage for standard Zod validator.The test properly verifies that Zod schemas with transforms are correctly typed through the validator chain, ensuring the transformed output type flows through to the handler's data parameter.
99-134: Excellent! Async validator type support verified.This test confirms that async Zod validators (using
.refine(async ...)) maintain correct type inference throughout the chain, which directly addresses the maintainer's concern about TypeScript type support for async functions.e2e/react-start/server-functions/tests/server-functions.spec.ts (1)
316-362: Excellent e2e test coverage for async validation!The test suite properly covers both success and failure paths for async validation, correctly whitelists expected validation errors, and follows Playwright best practices. This directly addresses the maintainer's request for end-to-end tests under
e2e/react-start/server-functions.e2e/react-start/server-functions/src/routes/async-validation.tsx (2)
14-16: LGTM! Server function properly configured with async validator.The server function correctly applies the input validator and extracts the validated data.
18-66: Solid component implementation with proper error handling.The component correctly manages async state, handles errors, and provides test IDs for e2e testing. The error handling properly extracts the message from Error instances.
e2e/react-start/server-functions/src/routeTree.gen.ts (1)
23-23: Auto-generated route tree properly updated.All changes are mechanical additions for the new
/async-validationroute, following the consistent pattern used for other routes. The file header correctly indicates this file is auto-generated and should not be manually edited.Also applies to: 92-96, 164-164, 190-190, 217-217, 245-245, 271-271, 297-297, 324-324, 427-433, 524-524
|
View your CI Pipeline Execution ↗ for commit feb392e
☁️ Nx Cloud last updated this comment at |
More templates
@tanstack/arktype-adapter
@tanstack/directive-functions-plugin
@tanstack/eslint-plugin-router
@tanstack/history
@tanstack/nitro-v2-vite-plugin
@tanstack/react-router
@tanstack/react-router-devtools
@tanstack/react-router-ssr-query
@tanstack/react-start
@tanstack/react-start-client
@tanstack/react-start-server
@tanstack/router-cli
@tanstack/router-core
@tanstack/router-devtools
@tanstack/router-devtools-core
@tanstack/router-generator
@tanstack/router-plugin
@tanstack/router-ssr-query-core
@tanstack/router-utils
@tanstack/router-vite-plugin
@tanstack/server-functions-plugin
@tanstack/solid-router
@tanstack/solid-router-devtools
@tanstack/solid-router-ssr-query
@tanstack/solid-start
@tanstack/solid-start-client
@tanstack/solid-start-server
@tanstack/start-client-core
@tanstack/start-plugin-core
@tanstack/start-server-core
@tanstack/start-static-server-functions
@tanstack/start-storage-context
@tanstack/valibot-adapter
@tanstack/virtual-file-routes
@tanstack/zod-adapter
commit: |
|
can we also just to |
There was a problem hiding this 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 (1)
packages/start-client-core/src/tests/createServerFn.test-d.ts (1)
151-168: Consider extracting standard validator interfaces to reduce duplication.The
SyncValidatorandAsyncValidatorinterfaces are defined inline and share similar structure. While this keeps tests self-contained, you could reduce duplication by extracting these to helper types at the file level.Example refactor:
// At file level type StandardValidatorShape<TSync extends boolean = false> = { readonly '~standard': { types?: { input: string output: string } validate: (input: unknown) => TSync extends true ? { value: string } : Promise<{ value: string }> } } // In tests const syncValidator: StandardValidatorShape<true> = { ... } const asyncValidator: StandardValidatorShape<false> = { ... }However, keeping them inline is also acceptable for test clarity and independence.
Also applies to: 197-215
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/router-core/src/validators.ts(1 hunks)packages/start-client-core/src/tests/createServerFn.test-d.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/router-core/src/validators.tspackages/start-client-core/src/tests/createServerFn.test-d.ts
packages/router-core/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep framework-agnostic core router logic in packages/router-core/
Files:
packages/router-core/src/validators.ts
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-client-core/src/tests/createServerFn.test-d.ts
🧬 Code graph analysis (1)
packages/start-client-core/src/tests/createServerFn.test-d.ts (1)
packages/start-client-core/src/createServerFn.ts (1)
createServerFn(49-170)
🔇 Additional comments (1)
packages/start-client-core/src/tests/createServerFn.test-d.ts (1)
65-241: E2E tests for async validators are already present.The type-level tests comprehensively cover different async validator shapes (async functions, parse methods, and standard validators). E2E tests also exist at
e2e/react-start/server-functions/tests/server-functions.spec.ts(lines 316+) with test cases for both valid and invalid input scenarios at the/async-validationroute. Async validator functionality has complete test coverage.
|
we will need to wait with this until #5517 is merged |
@schiller-manuel Got it. I'll take a look to see if any changes are needed after that PR merges. Thanks for the code review so far and for pointing out improvements! |

The
inputValidatorincreateServerFndoesn't currently support async validate. However, theexecValidatorresult is awaited, even though it doesn't return a promise. Thus, I don't see a technical reason whyinputValidatorcouldn't support async validation. I'm proposing this change because I'm hoping to be able to use an async zod refiner in my application.Summary by CodeRabbit
New Features
Bug Fixes
Tests