Skip to content

fix(zod): json type compatibility between inferred zod types and @zenstackhq/orm types#2641

Merged
ymc9 merged 1 commit into
zenstackhq:devfrom
Azzerty23:fix/zod-json-orm-type-compatibility
May 6, 2026
Merged

fix(zod): json type compatibility between inferred zod types and @zenstackhq/orm types#2641
ymc9 merged 1 commit into
zenstackhq:devfrom
Azzerty23:fix/zod-json-orm-type-compatibility

Conversation

@Azzerty23
Copy link
Copy Markdown
Contributor

@Azzerty23 Azzerty23 commented May 3, 2026

Fixes #2639

A small fix that copy JsonValue from @zenstackhq/orm to @zenstackhq/zod.
Add a test to ensure zod inferred type is compatible with $ModelReturn type from orm (except optionality).

Summary by CodeRabbit

  • New Features

    • Added ORM schema generation with test model definitions and type exports.
    • Introduced JsonValue type export for improved JSON type handling.
  • Tests

    • Enhanced schema test generation tooling with updated CLI flags.
    • Added Zod-to-ORM type compatibility verification tests.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

📝 Walkthrough

Walkthrough

This PR fixes JSON type incompatibility between zenstack/orm and zenstack/zod by introducing a concrete JsonValue TypeScript type that excludes null, updating Zod schema generation to use this type, and adding comprehensive type compatibility tests to verify ORM and Zod-generated types align correctly.

Changes

JSON Type Compatibility Fix

Layer / File(s) Summary
Core Type Definition
packages/zod/src/types.ts
Introduces JsonValue type (string | number | boolean | JsonObject | JsonArray) and updates JsonZodType from a union of explicit Zod primitives/objects/arrays to z.ZodType<JsonValue>, removing null from the JSON value shape itself.
Type Export
packages/zod/src/index.ts
Exports JsonValue alongside existing ModelSchemaOptions and GetModelSchemaShapeWithOptions to make the new type publicly available.
Test Infrastructure
packages/orm/package.json, scripts/test-generate.ts
Adds pack and test:generate scripts to orm package; updates CLI invocation in test-generate to pass schema path via --schema flag instead of positional argument.
Test Schema Definitions
packages/orm/test/schema/schema.zmodel, schema.ts, models.ts
Generates a complete ORM schema with User, Post, Product (with computed field), delegated Asset model, Video/Image inheritance, Status enum, and Address type; exports corresponding TypeScript model and type definitions.
Type Compatibility Verification
packages/zod/test/factory.test.ts, packages/orm/test/zod-compat.test.ts
Updates factory.test.ts to assert inferred User['metadata'] as JsonValue | null | undefined and adds runtime null test; introduces new zod-compat.test.ts file that verifies z.infer<typeof userSchema> extends the ORM User type and confirms .required() variant compatibility.
Type Annotation Refinements
packages/zod/test/schema/schema.ts
Adds explicit TypeScript type assertions throughout generated schema metadata: attributes arrays are cast to readonly AttributeApplication[], field default values to FieldDefault, and relation metadata to readonly string[].

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

Poem

🐰 A rabbit hops through types so neat,
Where Json fields now safely meet,
From Zod and ORM, side by side,
With JsonValue as our guide,
No null shall slip between the crates!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: addressing JSON type incompatibility between zod-inferred types and ORM types.
Linked Issues check ✅ Passed The PR successfully addresses issue #2639 by aligning zod's JSON type with ORM's JsonValue, adding proper type exports and cross-package compatibility tests.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing JSON type compatibility: adding JsonValue type, test schemas, factory tests, and CLI script updates are all necessary for the fix.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@Azzerty23 Azzerty23 force-pushed the fix/zod-json-orm-type-compatibility branch 2 times, most recently from c000930 to bc3f177 Compare May 3, 2026 18:57
Replace the loose union of Zod types for JSON fields with a proper
recursive JsonValue type that matches the ORM's JsonValue definition,
and export it. Adds cross-package type compatibility tests in the ORM
package to prevent regressions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Azzerty23 Azzerty23 force-pushed the fix/zod-json-orm-type-compatibility branch from bc3f177 to 1426e12 Compare May 3, 2026 18:59
@Azzerty23 Azzerty23 changed the title fix(zod): align Json and TypeDef zod types with @zenstackhq/orm types fix(zod): json type compatibility between inferred zod types and @zenstackhq/orm types May 3, 2026
@Azzerty23 Azzerty23 marked this pull request as ready for review May 3, 2026 20:12
Copy link
Copy Markdown
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

