@orpc/zod 0.0.0-next.75f1e0e β†’ 0.0.0-next.7605f6c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,22 +1,25 @@
1
1
  <div align="center">
2
- <image align="center" src="https://orpc.unnoq.com/logo.webp" width=280 alt="oRPC logo" />
2
+ <image align="center" src="https://orpc.dev/logo.webp" width=280 alt="oRPC logo" />
3
3
  </div>
4
4
 
5
5
  <h1></h1>
6
6
 
7
7
  <div align="center">
8
- <a href="https://codecov.io/gh/unnoq/orpc">
9
- <img alt="codecov" src="https://codecov.io/gh/unnoq/orpc/branch/main/graph/badge.svg">
8
+ <a href="https://codecov.io/gh/middleapi/orpc">
9
+ <img alt="codecov" src="https://codecov.io/gh/middleapi/orpc/branch/main/graph/badge.svg">
10
10
  </a>
11
11
  <a href="https://www.npmjs.com/package/@orpc/zod">
12
12
  <img alt="weekly downloads" src="https://img.shields.io/npm/dw/%40orpc%2Fzod?logo=npm" />
13
13
  </a>
14
- <a href="https://github.com/unnoq/orpc/blob/main/LICENSE">
15
- <img alt="MIT License" src="https://img.shields.io/github/license/unnoq/orpc?logo=open-source-initiative" />
14
+ <a href="https://github.com/middleapi/orpc/blob/main/LICENSE">
15
+ <img alt="MIT License" src="https://img.shields.io/github/license/middleapi/orpc?logo=open-source-initiative" />
16
16
  </a>
17
17
  <a href="https://discord.gg/TXEbwRBvQn">
18
18
  <img alt="Discord" src="https://img.shields.io/discord/1308966753044398161?color=7389D8&label&logo=discord&logoColor=ffffff" />
19
19
  </a>
20
+ <a href="https://deepwiki.com/middleapi/orpc">
21
+ <img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki">
22
+ </a>
20
23
  </div>
21
24
 
22
25
  <h3 align="center">Typesafe APIs Made Simple πŸͺ„</h3>
@@ -30,7 +33,8 @@
30
33
  - **πŸ”— End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server.
31
34
  - **πŸ“˜ First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard.
32
35
  - **πŸ“ Contract-First Development**: Optionally define your API contract before implementation.
33
- - **βš™οΈ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more.
36
+ - **πŸ” First-Class OpenTelemetry**: Seamlessly integrate with OpenTelemetry for observability.
37
+ - **βš™οΈ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), SWR, Pinia Colada, and more.
34
38
  - **πŸš€ Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
35
39
  - **πŸ”  Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
36
40
  - **πŸ—ƒοΈ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more.
@@ -38,11 +42,10 @@
38
42
  - **πŸ“‘ SSE & Streaming**: Enjoy full type-safe support for SSE and streaming.
39
43
  - **🌍 Multi-Runtime Support**: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond.
40
44
  - **πŸ”Œ Extendability**: Easily extend functionality with plugins, middleware, and interceptors.
41
- - **πŸ›‘οΈ Reliability**: Well-tested, TypeScript-based, production-ready, and MIT licensed.
42
45
 
43
46
  ## Documentation
44
47
 
