Skip to content

Conversation

@unnoq
Copy link
Member

@unnoq unnoq commented Dec 29, 2025

Fixes #1317

Summary by CodeRabbit

  • Tests

    • Added test coverage for preprocess functionality with string schemas.
  • Bug Fixes

    • Improved handling of pipe operations in schema conversion to more accurately process transformations with input strategy.

✏️ Tip: You can customize this high-level summary in your review settings.

@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Dec 29, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 29, 2025

📝 Walkthrough

Walkthrough

Modified the z.preprocess() handling in the Zod-to-JSON-Schema converter by adjusting how the 'pipe' case selects source schemas when using 'input' conversion strategy. The logic now checks for 'transform' inner types and conditionally uses either the input or output branch accordingly. Added a corresponding test case for the preprocess scenario.

Changes

Cohort / File(s) Summary
Converter test addition
packages/zod/src/zod4/converter.processed.test.ts
Added test case for z.preprocess(x => x, z.string()) verifying identity preprocessing behavior with expected input/output schema matching
Converter logic modification
packages/zod/src/zod4/converter.ts
Updated 'pipe' case handling in input conversion strategy to conditionally select between in and out branches based on whether the inner type is a 'transform'; falls back to out when transform is detected instead of always using in

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • unnoq/orpc#579: Modifies pipe schema handling to selectively choose between input and output types based on conversion strategy, addressing similar control-flow concerns.

Suggested labels

size:M

Poem

🐰 A preprocess path once lost in the pipes,
Now finds its way through selective types,
Transform or not—the schema knows best,
Input or output—we've passed the test! ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: enhancing schema conversion logic specifically for zod4 preprocess functionality, which directly aligns with the primary objective of fixing preprocess support in OpenAPI schema generation.
Linked Issues check ✅ Passed The PR code changes implement preprocess support by adjusting the pipe case handling in the converter to correctly process preprocess schemas, directly addressing the core requirement from issue #1317 to enable OpenAPI generation with z.preprocess().
Out of Scope Changes check ✅ Passed All changes are directly scoped to the preprocess schema conversion issue: the converter logic handles the pipe case, and the test validates the preprocess functionality without introducing unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch unnoq/issue1317

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 and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @unnoq, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the schema conversion logic within the ZodToJsonSchemaConverter to correctly interpret and represent z.preprocess and z.transform types in the generated JSON schema. By adjusting the selection of input versus output schemas in pipe conversions, the PR ensures that the JSON schema accurately reflects the data type after any preprocessing or transformation, addressing an issue where these schemas were not being converted as expected.

Highlights

  • Enhanced Schema Conversion for Preprocess/Transform: The ZodToJsonSchemaConverter now intelligently handles z.preprocess and z.transform types within pipe schemas. When the conversion strategy is 'input' and the input schema is a transform type, the converter will now prioritize the output schema (_zod.def.out) to ensure the generated JSON schema accurately reflects the processed type.
  • Improved Accuracy for Input Schemas: This change prevents scenarios where the JSON schema might incorrectly represent the raw input type of a preprocess or transform schema, instead providing a more accurate representation of the data type after the transformation has occurred.
  • New Test Case for Preprocess: A new test case has been added to validate the correct conversion of z.preprocess(x => x, z.string()), confirming that a simple preprocess with an identity function correctly yields the underlying string schema's JSON representation.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@unnoq unnoq changed the title feat(zod): enhance schema conversion logic for zod4 preprocess fix(zod): enhance schema conversion logic for zod4 preprocess Dec 29, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request correctly enhances the Zod schema conversion logic to handle preprocess functions, which are implemented as ZodPipe with a transform on the input side. The fix ensures that for an input strategy, the out schema is used, which is the desired behavior for preprocess. The change is well-supported by a new test case that validates this scenario. The implementation is solid, and I have one minor suggestion to improve code readability for future maintenance.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 29, 2025

More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1318

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1318

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1318

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1318

@orpc/experimental-durable-iterator

npm i https://pkg.pr.new/@orpc/experimental-durable-iterator@1318

@orpc/hey-api

npm i https://pkg.pr.new/@orpc/hey-api@1318

@orpc/interop

npm i https://pkg.pr.new/@orpc/interop@1318

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1318

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1318

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1318

@orpc/openapi-client

npm i https://pkg.pr.new/@orpc/openapi-client@1318

@orpc/otel

npm i https://pkg.pr.new/@orpc/otel@1318

@orpc/experimental-pino

npm i https://pkg.pr.new/@orpc/experimental-pino@1318

@orpc/experimental-publisher

npm i https://pkg.pr.new/@orpc/experimental-publisher@1318

@orpc/experimental-publisher-durable-object

npm i https://pkg.pr.new/@orpc/experimental-publisher-durable-object@1318

@orpc/experimental-ratelimit

