Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Sep 8, 2025

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 8, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (3)
  • packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json is excluded by !**/*.json
  • packages/plugins/trpc/tests/projects/t3-trpc-v11/package-lock.json is excluded by !**/package-lock.json, !**/*.json
  • packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json is excluded by !**/*.json

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

Updates Zod handling and generated schemas for Zod v4 compatibility across multiple packages: improves lazy schema unwrapping, relaxes Decimal handling, makes record keys explicitly string-typed in many generated schemas, adjusts Zod error message extraction, tightens some tests, and bumps test scaffold/CLI Zod versions.

Changes

Cohort / File(s) Summary
Type annotation tweak
packages/runtime/src/enhancements/node/policy/handler.ts
Added explicit const validatedData: any in validateUpdateInputSchema; no runtime behavior change.
Zod lazy unwrapping logic
packages/runtime/src/zod-utils.ts
Expanded unwrapLazy to handle multiple Zod versions: early return if not lazy; call .unwrap() if present; fallback to .schema; otherwise throw a descriptive error. Affects lazy-unwrapping control flow and error handling.
Zod schema generation (Decimal + numeric records)
packages/schema/src/plugins/zod/generator.ts
Replaced strict DecimalSchema union with z.any().refine(...) accepting strings/numbers/decimal-like objects; numeric field unions changed z.record(z.unknown())z.record(z.string(), z.unknown()) for Prisma create schemas.
JSON schema transformer record keys
packages/schema/src/plugins/zod/transformer.ts
Replaced z.record(jsonSchema.nullable()) with z.record(z.string(), jsonSchema.nullable()) inside generated JSON-union schemas.
Schema-gen record keys for model references
packages/schema/src/plugins/zod/utils/schema-gen.ts
For non-array reference fields, changed z.record(z.unknown())z.record(z.string(), z.unknown()), preserving optionality via .optional().
Server validation and error handling
packages/server/src/api/rest/index.ts, packages/server/src/api/rpc/index.ts
REST: relationships map now uses z.record(z.string(), ...). RPC: replaced fromZodError with getZodErrorMessage, widened makeError zodErrors param to ZodError<any>, and replaced message extraction calls accordingly.
OpenAPI schema record keys
packages/plugins/openapi/src/schema.ts
Top-level security schemes changed from z.record(z.union([...]))z.record(z.string(), z.union([...])); oauth2 flows' scopes changed to z.record(z.string(), z.string()).
Test scaffold & CLI test deps
script/test-scaffold.ts, tests/integration/tests/cli/*.ts
Bumped Zod dependency in test scaffold and CLI test setups from ^3.25.0 to ^4.0.0.
Integration tests: concise error expectations
tests/integration/tests/enhancements/with-password/with-password.test.ts, tests/integration/tests/enhancements/with-policy/field-validation.test.ts
Updated assertions to expect shorter token-like error messages (e.g., "8 character", "email", "100") instead of previous verbose field-qualified messages.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant S as Server (REST / RPC)
  participant Z as Zod
  participant M as MessageUtils

  C->>S: Submit payload
  S->>Z: parse/validate(payload)
  alt valid
    Z-->>S: parsed data
    S-->>C: 200 OK
  else invalid
    Z-->>S: ZodError<any>
    S->>M: getZodErrorMessage(ZodError)
    M-->>S: concise message
    S-->>C: Error (message) + zodErrors
  end
Loading
sequenceDiagram
  autonumber
  participant Caller as smartUnion / caller
  participant Unwrap as unwrapLazy(schema)

  Caller->>Unwrap: schema
  alt not a ZodLazy
    Unwrap-->>Caller: schema
  else has unwrap()
    Unwrap->>Unwrap: schema.unwrap()
    Unwrap-->>Caller: unwrapped schema
  else has .schema
    Unwrap-->>Caller: schema.schema
  else unknown shape
    Unwrap-->>Caller: throw "Unable to determine how to unwrap a lazy schema..."
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks (3 warnings)

❌ Failed Checks (3 warnings)
Check Name Status Explanation Resolution
Title Check ⚠️ Warning The title mentions fixing zod4 compatibility with the server package, but the changeset spans multiple packages—including runtime, schema plugins, openapi, CLI tests, and integration tests—making the title misleadingly narrow. Revise the title to reflect the broad scope of zod4 compatibility updates across various packages, for example “fix: zod4 compatibility across runtime, schema, server, and plugins.”
Description Check ⚠️ Warning The description is empty and lacks context, rationale, and a summary of the key changes, which prevents reviewers from understanding the purpose and impact of this pull request. Provide a detailed description outlining the objectives, major code modifications, and reasons for the zod4 upgrade, and consider adding a pull request template to the repository to ensure future submissions include all necessary context.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/zod4-server

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.

Copy link
Contributor

@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/runtime/src/enhancements/node/policy/handler.ts (1)

1265-1276: Use Record<string, unknown> instead of any and drop the ?? {} fallback
validateZodSchema either returns an object or throws, so the nullish-coalescing fallback is never needed.

packages/server/src/api/rest/index.ts (1)

1972-2003: Widen ZodError type parameter — consistent with Zod v4

Using ZodError avoids generic mismatches across Zod versions. Consider aligning internal casts to the same type for consistency.

Outside this hunk, in handlePrismaError:

// before
err.meta?.zodErrors as ZodError

// after (suggested)
err.meta?.zodErrors as ZodError<any>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b004868 and 7e871fd.

⛔ Files ignored due to path filters (3)
  • packages/runtime/package.json is excluded by !**/*.json
  • packages/server/package.json is excluded by !**/*.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
📒 Files selected for processing (4)
  • packages/runtime/src/enhancements/node/policy/handler.ts (1 hunks)
  • packages/runtime/src/zod-utils.ts (1 hunks)
  • packages/server/src/api/rest/index.ts (2 hunks)
  • packages/server/src/api/rpc/index.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/server/src/api/rpc/index.ts (1)
packages/runtime/src/local-helpers/zod-utils.ts (1)
  • getZodErrorMessage (8-22)
⏰ 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). (5)
  • GitHub Check: build-test (20.x)
  • GitHub Check: OSSAR-Scan
  • GitHub Check: dependency-review
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
🔇 Additional comments (5)
packages/server/src/api/rest/index.ts (1)

203-211: z.record(z.string(), ...) for relationships — good Zod v4/v3 compatibility

Explicit string key schema is correct and future-proof. No runtime impact; validation gets stricter as intended.

packages/runtime/src/zod-utils.ts (1)

124-134: Robust lazy unwrapping across Zod versions — LGTM

Covers both unwrap() and schema property; sensible error when unsupported.

packages/server/src/api/rpc/index.ts (3)

10-11: Centralize Zod error messages via getZodErrorMessage — LGTM

Removes direct dependency on zod-error helpers and unifies messaging.


204-218: makeError accepts ZodError — LGTM

Signature matches wider Zod generics while preserving response shape.


254-256: Switch to getZodErrorMessage on validation failure — LGTM

Improves compatibility across Zod versions and keeps concise messages.

Copy link
Contributor

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/runtime/src/enhancements/node/policy/handler.ts (1)

1260-1266: Null updates bypass Zod validation; include null in literalData

typeof null === 'object', so null assignments are excluded from validation, potentially letting invalid null writes slip through.

Apply:

-        const literalData = Object.entries(data).reduce<any>(
-            (acc, [k, v]) => ({ ...acc, ...(typeof v !== 'object' ? { [k]: v } : {}) }),
-            {}
-        );
+        const literalData = Object.fromEntries(
+            Object.entries(data).filter(([, v]) => v === null || typeof v !== 'object')
+        );

Add a test for updating a nullable and a non-nullable field with null.

packages/schema/src/plugins/zod/generator.ts (1)

401-405: Drop unused Decimal import from generated model files.

DecimalSchema no longer relies on Decimal; this import becomes unused and may trigger TS noUnusedLocals.

         if (decl.fields.some((field) => field.type.type === 'Decimal')) {
             writer.writeLine(`import { DecimalSchema } from '../common';`);
-            writer.writeLine(`import { Decimal } from 'decimal.js';`);
         }
🧹 Nitpick comments (4)
packages/schema/src/plugins/zod/transformer.ts (1)

489-490: Record key typing for JSON: LGTM; confirm top-level JSON null semantics

z.record(z.string(), jsonSchema.nullable()) aligns with Zod v4. If top-level JSON null should be allowed (distinct from DB null), consider including z.null() at the top-level union or ensure field-level .nullable() covers it.

packages/server/src/api/rpc/index.ts (3)

169-171: Type consistency: cast to ZodError for clarity.

Minor nit: keep the generic consistent with the updated signature.

-                    err.meta?.zodErrors as ZodError
+                    err.meta?.zodErrors as ZodError<any>

97-104: Grammar nit in error text.

Use “or” instead of uppercased “AND”.

-                        body: this.makeError('invalid request method, only PUT AND PATCH are supported'),
+                        body: this.makeError('invalid request method, only PUT or PATCH are supported'),

194-199: Avoid leaking internal error details; use 500 for unknown errors.

Returning raw err.message with 400 can leak internals and misclassify server faults.

-                return {
-                    status: 400,
-                    body: this.makeError((err as Error).message),
-                };
+                return {
+                    status: 500,
+                    body: this.makeError('internal server error'),
+                };

Optionally add a correlation ID to logs/response meta if needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b004868 and d8ccad6.

⛔ Files ignored due to path filters (9)
  • packages/plugins/trpc/tests/projects/nuxt-trpc-v10/package.json is excluded by !**/*.json
  • packages/plugins/trpc/tests/projects/nuxt-trpc-v11/package.json is excluded by !**/*.json
  • packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json is excluded by !**/*.json
  • packages/runtime/package.json is excluded by !**/*.json
  • packages/server/package.json is excluded by !**/*.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
  • tests/integration/test-run/package.json is excluded by !**/*.json
  • tests/integration/tests/frameworks/nextjs/test-project/package.json is excluded by !**/*.json
  • tests/integration/tests/frameworks/trpc/test-project/package.json is excluded by !**/*.json
📒 Files selected for processing (10)
  • packages/runtime/src/enhancements/node/policy/handler.ts (1 hunks)
  • packages/runtime/src/zod-utils.ts (1 hunks)
  • packages/schema/src/plugins/zod/generator.ts (2 hunks)
  • packages/schema/src/plugins/zod/transformer.ts (1 hunks)
  • packages/schema/src/plugins/zod/utils/schema-gen.ts (1 hunks)
  • packages/server/src/api/rest/index.ts (2 hunks)
  • packages/server/src/api/rpc/index.ts (3 hunks)
  • script/test-scaffold.ts (1 hunks)
  • tests/integration/tests/enhancements/with-password/with-password.test.ts (2 hunks)
  • tests/integration/tests/enhancements/with-policy/field-validation.test.ts (16 hunks)
⏰ 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). (5)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: OSSAR-Scan
  • GitHub Check: dependency-review
🔇 Additional comments (10)
tests/integration/tests/enhancements/with-password/with-password.test.ts (1)

97-98: Updated expectations to concise tokens: LGTM

Matches the new getZodErrorMessage style.

Also applies to: 106-107

packages/schema/src/plugins/zod/utils/schema-gen.ts (1)

23-26: Zod v4-compatible record typing: LGTM

Switch to z.record(z.string(), z.unknown()) with preserved optionality is correct.

packages/runtime/src/zod-utils.ts (1)

124-134: Robust unwrapLazy across Zod versions: LGTM

Covers unwrap() and legacy schema property with a clear error fallback.

tests/integration/tests/enhancements/with-policy/field-validation.test.ts (1)

68-69: Assertion updates to tokenized messages: LGTM

Consistent with shorter Zod error messaging and policy surfacing.

Also applies to: 101-102, 122-123, 169-178, 236-237, 249-250, 268-269, 286-287, 347-348, 360-361, 390-391, 406-407, 446-447, 462-463, 975-976

packages/server/src/api/rest/index.ts (2)

204-205: Use of z.record(z.string(), ...) for relationships: LGTM

Correct for Zod v4 and keeps payload shape explicit.


1977-1978: Broadened type to ZodError<any>: LGTM

Avoids type incompatibility across Zod versions in error plumbing.

packages/server/src/api/rpc/index.ts (3)

10-10: Good swap to internal helper for Zod messages.

Replacing the external fromZodError with getZodErrorMessage keeps dependencies lean and aligns with Zod v4 behavior.


204-206: makeError now accepts ZodError — aligned with Zod v4.

Signature change is appropriate and non-breaking to callers here.


254-256: Validation message extraction updated correctly.

Using getZodErrorMessage(parseResult.error) produces concise messages while preserving zodErrors in the payload.

packages/schema/src/plugins/zod/generator.ts (1)

564-565: Explicit string-keyed records for atomic ops — good.

z.record(z.string(), z.unknown()) matches Zod v4 expectations and removes implicit defaults.

Copy link
Contributor

@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 (3)
packages/plugins/openapi/src/schema.ts (1)

24-25: DRY up repeated scopes schema

All four occurrences are identical. Consider extracting a shared ScopesSchema to reduce duplication and ease future changes.

Apply:

 import z from 'zod';

+const ScopesSchema = z.record(z.string(), z.string());
+
 export const SecuritySchemesSchema = z.record(
   z.string(),
   z.union([
@@
-                    scopes: z.record(z.string(), z.string()),
+                    scopes: ScopesSchema,
@@
-                    scopes: z.record(z.string(), z.string()),
+                    scopes: ScopesSchema,
@@
-                    scopes: z.record(z.string(), z.string()),
+                    scopes: ScopesSchema,
@@
-                    scopes: z.record(z.string(), z.string()),
+                    scopes: ScopesSchema,

Also applies to: 29-30, 34-35, 39-40

tests/integration/tests/cli/plugins.test.ts (1)

73-73: De-duplicate Zod version: pull from a shared constant

Reduce drift by centralizing the version in tests’ shared helpers.

Apply within this file:

-            'zod@^4.0.0',
+            'zod@' + ZOD_VERSION,

And add (outside this hunk):

  • In tests/integration/tests/cli/share.ts:
export const ZOD_VERSION = '^4.0.0';
  • Update imports at the top of this file:
import { ZOD_VERSION } from './share';
tests/integration/tests/cli/generate.test.ts (1)

48-48: Reuse shared ZOD_VERSION for consistency

Same suggestion as other suite to avoid future bumps in multiple places.

Apply within this file:

-        installPackage('prisma @prisma/client zod@^4.0.0');
+        installPackage('prisma @prisma/client zod@' + ZOD_VERSION);

Also update the import (outside this hunk):

import { createNpmrc, ZOD_VERSION } from './share';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8ccad6 and d1dd828.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
  • pnpm-workspace.yaml is excluded by !**/*.yaml