45
- You can find the full documentation [here](https://orpc.unnoq.com).
48
+ You can find the full documentation [here](https://orpc.dev).
46
49
 
47
50
  ## Packages
48
51
 
@@ -50,9 +53,11 @@ You can find the full documentation [here](https://orpc.unnoq.com).
50
53
  - [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build your API or implement API contract.
51
54
  - [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety.
52
55
  - [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests.
56
+ - [@orpc/otel](https://www.npmjs.com/package/@orpc/otel): [OpenTelemetry](https://opentelemetry.io/) integration for observability.
53
57
  - [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
54
58
  - [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
55
59
  - [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): [TanStack Query](https://tanstack.com/query/latest) integration.
60
+ - [@orpc/experimental-react-swr](https://www.npmjs.com/package/@orpc/experimental-react-swr): [SWR](https://swr.vercel.app/) integration.
56
61
  - [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
57
62
  - [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
58
63
  - [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
@@ -72,7 +77,7 @@ More schemas that [Zod](https://zod.dev/) doesn't support yet, and provides `Zod
72
77
 
73
78
  ```ts
74
79
  import { oz } from '@orpc/zod'
75
- import { z } from 'zod'
80
+ import { z } from 'zod/v3'
76
81
 
77
82
  const Example = z.object({
78
83
  url: oz.url(),
@@ -86,7 +91,7 @@ const Example = z.object({
86
91
 
87
92
  ```ts
88
93
  import { OpenAPIGenerator } from '@orpc/openapi'
89
- import { ZodToJsonSchemaConverter } from '@orpc/zod'
94
+ import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'
90
95
 
91
96
  const openAPIGenerator = new OpenAPIGenerator({
92
97
  schemaConverters: [new ZodToJsonSchemaConverter()],
@@ -111,7 +116,7 @@ const specFromRouter = await openAPIGenerator.generate(router, {
111
116
 
112
117
  ```ts
113
118
  import { oz } from '@orpc/zod'
114
- import { z } from 'zod'
119
+ import * as z from 'zod'
115
120
 
116
121
  const InputSchema = oz.openapi(
117
122
  z.object({
@@ -129,12 +134,119 @@ const InputSchema = oz.openapi(
129
134
 
130
135
  ## Sponsors
131
136
 
132
- <p align="center">
133
- <a href="https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg">
134
- <img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg'/>
135
- </a>
137
+ If you find oRPC valuable and would like to support its development, you can do so here: [GitHub Sponsors](https://github.com/sponsors/dinwwwh).
138
+
139
+ ### πŸ† Platinum Sponsor
140
+
141
+ <table>
142
+ <tr>
143
+ <td align="center"><a href="https://screenshotone.com/?ref=orpc" target="_blank" rel="noopener" title="ScreenshotOne.com"><img src="https://avatars.githubusercontent.com/u/97035603?v=4" width="279" alt="ScreenshotOne.com"/><br />ScreenshotOne.com</a></td>
144
+ </tr>
145
+ </table>
146
+
147
+ ### πŸ₯ˆ Silver Sponsor
148
+
149
+ <table>
150
+ <tr>
151
+ <td align="center"><a href="https://misskey.io/?ref=orpc" target="_blank" rel="noopener" title="ζ‘δΈŠγ•γ‚“"><img src="https://avatars.githubusercontent.com/u/37681609?u=0dd4c7e4ba937cbb52b068c55914b1d8164dc0c7&amp;v=4" width="209" alt="ζ‘δΈŠγ•γ‚“"/><br />ζ‘δΈŠγ•γ‚“</a></td>
152
+ </tr>
153
+ </table>
154
+
155
+ ### Generous Sponsors
156
+
157
+ <table>
158
+ <tr>
159
+ <td align="center"><a href="https://github.com/ln-markets?ref=orpc" target="_blank" rel="noopener" title="LN Markets"><img src="https://avatars.githubusercontent.com/u/70597625?v=4" width="167" alt="LN Markets"/><br />LN Markets</a></td>
160
+ </tr>
161
+ </table>
162
+
163
+ ### Sponsors
164
+
165
+ <table>
166
+ <tr>
167
+ <td align="center"><a href="https://github.com/hrmcdonald?ref=orpc" target="_blank" rel="noopener" title="Reece McDonald"><img src="https://avatars.githubusercontent.com/u/39349270?v=4" width="139" alt="Reece McDonald"/><br />Reece McDonald</a></td>
168
+ <td align="center"><a href="https://github.com/nicognaW?ref=orpc" target="_blank" rel="noopener" title="nk"><img src="https://avatars.githubusercontent.com/u/66731869?u=4699bda3a9092d3ec34fbd959450767bcc8b8b6d&amp;v=4" width="139" alt="nk"/><br />nk</a></td>
169
+ <td align="center"><a href="https://github.com/supastarter?ref=orpc" target="_blank" rel="noopener" title="supastarter"><img src="https://avatars.githubusercontent.com/u/110960143?v=4" width="139" alt="supastarter"/><br />supastarter</a></td>
170
+ <td align="center"><a href="https://github.com/divmgl?ref=orpc" target="_blank" rel="noopener" title="Dexter Miguel"><img src="https://avatars.githubusercontent.com/u/5452298?u=645993204be8696c085ecf0d228c3062efe2ed65&amp;v=4" width="139" alt="Dexter Miguel"/><br />Dexter Miguel</a></td>
171
+ <td align="center"><a href="https://github.com/herrfugbaum?ref=orpc" target="_blank" rel="noopener" title="herrfugbaum"><img src="https://avatars.githubusercontent.com/u/12859776?u=644dc1666d0220bc0468eb0de3c56b919f635b16&amp;v=4" width="139" alt="herrfugbaum"/><br />herrfugbaum</a></td>
172
+ <td align="center"><a href="https://github.com/ryota-murakami?ref=orpc" target="_blank" rel="noopener" title="Ryota Murakami"><img src="https://avatars.githubusercontent.com/u/5501268?u=599389e03340734325726ca3f8f423c021d47d7f&amp;v=4" width="139" alt="Ryota Murakami"/><br />Ryota Murakami</a></td>
173
+ </tr>
174
+ <tr>
175
+ <td align="center"><a href="https://github.com/dcramer?ref=orpc" target="_blank" rel="noopener" title="David Cramer"><img src="https://avatars.githubusercontent.com/u/23610?v=4" width="139" alt="David Cramer"/><br />David Cramer</a></td>
176
+ <td align="center"><a href="https://github.com/valerii15298?ref=orpc" target="_blank" rel="noopener" title="Valerii Petryniak"><img src="https://avatars.githubusercontent.com/u/44531564?u=88ac74d9bacd20401518441907acad21063cd397&amp;v=4" width="139" alt="Valerii Petryniak"/><br />Valerii Petryniak</a></td>
177
+ <td align="center"><a href="https://github.com/letstri?ref=orpc" target="_blank" rel="noopener" title="Valerii Strilets"><img src="https://avatars.githubusercontent.com/u/13253748?u=c7b10399ccc8f8081e24db94ec32cd9858e86ac3&amp;v=4" width="139" alt="Valerii Strilets"/><br />Valerii Strilets</a></td>
178
+ <td align="center"><a href="https://github.com/K-Mistele?ref=orpc" target="_blank" rel="noopener" title="Kyle Mistele"><img src="https://avatars.githubusercontent.com/u/18430555?u=3afebeb81de666e35aaac3ed46f14159d7603ffb&amp;v=4" width="139" alt="Kyle Mistele"/><br />Kyle Mistele</a></td>
179
+ <td align="center"><a href="https://github.com/andrewpeters9?ref=orpc" target="_blank" rel="noopener" title="Andrew Peters"><img src="https://avatars.githubusercontent.com/u/36251325?v=4" width="139" alt="Andrew Peters"/><br />Andrew Peters</a></td>
180
+ <td align="center"><a href="https://github.com/R44VC0RP?ref=orpc" target="_blank" rel="noopener" title="Ryan Vogel"><img src="https://avatars.githubusercontent.com/u/89211796?u=1857347b9787d8d8a7ea5bfc333f96be92d5a683&amp;v=4" width="139" alt="Ryan Vogel"/><br />Ryan Vogel</a></td>
181
+ </tr>
182
+ <tr>
183
+ <td align="center"><a href="https://github.com/christ12938?ref=orpc" target="_blank" rel="noopener" title="christ12938"><img src="https://avatars.githubusercontent.com/u/25758598?v=4" width="139" alt="christ12938"/><br />christ12938</a></td>
184
+ <td align="center"><a href="https://github.com/peter-adam-dy?ref=orpc" target="_blank" rel="noopener" title="Peter Adam"><img src="https://avatars.githubusercontent.com/u/132129459?u=4f3dbbb3b443990b56acb7d6a5d11ed2c555f6db&amp;v=4" width="139" alt="Peter Adam"/><br />Peter Adam</a></td>
185
+ <td align="center"><a href="https://github.com/yukimotochern?ref=orpc" target="_blank" rel="noopener" title="Chen, Zhi-Yuan"><img src="https://avatars.githubusercontent.com/u/20896173?u=945c33fc21725e4d566a0d02afc54b136ca1d67a&amp;v=4" width="139" alt="Chen, Zhi-Yuan"/><br />Chen, Zhi-Yuan</a></td>
186
+ <td align="center"><a href="https://github.com/Ryanjso?ref=orpc" target="_blank" rel="noopener" title="Ryan Soderberg"><img src="https://avatars.githubusercontent.com/u/39172778?u=5ed913c31d57e7221b75784abcad48c7ebddde27&amp;v=4" width="139" alt="Ryan Soderberg"/><br />Ryan Soderberg</a></td>
187
+ </tr>
188
+ </table>
189
+
190
+ ### Backers
191
+
192
+ <table>
193
+ <tr>
194
+ <td align="center"><a href="https://github.com/rhinodavid?ref=orpc" target="_blank" rel="noopener" title="David Walsh"><img src="https://avatars.githubusercontent.com/u/5778036?u=b5521f07d2f88c3db2a0dae62b5f2f8357214af0&amp;v=4" width="119" alt="David Walsh"/><br />David Walsh</a></td>
195
+ <td align="center"><a href="https://github.com/Robbe95?ref=orpc" target="_blank" rel="noopener" title="Robbe Vaes"><img src="https://avatars.githubusercontent.com/u/44748019?u=e0232402c045ad4eac7cbd217f1f47e083103b89&amp;v=4" width="119" alt="Robbe Vaes"/><br />Robbe Vaes</a></td>
196
+ <td align="center"><a href="https://github.com/aidansunbury?ref=orpc" target="_blank" rel="noopener" title="Aidan Sunbury"><img src="https://avatars.githubusercontent.com/u/64103161?v=4" width="119" alt="Aidan Sunbury"/><br />Aidan Sunbury</a></td>
197
+ <td align="center"><a href="https://github.com/soonoo?ref=orpc" target="_blank" rel="noopener" title="soonoo"><img src="https://avatars.githubusercontent.com/u/5436405?u=5d0b4aa955c87e30e6bda7f0cccae5402da99528&amp;v=4" width="119" alt="soonoo"/><br />soonoo</a></td>
198
+ <td align="center"><a href="https://github.com/kporten?ref=orpc" target="_blank" rel="noopener" title="Kevin Porten"><img src="https://avatars.githubusercontent.com/u/1839345?u=dc2263d5cfe0d927ce1a0be04a1d55dd6b55405c&amp;v=4" width="119" alt="Kevin Porten"/><br />Kevin Porten</a></td>
199
+ <td align="center"><a href="https://github.com/pumpkinlink?ref=orpc" target="_blank" rel="noopener" title="Denis"><img src="https://avatars.githubusercontent.com/u/11864620?u=5f47bbe6c65d0f6f5cf011021490238e4b0593d0&amp;v=4" width="119" alt="Denis"/><br />Denis</a></td>
200
+ <td align="center"><a href="https://github.com/christopher-kapic?ref=orpc" target="_blank" rel="noopener" title="Christopher Kapic"><img src="https://avatars.githubusercontent.com/u/59740769?u=e7ad4b72b5bf6c9eb1644c26dbf3332a8f987377&amp;v=4" width="119" alt="Christopher Kapic"/><br />Christopher Kapic</a></td>
201
+ </tr>
202
+ <tr>
203
+ <td align="center"><a href="https://github.com/thomasballinger?ref=orpc" target="_blank" rel="noopener" title="Tom Ballinger"><img src="https://avatars.githubusercontent.com/u/458879?u=4b045ac75d721b6ac2b42a74d7d37f61f0414031&amp;v=4" width="119" alt="Tom Ballinger"/><br />Tom Ballinger</a></td>
204
+ <td align="center"><a href="https://github.com/SSam0419?ref=orpc" target="_blank" rel="noopener" title="Sam"><img src="https://avatars.githubusercontent.com/u/102863520?u=3c89611f549d5070be232eb4532f690c8f2e7a65&amp;v=4" width="119" alt="Sam"/><br />Sam</a></td>
205
+ <td align="center"><a href="https://github.com/Titoine?ref=orpc" target="_blank" rel="noopener" title="Titoine"><img src="https://avatars.githubusercontent.com/u/3514286?u=1bb1e86b0c99c8a1121372e56d51a177eea12191&amp;v=4" width="119" alt="Titoine"/><br />Titoine</a></td>
206
+ <td align="center"><a href="https://github.com/Mnigos?ref=orpc" target="_blank" rel="noopener" title="Igor Makowski"><img src="https://avatars.githubusercontent.com/u/56691628?u=ee8c879478f7c151b9156aef6c74243fa3e247a8&amp;v=4" width="119" alt="Igor Makowski"/><br />Igor Makowski</a></td>
207
+ <td align="center"><a href="https://github.com/steelbrain?ref=orpc" target="_blank" rel="noopener" title="Anees Iqbal"><img src="https://avatars.githubusercontent.com/u/4278113?u=22b80b5399eed68ac76cd58b02961b0481f1db11&amp;v=4" width="119" alt="Anees Iqbal"/><br />Anees Iqbal</a></td>
208
+ <td align="center"><a href="https://github.com/hanayashiki?ref=orpc" target="_blank" rel="noopener" title="wang chenyu"><img src="https://avatars.githubusercontent.com/u/26056783?u=06c3b9205a16fd41a871e82da1cc2a09306d53f5&amp;v=4" width="119" alt="wang chenyu"/><br />wang chenyu</a></td>
209
+ <td align="center"><a href="https://github.com/piscis?ref=orpc" target="_blank" rel="noopener" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&amp;v=4" width="119" alt="Alex"/><br />Alex</a></td>
210
+ </tr>
211
+ <tr>
212
+ <td align="center"><a href="https://github.com/nattstack?ref=orpc" target="_blank" rel="noopener" title="nattstack"><img src="https://avatars.githubusercontent.com/u/31426677?u=fa9dbb8b3e66eb0ea3c88db5dc07f31c8c5418fe&amp;v=4" width="119" alt="nattstack"/><br />nattstack</a></td>
213
+ </tr>
214
+ </table>
215
+
216
+ ### Past Sponsors
217
+
218
+ <p>
219
+ <a href="https://github.com/MrMaxie?ref=orpc" target="_blank" rel="noopener" title="Maxie"><img src="https://avatars.githubusercontent.com/u/3857836?u=5e6b57973d4385d655663ffdd836e487856f2984&amp;v=4" width="32" height="32" alt="Maxie" /></a>
220
+ <a href="https://github.com/Stijn-Timmer?ref=orpc" target="_blank" rel="noopener" title="Stijn Timmer"><img src="https://avatars.githubusercontent.com/u/100147665?u=106b2c18e9c98a61861b4ee7fc100f5b9906a6c9&amp;v=4" width="32" height="32" alt="Stijn Timmer" /></a>
221
+ <a href="https://github.com/u1-liquid?ref=orpc" target="_blank" rel="noopener" title="あわわわとーにゅ"><img src="https://avatars.githubusercontent.com/u/17376330?u=de3353804be889f009f7e0a1582daf04d0ab292d&amp;v=4" width="32" height="32" alt="あわわわとーにゅ" /></a>
222
+ <a href="https://github.com/zuplo?ref=orpc" target="_blank" rel="noopener" title="Zuplo"><img src="https://avatars.githubusercontent.com/u/85497839?v=4" width="32" height="32" alt="Zuplo" /></a>
223
+ <a href="https://github.com/motopods?ref=orpc" target="_blank" rel="noopener" title="motopods"><img src="https://avatars.githubusercontent.com/u/58200641?u=18833983d65b481ae90a4adec2373064ec58bcf3&amp;v=4" width="32" height="32" alt="motopods" /></a>
224
+ <a href="https://github.com/franciscohermida?ref=orpc" target="_blank" rel="noopener" title="Francisco Hermida"><img src="https://avatars.githubusercontent.com/u/483242?u=bbcbc80eb9d8781ff401f7dafc3b59cd7bea0561&amp;v=4" width="32" height="32" alt="Francisco Hermida" /></a>
225
+ <a href="https://github.com/theoludwig?ref=orpc" target="_blank" rel="noopener" title="ThΓ©o LUDWIG"><img src="https://avatars.githubusercontent.com/u/25207499?u=a6a9653725a2f574c07893748806668e0598cdbe&amp;v=4" width="32" height="32" alt="ThΓ©o LUDWIG" /></a>
226
+ <a href="https://github.com/abhay-ramesh?ref=orpc" target="_blank" rel="noopener" title="Abhay Ramesh"><img src="https://avatars.githubusercontent.com/u/66196314?u=c5c2b0327b26606c2efcfaf17046ab18c3d25c57&amp;v=4" width="32" height="32" alt="Abhay Ramesh" /></a>
227
+ <a href="https://github.com/shr-ink?ref=orpc" target="_blank" rel="noopener" title="shr.ink oΓΌ"><img src="https://avatars.githubusercontent.com/u/139700438?v=4" width="32" height="32" alt="shr.ink oΓΌ" /></a>
228
+ <a href="https://github.com/johngerome?ref=orpc" target="_blank" rel="noopener" title="0x4e32"><img src="https://avatars.githubusercontent.com/u/2002000?u=24e8dd943cfc862aa284d858a023532c75071ade&amp;v=4" width="32" height="32" alt="0x4e32" /></a>
229
+ <a href="https://github.com/yzuyr?ref=orpc" target="_blank" rel="noopener" title="Ryuz"><img src="https://avatars.githubusercontent.com/u/196539378?u=d38374588d219b6748b16406982f6559411466d4&amp;v=4" width="32" height="32" alt="Ryuz" /></a>
230
+ <a href="https://github.com/happyboy2022?ref=orpc" target="_blank" rel="noopener" title="happyboy"><img src="https://avatars.githubusercontent.com/u/103669586?u=65b49c4b893ed3703909fbb3a7a22313f3f9c121&amp;v=4" width="32" height="32" alt="happyboy" /></a>
231
+ <a href="https://github.com/YiCChi?ref=orpc" target="_blank" rel="noopener" title="yicchi"><img src="https://avatars.githubusercontent.com/u/86967274?u=6c2756f09fe15dd94d572f560e979cd157982852&amp;v=4" width="32" height="32" alt="yicchi" /></a>
232
+ <a href="https://github.com/cloudycotton?ref=orpc" target="_blank" rel="noopener" title="Saksham"><img src="https://avatars.githubusercontent.com/u/168998965?u=9b9634a5aed66a51c1b880663272725b00b92b14&amp;v=4" width="32" height="32" alt="Saksham" /></a>
233
+ <a href="https://github.com/hrynevychroman?ref=orpc" target="_blank" rel="noopener" title="Roman Hrynevych"><img src="https://avatars.githubusercontent.com/u/82209198?u=1a1d111ab3d589855b9cc8a7fefb1b5c6a4fbbaf&amp;v=4" width="32" height="32" alt="Roman Hrynevych" /></a>
234
+ <a href="https://github.com/rokitgg?ref=orpc" target="_blank" rel="noopener" title="rokitg"><img src="https://avatars.githubusercontent.com/u/125133357?u=06c74aefaa2236b06a2e5fba5a5c612339f45912&amp;v=4" width="32" height="32" alt="rokitg" /></a>
235
+ <a href="https://github.com/omarkhatibgg?ref=orpc" target="_blank" rel="noopener" title="Omar Khatib"><img src="https://avatars.githubusercontent.com/u/9054278?u=afbba7331b85c51b8eee4130f5fd31b1017dc919&amp;v=4" width="32" height="32" alt="Omar Khatib" /></a>
236
+ <a href="https://github.com/YuSabo90002?ref=orpc" target="_blank" rel="noopener" title="Yu-Sabo"><img src="https://avatars.githubusercontent.com/u/13120582?v=4" width="32" height="32" alt="Yu-Sabo" /></a>
237
+ <a href="https://github.com/bapspatil?ref=orpc" target="_blank" rel="noopener" title="Bapusaheb Patil"><img src="https://avatars.githubusercontent.com/u/16699418?u=6d9d8e0a64a6f91ca1c4d559c72d931172bdcbbd&amp;v=4" width="32" height="32" alt="Bapusaheb Patil" /></a>
238
+ <a href="https://github.com/ripgrim?ref=orpc" target="_blank" rel="noopener" title="grim"><img src="https://avatars.githubusercontent.com/u/75869731?u=b17c42ec2309552fdb822a86b25a2f99146a4d72&amp;v=4" width="32" height="32" alt="grim" /></a>
239
+ <a href="https://github.com/nelsonlaidev?ref=orpc" target="_blank" rel="noopener" title="Nelson Lai"><img src="https://avatars.githubusercontent.com/u/75498339?u=2fc0e0b95dd184c5ffb744df977cb15a18b60672&amp;v=4" width="32" height="32" alt="Nelson Lai" /></a>
240
+ <a href="https://github.com/nguyenlc1993?ref=orpc" target="_blank" rel="noopener" title="LΓͺ Cao NguyΓͺn"><img src="https://avatars.githubusercontent.com/u/13871971?u=83c8b69d9e35b589c4e1f066cc113b1d9461386f&amp;v=4" width="32" height="32" alt="LΓͺ Cao NguyΓͺn" /></a>
241
+ <a href="https://github.com/wobsoriano?ref=orpc" target="_blank" rel="noopener" title="Robert Soriano"><img src="https://avatars.githubusercontent.com/u/13049130?u=6d72104182e7c9ed25934815313fb69107332111&amp;v=4" width="32" height="32" alt="Robert Soriano" /></a>
242
+ <a href="https://github.com/SKostyukovich?ref=orpc" target="_blank" rel="noopener" title="SKostyukovich"><img src="https://avatars.githubusercontent.com/u/10700067?v=4" width="32" height="32" alt="SKostyukovich" /></a>
243
+ <a href="https://github.com/FabworksHQ?ref=orpc" target="_blank" rel="noopener" title="Fabworks"><img src="https://avatars.githubusercontent.com/u/160179500?v=4" width="32" height="32" alt="Fabworks" /></a>
244
+ <a href="https://github.com/NovakAnton?ref=orpc" target="_blank" rel="noopener" title="Novak Antonijevic"><img src="https://avatars.githubusercontent.com/u/157126729?u=ae49fa22292d55c0434ff0ca008206155b18663b&amp;v=4" width="32" height="32" alt="Novak Antonijevic" /></a>
245
+ <a href="https://github.com/laduniestu?ref=orpc" target="_blank" rel="noopener" title="Laduni Estu Syalwa"><img src="https://avatars.githubusercontent.com/u/44757637?u=a2fc1ea8f7d827a96721176f79d30592d1c48059&amp;v=4" width="32" height="32" alt="Laduni Estu Syalwa" /></a>
246
+ <a href="https://github.com/illarionvk?ref=orpc" target="_blank" rel="noopener" title="Illarion Koperski"><img src="https://avatars.githubusercontent.com/u/5012724?u=7cfa13652f7ac5fb3c56d880e3eb3fbe40c3ea34&amp;v=4" width="32" height="32" alt="Illarion Koperski" /></a>
247
+ <a href="https://github.com/Scrumplex?ref=orpc" target="_blank" rel="noopener" title="Sefa Eyeoglu"><img src="https://avatars.githubusercontent.com/u/11587657?u=ab503582165c0bbff0cca47ce31c9450bb1553c9&amp;v=4" width="32" height="32" alt="Sefa Eyeoglu" /></a>
136
248
  </p>
137
249
 
138
250
  ## License
139
251
 
140
- Distributed under the MIT License. See [LICENSE](https://github.com/unnoq/orpc/blob/main/LICENSE) for more information.
252
+ Distributed under the MIT License. See [LICENSE](https://github.com/middleapi/orpc/blob/main/LICENSE) for more information.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { JSONSchema, ConditionalSchemaConverter, SchemaConvertOptions } from '@orpc/openapi';
2
- import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod';
2
+ import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod/v3';
3
3
  import { Context } from '@orpc/server';
4
4
  import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
5
5
  import { AnySchema } from '@orpc/contract';
@@ -40,34 +40,43 @@ declare class ZodSmartCoercionPlugin<TContext extends Context> implements Standa
40
40
 
41
41
  interface ZodToJsonSchemaOptions {
42
42
  /**
43
- * Max depth of lazy type, if it exceeds.
43
+ * Max depth of lazy type
44
44
  *
45
- * Used `{}` when reach max depth
45
+ * Used `{}` when exceed max depth
46
46
  *
47
47
  * @default 3
48
48
  */
49
49
  maxLazyDepth?: number;
50
50
  /**
51
- * The schema to be used when the Zod schema is unsupported.
51
+ * Max depth of nested types
52
52
  *
53
- * @default { not: {} }
53
+ * Used anyJsonSchema (`{}`) when exceed max depth
54
+ *
55
+ * @default 10
54
56
  */
55
- unsupportedJsonSchema?: Exclude<JSONSchema, boolean>;
57
+ maxStructureDepth?: number;
56
58
  /**
57
59
  * The schema to be used to represent the any | unknown type.
58
60
  *
59
61
  * @default { }
60
62
  */
61
63
  anyJsonSchema?: Exclude<JSONSchema, boolean>;
64
+ /**
65
+ * The schema to be used when the Zod schema is unsupported.
66
+ *
67
+ * @default { not: {} }
68
+ */
69
+ unsupportedJsonSchema?: Exclude<JSONSchema, boolean>;
62
70
  }
63
71
  declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
64
72
  #private;
65
73
  private readonly maxLazyDepth;
74
+ private readonly maxStructureDepth;
66
75
  private readonly unsupportedJsonSchema;
67
76
  private readonly anyJsonSchema;
68
77
  constructor(options?: ZodToJsonSchemaOptions);
69
78
  condition(schema: AnySchema | undefined): boolean;
70
- convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
79
+ convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean, structureDepth?: number): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
71
80
  }
72
81
 
73
82
  declare const oz: {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { JSONSchema, ConditionalSchemaConverter, SchemaConvertOptions } from '@orpc/openapi';
2
- import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod';
2
+ import { ZodTypeAny, input, output, ZodTypeDef, CustomErrorParams, ZodType, ZodEffects } from 'zod/v3';
3
3
  import { Context } from '@orpc/server';
4
4
  import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
5
5
  import { AnySchema } from '@orpc/contract';
@@ -40,34 +40,43 @@ declare class ZodSmartCoercionPlugin<TContext extends Context> implements Standa
40
40
 
41
41
  interface ZodToJsonSchemaOptions {
42
42
  /**
43
- * Max depth of lazy type, if it exceeds.
43
+ * Max depth of lazy type
44
44
  *
45
- * Used `{}` when reach max depth
45
+ * Used `{}` when exceed max depth
46
46
  *
47
47
  * @default 3
48
48
  */
49
49
  maxLazyDepth?: number;
50
50
  /**
51
- * The schema to be used when the Zod schema is unsupported.
51
+ * Max depth of nested types
52
52
  *
53
- * @default { not: {} }
53
+ * Used anyJsonSchema (`{}`) when exceed max depth
54
+ *
55
+ * @default 10
54
56
  */
55
- unsupportedJsonSchema?: Exclude<JSONSchema, boolean>;
57
+ maxStructureDepth?: number;
56
58
  /**
57
59
  * The schema to be used to represent the any | unknown type.
58
60
  *
59
61
  * @default { }
60
62
  */
61
63
  anyJsonSchema?: Exclude<JSONSchema, boolean>;
64
+ /**
65
+ * The schema to be used when the Zod schema is unsupported.
66
+ *
67
+ * @default { not: {} }
68
+ */
69
+ unsupportedJsonSchema?: Exclude<JSONSchema, boolean>;
62
70
  }
63
71
  declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
64
72
  #private;
65
73
  private readonly maxLazyDepth;
74
+ private readonly maxStructureDepth;
66
75
  private readonly unsupportedJsonSchema;
67
76
  private readonly anyJsonSchema;
68
77
  constructor(options?: ZodToJsonSchemaOptions);
69
78
  condition(schema: AnySchema | undefined): boolean;
70
- convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
79
+ convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean, structureDepth?: number): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
71
80
  }
72
81
 
73
82
  declare const oz: {
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
- import { custom, ZodFirstPartyTypeKind } from 'zod';
1
+ import { custom, ZodFirstPartyTypeKind } from 'zod/v3';
2
2
  import wcmatch from 'wildcard-match';
3
- import { isObject, guard } from '@orpc/shared';
3
+ import { isObject, guard, toArray } from '@orpc/shared';
4
+ import { JsonSchemaXNativeType } from '@orpc/json-schema';
4
5
  import { JSONSchemaFormat } from '@orpc/openapi';
5
6
  import escapeStringRegexp from 'escape-string-regexp';
6
7
 
@@ -128,7 +129,7 @@ class ZodSmartCoercionPlugin {
128
129
  options.clientInterceptors ??= [];
129
130
  options.clientInterceptors.unshift((options2) => {
130
131
  const inputSchema = options2.procedure["~orpc"].inputSchema;
131
- if (!inputSchema || inputSchema["~standard"].vendor !== "zod") {
132
+ if (!inputSchema || inputSchema["~standard"].vendor !== "zod" || "_zod" in inputSchema) {
132
133
  return options2.next();
133
134
  }
134
135
  const coercedInput = zodCoerceInternal(inputSchema, options2.input);
@@ -390,25 +391,39 @@ function safeToDate(value) {
390
391
 
391
392
  class ZodToJsonSchemaConverter {
392
393
  maxLazyDepth;
394
+ maxStructureDepth;
393
395
  unsupportedJsonSchema;
394
396
  anyJsonSchema;
395
397
  constructor(options = {}) {
396
398
  this.maxLazyDepth = options.maxLazyDepth ?? 3;
399
+ this.maxStructureDepth = options.maxStructureDepth ?? 10;
397
400
  this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
398
401
  this.anyJsonSchema = options.anyJsonSchema ?? {};
399
402
  }
400
403
  condition(schema) {
401
- return schema !== void 0 && schema["~standard"].vendor === "zod";
404
+ return schema !== void 0 && schema["~standard"].vendor === "zod" && !("_zod" in schema);
402
405
  }
403
- convert(schema, options, lazyDepth = 0, isHandledCustomJSONSchema = false, isHandledZodDescription = false) {
406
+ convert(schema, options, lazyDepth = 0, isHandledCustomJSONSchema = false, isHandledZodDescription = false, structureDepth = 0) {
404
407
  const def = schema._def;
408
+ if (structureDepth > this.maxStructureDepth) {
409
+ return [false, this.anyJsonSchema];
410
+ }
411
+ if (!options.minStructureDepthForRef || options.minStructureDepthForRef <= structureDepth) {
412
+ const components = toArray(options.components);
413
+ for (const component of components) {
414
+ if (component.schema === schema && component.allowedStrategies.includes(options.strategy)) {
415
+ return [component.required, { $ref: component.ref }];
416
+ }
417
+ }
418
+ }
405
419
  if (!isHandledZodDescription && "description" in def && typeof def.description === "string") {
406
420
  const [required, json] = this.convert(
407
421
  schema,
408
422
  options,
409
423
  lazyDepth,
410
424
  isHandledCustomJSONSchema,
411
- true
425
+ true,
426
+ structureDepth
412
427
  );
413
428
  return [required, { ...json, description: def.description }];
414
429
  }
@@ -420,7 +435,8 @@ class ZodToJsonSchemaConverter {
420
435
  options,
421
436
  lazyDepth,
422
437
  true,
423
- isHandledZodDescription
438
+ isHandledZodDescription,
439
+ structureDepth
424
440
  );
425
441
  return [required, { ...json, ...customJSONSchema }];
426
442
  }
@@ -548,7 +564,11 @@ class ZodToJsonSchemaConverter {
548
564
  return [true, json];
549
565
  }
550
566
  case ZodFirstPartyTypeKind.ZodBigInt: {
551
- const json = { type: "string", pattern: "^-?[0-9]+$" };
567
+ const json = {
568
+ "type": "string",
569
+ "pattern": "^-?[0-9]+$",
570
+ "x-native-type": JsonSchemaXNativeType.BigInt
571
+ };
552
572
  return [true, json];
553
573
  }
554
574
  case ZodFirstPartyTypeKind.ZodNaN: {
@@ -558,7 +578,11 @@ class ZodToJsonSchemaConverter {
558
578
  return [true, { type: "boolean" }];
559
579
  }
560
580
  case ZodFirstPartyTypeKind.ZodDate: {
561
- const schema2 = { type: "string", format: JSONSchemaFormat.DateTime };
581
+ const schema2 = {
582
+ "type": "string",
583
+ "format": JSONSchemaFormat.DateTime,
584
+ "x-native-type": JsonSchemaXNativeType.Date
585
+ };
562
586
  return [true, schema2];
563
587
  }
564
588
  case ZodFirstPartyTypeKind.ZodNull: {
@@ -581,17 +605,26 @@ class ZodToJsonSchemaConverter {
581
605
  }
582
606
  case ZodFirstPartyTypeKind.ZodEnum: {
583
607
  const schema_ = schema;
584
- return [true, { enum: schema_._def.values }];
608
+ const values = schema_._def.values;
609
+ const json = { enum: values, type: "string" };
610
+ return [true, json];
585
611
  }
586
612
  case ZodFirstPartyTypeKind.ZodNativeEnum: {
587
613
  const schema_ = schema;
588
- return [true, { enum: Object.values(schema_._def.values) }];
614
+ const values = getEnumValues(schema_._def.values);
615
+ const json = { enum: values };
616
+ if (values.every((v) => typeof v === "string")) {
617
+ json.type = "string";
618
+ } else if (values.every((v) => Number.isFinite(v))) {
619
+ json.type = "number";
620
+ }
621
+ return [true, json];
589
622
  }
590
623
  case ZodFirstPartyTypeKind.ZodArray: {
591
624
  const schema_ = schema;
592
625
  const def2 = schema_._def;
593
626
  const json = { type: "array" };
594
- const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false);
627
+ const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false, structureDepth + 1);
595
628
  json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
596
629
  if (def2.exactLength) {
597
630
  json.maxItems = def2.exactLength.value;
@@ -610,7 +643,7 @@ class ZodToJsonSchemaConverter {
610
643
  const prefixItems = [];
611
644
  const json = { type: "array" };
612
645
  for (const item of schema_._def.items) {
613
- const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
646
+ const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
614
647
  prefixItems.push(
615
648
  this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy)
616
649
  );
@@ -619,7 +652,7 @@ class ZodToJsonSchemaConverter {
619
652
  json.prefixItems = prefixItems;
620
653
  }
621
654
  if (schema_._def.rest) {
622
- const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false);
655
+ const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false, structureDepth + 1);
623
656
  json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
624
657
  }
625
658
  return [true, json];
@@ -630,7 +663,7 @@ class ZodToJsonSchemaConverter {
630
663
  const properties = {};
631
664
  const required = [];
632
665
  for (const [key, value] of Object.entries(schema_.shape)) {
633
- const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false);
666
+ const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false, structureDepth + 1);
634
667
  properties[key] = itemJson;
635
668
  if (itemRequired) {
636
669
  required.push(key);
@@ -648,7 +681,7 @@ class ZodToJsonSchemaConverter {
648
681
  json.additionalProperties = false;
649
682
  }
650
683
  } else {
651
- const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false);
684
+ const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false, structureDepth + 1);
652
685
  json.additionalProperties = addJson;
653
686
  }
654
687
  return [true, json];
@@ -656,28 +689,32 @@ class ZodToJsonSchemaConverter {
656
689
  case ZodFirstPartyTypeKind.ZodRecord: {
657
690
  const schema_ = schema;
658
691
  const json = { type: "object" };
659
- const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
692
+ const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
660
693
  if (Object.entries(keyJson).some(([k, v]) => k !== "type" || v !== "string")) {
661
694
  json.propertyNames = keyJson;
662
695
  }
663
- const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
696
+ const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
664
697
  json.additionalProperties = itemJson;
665
698
  return [true, json];
666
699
  }
667
700
  case ZodFirstPartyTypeKind.ZodSet: {
668
701
  const schema_ = schema;
669
- const json = { type: "array", uniqueItems: true };
670
- const [itemRequired, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
702
+ const json = {
703
+ "type": "array",
704
+ "uniqueItems": true,
705
+ "x-native-type": JsonSchemaXNativeType.Set
706
+ };
707
+ const [itemRequired, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
671
708
  json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
672
709
  return [true, json];
673
710
  }
674
711
  case ZodFirstPartyTypeKind.ZodMap: {
675
712
  const schema_ = schema;
676
- const [keyRequired, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
677
- const [valueRequired, valueJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
678
- return [true, {
679
- type: "array",
680
- items: {
713
+ const [keyRequired, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
714
+ const [valueRequired, valueJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
715
+ const json = {
716
+ "type": "array",
717
+ "items": {
681
718
  type: "array",
682
719
  prefixItems: [
683
720
  this.#toArrayItemJsonSchema(keyRequired, keyJson, options.strategy),
@@ -685,8 +722,10 @@ class ZodToJsonSchemaConverter {
685
722
  ],
686
723
  maxItems: 2,
687
724
  minItems: 2
688
- }
689
- }];
725
+ },
726
+ "x-native-type": JsonSchemaXNativeType.Map
727
+ };
728
+ return [true, json];
690
729
  }
691
730
  case ZodFirstPartyTypeKind.ZodUnion:
692
731
  case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
@@ -694,7 +733,7 @@ class ZodToJsonSchemaConverter {
694
733
  const anyOf = [];
695
734
  let required = true;
696
735
  for (const item of schema_._def.options) {
697
- const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
736
+ const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
698
737
  if (!itemRequired) {
699
738
  required = false;
700
739
  if (itemJson !== this.unsupportedJsonSchema) {
@@ -704,9 +743,6 @@ class ZodToJsonSchemaConverter {
704
743
  anyOf.push(itemJson);
705
744
  }
706
745
  }
707
- if (anyOf.length === 1) {
708
- return [required, anyOf[0]];
709
- }
710
746
  return [required, { anyOf }];
711
747
  }
712
748
  case ZodFirstPartyTypeKind.ZodIntersection: {
@@ -714,7 +750,7 @@ class ZodToJsonSchemaConverter {
714
750
  const allOf = [];
715
751
  let required = false;
716
752
  for (const item of [schema_._def.left, schema_._def.right]) {
717
- const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
753
+ const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
718
754
  allOf.push(itemJson);
719
755
  if (itemRequired) {
720
756
  required = true;
@@ -723,25 +759,26 @@ class ZodToJsonSchemaConverter {
723
759
  return [required, { allOf }];
724
760
  }
725
761
  case ZodFirstPartyTypeKind.ZodLazy: {
726
- if (lazyDepth >= this.maxLazyDepth) {
762
+ const currentLazyDepth = lazyDepth + 1;
763
+ if (currentLazyDepth > this.maxLazyDepth) {
727
764
  return [false, this.anyJsonSchema];
728
765
  }
729
766
  const schema_ = schema;
730
- return this.convert(schema_._def.getter(), options, lazyDepth + 1, false, false);
767
+ return this.convert(schema_._def.getter(), options, currentLazyDepth, false, false, structureDepth);
731
768
  }
732
769
  case ZodFirstPartyTypeKind.ZodOptional: {
733
770
  const schema_ = schema;
734
- const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
771
+ const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
735
772
  return [false, inner];
736
773
  }
737
774
  case ZodFirstPartyTypeKind.ZodReadonly: {
738
775
  const schema_ = schema;
739
- const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
776
+ const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
740
777
  return [required, { ...json, readOnly: true }];
741
778
  }
742
779
  case ZodFirstPartyTypeKind.ZodDefault: {
743
780
  const schema_ = schema;
744
- const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
781
+ const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
745
782
  return [false, { default: schema_._def.defaultValue(), ...json }];
746
783
  }
747
784
  case ZodFirstPartyTypeKind.ZodEffects: {
@@ -749,15 +786,15 @@ class ZodToJsonSchemaConverter {
749
786
  if (schema_._def.effect.type === "transform" && options.strategy === "output") {
750
787
  return [false, this.anyJsonSchema];
751
788
  }
752
- return this.convert(schema_._def.schema, options, lazyDepth, false, false);
789
+ return this.convert(schema_._def.schema, options, lazyDepth, false, false, structureDepth);
753
790
  }
754
791
  case ZodFirstPartyTypeKind.ZodCatch: {
755
792
  const schema_ = schema;
756
- return this.convert(schema_._def.innerType, options, lazyDepth, false, false);
793
+ return this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
757
794
  }
758
795
  case ZodFirstPartyTypeKind.ZodBranded: {
759
796
  const schema_ = schema;
760
- return this.convert(schema_._def.type, options, lazyDepth, false, false);
797
+ return this.convert(schema_._def.type, options, lazyDepth, false, false, structureDepth);
761
798
  }
762
799
  case ZodFirstPartyTypeKind.ZodPipeline: {
763
800
  const schema_ = schema;
@@ -766,13 +803,14 @@ class ZodToJsonSchemaConverter {
766
803
  options,
767
804
  lazyDepth,
768
805
  false,
769
- false
806
+ false,
807
+ structureDepth
770
808
  );
771
809
  }
772
810
  case ZodFirstPartyTypeKind.ZodNullable: {
773
811
  const schema_ = schema;
774
- const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
775
- return [required, { anyOf: [{ type: "null" }, json] }];
812
+ const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
813
+ return [required, { anyOf: [json, { type: "null" }] }];
776
814
  }
777
815
  }
778
816
  return [true, this.unsupportedJsonSchema];
@@ -791,12 +829,17 @@ class ZodToJsonSchemaConverter {
791
829
  }
792
830
  case "regexp": {
793
831
  return {
794
- type: "string",
795
- pattern: "^\\/(.*)\\/([a-z]*)$"
832
+ "type": "string",
833
+ "pattern": "^\\/(.*)\\/([a-z]*)$",
834
+ "x-native-type": JsonSchemaXNativeType.RegExp
796
835
  };
797
836
  }
798
837
  case "url": {
799
- return { type: "string", format: JSONSchemaFormat.URI };
838
+ return {
839
+ "type": "string",
840
+ "format": JSONSchemaFormat.URI,
841
+ "x-native-type": JsonSchemaXNativeType.Url
842
+ };
800
843
  }
801
844
  }
802
845
  }
@@ -810,6 +853,11 @@ class ZodToJsonSchemaConverter {
810
853
  return strategy === "input" ? { anyOf: [schema, this.unsupportedJsonSchema] } : { anyOf: [schema, { type: "null" }] };
811
854
  }
812
855
  }
856
+ function getEnumValues(entries) {
857
+ const numericValues = Object.values(entries).filter((v) => typeof v === "number");
858
+ const values = Object.entries(entries).filter(([k, _]) => !numericValues.includes(+k)).map(([_, v]) => v);
859
+ return values;
860
+ }
813
861
 
814
862
  const oz = {
815
863
  file,
@@ -6,20 +6,31 @@ import { Interceptor } from '@orpc/shared';
6
6
  import * as zod_v4_core from 'zod/v4/core';
7
7
  import { $ZodType, $input, $output } from 'zod/v4/core';
8
8
 
9
+ /**
10
+ * @deprecated Use [Smart Coercion Plugin](https://orpc.dev/docs/openapi/plugins/smart-coercion) instead.
11
+ */
9
12
  declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> implements StandardHandlerPlugin<TContext> {
10
13
  #private;
11
14
  init(options: StandardHandlerOptions<TContext>): void;
12
15
  }
13
16
 
14
- interface experimental_ZodToJsonSchemaOptions {
17
+ interface ZodToJsonSchemaConverterOptions {
15
18
  /**
16
- * Max depth of lazy type, if it exceeds.
19
+ * Max depth of lazy type.
17
20
  *
18
- * Used anyJsonSchema (`{}`) when reach max depth
21
+ * Used anyJsonSchema (`{}`) when exceed max depth
19
22
  *
20
23
  * @default 2
21
24
  */
22
25
  maxLazyDepth?: number;
26
+ /**
27
+ * Max depth of nested types.
28
+ *
29
+ * Used anyJsonSchema (`{}`) when exceed max depth
30
+ *
31
+ * @default 10
32
+ */
33
+ maxStructureDepth?: number;
23
34
  /**
24
35
  * The schema to be used to represent the any | unknown type.
25
36
  *
@@ -48,14 +59,15 @@ interface experimental_ZodToJsonSchemaOptions {
48
59
  jsonSchema: Exclude<JSONSchema, boolean>
49
60
  ]>[];
50
61
  }
51
- declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
62
+ declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
52
63
  #private;
53
64
  private readonly maxLazyDepth;
65
+ private readonly maxStructureDepth;
54
66
  private readonly anyJsonSchema;
55
67
  private readonly unsupportedJsonSchema;
56
68
  private readonly undefinedJsonSchema;
57
69
  private readonly interceptors;
58
- constructor(options?: experimental_ZodToJsonSchemaOptions);
70
+ constructor(options?: ZodToJsonSchemaConverterOptions);
59
71
  condition(schema: AnySchema | undefined): boolean;
60
72
  convert(schema: AnySchema | undefined, options: SchemaConvertOptions): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
61
73
  }
@@ -77,7 +89,7 @@ declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchema
77
89
  * })
78
90
  * ```
79
91
  */
80
- declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
92
+ declare const JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
81
93
  $anchor?: string;
82
94
  $comment?: string;
83
95
  $defs?: Record<string, JSONSchema>;
@@ -156,7 +168,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
156
168
  * })
157
169
  * ```
158
170
  */
159
- declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
171
+ declare const JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
160
172
  $anchor?: string;
161
173
  $comment?: string;
162
174
  $defs?: Record<string, JSONSchema>;
@@ -235,7 +247,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<
235
247
  * })
236
248
  * ```
237
249
  */
238
- declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
250
+ declare const JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
239
251
  $anchor?: string;
240
252
  $comment?: string;
241
253
  $defs?: Record<string, JSONSchema>;
@@ -298,5 +310,5 @@ declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry
298
310
  writeOnly?: boolean;
299
311
  }, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
300
312
 
301
- export { experimental_JSON_SCHEMA_INPUT_REGISTRY, experimental_JSON_SCHEMA_OUTPUT_REGISTRY, experimental_JSON_SCHEMA_REGISTRY, experimental_ZodSmartCoercionPlugin, experimental_ZodToJsonSchemaConverter };
302
- export type { experimental_ZodToJsonSchemaOptions };
313
+ export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter, experimental_ZodSmartCoercionPlugin };
314
+ export type { ZodToJsonSchemaConverterOptions };
@@ -6,20 +6,31 @@ import { Interceptor } from '@orpc/shared';
6
6
  import * as zod_v4_core from 'zod/v4/core';
7
7
  import { $ZodType, $input, $output } from 'zod/v4/core';
8
8
 
9
+ /**
10
+ * @deprecated Use [Smart Coercion Plugin](https://orpc.dev/docs/openapi/plugins/smart-coercion) instead.
11
+ */
9
12
  declare class experimental_ZodSmartCoercionPlugin<TContext extends Context> implements StandardHandlerPlugin<TContext> {
10
13
  #private;
11
14
  init(options: StandardHandlerOptions<TContext>): void;
12
15
  }
13
16
 
14
- interface experimental_ZodToJsonSchemaOptions {
17
+ interface ZodToJsonSchemaConverterOptions {
15
18
  /**
16
- * Max depth of lazy type, if it exceeds.
19
+ * Max depth of lazy type.
17
20
  *
18
- * Used anyJsonSchema (`{}`) when reach max depth
21
+ * Used anyJsonSchema (`{}`) when exceed max depth
19
22
  *
20
23
  * @default 2
21
24
  */
22
25
  maxLazyDepth?: number;
26
+ /**
27
+ * Max depth of nested types.
28
+ *
29
+ * Used anyJsonSchema (`{}`) when exceed max depth
30
+ *
31
+ * @default 10
32
+ */
33
+ maxStructureDepth?: number;
23
34
  /**
24
35
  * The schema to be used to represent the any | unknown type.
25
36
  *
@@ -48,14 +59,15 @@ interface experimental_ZodToJsonSchemaOptions {
48
59
  jsonSchema: Exclude<JSONSchema, boolean>
49
60
  ]>[];
50
61
  }
51
- declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
62
+ declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
52
63
  #private;
53
64
  private readonly maxLazyDepth;
65
+ private readonly maxStructureDepth;
54
66
  private readonly anyJsonSchema;
55
67
  private readonly unsupportedJsonSchema;
56
68
  private readonly undefinedJsonSchema;
57
69
  private readonly interceptors;
58
- constructor(options?: experimental_ZodToJsonSchemaOptions);
70
+ constructor(options?: ZodToJsonSchemaConverterOptions);
59
71
  condition(schema: AnySchema | undefined): boolean;
60
72
  convert(schema: AnySchema | undefined, options: SchemaConvertOptions): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
61
73
  }
@@ -77,7 +89,7 @@ declare class experimental_ZodToJsonSchemaConverter implements ConditionalSchema
77
89
  * })
78
90
  * ```
79
91
  */
80
- declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
92
+ declare const JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
81
93
  $anchor?: string;
82
94
  $comment?: string;
83
95
  $defs?: Record<string, JSONSchema>;
@@ -156,7 +168,7 @@ declare const experimental_JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<{
156
168
  * })
157
169
  * ```
158
170
  */
159
- declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
171
+ declare const JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
160
172
  $anchor?: string;
161
173
  $comment?: string;
162
174
  $defs?: Record<string, JSONSchema>;
@@ -235,7 +247,7 @@ declare const experimental_JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<
235
247
  * })
236
248
  * ```
237
249
  */
238
- declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
250
+ declare const JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<{
239
251
  $anchor?: string;
240
252
  $comment?: string;
241
253
  $defs?: Record<string, JSONSchema>;
@@ -298,5 +310,5 @@ declare const experimental_JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry
298
310
  writeOnly?: boolean;
299
311
  }, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
300
312
 
301
- export { experimental_JSON_SCHEMA_INPUT_REGISTRY, experimental_JSON_SCHEMA_OUTPUT_REGISTRY, experimental_JSON_SCHEMA_REGISTRY, experimental_ZodSmartCoercionPlugin, experimental_ZodToJsonSchemaConverter };
302
- export type { experimental_ZodToJsonSchemaOptions };
313
+ export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter, experimental_ZodSmartCoercionPlugin };
314
+ export type { ZodToJsonSchemaConverterOptions };
@@ -1,4 +1,5 @@
1
- import { isObject, guard, intercept } from '@orpc/shared';
1
+ import { isObject, guard, intercept, toArray } from '@orpc/shared';
2
+ import { JsonSchemaXNativeType } from '@orpc/json-schema';
2
3
  import { JSONSchemaFormat, JSONSchemaContentEncoding } from '@orpc/openapi';
3
4
  import { registry, globalRegistry } from 'zod/v4/core';
4
5
 
@@ -7,7 +8,7 @@ class experimental_ZodSmartCoercionPlugin {
7
8
  options.clientInterceptors ??= [];
8
9
  options.clientInterceptors.unshift((options2) => {
9
10
  const inputSchema = options2.procedure["~orpc"].inputSchema;
10
- if (!inputSchema || inputSchema["~standard"].vendor !== "zod") {
11
+ if (!inputSchema || inputSchema["~standard"].vendor !== "zod" || !("_zod" in inputSchema)) {
11
12
  return options2.next();
12
13
  }
13
14
  const coercedInput = this.#coerce(inputSchema, options2.input);
@@ -268,38 +269,51 @@ class experimental_ZodSmartCoercionPlugin {
268
269
  }
269
270
  }
270
271
 
271
- const experimental_JSON_SCHEMA_REGISTRY = registry();
272
- const experimental_JSON_SCHEMA_INPUT_REGISTRY = registry();
273
- const experimental_JSON_SCHEMA_OUTPUT_REGISTRY = registry();
272
+ const JSON_SCHEMA_REGISTRY = registry();
273
+ const JSON_SCHEMA_INPUT_REGISTRY = registry();
274
+ const JSON_SCHEMA_OUTPUT_REGISTRY = registry();
274
275
 
275
- class experimental_ZodToJsonSchemaConverter {
276
+ class ZodToJsonSchemaConverter {
276
277
  maxLazyDepth;
278
+ maxStructureDepth;
277
279
  anyJsonSchema;
278
280
  unsupportedJsonSchema;
279
281
  undefinedJsonSchema;
280
282
  interceptors;
281
283
  constructor(options = {}) {
282
284
  this.maxLazyDepth = options.maxLazyDepth ?? 2;
285
+ this.maxStructureDepth = options.maxStructureDepth ?? 10;
283
286
  this.anyJsonSchema = options.anyJsonSchema ?? {};
284
287
  this.unsupportedJsonSchema = options.unsupportedJsonSchema ?? { not: {} };
285
288
  this.undefinedJsonSchema = options.undefinedJsonSchema ?? { not: {} };
286
289
  this.interceptors = options.interceptors ?? [];
287
290
  }
288
291
  condition(schema) {
289
- return schema !== void 0 && schema["~standard"].vendor === "zod";
292
+ return schema !== void 0 && schema["~standard"].vendor === "zod" && "_zod" in schema;
290
293
  }
291
294
  convert(schema, options) {
292
- return this.#convert(schema, options, 0);
295
+ return this.#convert(schema, options, 0, 0);
293
296
  }
294
- #convert(schema, options, lazyDepth, isHandledCustomJSONSchema = false) {
297
+ #convert(schema, options, lazyDepth, structureDepth, isHandledCustomJSONSchema = false) {
295
298
  return intercept(
296
299
  this.interceptors,
297
300
  { schema, options, lazyDepth, isHandledCustomJSONSchema },
298
301
  ({ schema: schema2, options: options2, lazyDepth: lazyDepth2, isHandledCustomJSONSchema: isHandledCustomJSONSchema2 }) => {
302
+ if (structureDepth > this.maxStructureDepth) {
303
+ return [false, this.anyJsonSchema];
304
+ }
305
+ if (!options2.minStructureDepthForRef || options2.minStructureDepthForRef <= structureDepth) {
306
+ const components = toArray(options2.components);
307
+ for (const component of components) {
308
+ if (component.schema === schema2 && component.allowedStrategies.includes(options2.strategy)) {
309
+ return [component.required, { $ref: component.ref }];
310
+ }
311
+ }
312
+ }
299
313
  if (!isHandledCustomJSONSchema2) {
300
314
  const customJSONSchema = this.#getCustomJsonSchema(schema2, options2);
301
315
  if (customJSONSchema) {
302
- const [required, json] = this.#convert(schema2, options2, lazyDepth2, true);
316
+ const [required, json] = this.#convert(schema2, options2, lazyDepth2, structureDepth, true);
303
317
  return [required, { ...json, ...customJSONSchema }];
304
318
  }
305
319
  }
@@ -363,10 +377,18 @@ class experimental_ZodToJsonSchemaConverter {
363
377
  return [true, { type: "boolean" }];
364
378
  }
365
379
  case "bigint": {
366
- return [true, { type: "string", pattern: "^-?[0-9]+$" }];
380
+ return [true, {
381
+ "type": "string",
382
+ "pattern": "^-?[0-9]+$",
383
+ "x-native-type": JsonSchemaXNativeType.BigInt
384
+ }];
367
385
  }
368
386
  case "date": {
369
- return [true, { type: "string", format: JSONSchemaFormat.DateTime }];
387
+ return [true, {
388
+ "type": "string",
389
+ "format": JSONSchemaFormat.DateTime,
390
+ "x-native-type": JsonSchemaXNativeType.Date
391
+ }];
370
392
  }
371
393
  case "null": {
372
394
  return [true, { type: "null" }];
@@ -394,14 +416,14 @@ class experimental_ZodToJsonSchemaConverter {
394
416
  if (typeof maximum === "number") {
395
417
  json.maxItems = maximum;
396
418
  }
397
- json.items = this.#handleArrayItemJsonSchema(this.#convert(array._zod.def.element, options2, lazyDepth2), options2);
419
+ json.items = this.#handleArrayItemJsonSchema(this.#convert(array._zod.def.element, options2, lazyDepth2, structureDepth + 1), options2);
398
420
  return [true, json];
399
421
  }
400
422
  case "object": {
401
423
  const object = schema2;
402
424
  const json = { type: "object" };
403
425
  for (const [key, value] of Object.entries(object._zod.def.shape)) {
404
- const [itemRequired, itemJson] = this.#convert(value, options2, lazyDepth2);
426
+ const [itemRequired, itemJson] = this.#convert(value, options2, lazyDepth2, structureDepth + 1);
405
427
  json.properties ??= {};
406
428
  json.properties[key] = itemJson;
407
429
  if (itemRequired) {
@@ -413,7 +435,7 @@ class experimental_ZodToJsonSchemaConverter {
413
435
  if (object._zod.def.catchall._zod.def.type === "never") {
414
436
  json.additionalProperties = false;
415
437
  } else {
416
- const [_, addJson] = this.#convert(object._zod.def.catchall, options2, lazyDepth2);
438
+ const [_, addJson] = this.#convert(object._zod.def.catchall, options2, lazyDepth2, structureDepth + 1);
417
439
  json.additionalProperties = addJson;
418
440
  }
419
441
  }
@@ -424,7 +446,7 @@ class experimental_ZodToJsonSchemaConverter {
424
446
  const anyOf = [];
425
447
  let required = true;
426
448
  for (const item of union._zod.def.options) {
427
- const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2);
449
+ const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth + 1);
428
450
  if (!itemRequired) {
429
451
  required = false;
430
452
  }
@@ -438,14 +460,14 @@ class experimental_ZodToJsonSchemaConverter {
438
460
  }
439
461
  }
440
462
  }
441
- return [required, anyOf.length === 1 ? anyOf[0] : { anyOf }];
463
+ return [required, { anyOf }];
442
464
  }
443
465
  case "intersection": {
444
466
  const intersection = schema2;
445
467
  const json = { allOf: [] };
446
468
  let required = false;
447
469
  for (const item of [intersection._zod.def.left, intersection._zod.def.right]) {
448
- const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2);
470
+ const [itemRequired, itemJson] = this.#convert(item, options2, lazyDepth2, structureDepth + 1);
449
471
  json.allOf.push(itemJson);
450
472
  if (itemRequired) {
451
473
  required = true;
@@ -457,10 +479,10 @@ class experimental_ZodToJsonSchemaConverter {
457
479
  const tuple = schema2;
458
480
  const json = { type: "array", prefixItems: [] };
459
481
  for (const item of tuple._zod.def.items) {
460
- json.prefixItems.push(this.#handleArrayItemJsonSchema(this.#convert(item, options2, lazyDepth2), options2));
482
+ json.prefixItems.push(this.#handleArrayItemJsonSchema(this.#convert(item, options2, lazyDepth2, structureDepth + 1), options2));
461
483
  }
462
484
  if (tuple._zod.def.rest) {
463
- json.items = this.#handleArrayItemJsonSchema(this.#convert(tuple._zod.def.rest, options2, lazyDepth2), options2);
485
+ json.items = this.#handleArrayItemJsonSchema(this.#convert(tuple._zod.def.rest, options2, lazyDepth2, structureDepth + 1), options2);
464
486
  }
465
487
  const { minimum, maximum } = tuple._zod.bag;
466
488
  if (typeof minimum === "number") {
@@ -474,36 +496,45 @@ class experimental_ZodToJsonSchemaConverter {
474
496
  case "record": {
475
497
  const record = schema2;
476
498
  const json = { type: "object" };
477
- json.propertyNames = this.#convert(record._zod.def.keyType, options2, lazyDepth2)[1];
478
- json.additionalProperties = this.#convert(record._zod.def.valueType, options2, lazyDepth2)[1];
499
+ json.propertyNames = this.#convert(record._zod.def.keyType, options2, lazyDepth2, structureDepth + 1)[1];
500
+ json.additionalProperties = this.#convert(record._zod.def.valueType, options2, lazyDepth2, structureDepth + 1)[1];
479
501
  return [true, json];
480
502
  }
481
503
  case "map": {
482
504
  const map = schema2;
483
505
  return [true, {
484
- type: "array",
485
- items: {
506
+ "type": "array",
507
+ "items": {
486
508
  type: "array",
487
509
  prefixItems: [
488
- this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.keyType, options2, lazyDepth2), options2),
489
- this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.valueType, options2, lazyDepth2), options2)
510
+ this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.keyType, options2, lazyDepth2, structureDepth + 1), options2),
511
+ this.#handleArrayItemJsonSchema(this.#convert(map._zod.def.valueType, options2, lazyDepth2, structureDepth + 1), options2)
490
512
  ],
491
513
  maxItems: 2,
492
514
  minItems: 2
493
- }
515
+ },
516
+ "x-native-type": JsonSchemaXNativeType.Map
494
517
  }];
495
518
  }
496
519
  case "set": {
497
520
  const set = schema2;
498
521
  return [true, {
499
- type: "array",
500
- uniqueItems: true,
501
- items: this.#handleArrayItemJsonSchema(this.#convert(set._zod.def.valueType, options2, lazyDepth2), options2)
522
+ "type": "array",
523
+ "uniqueItems": true,
524
+ "items": this.#handleArrayItemJsonSchema(this.#convert(set._zod.def.valueType, options2, lazyDepth2, structureDepth + 1), options2),
525
+ "x-native-type": JsonSchemaXNativeType.Set
502
526
  }];
503
527
  }
504
528
  case "enum": {
505
529
  const enum_ = schema2;
506
- return [true, { enum: Object.values(enum_._zod.def.entries) }];
530
+ const values = getEnumValues(enum_._zod.def.entries);
531
+ const json = { enum: values };
532
+ if (values.every((v) => typeof v === "string")) {
533
+ json.type = "string";
534
+ } else if (values.every((v) => Number.isFinite(v))) {
535
+ json.type = "number";
536
+ }
537
+ return [true, json];
507
538
  }
508
539
  case "literal": {
509
540
  const literal = schema2;
@@ -538,12 +569,12 @@ class experimental_ZodToJsonSchemaConverter {
538
569
  }
539
570
  case "nullable": {
540
571
  const nullable = schema2;
541
- const [required, json] = this.#convert(nullable._zod.def.innerType, options2, lazyDepth2);
572
+ const [required, json] = this.#convert(nullable._zod.def.innerType, options2, lazyDepth2, structureDepth);
542
573
  return [required, { anyOf: [json, { type: "null" }] }];
543
574
  }
544
575
  case "nonoptional": {
545
576
  const nonoptional = schema2;
546
- const [, json] = this.#convert(nonoptional._zod.def.innerType, options2, lazyDepth2);
577
+ const [, json] = this.#convert(nonoptional._zod.def.innerType, options2, lazyDepth2, structureDepth);
547
578
  return [true, json];
548
579
  }
549
580
  case "success": {
@@ -552,7 +583,7 @@ class experimental_ZodToJsonSchemaConverter {
552
583
  case "default":
553
584
  case "prefault": {
554
585
  const default_ = schema2;
555
- const [, json] = this.#convert(default_._zod.def.innerType, options2, lazyDepth2);
586
+ const [, json] = this.#convert(default_._zod.def.innerType, options2, lazyDepth2, structureDepth);
556
587
  return [false, {
557
588
  ...json,
558
589
  default: default_._zod.def.defaultValue
@@ -560,18 +591,24 @@ class experimental_ZodToJsonSchemaConverter {
560
591
  }
561
592
  case "catch": {
562
593
  const catch_ = schema2;
563
- return this.#convert(catch_._zod.def.innerType, options2, lazyDepth2);
594
+ return this.#convert(catch_._zod.def.innerType, options2, lazyDepth2, structureDepth);
564
595
  }
565
596
  case "nan": {
566
597
  return [true, options2.strategy === "input" ? this.unsupportedJsonSchema : { type: "null" }];
567
598
  }
568
599
  case "pipe": {
569
600
  const pipe = schema2;
570
- return this.#convert(options2.strategy === "input" ? pipe._zod.def.in : pipe._zod.def.out, options2, lazyDepth2);
601
+ return this.#convert(
602
+ // prefer out schema when in schema is preprocess/transform
603
+ options2.strategy === "input" && pipe._zod.def.in._zod.def.type !== "transform" ? pipe._zod.def.in : pipe._zod.def.out,
604
+ options2,
605
+ lazyDepth2,
606
+ structureDepth
607
+ );
571
608
  }
572
609
  case "readonly": {
573
610
  const readonly_ = schema2;
574
- const [required, json] = this.#convert(readonly_._zod.def.innerType, options2, lazyDepth2);
611
+ const [required, json] = this.#convert(readonly_._zod.def.innerType, options2, lazyDepth2, structureDepth);
575
612
  return [required, { ...json, readOnly: true }];
576
613
  }
577
614
  case "template_literal": {
@@ -583,15 +620,16 @@ class experimental_ZodToJsonSchemaConverter {
583
620
  }
584
621
  case "optional": {
585
622
  const optional = schema2;
586
- const [, json] = this.#convert(optional._zod.def.innerType, options2, lazyDepth2);
623
+ const [, json] = this.#convert(optional._zod.def.innerType, options2, lazyDepth2, structureDepth);
587
624
  return [false, json];
588
625
  }
589
626
  case "lazy": {
590
627
  const lazy = schema2;
591
- if (lazyDepth2 >= this.maxLazyDepth) {
628
+ const currentLazyDepth = lazyDepth2 + 1;
629
+ if (currentLazyDepth > this.maxLazyDepth) {
592
630
  return [false, this.anyJsonSchema];
593
631
  }
594
- return this.#convert(lazy._zod.def.getter(), options2, lazyDepth2 + 1);
632
+ return this.#convert(lazy._zod.def.getter(), options2, currentLazyDepth, structureDepth);
595
633
  }
596
634
  default: {
597
635
  schema2._zod.def.type;
@@ -602,18 +640,19 @@ class experimental_ZodToJsonSchemaConverter {
602
640
  );
603
641
  }
604
642
  #getCustomJsonSchema(schema, options) {
605
- if (options.strategy === "input" && experimental_JSON_SCHEMA_INPUT_REGISTRY.has(schema)) {
606
- return experimental_JSON_SCHEMA_INPUT_REGISTRY.get(schema);
643
+ if (options.strategy === "input" && JSON_SCHEMA_INPUT_REGISTRY.has(schema)) {
644
+ return JSON_SCHEMA_INPUT_REGISTRY.get(schema);
607
645
  }
608
- if (options.strategy === "output" && experimental_JSON_SCHEMA_OUTPUT_REGISTRY.has(schema)) {
609
- return experimental_JSON_SCHEMA_OUTPUT_REGISTRY.get(schema);
646
+ if (options.strategy === "output" && JSON_SCHEMA_OUTPUT_REGISTRY.has(schema)) {
647
+ return JSON_SCHEMA_OUTPUT_REGISTRY.get(schema);
610
648
  }
611
- if (experimental_JSON_SCHEMA_REGISTRY.has(schema)) {
612
- return experimental_JSON_SCHEMA_REGISTRY.get(schema);
649
+ if (JSON_SCHEMA_REGISTRY.has(schema)) {
650
+ return JSON_SCHEMA_REGISTRY.get(schema);
613
651
  }
614
652
  const global = globalRegistry.get(schema);
615
653
  if (global) {
616
654
  return {
655
+ title: global.title,
617
656
  description: global.description,
618
657
  examples: Array.isArray(global.examples) ? global.examples : void 0
619
658
  };
@@ -650,5 +689,10 @@ class experimental_ZodToJsonSchemaConverter {
650
689
  return Object.values(JSONSchemaContentEncoding).includes(contentEncoding) ? contentEncoding : void 0;
651
690
  }
652
691
  }
692
+ function getEnumValues(entries) {
693
+ const numericValues = Object.values(entries).filter((v) => typeof v === "number");
694
+ const values = Object.entries(entries).filter(([k, _]) => !numericValues.includes(+k)).map(([_, v]) => v);
695
+ return values;
696
+ }
653
697
 
654
- export { experimental_JSON_SCHEMA_INPUT_REGISTRY, experimental_JSON_SCHEMA_OUTPUT_REGISTRY, experimental_JSON_SCHEMA_REGISTRY, experimental_ZodSmartCoercionPlugin, experimental_ZodToJsonSchemaConverter };
698
+ export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter, experimental_ZodSmartCoercionPlugin };
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@orpc/zod",
3
3
  "type": "module",
4
- "version": "0.0.0-next.75f1e0e",
4
+ "version": "0.0.0-next.7605f6c",
5
5
  "license": "MIT",
6
- "homepage": "https://orpc.unnoq.com",
6
+ "homepage": "https://orpc.dev",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/unnoq/orpc.git",
9
+ "url": "git+https://github.com/middleapi/orpc.git",
10
10
  "directory": "packages/zod"
11
11
  },
12
12
  "keywords": [
13
- "unnoq",
14
13
  "orpc"
15
14
  ],
15
+ "sideEffects": false,
16
16
  "exports": {
17
17
  ".": {
18
18
  "types": "./dist/index.d.mts",
@@ -29,19 +29,19 @@
29
29
  "dist"
30
30
  ],
31
31
  "peerDependencies": {
32
- "zod": ">=3.24.2",
33
- "@orpc/contract": "0.0.0-next.75f1e0e",
34
- "@orpc/server": "0.0.0-next.75f1e0e"
32
+ "zod": ">=3.25.0",
33
+ "@orpc/contract": "0.0.0-next.7605f6c",
34
+ "@orpc/server": "0.0.0-next.7605f6c"
35
35
  },
36
36
  "dependencies": {
37
37
  "escape-string-regexp": "^5.0.0",
38
- "wildcard-match": "^5.1.3",
39
- "@orpc/openapi": "0.0.0-next.75f1e0e",
40
- "@orpc/shared": "0.0.0-next.75f1e0e"
38
+ "wildcard-match": "^5.1.4",
39
+ "@orpc/json-schema": "0.0.0-next.7605f6c",
40
+ "@orpc/shared": "0.0.0-next.7605f6c",
41
+ "@orpc/openapi": "0.0.0-next.7605f6c"
41
42
  },
42
43
  "devDependencies": {
43
- "zod": "^3.25.49",
44
- "zod-to-json-schema": "^3.24.5"
44
+ "zod": "^4.3.6"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "unbuild",