Skip to content

feat(json-schema): smart coercion plugin for any standard schema#748

Merged
dinwwwh merged 21 commits intomainfrom
feat/json-schema/coercer
Jul 11, 2025
Merged

feat(json-schema): smart coercion plugin for any standard schema#748
dinwwwh merged 21 commits intomainfrom
feat/json-schema/coercer

Conversation

@dinwwwh
Copy link
Copy Markdown
Member

@dinwwwh dinwwwh commented Jul 11, 2025

Closes: https://github.com/unnoq/orpc/issues/395

Summary by CodeRabbit

  • New Features

    • Introduced the experimental Smart Coercion Plugin for automatic, deep type coercion based on JSON Schema, supporting native JavaScript types like BigInt, Date, RegExp, URL, Set, and Map.
    • Added detailed documentation for the Smart Coercion Plugin, including installation, setup, usage examples, and conversion rules.
    • Added new sidebar navigation entries for the Smart Coercion Plugin and legacy Zod Smart Coercion in the documentation.
  • Improvements

    • Enhanced JSON Schema conversion by annotating schemas with native type metadata (bigint, date, set, map, regexp, url).
    • Updated playgrounds and OpenAPI handler configurations to replace the deprecated ZodSmartCoercionPlugin with the new Smart Coercion Plugin.
    • Marked the ZodSmartCoercionPlugin as deprecated in favor of the new plugin.
  • Bug Fixes

    • Expanded test coverage for coercion logic, validating handling of diverse schema constructs and native types.
  • Chores

    • Added the new @orpc/json-schema package with source code, tests, documentation, and build configuration.
    • Updated dependencies and TypeScript project references in multiple packages and playgrounds to include @orpc/json-schema.
    • Added .gitignore and README files for the new package.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jul 11, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
orpc ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2025 2:46am

@dosubot dosubot Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Jul 11, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 11, 2025

Walkthrough

A new @orpc/json-schema package is introduced, providing a smart coercion plugin and a JSON Schema coercer that supports native JavaScript types and deep, schema-guided value transformations. The Zod-specific smart coercion plugin is deprecated in favor of this new plugin. All playgrounds and documentation are updated to use the new plugin, and test suites are added for smart coercion and schema conversion.

Changes

Files / Groups Change Summary
packages/json-schema/ (all new: src, tests, config, README, package.json) Introduced new package with JSON Schema coercion logic, smart coercion plugin, type definitions, tests, documentation, config, and manifest.
packages/zod/src/converter.ts, zod4/converter.ts, zod4/converter.*.test.ts, converter.test.ts, tests/shared.ts Added "x-native-type" to JSON Schema outputs for native types; updated tests and types accordingly.
packages/zod/package.json, tsconfig.json Added dependency and project reference to @orpc/json-schema.
packages/zod/src/zod4/coercer.ts Deprecated Zod-specific smart coercion plugin via JSDoc.
packages/openapi/src/schema-converter.ts Made schema converter array property readonly for immutability.
apps/content/.vitepress/config.ts, docs/openapi/plugins/smart-coercion.md Added documentation and sidebar entry for the new Smart Coercion Plugin.
playgrounds/*/package.json Added @orpc/json-schema as a devDependency in all playgrounds.
playgrounds/*/src/... Switched from ZodSmartCoercionPlugin to new SmartCoercionPlugin using JSON Schema, updated plugin instantiation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant SmartCoercionPlugin
    participant SchemaConverter
    participant JsonSchemaCoercer
    participant Handler

    Client->>SmartCoercionPlugin: Send input with schema
    SmartCoercionPlugin->>SchemaConverter: Convert schema to JSON Schema
    SchemaConverter-->>SmartCoercionPlugin: Return JSON Schema
    SmartCoercionPlugin->>JsonSchemaCoercer: Coerce input using JSON Schema
    JsonSchemaCoercer-->>SmartCoercionPlugin: Return coerced input
    SmartCoercionPlugin->>Handler: Pass coerced input
    Handler-->>Client: Return response
Loading

Assessment against linked issues