🧹 Nitpick comments (2)
packages/orm/package.json (1)

21-21: 💤 Low value

"pack": "pnpm pack" is redundant.

pnpm pack can be called directly; a wrapper script adds no value here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/orm/package.json` at line 21, Remove the redundant npm script entry
"pack": "pnpm pack" from package.json; locate the "scripts" object where the
"pack" key is defined and delete that key/value pair so callers can run pnpm
pack directly without an unnecessary wrapper.
packages/zod/src/types.ts (1)

138-138: Remove JsonValue duplication: ORM should import from @zenstackhq/zod instead of maintaining a separate definition.

ORM's JsonValue definition in packages/orm/src/common-types.ts is structurally identical to the new zod definition. However, ORM currently maintains its own separate definition rather than importing from the zod package. This creates code duplication and drift risk. Update ORM to import JsonValue from @zenstackhq/zod and re-export it if needed by other packages.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/zod/src/types.ts` at line 138, Replace the duplicated local
JsonValue type with an import from the zod package: remove the local export/type
alias named JsonValue in the ORM's common-types (the existing JsonValue
definition) and add an import from "@zenstackhq/zod" importing JsonValue, then
re-export it if other modules rely on it (e.g., export { JsonValue } or export
type { JsonValue } so callers remain unchanged); ensure any references to the
old local symbol continue to use the imported JsonValue.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/zod/src/types.ts`:
- Around line 138-142: The current type/runtime mismatch stems from JsonValue
excluding null while makeJsonSchema() accepts top-level null; fix it by removing
top-level z.null() from makeJsonSchema() and introduce a new helper
makeJsonItemSchema() that returns a z.ZodType allowing JsonValue | null; update
makeJsonSchema() to use z.array(z.lazy(() => this.makeJsonItemSchema())) and
z.object({}).catchall(z.lazy(() => this.makeJsonItemSchema())) so recursive
items can be null while the top-level schema (used for required Json fields)
remains non-null and matches the JsonValue / JsonZodType typing.

In `@scripts/test-generate.ts`:
- Line 25: The command string in scripts/test-generate.ts interpolates
${schemaPath} unquoted so paths with spaces will be split by the shell; update
the template to quote the schema path (e.g., change the fragment to --schema
"${schemaPath}") in the same template string that builds `${RUNTIME} ${cliPath}
generate ... ${options.join(' ')} ...` so execSync receives the schema path as a
single argument; ensure you escape any embedded quotes in schemaPath if
necessary or prefer using execFileSync to avoid shell parsing.

---

Nitpick comments:
In `@packages/orm/package.json`:
- Line 21: Remove the redundant npm script entry "pack": "pnpm pack" from
package.json; locate the "scripts" object where the "pack" key is defined and
delete that key/value pair so callers can run pnpm pack directly without an
unnecessary wrapper.

In `@packages/zod/src/types.ts`:
- Line 138: Replace the duplicated local JsonValue type with an import from the
zod package: remove the local export/type alias named JsonValue in the ORM's
common-types (the existing JsonValue definition) and add an import from
"@zenstackhq/zod" importing JsonValue, then re-export it if other modules rely
on it (e.g., export { JsonValue } or export type { JsonValue } so callers remain
unchanged); ensure any references to the old local symbol continue to use the
imported JsonValue.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c5ea96f4-5966-4e18-b009-3de1d1b71859

📥 Commits

Reviewing files that changed from the base of the PR and between a31a32e and 1426e12.

📒 Files selected for processing (10)
  • packages/orm/package.json
  • packages/orm/test/schema/models.ts
  • packages/orm/test/schema/schema.ts
  • packages/orm/test/schema/schema.zmodel
  • packages/orm/test/zod-compat.test.ts
  • packages/zod/src/index.ts
  • packages/zod/src/types.ts
  • packages/zod/test/factory.test.ts
  • packages/zod/test/schema/schema.ts
  • scripts/test-generate.ts

Comment thread packages/zod/src/types.ts
Comment thread scripts/test-generate.ts
@ymc9 ymc9 merged commit 090be2c into zenstackhq:dev May 6, 2026
14 checks passed
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.

zenstack/zod generates incompatible types for Json fields when comparing Types generated by zenstack/ormand zenstack/zod

2 participants