npm i https://pkg.pr.new/@orpc/experimental-ratelimit@1318

@orpc/react

npm i https://pkg.pr.new/@orpc/react@1318

@orpc/react-query

npm i https://pkg.pr.new/@orpc/react-query@1318

@orpc/experimental-react-swr

npm i https://pkg.pr.new/@orpc/experimental-react-swr@1318

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1318

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1318

@orpc/solid-query

npm i https://pkg.pr.new/@orpc/solid-query@1318

@orpc/standard-server

npm i https://pkg.pr.new/@orpc/standard-server@1318

@orpc/standard-server-aws-lambda

npm i https://pkg.pr.new/@orpc/standard-server-aws-lambda@1318

@orpc/standard-server-fastify

npm i https://pkg.pr.new/@orpc/standard-server-fastify@1318

@orpc/standard-server-fetch

npm i https://pkg.pr.new/@orpc/standard-server-fetch@1318

@orpc/standard-server-node

npm i https://pkg.pr.new/@orpc/standard-server-node@1318

@orpc/standard-server-peer

npm i https://pkg.pr.new/@orpc/standard-server-peer@1318

@orpc/svelte-query

npm i https://pkg.pr.new/@orpc/svelte-query@1318

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1318

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1318

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1318

@orpc/vue-colada

npm i https://pkg.pr.new/@orpc/vue-colada@1318

@orpc/vue-query

npm i https://pkg.pr.new/@orpc/vue-query@1318

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1318

commit: 691e0b3

@codecov
Copy link

codecov bot commented Dec 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link

@coderabbitai coderabbitai bot left a 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/zod/src/zod4/converter.ts (1)

522-530: Logic correctly handles z.preprocess() for OpenAPI generation.

The conditional logic properly addresses issue #1317 by detecting when the input schema is a transform (as created by z.preprocess()) and using the output schema instead. This ensures OpenAPI input schemas describe the validated type rather than the preprocessing transformation.

For clarity, consider refining the comment to be more specific:

-  // prefer out schema when in schema is preprocess/transform
+  // For input strategy: use in schema unless it's a transform (e.g., z.preprocess),
+  // in which case use out schema to represent the validated type after preprocessing
packages/zod/src/zod4/converter.processed.test.ts (1)

21-26: Test validates the fix, but consider expanding coverage.

The test correctly demonstrates that z.preprocess() now produces consistent string schemas for both input and output strategies, resolving issue #1317.

However, given that this fixes a critical OpenAPI generation blocker, consider adding tests for:

  • Non-trivial preprocessing (e.g., z.preprocess(x => String(x).toUpperCase(), z.string()))
  • Complex schemas (objects, arrays with preprocess in nested fields)
  • Interaction with other Zod features (nullable, optional, default with preprocess)
🔎 Example additional test cases
+  {
+    name: 'object with preprocess field',
+    schema: z.object({
+      name: z.preprocess(x => String(x).trim(), z.string()),
+    }),
+    input: [true, { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] }],
+    output: [true, { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] }],
+  },
+  {
+    name: 'preprocess with optional',
+    schema: z.preprocess(x => x, z.string()).optional(),
+    input: [false, { type: 'string' }],
+    output: [false, { type: 'string' }],
+  },
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a8f52f0 and 691e0b3.

📒 Files selected for processing (2)
  • packages/zod/src/zod4/converter.processed.test.ts
  • packages/zod/src/zod4/converter.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: publish-commit
  • GitHub Check: lint
  • GitHub Check: test
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
packages/zod/src/zod4/converter.ts (1)

524-524: Verify handling of edge cases and complex preprocessing scenarios.

The condition pipe._zod.def.in._zod.def.type !== 'transform' correctly identifies preprocessing, but ensure this handles:

  • Nested or chained preprocessing (e.g., z.preprocess(f1, z.preprocess(f2, z.string())))
  • Preprocessing with complex schemas (objects with multiple fields using preprocess)
  • Combinations with other transformations

Consider adding tests for these scenarios:

// Test: Nested preprocess
z.preprocess(x => x, z.preprocess(y => y, z.string()))

// Test: Preprocess with object schema
z.object({
  field: z.preprocess(x => x?.toUpperCase(), z.string())
})

// Test: Preprocess then transform
z.preprocess(x => x?.trim(), z.string()).transform(s => s.length)

Would you like me to generate these additional test cases?

@cloudflare-workers-and-pages
Copy link

Deploying orpc with  Cloudflare Pages  Cloudflare Pages

Latest commit: 691e0b3
Status: ✅  Deploy successful!
Preview URL: https://ec7bf25e.orpc-1qh.pages.dev
Branch Preview URL: https://unnoq-issue1317.orpc-1qh.pages.dev

View logs

@unnoq unnoq merged commit fc2dc8f into main Dec 29, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to generate OpenAPI schema while using z.preprocess()

2 participants