Objective Addressed Explanation
Implement ArkType coercer (#395) No ArkType coercer or ArkType-specific logic is present; only Zod and JSON Schema coercion are implemented.
Deprecate Zod-specific smart coercion in favor of generic plugin (#395)
Update documentation and playgrounds to use new smart coercion plugin (#395)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Added .gitignore and README to packages/json-schema These are standard package setup files unrelated to the feature objectives.
Made CompositeSchemaConverter.converters readonly in packages/openapi/src/schema-converter.ts This is an internal type safety improvement unrelated to coercion features.
Removed blank line in Nest integration docs (apps/content/docs/openapi/integrations/implement-contract-in-nest.md) Minor formatting change unrelated to coercion or plugin features.

Possibly related PRs

  • unnoq/orpc#462: Introduces a new "Smart Coercion" plugin based on JSON Schema coercion and replaces the legacy "Zod Smart Coercion" plugin with it; related by domain but distinct in implementation and target Zod version.

Poem

In a warren of code, a new path is shown,
With schemas and types, smart coercion has grown.
Zod’s plugin retired, JSON Schema takes stage,
Now rabbits can hop through each native type cage!
So let’s nibble some carrots and celebrate here—
For smart, schema-driven coercion is finally here! 🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
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.

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 introduces a powerful new 'smart coercion' feature to oRPC, enabling automatic and safe type conversion of incoming data based on its defined JSON Schema. This significantly improves developer experience by reducing the need for manual data transformation, and is implemented through a new dedicated @orpc/json-schema package, along with necessary updates to existing schema converters.

Highlights

  • New Core Package: Introduced a new @orpc/json-schema package, which provides a generic experimental_JsonSchemaCoercer for intelligent type conversion based on JSON Schema definitions, and an experimental_SmartCoercionPlugin to integrate this functionality into the oRPC client request pipeline.
  • Enhanced Schema Generation: Updated the @orpc/zod package's JSON Schema converter to emit custom x-native-type metadata for native JavaScript types (like BigInt, Date, RegExp, URL, Set, and Map). This metadata is crucial for the new smart coercion logic to correctly identify and transform these types.
  • Plugin Deprecation and Migration: The existing experimental_ZodSmartCoercionPlugin in @orpc/zod has been deprecated in favor of the new, more versatile experimental_SmartCoercionPlugin from @orpc/json-schema. Playgrounds have been updated to reflect this migration.
  • Comprehensive Documentation and Testing: Added detailed documentation for the new Smart Coercion Plugin, explaining its purpose, usage, and conversion rules. Extensive unit tests have also been included to ensure the robustness and correctness of the coercion logic across various data types and schema structures.
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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 is currently in preview and 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 to provide feedback.

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.

Copy link
Copy Markdown
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 introduces a new @orpc/json-schema package with a generic smart coercion plugin. The date coercion implementation in coercer.ts has a potential timezone issue, and x-native-type metadata is missing in zod/src/converter.ts for bigint, date, set, and map.

Comment thread packages/json-schema/src/coercer.ts
Copy link
Copy Markdown

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

♻️ Duplicate comments (3)
playgrounds/solid-start/package.json (1)

10-14: Same runtime / dev-only concern as commented in Nuxt playground.
See previous note; ensure @orpc/json-schema is available in production builds.

playgrounds/astro/package.json (1)

12-18: Same runtime / dev-only concern as commented in Nuxt playground.
Verify whether @orpc/json-schema should move from devDependencies to dependencies.

playgrounds/svelte-kit/package.json (1)

14-18: Same runtime / dev-only concern as commented in Nuxt playground.
Confirm correct placement of @orpc/json-schema.

🧹 Nitpick comments (11)
playgrounds/solid-start/src/routes/api/[...rest].ts (1)

20-24: Plugin configuration follows the correct pattern.

The new plugin is properly configured with the ZodToJsonSchemaConverter to maintain compatibility with existing Zod schemas while leveraging the more flexible JSON Schema coercion system.

Consider adding a comment about the experimental nature of the plugin:

+    // Using experimental JSON Schema-based coercion plugin
     new SmartCoercionPlugin({
       schemaConverters: [
         new ZodToJsonSchemaConverter(),
       ],
     }),
packages/json-schema/README.md (2)

49-61: Improve readability by varying sentence beginnings.

The package descriptions all start with similar patterns, making them repetitive. Consider varying the sentence structures for better readability.

- [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Build your API contract.
- [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build your API or implement API contract.
- [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety.
- [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests.
+ [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Build your API contract.
+ [@orpc/server](https://www.npmjs.com/package/@orpc/server): Create your API or implement API contract.
+ [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety.
+ [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests.

70-70: Add alt text for accessibility.

The sponsors image is missing alt text, which is important for accessibility.

-    <img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg'/>
+    <img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg' alt='Sponsors'/>
packages/json-schema/src/smart-coercion-plugin.test.ts (1)

5-37: LGTM: Basic functionality tests are correct.

The test structure properly simulates the plugin's interceptor behavior and covers fundamental coercion scenarios.

Consider expanding test coverage to include:

  • Error handling scenarios (invalid inputs, malformed schemas)
  • Complex schema types (nested objects, arrays, unions)
  • Native type coercion (Date, BigInt, URL, etc.)
  • Edge cases (null, undefined, empty values)

Example additional test:

expect(await coerce(z.object({ date: z.date() }), { date: '2023-01-01' })).toEqual({ date: new Date('2023-01-01') })
apps/content/docs/openapi/plugins/smart-coercion.md (1)

82-82: Simplify the wording for better readability.

The phrase "with the exception of" can be replaced with a more concise alternative.

Apply this diff to improve readability:

-The built-in [JSON Schema Converters](/docs/openapi/openapi-specification#generating-specifications) handle these cases (with the exception of some experimental converters).
+The built-in [JSON Schema Converters](/docs/openapi/openapi-specification#generating-specifications) handle these cases (except for some experimental converters).
packages/json-schema/src/coercer.test.ts (4)

7-12: Fix typo in test description.

The test description contains a grammatical error.

-  it('do no thing with boolean/any schema', () => {
+  it('does nothing with boolean/any schema', () => {

33-37: Address the TODO comment for multiple types test.

There's an unfinished test case for coercing with multiple types including 'null'.

Would you like me to help implement this test case or open an issue to track this?


52-52: Use regex literal instead of RegExp constructor.

Static analysis correctly identifies that a regex literal would be cleaner here.

-    expect(coercer.coerce({ 'type': 'string', 'x-native-type': 'regexp' } as any, '/abc/i')).toEqual(new RegExp('abc', 'i'))
+    expect(coercer.coerce({ 'type': 'string', 'x-native-type': 'regexp' } as any, '/abc/i')).toEqual(/abc/i)

258-280: Add type cast for consistency.

For consistency with other tests, add the as any type cast to the schema.

       },
       required: ['a'],
-    }
+    } as any
packages/json-schema/src/coercer.ts (2)

121-123: Remove unnecessary type assertion.

The type assertion as JsonSchema | undefined is redundant here.

            const itemSchema: JsonSchema | undefined = Array.isArray(schema.items)
              ? schema.additionalItems
-              : schema.items as JsonSchema | undefined
+              : schema.items

169-170: Consider caching compiled regex patterns for better performance.

Creating RegExp objects on every coercion call could impact performance when processing many objects with the same schema.

Consider caching the compiled regex patterns at the schema level or in a WeakMap to avoid repeated compilation of the same patterns.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb23f2f and b68f5cf.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (37)
  • apps/content/.vitepress/config.ts (1 hunks)
  • apps/content/docs/openapi/plugins/smart-coercion.md (1 hunks)
  • packages/json-schema/.gitignore (1 hunks)
  • packages/json-schema/README.md (1 hunks)
  • packages/json-schema/package.json (1 hunks)
  • packages/json-schema/src/coercer.test.ts (1 hunks)
  • packages/json-schema/src/coercer.ts (1 hunks)
  • packages/json-schema/src/index.ts (1 hunks)
  • packages/json-schema/src/smart-coercion-plugin.test.ts (1 hunks)
  • packages/json-schema/src/smart-coercion-plugin.ts (1 hunks)
  • packages/json-schema/src/types.ts (1 hunks)
  • packages/json-schema/tsconfig.json (1 hunks)
  • packages/openapi/src/schema-converter.ts (1 hunks)
  • packages/zod/package.json (1 hunks)
  • packages/zod/src/converter.test.ts (9 hunks)
  • packages/zod/src/converter.ts (8 hunks)
  • packages/zod/src/zod4/coercer.ts (1 hunks)
  • packages/zod/src/zod4/converter.native.test.ts (1 hunks)
  • packages/zod/src/zod4/converter.number.test.ts (1 hunks)
  • packages/zod/src/zod4/converter.structure.test.ts (2 hunks)
  • packages/zod/src/zod4/converter.ts (4 hunks)
  • packages/zod/tests/shared.ts (1 hunks)
  • packages/zod/tsconfig.json (1 hunks)
  • playgrounds/astro/package.json (1 hunks)
  • playgrounds/astro/src/pages/api/[...rest].ts (2 hunks)
  • playgrounds/contract-first/package.json (1 hunks)
  • playgrounds/contract-first/src/main.ts (2 hunks)
  • playgrounds/next/package.json (1 hunks)
  • playgrounds/next/src/app/api/[[...rest]]/route.ts (2 hunks)
  • playgrounds/nuxt/package.json (1 hunks)
  • playgrounds/nuxt/server/routes/api/[...].ts (2 hunks)
  • playgrounds/solid-start/package.json (1 hunks)
  • playgrounds/solid-start/src/routes/api/[...rest].ts (2 hunks)
  • playgrounds/svelte-kit/package.json (1 hunks)
  • playgrounds/svelte-kit/src/routes/api/[...rest]/+server.ts (2 hunks)
  • playgrounds/tanstack-start/package.json (1 hunks)
  • playgrounds/tanstack-start/src/routes/api/$.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (11)
packages/zod/tests/shared.ts (1)
packages/openapi/src/schema.ts (1)
  • JSONSchema (6-6)
playgrounds/solid-start/src/routes/api/[...rest].ts (1)
packages/zod/src/converter.ts (1)
  • ZodToJsonSchemaConverter (77-695)
playgrounds/tanstack-start/src/routes/api/$.ts (1)
packages/zod/src/converter.ts (1)
  • ZodToJsonSchemaConverter (77-695)
playgrounds/next/src/app/api/[[...rest]]/route.ts (1)
packages/zod/src/converter.ts (1)
  • ZodToJsonSchemaConverter (77-695)
playgrounds/astro/src/pages/api/[...rest].ts (1)
packages/zod/src/converter.ts (1)
  • ZodToJsonSchemaConverter (77-695)
playgrounds/svelte-kit/src/routes/api/[...rest]/+server.ts (1)
packages/zod/src/converter.ts (1)
  • ZodToJsonSchemaConverter (77-695)
playgrounds/nuxt/server/routes/api/[...].ts (1)
packages/zod/src/converter.ts (1)
  • ZodToJsonSchemaConverter (77-695)
packages/json-schema/src/smart-coercion-plugin.ts (8)
packages/openapi/src/schema-converter.ts (3)
  • ConditionalSchemaConverter (34-36)
  • SchemaConverter (30-32)
  • CompositeSchemaConverter (38-54)
packages/server/src/context.ts (1)
  • Context (1-1)
packages/server/src/adapters/standard/plugin.ts (1)
  • StandardHandlerPlugin (5-8)
packages/contract/src/schema.ts (1)
  • AnySchema (7-7)
packages/json-schema/src/types.ts (1)
  • JsonSchema (6-9)
packages/shared/src/array.ts (1)
  • toArray (1-3)
packages/server/src/adapters/standard/handler.ts (1)
  • StandardHandlerOptions (27-48)
packages/json-schema/src/coercer.ts (11)
  • schema (15-336)
  • value (338-346)
  • value (348-356)
  • value (358-370)
  • value (372-374)
  • value (376-384)
  • value (386-395)
  • value (397-399)
  • value (401-403)
  • value (405-413)
  • value (415-421)
packages/zod/src/zod4/converter.ts (2)
packages/openapi/src/schema.ts (1)
  • JSONSchemaFormat (5-5)
packages/json-schema/src/coercer.ts (1)
  • schema (15-336)
packages/zod/src/converter.test.ts (2)
packages/openapi/src/schema.ts (1)
  • JSONSchema (6-6)
packages/zod/src/schemas/url.ts (1)
  • url (6-20)
packages/json-schema/src/coercer.test.ts (1)
packages/json-schema/src/coercer.ts (1)
  • schema (15-336)
🪛 LanguageTool
packages/json-schema/README.md

[style] ~51-~51: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... your API or implement API contract. - [@orpc/client](https://www.npmjs.com/package/@...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~52-~52: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... API on the client with type-safety. - [@orpc/openapi](https://www.npmjs.com/package/...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~53-~53: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...I specs and handle OpenAPI requests. - [@orpc/nest](https://www.npmjs.com/package/@or...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~54-~54: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... with NestJS. - [@orpc/react](https://www.npmjs.com/package/@o...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~55-~55: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...with React and React Server Actions. - [@orpc/tanstack-query](https://www.npmjs.com/p...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~56-~56: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...stack.com/query/latest) integration. - [@orpc/vue-colada](https://www.npmjs.com/packa...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~57-~57: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ada](https://pinia-colada.esm.dev/). - [@orpc/hey-api](https://www.npmjs.com/package/...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~58-~58: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...I](https://heyapi.dev/) integration. - [@orpc/zod](https://www.npmjs.com/package/@orp...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~59-~59: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...tps://zod.dev/) doesn't support yet. - [@orpc/valibot](https://www.npmjs.com/package/...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~60-~60: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...rom Valibot. - [@orpc/arktype](https://www.npmjs.com/package/...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

apps/content/docs/openapi/plugins/smart-coercion.md

[style] ~82-~82: ‘with the exception of’ might be wordy. Consider a shorter alternative.
Context: ...ing-specifications) handle these cases (with the exception of some experimental converters). Since th...

(EN_WORDINESS_PREMIUM_WITH_THE_EXCEPTION_OF)

🪛 markdownlint-cli2 (0.17.2)
packages/json-schema/README.md

70-70: Images should have alternate text (alt text)

(MD045, no-alt-text)

🪛 Biome (1.9.4)
packages/json-schema/src/coercer.test.ts

[error] 52-52: Use a regular expression literal instead of the RegExp constructor.

Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.

(lint/complexity/useRegexLiterals)

⏰ 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). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (38)
playgrounds/nuxt/package.json (1)

12-17: Verify the correct section (dependencies vs devDependencies).

@orpc/json-schema looks like it is imported at runtime by the playground’s route handlers (e.g. when the coercion plugin is instantiated inside the server-side API route). If that’s the case Nuxt will need the package in production, so it should live under the regular dependencies key rather than devDependencies, otherwise the built container/image may miss it at runtime.

Please double-check how the package is consumed and move it if necessary.

-  "devDependencies": {
-    "@orpc/client": "next",
-    "@orpc/json-schema": "next",
+  "dependencies": {
+    "@orpc/json-schema": "next"
+  },
+  "devDependencies": {
+    "@orpc/client": "next",
packages/zod/package.json (1)

47-50: No circular dependency detected; please verify @orpc/json-schema’s Zod usage
Running a full tsort of every package.json dependency edge produced no cycles, so adding @orpc/json-schema as a hard dependency in @orpc/zod does not currently introduce a cycle.

Please confirm that packages/json-schema/package.json does not list zod or zod-to-json-schema in either its dependencies or peerDependencies.

  • If you find any Zod‐related entries there, consider moving them to a peerDependency or extracting the conversion logic into a separate package to avoid a cycle.
  • If no such entries exist, the current setup is safe.
playgrounds/contract-first/package.json (1)

14-14: LGTM! Consistent with migration pattern.

The addition of @orpc/json-schema dependency aligns with the broader migration from Zod-specific to JSON Schema-based smart coercion plugin across all playgrounds.

Note: The "next" tag indicates a pre-release version, which appears intentional for this migration.

playgrounds/tanstack-start/package.json (1)

14-14: LGTM! Consistent dependency addition.

The addition of @orpc/json-schema dependency follows the same pattern as other playgrounds in this migration.

playgrounds/next/package.json (1)

14-14: LGTM! Consistent with migration pattern.

The dependency addition matches the pattern used across all playgrounds for this migration.

apps/content/.vitepress/config.ts (1)

211-211: Smart Coercion docs link verified

The file apps/content/docs/openapi/plugins/smart-coercion.md exists alongside zod-smart-coercion.md, so the sidebar link is valid. LGTM—approving this addition.

packages/zod/src/zod4/converter.number.test.ts (1)

38-38: LGTM! Proper JSON Schema extension for native type annotation.

The addition of 'x-native-type': 'bigint' correctly follows JSON Schema extension conventions (using the x- prefix) and provides necessary type information for the smart coercion plugin.

packages/zod/tsconfig.json (1)

5-5: LGTM! Clean integration of the new package reference.

The addition of the json-schema package reference follows the established pattern and correctly integrates the new @orpc/json-schema package into the Zod package's TypeScript project configuration.

packages/zod/src/zod4/converter.native.test.ts (1)

23-23: LGTM! Correctly adds native type annotation for date schema.

The addition of 'x-native-type': 'date' to the expected JSON Schema output properly reflects the new native type annotation system introduced for enhanced coercion capabilities.

packages/json-schema/src/index.ts (1)

1-3: LGTM! Clean barrel export pattern for the new package.

The entry point file follows best practices by consolidating exports from core modules (coercer, smart-coercion-plugin, and types) into a single interface, making the API more user-friendly.

packages/zod/src/zod4/converter.structure.test.ts (4)

61-61: LGTM! Correctly adds native type annotation for set schema.

The addition of 'x-native-type': 'set' to the expected JSON Schema output properly supports the new native type annotation system for Set types.


66-67: LGTM! Consistent native type annotations for optional set schema.

The native type annotations are correctly applied to both input and output schemas for the optional set test case, maintaining consistency across the coercion system.


112-112: LGTM! Correctly adds native type annotation for map schema.

The addition of 'x-native-type': 'map' to the expected JSON Schema output properly supports the new native type annotation system for Map types.


117-118: LGTM! Consistent native type annotations for optional map schema.

The native type annotations are correctly applied to both input and output schemas for the optional map test case, ensuring proper coercion behavior for Map types with optional values.

playgrounds/tanstack-start/src/routes/api/$.ts (2)

4-5: LGTM! Clean migration to the new JSON Schema-based plugin.

The import changes correctly replace the deprecated ZodSmartCoercionPlugin with the new experimental_SmartCoercionPlugin from @orpc/json-schema, maintaining the same functionality while adopting the more extensible architecture.


21-25: LGTM! Proper configuration of the new smart coercion plugin.

The plugin configuration correctly uses the schemaConverters array with ZodToJsonSchemaConverter, providing the same coercion capabilities as the deprecated plugin while enabling future extensibility with additional schema converters.

packages/json-schema/tsconfig.json (1)

1-17: LGTM! Well-structured TypeScript configuration.

The configuration properly extends the base lib config, establishes correct project references, and uses appropriate include/exclude patterns for a library package.

playgrounds/solid-start/src/routes/api/[...rest].ts (1)

4-5: Migration to JSON Schema-based coercion looks good.

The import changes correctly migrate from the deprecated Zod-specific plugin to the new experimental JSON Schema-based approach. The aliasing of experimental_SmartCoercionPlugin as SmartCoercionPlugin improves readability.

playgrounds/astro/src/pages/api/[...rest].ts (2)

4-5: Consistent migration pattern across playgrounds.

The import changes follow the same pattern as other playgrounds, maintaining consistency in the migration from Zod-specific to JSON Schema-based coercion.


20-24: Plugin configuration is consistent and correct.

The configuration matches the pattern used in other playgrounds, ensuring uniform behavior across different environments.

packages/json-schema/.gitignore (1)

1-26: Comprehensive .gitignore configuration.

The ignore patterns cover all standard artifacts for a Node.js/TypeScript project including build outputs, dependencies, logs, and temporary files. The configuration is well-organized and follows best practices.

packages/zod/tests/shared.ts (1)

11-12: Good type refinement for improved type safety.

The intersection with Record<string, unknown> ensures that the JSON schema objects have string keys, which aligns with the enhanced native type support being introduced in this PR.

playgrounds/svelte-kit/src/routes/api/[...rest]/+server.ts (2)

5-6: Good migration to the new JSON Schema-based plugin.

The import changes correctly replace the Zod-specific plugin with the more flexible JSON Schema-based SmartCoercionPlugin.


20-24: Ensure SmartCoercionPlugin fully replaces ZodSmartCoercionPlugin

All application code now imports experimental_SmartCoercionPlugin as SmartCoercionPlugin from @orpc/json-schema, and there are no remaining references to the old ZodSmartCoercionPlugin.

Please run your coercion test suite (or add new tests) to confirm that the new plugin’s behavior matches the previous implementation.

• Verified in:
– playgrounds/*/src/routes/api/[...rest]
– playgrounds/nuxt/server/routes/api/[...].ts
– playgrounds/next/src/app/api/[[...rest]]/route.ts
– …and other playgrounds under playgrounds/
• Confirmed no ZodSmartCoercionPlugin usage outside of package tests

playgrounds/contract-first/src/main.ts (2)

5-6: Consistent migration pattern across playground files.

The import changes follow the same pattern as other playground files, replacing the Zod-specific plugin with the flexible JSON Schema-based plugin.


21-25: Plugin configuration matches other playground implementations.

The SmartCoercionPlugin configuration with ZodToJsonSchemaConverter is consistent with the pattern used in other playground files.

packages/openapi/src/schema-converter.ts (1)

39-41: Excellent immutability improvement.

Making the converters array readonly prevents accidental mutations and ensures the converter composition remains stable after construction. This is particularly important for the new SmartCoercionPlugin that relies on stable converter arrays.

playgrounds/next/src/app/api/[[...rest]]/route.ts (2)

4-5: Consistent migration pattern completion.

The import changes complete the uniform migration across all playground files, maintaining consistency in the codebase.


19-23: ✅ Migration completeness verified across all playgrounds

No occurrences of ZodSmartCoercionPlugin remain, and every playground now uses SmartCoercionPlugin as intended. Approving these changes.

packages/json-schema/src/types.ts (2)

6-9: LGTM: Comprehensive JSON Schema type support.

The union type covering multiple JSON Schema draft versions provides excellent compatibility and future-proofing.


11-18: LGTM: Well-defined native type enum.

The enum effectively captures native JavaScript types that need special handling in JSON Schema contexts. The string literal values are appropriate for use as JSON Schema extension properties.

playgrounds/nuxt/server/routes/api/[...].ts (2)

3-4: LGTM: Correct import migration.

The import change from the Zod-specific plugin to the experimental JSON Schema-based plugin is appropriate for the new architecture.


18-22: LGTM: Proper plugin configuration.

The plugin instantiation with schemaConverters configuration correctly bridges Zod schemas to JSON Schema format, maintaining compatibility while using the new plugin architecture.

packages/json-schema/package.json (1)

1-46: LGTM: Well-structured package configuration.

The package.json follows oRPC conventions with proper ES module configuration, appropriate dependencies, and correct build setup.

packages/zod/src/converter.ts (1)

35-35: Native type annotations are correctly implemented.

The addition of x-native-type properties to the JSON Schema output for native JavaScript types (BigInt, Date, Set, Map, RegExp, URL) is implemented correctly and consistently. This metadata will enable proper coercion in the smart coercion plugin.

Also applies to: 286-290, 308-312, 470-474, 489-501, 643-643, 660-664, 668-672

packages/json-schema/src/smart-coercion-plugin.ts (1)

26-40: Plugin implementation looks good.

The smart coercion plugin is well-implemented with proper caching and async support. The use of WeakMap for caching ensures that schemas can be garbage collected when no longer referenced.

packages/zod/src/zod4/converter.ts (1)

30-30: Native type annotations correctly implemented for Zod v4.

The implementation of x-native-type annotations for Zod v4 schemas is consistent with the main converter and correctly handles all native JavaScript types.

Also applies to: 237-241, 245-249, 407-418, 423-428

packages/zod/src/converter.test.ts (1)

14-15: Test coverage for native type annotations is comprehensive.

The test updates correctly verify that x-native-type properties are included in the JSON Schema output for all native JavaScript types. The consistent property quoting and type refinements ensure proper TypeScript type checking.

Also applies to: 145-147, 169-171, 346-346, 351-351, 540-544, 554-555, 565-576, 592-595

Comment thread packages/zod/src/zod4/coercer.ts
Comment thread packages/json-schema/src/coercer.ts Outdated
Comment thread packages/json-schema/src/coercer.ts
Comment thread packages/json-schema/src/coercer.ts
@codecov
Copy link
Copy Markdown

codecov Bot commented Jul 11, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@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/json-schema/src/coercer.test.ts (3)

1-1: Consider removing the eslint disable comment.

The prefer-regex-literals rule is disabled, but it would be better to fix the actual issue (line 53) rather than disabling the rule for the entire file.


34-35: Address or remove the TODO comment.

The commented-out test suggests incomplete functionality for multiple type coercion. This should either be implemented and uncommented, or removed if not needed.

Would you like me to help implement the missing multiple type coercion functionality or create an issue to track this task?


53-53: Use regex literal instead of RegExp constructor.

The static analysis tool correctly identifies this as an issue - regex literals are more readable and avoid escaping issues.

-expect(coercer.coerce({ 'type': 'string', 'x-native-type': 'regexp' } as any, '/abc/i')).toEqual(new RegExp('abc', 'i'))
+expect(coercer.coerce({ 'type': 'string', 'x-native-type': 'regexp' } as any, '/abc/i')).toEqual(/abc/i)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51b6ebb and b5b729c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • apps/content/docs/openapi/plugins/smart-coercion.md (1 hunks)
  • packages/json-schema/src/coercer.test.ts (1 hunks)
  • packages/json-schema/src/coercer.ts (1 hunks)
  • packages/zod/package.json (1 hunks)
  • playgrounds/astro/package.json (1 hunks)
  • playgrounds/contract-first/package.json (1 hunks)
  • playgrounds/next/package.json (1 hunks)
  • playgrounds/nuxt/package.json (1 hunks)
  • playgrounds/solid-start/package.json (1 hunks)
  • playgrounds/svelte-kit/package.json (1 hunks)
  • playgrounds/tanstack-start/package.json (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • playgrounds/svelte-kit/package.json
  • playgrounds/contract-first/package.json
  • playgrounds/next/package.json
🚧 Files skipped from review as they are similar to previous changes (7)
  • playgrounds/astro/package.json
  • playgrounds/tanstack-start/package.json
  • playgrounds/solid-start/package.json
  • packages/zod/package.json
  • playgrounds/nuxt/package.json
  • apps/content/docs/openapi/plugins/smart-coercion.md
  • packages/json-schema/src/coercer.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/json-schema/src/coercer.test.ts (1)
packages/json-schema/src/coercer.ts (1)
  • schema (15-336)
🪛 Biome (1.9.4)
packages/json-schema/src/coercer.test.ts

[error] 53-53: Use a regular expression literal instead of the RegExp constructor.

Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.

(lint/complexity/useRegexLiterals)

⏰ 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). (2)
  • GitHub Check: publish-commit
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (11)
packages/json-schema/src/coercer.test.ts (11)

7-12: Good coverage of boolean and any schema edge cases.

The tests correctly verify that boolean schemas and empty schemas pass through values unchanged, including the not: {} case.


14-31: Comprehensive primitive type coercion tests.

The tests cover successful coercion cases (string to number/boolean/integer) and failed coercion cases where the original value is preserved. The edge cases with undefined values are particularly valuable.


39-76: Excellent coverage of native type coercion.

The tests thoroughly validate coercion for Date, BigInt, URL, RegExp, Set, and Map types, including both successful conversions and fallback behavior for invalid inputs. The edge cases for Set and Map coercion are particularly well-tested.


78-89: Solid enum and const value coercion tests.

The tests validate string-to-number and string-to-boolean coercion within enum constraints, and properly test fallback behavior for invalid values.


91-121: Thorough array and tuple coercion coverage.

The tests cover both JSON Schema draft-07 (items with additionalItems) and draft-2020-12 (prefixItems with items) array schemas, ensuring compatibility across schema versions.


123-156: Comprehensive object coercion tests.

The tests validate property coercion, pattern properties, additional properties, required fields, and array-to-object conversion. The combination of different property types demonstrates the recursive nature of the coercion.


158-196: Well-designed union type tests.

The tests effectively validate anyOf schema handling, including preference for exact matches and complex nested union scenarios. The array tuple union test is particularly sophisticated.


198-208: Excellent discriminated union validation.

The tests demonstrate proper handling of discriminated unions based on constant values, ensuring the correct branch is chosen and appropriate coercion is applied.


210-222: Good intersection type coverage.

The allOf tests validate that all schemas in the intersection are satisfied and that properties from multiple schemas are properly merged and coerced.


224-257: Robust recursive schema testing.

The test validates $ref resolution and recursive coercion with proper component resolution. The nested structure demonstrates the coercer's ability to handle complex recursive types.


259-298: Excellent complex structure integration test.

This test validates the complete coercion pipeline with nested objects, arrays, native types, and Sets, demonstrating the full capability of the coercer in real-world scenarios.

@dinwwwh dinwwwh requested a review from Copilot July 11, 2025 01:57
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jul 11, 2025

More templates

@orpc/arktype

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

@orpc/client

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

@orpc/contract

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

@orpc/experimental-durable-event-iterator

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

@orpc/hey-api

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

@orpc/json-schema

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

@orpc/nest

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

@orpc/openapi

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

@orpc/openapi-client

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

@orpc/react

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

@orpc/react-query

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

@orpc/server

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

@orpc/shared

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

@orpc/solid-query

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

@orpc/standard-server

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

@orpc/standard-server-aws-lambda

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

@orpc/standard-server-fetch

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

@orpc/standard-server-node

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

@orpc/standard-server-peer

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

@orpc/svelte-query

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

@orpc/tanstack-query

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

@orpc/trpc

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

@orpc/valibot

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

@orpc/vue-colada

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

@orpc/vue-query

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

@orpc/zod

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

commit: c5571fc

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Add the experimental Smart Coercion Plugin for deep JSON Schema–based type coercion and wire it into all playgrounds, update the Zod converters to emit x-native-type metadata, and include a new @orpc/json-schema package with implementation, tests, and docs.

  • Replace ZodSmartCoercionPlugin with the new Smart Coercion Plugin and update imports in all playground entry points
  • Add @orpc/json-schema as a dependency in playgrounds and workspace packages
  • Enhance Zod converters/tests to annotate schemas with x-native-type and ship a full coercer implementation

Reviewed Changes

Copilot reviewed 38 out of 39 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
playgrounds/*/src/routes/api/... Swapped in SmartCoercionPlugin import/usage
playgrounds/*/package.json Added @orpc/json-schema devDependency
packages/zod/src/{converter,coercer}.ts Inject x-native-type in schemas and deprecate old plugin
packages/zod/tests Adjusted JSONSchema types and expected test outputs
packages/openapi/src/schema-converter.ts Made converter list readonly
packages/json-schema/{tsconfig,src/types.ts,...} New package with types, plugin, coercer, tests, README
apps/content/docs/openapi/plugins/smart-coercion.md Added Smart Coercion plugin documentation
apps/content/.vitepress/config.ts Updated sidebar navigation entries
apps/content/docs/openapi/integrations/implement-contract-in-nest.md Removed stray blank line
Comments suppressed due to low confidence (2)

apps/content/docs/openapi/plugins/smart-coercion.md:53

  • The usage example calls new ZodToJsonSchemaConverter() but doesn’t import it. Add import { ZodToJsonSchemaConverter } from '@orpc/zod' above the snippet.
      schemaConverters: [

apps/content/.vitepress/config.ts:212

  • [nitpick] Consider renaming this sidebar label to 'Zod Smart Coercion (legacy)' for clarity that it’s the deprecated implementation.
            { text: 'Zod Smart Coercion (old)', link: '/docs/openapi/plugins/zod-smart-coercion' },

Comment thread packages/json-schema/README.md
Copy link
Copy Markdown

@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 (5)
packages/json-schema/src/coercer.test.ts (5)

1-1: Remove or justify the eslint disable comment.

The prefer-regex-literals rule is disabled at the file level, but the static analysis tool still flags this issue on line 55. Either remove the disable comment if it's not needed, or ensure it's properly configured.


7-7: Fix the typo in the test description.

"do no thing" should be "do nothing".

-  it('do no thing with boolean/any schema', () => {
+  it('do nothing with boolean/any schema', () => {

34-35: Address the TODO comment or remove it.

The TODO comment suggests incomplete functionality for multiple types coercion. Consider either implementing the test or removing the comment if it's not needed.

Would you like me to help implement this test case or should this TODO be removed?


41-50: Consider improving type safety for native type tests.

The tests use as any to bypass TypeScript's type checking for the x-native-type extension. While this may be necessary for testing extensions, consider creating a proper type definition for these extended schemas.

Consider creating a type definition for extended JSON schemas:

interface ExtendedJsonSchema extends JsonSchema {
  'x-native-type'?: string;
}

55-55: Use regex literal instead of RegExp constructor.

As flagged by the static analysis tool, regex literals are preferred over the RegExp constructor for better readability and static analysis.

-    expect(coercer.coerce({ 'type': 'string', 'x-native-type': 'regexp' } as any, '/abc/i')).toEqual(new RegExp('abc', 'i'))
+    expect(coercer.coerce({ 'type': 'string', 'x-native-type': 'regexp' } as any, '/abc/i')).toEqual(/abc/i)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4799c75 and c5571fc.

📒 Files selected for processing (3)
  • apps/content/docs/openapi/plugins/smart-coercion.md (1 hunks)
  • packages/json-schema/src/coercer.test.ts (1 hunks)
  • packages/json-schema/src/coercer.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/content/docs/openapi/plugins/smart-coercion.md
  • packages/json-schema/src/coercer.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/json-schema/src/coercer.test.ts (1)
packages/json-schema/src/coercer.ts (1)
  • schema (17-338)
🪛 Biome (1.9.4)
packages/json-schema/src/coercer.test.ts

[error] 55-55: Use a regular expression literal instead of the RegExp constructor.

Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.

(lint/complexity/useRegexLiterals)

⏰ 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). (3)
  • GitHub Check: publish-commit
  • GitHub Check: lint
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
packages/json-schema/src/coercer.test.ts (8)

64-78: Excellent test coverage for Set and Map coercion edge cases.

The tests properly verify that when coercion fails for Sets and Maps (due to duplicates or invalid array structures), the coercer falls back to returning the original array. This demonstrates good understanding of the coercion logic.


83-86: Verify the enum coercion logic for string-to-number conversion.

The test expects '123' to be coerced to 123 when the enum contains the number 123. This behavior should be documented or verified as intentional, as it represents implicit type coercion that might not be expected by all users.

Please confirm that the string-to-number coercion behavior in enums is intentional and documented.


101-123: Comprehensive coverage of array/tuple coercion patterns.

The tests cover both JSON Schema draft-07 (items as array + additionalItems) and draft-2020 (prefixItems + items) patterns. The expected behavior where additional items beyond the tuple length are only coerced if they match the additional/items schema is correctly tested.


152-157: Interesting test case for array-to-object coercion.

The test demonstrates that arrays can be coerced to objects when the schema expects numeric string keys. This is a useful edge case that shows the coercer's flexibility in handling different input formats.


160-198: Well-designed union type tests with increasing complexity.

The tests progressively increase in complexity:

  1. Simple union with different types
  2. Union with objects having different required properties
  3. Union with different tuple schemas

This demonstrates thorough understanding of how the coercer should handle ambiguous cases and prefer the most specific matching schema.


200-210: Excellent discriminated union test case.

The test properly verifies that discriminated unions work correctly by using the discriminator field (t) to determine which schema variant to apply, then coercing the value field (v) according to the selected schema.


226-259: Comprehensive recursive schema test with proper component resolution.

The test demonstrates proper handling of $ref resolution using the components option, and shows that recursive coercion works correctly with proper fallback behavior when coercion becomes impossible at deeper levels.


261-300: Excellent complex integration test.

This test effectively combines multiple coercion features:

  • Primitive type coercion (boolean, number)
  • Native type coercion (Date, URL, Set)
  • Nested object and array structures
  • Mixed coercion scenarios

This provides good confidence that the coercer works correctly in real-world scenarios.

@dinwwwh dinwwwh merged commit e5e2613 into main Jul 11, 2025
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: ArkType coercer

2 participants