📒 Files selected for processing (3)
  • packages/plugins/openapi/src/schema.ts (2 hunks)
  • tests/integration/tests/cli/generate.test.ts (1 hunks)
  • tests/integration/tests/cli/plugins.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/integration/tests/cli/generate.test.ts (1)
packages/testtools/src/schema.ts (1)
  • installPackage (68-70)
⏰ 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). (5)
  • GitHub Check: build-test (20.x)
  • GitHub Check: OSSAR-Scan
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: dependency-review
🔇 Additional comments (4)
packages/plugins/openapi/src/schema.ts (1)

6-8: Good Zod v4 migration: explicit key schema for record

Specifying z.string() for the record keys aligns with Zod 4’s overloads and removes ambiguity. Looks correct.

tests/integration/tests/cli/plugins.test.ts (2)

73-73: Zod v4 bump matches PR goal

Aligns test scaffold with repo-wide Zod v4 migration. Looks good.


73-73: Verify no lingering Zod v3 references
Double-check all package.json entries (dependencies, devDependencies, peerDependencies) and lockfiles for any ^3.x Zod pins to prevent mixed v3/v4 installs.

tests/integration/tests/cli/generate.test.ts (1)

48-48: Upgrade to Zod v4 here is consistent

Keeps this suite in sync with the v4 migration. Good.

@ymc9 ymc9 merged commit 8c98060 into dev Sep 8, 2025
11 checks passed
@ymc9 ymc9 deleted the fix/zod4-server branch September 8, 2025 22:39
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.

2 participants