@orpc/zod 2.0.0-beta.5 → 2.0.0-beta.50
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 +137 -102
- package/dist/converter.d.ts +30 -0
- package/dist/converter.js +107 -0
- package/dist/index.d.ts +4 -15
- package/dist/index.js +2 -0
- package/dist/registries.d.ts +62 -0
- package/dist/registries.js +63 -0
- package/package.json +28 -21
- package/dist/index.d.mts +0 -15
- package/dist/index.mjs +0 -66
package/README.md
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
<img alt="codecov" src="https://codecov.io/gh/middleapi/orpc/branch/main/graph/badge.svg">
|
|
6
6
|
</a>
|
|
7
7
|
<a href="https://www.npmjs.com/package/@orpc/zod">
|
|
8
|
-
<img alt="
|
|
8
|
+
<img alt="monthly downloads" src="https://img.shields.io/npm/dm/%40orpc%2Fzod?logo=npm" />
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://app.codspeed.io/middleapi/orpc?utm_source=badge">
|
|
11
|
+
<img alt="CodSpeed" src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" />
|
|
9
12
|
</a>
|
|
10
13
|
<a href="https://github.com/middleapi/orpc/blob/main/LICENSE">
|
|
11
14
|
<img alt="MIT License" src="https://img.shields.io/github/license/middleapi/orpc?logo=open-source-initiative" />
|
|
@@ -14,73 +17,122 @@
|
|
|
14
17
|
<img alt="Discord" src="https://img.shields.io/discord/1308966753044398161?color=7389D8&label&logo=discord&logoColor=ffffff" />
|
|
15
18
|
</a>
|
|
16
19
|
<a href="https://deepwiki.com/middleapi/orpc">
|
|
17
|
-
<img src="https://
|
|
20
|
+
<img alt="Ask DeepWiki" src="https://img.shields.io/badge/Ask-DeepWiki-blue" />
|
|
18
21
|
</a>
|
|
19
22
|
</div>
|
|
20
23
|
|
|
24
|
+
**oRPC** is a TypeScript framework for building end-to-end typesafe APIs. Write your API once as plain TypeScript functions, and oRPC gives you a fully typed client, a REST API with an OpenAPI document, and MCP tools for AI agents, with no code generation. It runs on Node.js, Bun, Deno, Cloudflare Workers, and more.
|
|
25
|
+
|
|
26
|
+
Define procedures on the server and serve them with an [RPC handler](https://orpc.dev/docs/rpc/handler):
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { os } from '@orpc/server'
|
|
30
|
+
import * as z from 'zod'
|
|
31
|
+
|
|
32
|
+
export const router = {
|
|
33
|
+
planet: {
|
|
34
|
+
find: os
|
|
35
|
+
.input(z.object({ id: z.number() }))
|
|
36
|
+
.handler(({ input }) => ({ id: input.id, name: 'Earth' })),
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then call them from a client that knows every input and output, without generating anything:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createORPCClient } from '@orpc/client'
|
|
45
|
+
import { RPCLink } from '@orpc/client/fetch'
|
|
46
|
+
import type { RouterClient } from '@orpc/server'
|
|
47
|
+
|
|
48
|
+
import type { router } from './router'
|
|
49
|
+
|
|
50
|
+
const link = new RPCLink({ origin: 'http://localhost:3000', url: '/rpc' })
|
|
51
|
+
const client: RouterClient<typeof router> = createORPCClient(link)
|
|
52
|
+
|
|
53
|
+
const planet = await client.planet.find({ id: 1 }) // { id: number, name: string }
|
|
54
|
+
```
|
|
55
|
+
|
|
21
56
|
## Documentation
|
|
22
57
|
|
|
23
|
-
|
|
58
|
+
Read the full documentation at [orpc.dev](https://orpc.dev), starting with the [Getting Started guide](https://orpc.dev/docs/getting-started).
|
|
24
59
|
|
|
25
60
|
## Packages
|
|
26
61
|
|
|
27
62
|
**Core**
|
|
28
63
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
64
|
+
| Package | Purpose | Docs |
|
|
65
|
+
| -------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
66
|
+
| [@orpc/contract](https://www.npmjs.com/package/@orpc/contract) | Define API contract as the single source of truth. | [Procedure Contract](https://orpc.dev/docs/contract/procedure), [Contract Router](https://orpc.dev/docs/contract/router), [Implementation](https://orpc.dev/docs/contract/implementation), [Generate from OpenAPI](https://orpc.dev/docs/contract/generate-from-openapi) |
|
|
67
|
+
| [@orpc/server](https://www.npmjs.com/package/@orpc/server) | Build APIs or implement contracts. | [Procedure](https://orpc.dev/docs/procedure), [Router](https://orpc.dev/docs/router), [Middleware](https://orpc.dev/docs/middleware), [Context](https://orpc.dev/docs/context), [RPC Handler](https://orpc.dev/docs/rpc/handler) |
|
|
68
|
+
| [@orpc/client](https://www.npmjs.com/package/@orpc/client) | Consume APIs with end-to-end type safety. | [Client-Side Clients](https://orpc.dev/docs/client/client-side), [Server-Side Clients](https://orpc.dev/docs/client/server-side), [RPC Link](https://orpc.dev/docs/rpc/link), [Error Handling](https://orpc.dev/docs/client/error-handling) |
|
|
69
|
+
| [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi) | Add OpenAPI compatibility to APIs. | [OpenAPI Handler](https://orpc.dev/docs/openapi/handler), [OpenAPI Link](https://orpc.dev/docs/openapi/link), [Specification](https://orpc.dev/docs/openapi/specification), [Scalar](https://orpc.dev/docs/openapi/scalar) |
|
|
33
70
|
|
|
34
71
|
**Schema validation**
|
|
35
72
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
73
|
+
| Package | Purpose | Docs |
|
|
74
|
+
| ------------------------------------------------------------ | ---------------------------------------------------------- | ----------------------------------------------------- |
|
|
75
|
+
| [@orpc/zod](https://www.npmjs.com/package/@orpc/zod) | JSON Schema converter for [Zod](https://zod.dev/). | [Zod](https://orpc.dev/docs/integrations/zod) |
|
|
76
|
+
| [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot) | JSON Schema converter for [Valibot](https://valibot.dev/). | [Valibot](https://orpc.dev/docs/integrations/valibot) |
|
|
77
|
+
| [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype) | JSON Schema converter for [ArkType](https://arktype.io/). | [ArkType](https://orpc.dev/docs/integrations/arktype) |
|
|
39
78
|
|
|
40
79
|
**Built-in features**
|
|
41
80
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
81
|
+
| Package | Purpose | Docs |
|
|
82
|
+
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
83
|
+
| [@orpc/publisher](https://www.npmjs.com/package/@orpc/publisher) | Pub/Sub with memory, Redis, and Upstash adapters. | [Publisher](https://orpc.dev/docs/helpers/publisher) |
|
|
84
|
+
| [@orpc/ratelimit](https://www.npmjs.com/package/@orpc/ratelimit) | Rate limiting with memory, Redis, and Upstash adapters. | [Rate Limit](https://orpc.dev/docs/helpers/ratelimit) |
|
|
85
|
+
| [@orpc/experimental-lock](https://www.npmjs.com/package/@orpc/experimental-lock) | Locking with memory, Redis, and Upstash adapters. | [Lock](https://orpc.dev/docs/helpers/lock) |
|
|
86
|
+
| [@orpc/hibernation](https://www.npmjs.com/package/@orpc/hibernation) | Leverage Hibernation APIs like [Cloudflare's Hibernation WebSocket](https://developers.cloudflare.com/durable-objects/best-practices/websockets/#durable-objects-hibernation-websocket-api). | [Hibernation](https://orpc.dev/docs/integrations/hibernation) |
|
|
87
|
+
| [@orpc/json-schema](https://www.npmjs.com/package/@orpc/json-schema) | Smart coercion for OpenAPI requests. | [Smart Coercion](https://orpc.dev/docs/plugins/smart-coercion) |
|
|
45
88
|
|
|
46
89
|
**Framework & ecosystem integrations**
|
|
47
90
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
91
|
+
| Package | Purpose | Docs |
|
|
92
|
+
| -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
93
|
+
| [@orpc/next](https://www.npmjs.com/package/@orpc/next) | Integrate with [Next.js Server Functions](https://nextjs.org/docs/app/getting-started/mutating-data). | [Next.js](https://orpc.dev/docs/integrations/next) |
|
|
94
|
+
| [@orpc/ai-sdk](https://www.npmjs.com/package/@orpc/ai-sdk) | Turn contracts and procedures into [AI SDK](https://ai-sdk.dev/) tools. | [AI SDK](https://orpc.dev/docs/integrations/ai-sdk) |
|
|
95
|
+
| [@orpc/mcp](https://www.npmjs.com/package/@orpc/mcp) | Expose procedures as [MCP](https://modelcontextprotocol.io/) tools. | [MCP](https://orpc.dev/docs/integrations/mcp) |
|
|
96
|
+
| [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query) | Integrate with [TanStack Query](https://tanstack.com/query/latest). | [TanStack Query](https://orpc.dev/docs/integrations/tanstack-query) |
|
|
97
|
+
| [@orpc/pinia-colada](https://www.npmjs.com/package/@orpc/pinia-colada) | Integrate with [Pinia Colada](https://pinia-colada.esm.dev/). | [Pinia Colada](https://orpc.dev/docs/integrations/pinia-colada) |
|
|
98
|
+
| [@orpc/swr](https://www.npmjs.com/package/@orpc/swr) | Integrate with [SWR](https://swr.vercel.app/). | [SWR](https://orpc.dev/docs/integrations/swr) |
|
|
99
|
+
| [@orpc/msw](https://www.npmjs.com/package/@orpc/msw) | Mock procedures with [Mock Service Worker](https://mswjs.io/). | [MSW](https://orpc.dev/docs/integrations/msw) |
|
|
100
|
+
| [@orpc/effect](https://www.npmjs.com/package/@orpc/effect) | Integrate with [Effect](https://effect.website/). | [Effect](https://orpc.dev/docs/integrations/effect) |
|
|
101
|
+
| [@orpc/nest](https://www.npmjs.com/package/@orpc/nest) | Implement your contract with [NestJS](https://nestjs.com/). | [NestJS](https://orpc.dev/docs/integrations/nest) |
|
|
102
|
+
| [@orpc/node](https://www.npmjs.com/package/@orpc/node) | [Node.js](https://nodejs.org/) plugins for static file serving and large uploads. | [Static File](https://orpc.dev/docs/plugins/static-file), [Tmp File Upload](https://orpc.dev/docs/plugins/tmp-file-upload), [Batch Response Compression](https://orpc.dev/docs/plugins/batch-response-compression) |
|
|
103
|
+
| [@orpc/bun](https://www.npmjs.com/package/@orpc/bun) | Adapters for [Bun's Redis](https://bun.sh/). | [Publisher](https://orpc.dev/docs/helpers/publisher), [Rate Limit](https://orpc.dev/docs/helpers/ratelimit), [Lock](https://orpc.dev/docs/helpers/lock) |
|
|
104
|
+
| [@orpc/cloudflare](https://www.npmjs.com/package/@orpc/cloudflare) | Adapters for [Cloudflare Workers](https://developers.cloudflare.com/workers/). | [Publisher](https://orpc.dev/docs/helpers/publisher), [Rate Limit](https://orpc.dev/docs/helpers/ratelimit), [Lock](https://orpc.dev/docs/helpers/lock), [Traces](https://orpc.dev/docs/integrations/cloudflare-traces) |
|
|
105
|
+
| [@orpc/trpc](https://www.npmjs.com/package/@orpc/trpc) | Reuse existing [tRPC](https://trpc.io/) routers within oRPC. | [tRPC](https://orpc.dev/docs/integrations/trpc) |
|
|
52
106
|
|
|
53
107
|
**Observability**
|
|
54
108
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
109
|
+
| Package | Purpose | Docs |
|
|
110
|
+
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
111
|
+
| [@orpc/opentelemetry](https://www.npmjs.com/package/@orpc/opentelemetry) | Integrate with [OpenTelemetry](https://opentelemetry.io/) for distributed tracing. | [OpenTelemetry](https://orpc.dev/docs/integrations/opentelemetry) |
|
|
112
|
+
| [@orpc/pino](https://www.npmjs.com/package/@orpc/pino) | Integrate with [Pino](https://getpino.io/) for logging. | [Pino](https://orpc.dev/docs/integrations/pino) |
|
|
113
|
+
| [@orpc/evlog](https://www.npmjs.com/package/@orpc/evlog) | Integrate with [Evlog](https://evlog.dev/) for logging. | [Evlog](https://orpc.dev/docs/integrations/evlog) |
|
|
58
114
|
|
|
59
115
|
## Sponsors
|
|
60
116
|
|
|
61
|
-
Like what we build over at [middleapi](https://github.com/middleapi)? You can help keep it going
|
|
62
|
-
|
|
63
|
-
### 🏆 Platinum Sponsor
|
|
117
|
+
Like what we build over at [middleapi](https://github.com/middleapi)? You can help keep it going through [GitHub Sponsors](https://github.com/sponsors/dinwwwh) or [Open Collective](https://opencollective.com/middleapi). Every bit helps! 🚀
|
|
64
118
|
|
|
65
119
|
<table>
|
|
66
120
|
<tr>
|
|
67
|
-
<td
|
|
121
|
+
<td width="2000"><a href="https://screenshotone.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="The screenshot API for developers"><img src="https://avatars.githubusercontent.com/u/97035603?v=4" width="64" align="left" hspace="12" alt="ScreenshotOne.com"/><b>ScreenshotOne.com</b></a><br /><sub>The screenshot API for developers</sub></td>
|
|
122
|
+
</tr>
|
|
123
|
+
<tr>
|
|
124
|
+
<td width="2000"><a href="https://yuzu.health/careers?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="We're hiring NYC based engineers"><img src="https://avatars.githubusercontent.com/u/102488956?v=4" width="64" align="left" hspace="12" alt="Yuzu"/><b>Yuzu</b></a><br /><sub>We're hiring NYC based engineers</sub></td>
|
|
68
125
|
</tr>
|
|
69
|
-
</table>
|
|
70
|
-
|
|
71
|
-
### 🥈 Silver Sponsor
|
|
72
|
-
|
|
73
|
-
<table>
|
|
74
126
|
<tr>
|
|
75
|
-
<td
|
|
127
|
+
<td width="2000"><a href="https://misskey.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Decentralized microblogging SNS born on Earth"><img src="https://github.com/MisskeyIO.png" width="64" align="left" hspace="12" alt="MisskeyHQ"/><b>MisskeyHQ</b></a><br /><sub>Decentralized microblogging SNS born on Earth</sub></td>
|
|
76
128
|
</tr>
|
|
77
129
|
</table>
|
|
78
130
|
|
|
79
|
-
###
|
|
131
|
+
### Organization Sponsors
|
|
80
132
|
|
|
81
133
|
<table>
|
|
82
134
|
<tr>
|
|
83
|
-
<td align="center"><a href="https://
|
|
135
|
+
<td align="center"><a href="https://lnmarkets.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="LN Markets"><img src="https://avatars.githubusercontent.com/u/70597625?v=4" width="209" alt="LN Markets"/><br />LN Markets</a></td>
|
|
84
136
|
</tr>
|
|
85
137
|
</table>
|
|
86
138
|
|
|
@@ -88,26 +140,30 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
|
|
|
88
140
|
|
|
89
141
|
<table>
|
|
90
142
|
<tr>
|
|
91
|
-
<td align="center"><a href="https://github.com/hrmcdonald?ref=
|
|
92
|
-
<td align="center"><a href="https://
|
|
93
|
-
<td align="center"><a href="https://github.com/
|
|
94
|
-
<td align="center"><a href="https://
|
|
95
|
-
<td align="center"><a href="https://github.com/herrfugbaum?ref=
|
|
96
|
-
<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&v=4" width="139" alt="Ryota Murakami"/><br />Ryota Murakami</a></td>
|
|
143
|
+
<td align="center"><a href="https://github.com/hrmcdonald?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Reece McDonald"><img src="https://avatars.githubusercontent.com/u/39349270?v=4" width="167" alt="Reece McDonald"/><br />Reece McDonald</a></td>
|
|
144
|
+
<td align="center"><a href="https://soymilk.party/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="あわわわとーにゅ"><img src="https://avatars.githubusercontent.com/u/17376330?u=de3353804be889f009f7e0a1582daf04d0ab292d&v=4" width="167" alt="あわわわとーにゅ"/><br />あわわわとーにゅ</a></td>
|
|
145
|
+
<td align="center"><a href="https://github.com/nicognaW?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="nk"><img src="https://avatars.githubusercontent.com/u/66731869?u=4699bda3a9092d3ec34fbd959450767bcc8b8b6d&v=4" width="167" alt="nk"/><br />nk</a></td>
|
|
146
|
+
<td align="center"><a href="https://supastarter.dev/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="supastarter"><img src="https://avatars.githubusercontent.com/u/110960143?v=4" width="167" alt="supastarter"/><br />supastarter</a></td>
|
|
147
|
+
<td align="center"><a href="https://github.com/herrfugbaum?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="herrfugbaum"><img src="https://avatars.githubusercontent.com/u/12859776?u=644dc1666d0220bc0468eb0de3c56b919f635b16&v=4" width="167" alt="herrfugbaum"/><br />herrfugbaum</a></td>
|
|
97
148
|
</tr>
|
|
98
149
|
<tr>
|
|
99
|
-
<td align="center"><a href="https://
|
|
100
|
-
<td align="center"><a href="https://
|
|
101
|
-
<td align="center"><a href="https://github.
|
|
102
|
-
<td align="center"><a href="https://
|
|
103
|
-
<td align="center"><a href="https://
|
|
104
|
-
<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&v=4" width="139" alt="Ryan Vogel"/><br />Ryan Vogel</a></td>
|
|
150
|
+
<td align="center"><a href="https://laststance.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Ryota Murakami"><img src="https://avatars.githubusercontent.com/u/5501268?u=599389e03340734325726ca3f8f423c021d47d7f&v=4" width="167" alt="Ryota Murakami"/><br />Ryota Murakami</a></td>
|
|
151
|
+
<td align="center"><a href="https://cra.mr/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="David Cramer"><img src="https://avatars.githubusercontent.com/u/23610?v=4" width="167" alt="David Cramer"/><br />David Cramer</a></td>
|
|
152
|
+
<td align="center"><a href="https://valerii15298.github.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Valerii Petryniak"><img src="https://avatars.githubusercontent.com/u/44531564?u=88ac74d9bacd20401518441907acad21063cd397&v=4" width="167" alt="Valerii Petryniak"/><br />Valerii Petryniak</a></td>
|
|
153
|
+
<td align="center"><a href="https://letstri.dev/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Valerii Strilets"><img src="https://avatars.githubusercontent.com/u/13253748?u=c7b10399ccc8f8081e24db94ec32cd9858e86ac3&v=4" width="167" alt="Valerii Strilets"/><br />Valerii Strilets</a></td>
|
|
154
|
+
<td align="center"><a href="https://blacklight.sh/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kyle Mistele"><img src="https://avatars.githubusercontent.com/u/18430555?u=3afebeb81de666e35aaac3ed46f14159d7603ffb&v=4" width="167" alt="Kyle Mistele"/><br />Kyle Mistele</a></td>
|
|
105
155
|
</tr>
|
|
106
156
|
<tr>
|
|
107
|
-
<td align="center"><a href="https://github.com/christ12938?ref=
|
|
108
|
-
<td align="center"><a href="https://github.com/
|
|
109
|
-
<td align="center"><a href="https://github.com/
|
|
110
|
-
<td align="center"><a href="https://github.com/
|
|
157
|
+
<td align="center"><a href="https://github.com/christ12938?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="christ12938"><img src="https://avatars.githubusercontent.com/u/25758598?v=4" width="167" alt="christ12938"/><br />christ12938</a></td>
|
|
158
|
+
<td align="center"><a href="https://github.com/Ryanjso?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Ryan Soderberg"><img src="https://avatars.githubusercontent.com/u/39172778?u=5ed913c31d57e7221b75784abcad48c7ebddde27&v=4" width="167" alt="Ryan Soderberg"/><br />Ryan Soderberg</a></td>
|
|
159
|
+
<td align="center"><a href="https://github.com/itigoore01?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="shota"><img src="https://avatars.githubusercontent.com/u/11831107?u=c976a6dc7e055eb026304c46c99100ed22b0c8e0&v=4" width="167" alt="shota"/><br />shota</a></td>
|
|
160
|
+
<td align="center"><a href="https://github.com/Nic13Gamer?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Nicholas"><img src="https://avatars.githubusercontent.com/u/54724556?u=56a7ab430ce7a80d648ab6eba051d454a818ed0b&v=4" width="167" alt="Nicholas"/><br />Nicholas</a></td>
|
|
161
|
+
<td align="center"><a href="https://github.com/ellis-driscoll?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Ellis Driscoll"><img src="https://avatars.githubusercontent.com/u/70685966?u=c5f95bc33b5991d9744abe00052542e4a2ed3cb9&v=4" width="167" alt="Ellis Driscoll"/><br />Ellis Driscoll</a></td>
|
|
162
|
+
</tr>
|
|
163
|
+
<tr>
|
|
164
|
+
<td align="center"><a href="https://github.com/hoangbn?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Hoang Nguyen"><img src="https://avatars.githubusercontent.com/u/38968280?u=c90084c6de65c56facabab7ba13a72a49ddbc3e4&v=4" width="167" alt="Hoang Nguyen"/><br />Hoang Nguyen</a></td>
|
|
165
|
+
<td align="center"><a href="https://opencollective.com/guest-ac41de3b?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Orestis Ioannou"><img src="https://images.opencollective.com/guest-ac41de3b/avatar/460.png" width="167" alt="Orestis Ioannou"/><br />Orestis Ioannou</a></td>
|
|
166
|
+
<td align="center"><a href="https://automatio.ai/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Stefan Smiljkovic"><img src="https://avatars.githubusercontent.com/u/1984909?u=b7bf5bc40ed49df3c22f69d2da7b8d78709c49ed&v=4" width="167" alt="Stefan Smiljkovic"/><br />Stefan Smiljkovic</a></td>
|
|
111
167
|
</tr>
|
|
112
168
|
</table>
|
|
113
169
|
|
|
@@ -115,67 +171,46 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
|
|
|
115
171
|
|
|
116
172
|
<table>
|
|
117
173
|
<tr>
|
|
118
|
-
<td align="center"><a href="https://github.com/rhinodavid?ref=
|
|
119
|
-
<td align="center"><a href="https://github.com/
|
|
120
|
-
<td align="center"><a href="https://
|
|
121
|
-
<td align="center"><a href="https://github.com/
|
|
122
|
-
<td align="center"><a href="https://github.com/
|
|
123
|
-
<td align="center"><a href="https://
|
|
124
|
-
|
|
174
|
+
<td align="center"><a href="https://github.com/rhinodavid?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="David Walsh"><img src="https://avatars.githubusercontent.com/u/5778036?u=b5521f07d2f88c3db2a0dae62b5f2f8357214af0&v=4" width="139" alt="David Walsh"/><br />David Walsh</a></td>
|
|
175
|
+
<td align="center"><a href="https://github.com/IPv4Addr?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="IPv4Addr"><img src="https://avatars.githubusercontent.com/u/100147665?u=59996b72f69bb53063cb7e9ff8b8f898616cd94d&v=4" width="139" alt="IPv4Addr"/><br />IPv4Addr</a></td>
|
|
176
|
+
<td align="center"><a href="https://robbevaes.be/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Robbe Vaes"><img src="https://avatars.githubusercontent.com/u/44748019?u=e0232402c045ad4eac7cbd217f1f47e083103b89&v=4" width="139" alt="Robbe Vaes"/><br />Robbe Vaes</a></td>
|
|
177
|
+
<td align="center"><a href="https://github.com/aidansunbury?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Aidan Sunbury"><img src="https://avatars.githubusercontent.com/u/64103161?v=4" width="139" alt="Aidan Sunbury"/><br />Aidan Sunbury</a></td>
|
|
178
|
+
<td align="center"><a href="https://github.com/soonoo?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="soonoo"><img src="https://avatars.githubusercontent.com/u/5436405?u=5d0b4aa955c87e30e6bda7f0cccae5402da99528&v=4" width="139" alt="soonoo"/><br />soonoo</a></td>
|
|
179
|
+
<td align="center"><a href="https://kevinporten.dev/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kevin Porten"><img src="https://avatars.githubusercontent.com/u/1839345?u=dc2263d5cfe0d927ce1a0be04a1d55dd6b55405c&v=4" width="139" alt="Kevin Porten"/><br />Kevin Porten</a></td>
|
|
180
|
+
</tr>
|
|
181
|
+
<tr>
|
|
182
|
+
<td align="center"><a href="https://github.com/pumpkinlink?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Denis"><img src="https://avatars.githubusercontent.com/u/11864620?u=5f47bbe6c65d0f6f5cf011021490238e4b0593d0&v=4" width="139" alt="Denis"/><br />Denis</a></td>
|
|
183
|
+
<td align="center"><a href="https://github.com/christopher-kapic?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Christopher Kapic"><img src="https://avatars.githubusercontent.com/u/59740769?u=e7ad4b72b5bf6c9eb1644c26dbf3332a8f987377&v=4" width="139" alt="Christopher Kapic"/><br />Christopher Kapic</a></td>
|
|
184
|
+
<td align="center"><a href="http://ballingt.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Tom Ballinger"><img src="https://avatars.githubusercontent.com/u/458879?u=4b045ac75d721b6ac2b42a74d7d37f61f0414031&v=4" width="139" alt="Tom Ballinger"/><br />Tom Ballinger</a></td>
|
|
185
|
+
<td align="center"><a href="https://lee-sam.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Sam"><img src="https://avatars.githubusercontent.com/u/102863520?u=3c89611f549d5070be232eb4532f690c8f2e7a65&v=4" width="139" alt="Sam"/><br />Sam</a></td>
|
|
186
|
+
<td align="center"><a href="https://github.com/Titoine?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Titoine"><img src="https://avatars.githubusercontent.com/u/3514286?u=1bb1e86b0c99c8a1121372e56d51a177eea12191&v=4" width="139" alt="Titoine"/><br />Titoine</a></td>
|
|
187
|
+
<td align="center"><a href="https://rigtch.fm/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Igor Makowski"><img src="https://avatars.githubusercontent.com/u/56691628?u=ee8c879478f7c151b9156aef6c74243fa3e247a8&v=4" width="139" alt="Igor Makowski"/><br />Igor Makowski</a></td>
|
|
125
188
|
</tr>
|
|
126
189
|
<tr>
|
|
127
|
-
<td align="center"><a href="https://
|
|
128
|
-
<td align="center"><a href="https://
|
|
129
|
-
<td align="center"><a href="https://
|
|
130
|
-
<td align="center"><a href="https://
|
|
131
|
-
<td align="center"><a href="https://
|
|
132
|
-
<td align="center"><a href="https://
|
|
133
|
-
<td align="center"><a href="https://github.com/mr-kelly?ref=orpc" target="_blank" rel="noopener" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&v=4" width="119" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
|
|
190
|
+
<td align="center"><a href="https://blog.cwang.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="hanayashiki"><img src="https://avatars.githubusercontent.com/u/26056783?u=06c3b9205a16fd41a871e82da1cc2a09306d53f5&v=4" width="139" alt="hanayashiki"/><br />hanayashiki</a></td>
|
|
191
|
+
<td align="center"><a href="https://dubinets.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Lev Dubinets"><img src="https://avatars.githubusercontent.com/u/3114081?u=f547f5d5012cab54851f1b1ad72d10e537f78fc2&v=4" width="139" alt="Lev Dubinets"/><br />Lev Dubinets</a></td>
|
|
192
|
+
<td align="center"><a href="https://kellychan.im/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&v=4" width="139" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
|
|
193
|
+
<td align="center"><a href="https://guyariely.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Guy Ariely"><img src="https://avatars.githubusercontent.com/u/42813496?u=edb6b7f563bf28e160a290832e7da57c0506f8ca&v=4" width="139" alt="Guy Ariely"/><br />Guy Ariely</a></td>
|
|
194
|
+
<td align="center"><a href="https://paulsenon.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="PaulSenon"><img src="https://avatars.githubusercontent.com/u/19531087?u=6385741eb91d200b8c513ec6045482e301767ca6&v=4" width="139" alt="PaulSenon"/><br />PaulSenon</a></td>
|
|
195
|
+
<td align="center"><a href="https://piscis.dev/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&v=4" width="139" alt="Alex"/><br />Alex</a></td>
|
|
134
196
|
</tr>
|
|
135
197
|
<tr>
|
|
136
|
-
<td align="center"><a href="https://
|
|
137
|
-
<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&v=4" width="119" alt="nattstack"/><br />nattstack</a></td>
|
|
138
|
-
<td align="center"><a href="https://github.com/finom?ref=orpc" target="_blank" rel="noopener" title="Andrey Gubanov"><img src="https://avatars.githubusercontent.com/u/1082083?u=29e91400dbd4a9c217048a8f59562c4f740498e6&v=4" width="119" alt="Andrey Gubanov"/><br />Andrey Gubanov</a></td>
|
|
198
|
+
<td align="center"><a href="https://opensource.gubanov.eu/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Andrey Gubanov"><img src="https://avatars.githubusercontent.com/u/1082083?u=c5f2daf7ebece498e85c83367bb37b4e10e2649d&v=4" width="139" alt="Andrey Gubanov"/><br />Andrey Gubanov</a></td>
|
|
139
199
|
</tr>
|
|
140
200
|
</table>
|
|
141
201
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
<a href="https://github.com/johngerome?ref=orpc" target="_blank" rel="noopener" title="0x4e32"><img src="https://avatars.githubusercontent.com/u/2002000?u=505e54608466ab53754f702973687b04c6424c1f&v=4" width="32" height="32" alt="0x4e32" /></a>
|
|
155
|
-
<a href="https://github.com/yzuyr?ref=orpc" target="_blank" rel="noopener" title="Ryuz"><img src="https://avatars.githubusercontent.com/u/196539378?u=d38374588d219b6748b16406982f6559411466d4&v=4" width="32" height="32" alt="Ryuz" /></a>
|
|
156
|
-
<a href="https://github.com/happyboy2022?ref=orpc" target="_blank" rel="noopener" title="happyboy"><img src="https://avatars.githubusercontent.com/u/103669586?u=65b49c4b893ed3703909fbb3a7a22313f3f9c121&v=4" width="32" height="32" alt="happyboy" /></a>
|
|
157
|
-
<a href="https://github.com/YiCChi?ref=orpc" target="_blank" rel="noopener" title="yicchi"><img src="https://avatars.githubusercontent.com/u/86967274?u=6c2756f09fe15dd94d572f560e979cd157982852&v=4" width="32" height="32" alt="yicchi" /></a>
|
|
158
|
-
<a href="https://github.com/cloudycotton?ref=orpc" target="_blank" rel="noopener" title="Saksham"><img src="https://avatars.githubusercontent.com/u/168998965?u=9b9634a5aed66a51c1b880663272725b00b92b14&v=4" width="32" height="32" alt="Saksham" /></a>
|
|
159
|
-
<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&v=4" width="32" height="32" alt="Roman Hrynevych" /></a>
|
|
160
|
-
<a href="https://github.com/rokitgg?ref=orpc" target="_blank" rel="noopener" title="rokitg"><img src="https://avatars.githubusercontent.com/u/125133357?u=06c74aefaa2236b06a2e5fba5a5c612339f45912&v=4" width="32" height="32" alt="rokitg" /></a>
|
|
161
|
-
<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&v=4" width="32" height="32" alt="Omar Khatib" /></a>
|
|
162
|
-
<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>
|
|
163
|
-
<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&v=4" width="32" height="32" alt="Bapusaheb Patil" /></a>
|
|
164
|
-
<a href="https://github.com/ripgrim?ref=orpc" target="_blank" rel="noopener" title="grim"><img src="https://avatars.githubusercontent.com/u/75869731?u=b17c42ec2309552fdb822a86b25a2f99146a4d72&v=4" width="32" height="32" alt="grim" /></a>
|
|
165
|
-
<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&v=4" width="32" height="32" alt="Nelson Lai" /></a>
|
|
166
|
-
<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&v=4" width="32" height="32" alt="Lê Cao Nguyên" /></a>
|
|
167
|
-
<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&v=4" width="32" height="32" alt="Robert Soriano" /></a>
|
|
168
|
-
<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>
|
|
169
|
-
<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>
|
|
170
|
-
<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&v=4" width="32" height="32" alt="Novak Antonijevic" /></a>
|
|
171
|
-
<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&v=4" width="32" height="32" alt="Laduni Estu Syalwa" /></a>
|
|
172
|
-
<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&v=4" width="32" height="32" alt="Chen, Zhi-Yuan" /></a>
|
|
173
|
-
<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&v=4" width="32" height="32" alt="Illarion Koperski" /></a>
|
|
174
|
-
<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&v=4" width="32" height="32" alt="Anees Iqbal" /></a>
|
|
175
|
-
<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&v=4" width="32" height="32" alt="Sefa Eyeoglu" /></a>
|
|
176
|
-
<a href="https://github.com/ChromeGG?ref=orpc" target="_blank" rel="noopener" title="Adam Tkaczyk"><img src="https://avatars.githubusercontent.com/u/39050595?u=a58ca6042a6950e94e6e92442db76ef584279bc0&v=4" width="32" height="32" alt="Adam Tkaczyk" /></a>
|
|
177
|
-
<a href="https://github.com/plancraft?ref=orpc" target="_blank" rel="noopener" title="plancraft"><img src="https://avatars.githubusercontent.com/u/46482287?v=4" width="32" height="32" alt="plancraft" /></a>
|
|
178
|
-
</p>
|
|
202
|
+
With thanks to [40 past sponsors](https://orpc.dev/sponsors#past-sponsors) who helped get oRPC here.
|
|
203
|
+
|
|
204
|
+
## Open Source Programs
|
|
205
|
+
|
|
206
|
+
[middleapi](https://github.com/middleapi) is supported by these open source programs:
|
|
207
|
+
|
|
208
|
+
<table>
|
|
209
|
+
<tr>
|
|
210
|
+
<td align="center"><a href="https://claude.com/contact-sales/claude-for-oss" target="_blank" rel="noopener" title="Claude for Open Source"><img src="https://cdn.simpleicons.org/claude" width="64" alt="Claude"/><br />Claude</a></td>
|
|
211
|
+
<td align="center"><a href="https://pullfrog.com/for-oss" target="_blank" rel="noopener" title="Pullfrog for OSS"><img src="https://avatars.githubusercontent.com/in/1768019?s=128&v=4" width="64" alt="Pullfrog"/><br />Pullfrog</a></td>
|
|
212
|
+
</tr>
|
|
213
|
+
</table>
|
|
179
214
|
|
|
180
215
|
## References
|
|
181
216
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AnySchema, JsonSchema, JsonSchemaConverter, JsonSchemaConverterDirection } from "@orpc/json-schema";
|
|
2
|
+
import { ToJSONSchemaParams } from "zod/v4/core";
|
|
3
|
+
export interface ZodToJsonSchemaConverterOptions extends Omit<ToJSONSchemaParams, "target" | "io"> {
|
|
4
|
+
/**
|
|
5
|
+
* Caches conversion results in a WeakMap keyed by the Zod schema instance,
|
|
6
|
+
* so converting the same schema again is free.
|
|
7
|
+
*
|
|
8
|
+
* When enabled, repeated conversions return the same JSON schema object,
|
|
9
|
+
* so treat returned schemas as immutable.
|
|
10
|
+
*
|
|
11
|
+
* @default false
|
|
12
|
+
*/
|
|
13
|
+
cache?: boolean | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Converts Zod schemas into JSON Schema using Zod's built-in `toJSONSchema`,
|
|
17
|
+
* with additional support for types such as `z.bigint()`, `z.date()`, `z.set()`, and `z.map()`.
|
|
18
|
+
*
|
|
19
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
20
|
+
*/
|
|
21
|
+
export declare class ZodToJsonSchemaConverter implements JsonSchemaConverter {
|
|
22
|
+
private readonly toJSONSchemaParams;
|
|
23
|
+
private readonly cache;
|
|
24
|
+
constructor({ cache, ...toJSONSchemaParams }?: ZodToJsonSchemaConverterOptions);
|
|
25
|
+
condition(schema: AnySchema | undefined, _direction: JsonSchemaConverterDirection): boolean;
|
|
26
|
+
convert(schema: AnySchema | undefined, direction: JsonSchemaConverterDirection): [jsonSchema: JsonSchema, optional: boolean];
|
|
27
|
+
private convertUncached;
|
|
28
|
+
private convertZod;
|
|
29
|
+
private getCustomJsonSchema;
|
|
30
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY } from "./registries.js";
|
|
2
|
+
import { JsonSchemaFormat, JsonSchemaXNativeType, isStandardSchemaOptional } from "@orpc/json-schema";
|
|
3
|
+
import { process, toJSONSchema } from "zod/v4/core";
|
|
4
|
+
// src/converter.ts
|
|
5
|
+
/**
|
|
6
|
+
* Converts Zod schemas into JSON Schema using Zod's built-in `toJSONSchema`,
|
|
7
|
+
* with additional support for types such as `z.bigint()`, `z.date()`, `z.set()`, and `z.map()`.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
10
|
+
*/
|
|
11
|
+
var ZodToJsonSchemaConverter = class {
|
|
12
|
+
toJSONSchemaParams;
|
|
13
|
+
cache;
|
|
14
|
+
constructor({ cache, ...toJSONSchemaParams } = {}) {
|
|
15
|
+
this.toJSONSchemaParams = toJSONSchemaParams;
|
|
16
|
+
if (cache) this.cache = {
|
|
17
|
+
input: /* @__PURE__ */ new WeakMap(),
|
|
18
|
+
output: /* @__PURE__ */ new WeakMap()
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
condition(schema, _direction) {
|
|
22
|
+
return schema?.["~standard"].vendor === "zod";
|
|
23
|
+
}
|
|
24
|
+
convert(schema, direction) {
|
|
25
|
+
const zodSchema = schema;
|
|
26
|
+
if (this.cache) {
|
|
27
|
+
const cached = this.cache[direction].get(zodSchema);
|
|
28
|
+
if (cached) return cached;
|
|
29
|
+
}
|
|
30
|
+
const result = this.convertUncached(zodSchema, direction);
|
|
31
|
+
if (this.cache) this.cache[direction].set(zodSchema, result);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
convertUncached(zodSchema, direction) {
|
|
35
|
+
return [this.convertZod(zodSchema, direction), isStandardSchemaOptional(zodSchema, direction)];
|
|
36
|
+
}
|
|
37
|
+
convertZod(schema, direction) {
|
|
38
|
+
const { unrepresentable = "any" } = this.toJSONSchemaParams;
|
|
39
|
+
const { $schema: _schema, ...rest } = toJSONSchema(schema, {
|
|
40
|
+
...this.toJSONSchemaParams,
|
|
41
|
+
target: "draft-2020-12",
|
|
42
|
+
io: direction,
|
|
43
|
+
unrepresentable(info) {
|
|
44
|
+
return convertNativeType(this, info.zodSchema, info.path) ?? (typeof unrepresentable === "function" ? unrepresentable(info) : unrepresentable);
|
|
45
|
+
},
|
|
46
|
+
override: (ctx) => {
|
|
47
|
+
const customJsonSchema = this.getCustomJsonSchema(ctx.zodSchema, direction);
|
|
48
|
+
if (customJsonSchema) Object.assign(ctx.jsonSchema, customJsonSchema);
|
|
49
|
+
this.toJSONSchemaParams.override?.(ctx);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return rest;
|
|
53
|
+
}
|
|
54
|
+
getCustomJsonSchema(schema, direction) {
|
|
55
|
+
const general = JSON_SCHEMA_REGISTRY.get(schema);
|
|
56
|
+
const directional = direction === "input" ? JSON_SCHEMA_INPUT_REGISTRY.get(schema) : JSON_SCHEMA_OUTPUT_REGISTRY.get(schema);
|
|
57
|
+
if (general === void 0 && directional === void 0) return;
|
|
58
|
+
return {
|
|
59
|
+
...general,
|
|
60
|
+
...directional
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function convertNativeType(ctx, zodSchema, path) {
|
|
65
|
+
const def = zodSchema._zod.def;
|
|
66
|
+
switch (def.type) {
|
|
67
|
+
case "bigint": return {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"pattern": "^-?[0-9]+$",
|
|
70
|
+
"x-native-type": JsonSchemaXNativeType.BigInt
|
|
71
|
+
};
|
|
72
|
+
case "date": return {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"format": JsonSchemaFormat.DateTime,
|
|
75
|
+
"x-native-type": JsonSchemaXNativeType.Date
|
|
76
|
+
};
|
|
77
|
+
case "set":
|
|
78
|
+
case "map": {
|
|
79
|
+
const schemaPath = [];
|
|
80
|
+
for (const [seenSchema, seen] of ctx.seen) if (seen.path && seen.path.length <= path.length && seen.path.every((segment, i) => segment === path[i])) schemaPath.push(seenSchema);
|
|
81
|
+
const processItems = (schema, ...segments) => process(schema, ctx, {
|
|
82
|
+
path: [
|
|
83
|
+
...path,
|
|
84
|
+
"items",
|
|
85
|
+
...segments
|
|
86
|
+
],
|
|
87
|
+
schemaPath
|
|
88
|
+
});
|
|
89
|
+
return def.type === "set" ? {
|
|
90
|
+
"type": "array",
|
|
91
|
+
"uniqueItems": true,
|
|
92
|
+
"items": processItems(def.valueType),
|
|
93
|
+
"x-native-type": JsonSchemaXNativeType.Set
|
|
94
|
+
} : {
|
|
95
|
+
"type": "array",
|
|
96
|
+
"items": {
|
|
97
|
+
type: "array",
|
|
98
|
+
prefixItems: [processItems(def.keyType, "prefixItems", 0), processItems(def.valueType, "prefixItems", 1)],
|
|
99
|
+
maxItems: 2,
|
|
100
|
+
minItems: 2
|
|
101
|
+
},
|
|
102
|
+
"x-native-type": JsonSchemaXNativeType.Map
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export { ZodToJsonSchemaConverter };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
declare class ZodToJsonSchemaConverter implements JsonSchemaConverter {
|
|
7
|
-
private readonly options;
|
|
8
|
-
constructor(options?: ZodToJsonSchemaConverterOptions);
|
|
9
|
-
condition(schema: AnySchema | undefined, _direction: JsonSchemaConverterDirection): boolean;
|
|
10
|
-
convert(schema: AnySchema | undefined, direction: JsonSchemaConverterDirection): [jsonSchema: JsonSchema, optional: boolean];
|
|
11
|
-
private convertZod;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export { ZodToJsonSchemaConverter };
|
|
15
|
-
export type { ZodToJsonSchemaConverterOptions };
|
|
1
|
+
import { ZodToJsonSchemaConverter, ZodToJsonSchemaConverterOptions } from "./converter.js";
|
|
2
|
+
import { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY } from "./registries.js";
|
|
3
|
+
import { JsonSchema } from "@orpc/json-schema";
|
|
4
|
+
export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, type JsonSchema, ZodToJsonSchemaConverter, ZodToJsonSchemaConverterOptions };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { JsonSchema } from "@orpc/json-schema";
|
|
2
|
+
import { $ZodRegistry, $input, $output } from "zod/v4/core";
|
|
3
|
+
/**
|
|
4
|
+
* Zod registry for customizing generated JSON schema, can use both for .input and .output
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { JSON_SCHEMA_REGISTRY } from '@orpc/zod'
|
|
9
|
+
*
|
|
10
|
+
* const user = z.object({
|
|
11
|
+
* name: z.string(),
|
|
12
|
+
* age: z.number(),
|
|
13
|
+
* })
|
|
14
|
+
*
|
|
15
|
+
* JSON_SCHEMA_REGISTRY.add(user, {
|
|
16
|
+
* examples: [{ name: 'John', age: 20 }],
|
|
17
|
+
* })
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
21
|
+
*/
|
|
22
|
+
export declare const JSON_SCHEMA_REGISTRY: $ZodRegistry<Exclude<JsonSchema<$input | $output>, boolean>>;
|
|
23
|
+
/**
|
|
24
|
+
* Zod registry for customizing generated JSON schema, only useful for .input
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { JSON_SCHEMA_INPUT_REGISTRY } from '@orpc/zod'
|
|
29
|
+
*
|
|
30
|
+
* const user = z.object({
|
|
31
|
+
* name: z.string(),
|
|
32
|
+
* age: z.string().transform(v => Number(v)),
|
|
33
|
+
* })
|
|
34
|
+
*
|
|
35
|
+
* JSON_SCHEMA_INPUT_REGISTRY.add(user, {
|
|
36
|
+
* examples: [{ name: 'John', age: "20" }],
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
41
|
+
*/
|
|
42
|
+
export declare const JSON_SCHEMA_INPUT_REGISTRY: $ZodRegistry<Exclude<JsonSchema<$input>, boolean>>;
|
|
43
|
+
/**
|
|
44
|
+
* Zod registry for customizing generated JSON schema, only useful for .output
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { JSON_SCHEMA_OUTPUT_REGISTRY } from '@orpc/zod'
|
|
49
|
+
*
|
|
50
|
+
* const user = z.object({
|
|
51
|
+
* name: z.string(),
|
|
52
|
+
* age: z.string().transform(v => Number(v)),
|
|
53
|
+
* })
|
|
54
|
+
*
|
|
55
|
+
* JSON_SCHEMA_OUTPUT_REGISTRY.add(user, {
|
|
56
|
+
* examples: [{ name: 'John', age: 20 }],
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
61
|
+
*/
|
|
62
|
+
export declare const JSON_SCHEMA_OUTPUT_REGISTRY: $ZodRegistry<Exclude<JsonSchema<$output>, boolean>>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { registry } from "zod/v4/core";
|
|
2
|
+
// src/registries.ts
|
|
3
|
+
/**
|
|
4
|
+
* Zod registry for customizing generated JSON schema, can use both for .input and .output
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { JSON_SCHEMA_REGISTRY } from '@orpc/zod'
|
|
9
|
+
*
|
|
10
|
+
* const user = z.object({
|
|
11
|
+
* name: z.string(),
|
|
12
|
+
* age: z.number(),
|
|
13
|
+
* })
|
|
14
|
+
*
|
|
15
|
+
* JSON_SCHEMA_REGISTRY.add(user, {
|
|
16
|
+
* examples: [{ name: 'John', age: 20 }],
|
|
17
|
+
* })
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
21
|
+
*/
|
|
22
|
+
const JSON_SCHEMA_REGISTRY = /* @__PURE__ */ registry();
|
|
23
|
+
/**
|
|
24
|
+
* Zod registry for customizing generated JSON schema, only useful for .input
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { JSON_SCHEMA_INPUT_REGISTRY } from '@orpc/zod'
|
|
29
|
+
*
|
|
30
|
+
* const user = z.object({
|
|
31
|
+
* name: z.string(),
|
|
32
|
+
* age: z.string().transform(v => Number(v)),
|
|
33
|
+
* })
|
|
34
|
+
*
|
|
35
|
+
* JSON_SCHEMA_INPUT_REGISTRY.add(user, {
|
|
36
|
+
* examples: [{ name: 'John', age: "20" }],
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
41
|
+
*/
|
|
42
|
+
const JSON_SCHEMA_INPUT_REGISTRY = /* @__PURE__ */ registry();
|
|
43
|
+
/**
|
|
44
|
+
* Zod registry for customizing generated JSON schema, only useful for .output
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { JSON_SCHEMA_OUTPUT_REGISTRY } from '@orpc/zod'
|
|
49
|
+
*
|
|
50
|
+
* const user = z.object({
|
|
51
|
+
* name: z.string(),
|
|
52
|
+
* age: z.string().transform(v => Number(v)),
|
|
53
|
+
* })
|
|
54
|
+
*
|
|
55
|
+
* JSON_SCHEMA_OUTPUT_REGISTRY.add(user, {
|
|
56
|
+
* examples: [{ name: 'John', age: 20 }],
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
|
|
61
|
+
*/
|
|
62
|
+
const JSON_SCHEMA_OUTPUT_REGISTRY = /* @__PURE__ */ registry();
|
|
63
|
+
export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY };
|
package/package.json
CHANGED
|
@@ -1,41 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/zod",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "2.0.0-beta.50",
|
|
4
|
+
"description": "Zod integration for oRPC: convert Zod schemas into JSON Schema for OpenAPI generation",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"json-schema",
|
|
7
|
+
"openapi",
|
|
8
|
+
"orpc",
|
|
9
|
+
"typesafe",
|
|
10
|
+
"typescript",
|
|
11
|
+
"validation",
|
|
12
|
+
"zod"
|
|
13
|
+
],
|
|
6
14
|
"homepage": "https://orpc.dev",
|
|
15
|
+
"license": "MIT",
|
|
7
16
|
"repository": {
|
|
8
17
|
"type": "git",
|
|
9
18
|
"url": "git+https://github.com/middleapi/orpc.git",
|
|
10
19
|
"directory": "packages/zod"
|
|
11
20
|
},
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
21
|
+
"funding": [
|
|
22
|
+
"https://github.com/sponsors/dinwwwh",
|
|
23
|
+
"https://opencollective.com/middleapi"
|
|
15
24
|
],
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
16
29
|
"sideEffects": false,
|
|
17
30
|
"exports": {
|
|
18
31
|
"./package.json": "./package.json",
|
|
19
32
|
".": {
|
|
20
|
-
"types": "./dist/index.d.
|
|
21
|
-
"import": "./dist/index.
|
|
22
|
-
"default": "./dist/index.
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"import": "./dist/index.js",
|
|
35
|
+
"default": "./dist/index.js"
|
|
23
36
|
}
|
|
24
37
|
},
|
|
25
|
-
"files": [
|
|
26
|
-
"dist"
|
|
27
|
-
],
|
|
28
|
-
"peerDependencies": {
|
|
29
|
-
"zod": ">=4.3.5"
|
|
30
|
-
},
|
|
31
38
|
"dependencies": {
|
|
32
|
-
"@orpc/json-schema": "2.0.0-beta.
|
|
39
|
+
"@orpc/json-schema": "2.0.0-beta.50"
|
|
33
40
|
},
|
|
34
41
|
"devDependencies": {
|
|
35
|
-
"zod": "^4.
|
|
42
|
+
"zod": "^4.6.7"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"zod": ">=4.5.0"
|
|
36
46
|
},
|
|
37
|
-
"scripts": {
|
|
38
|
-
"build": "unbuild",
|
|
39
|
-
"type:check": "tsc -b"
|
|
40
|
-
}
|
|
47
|
+
"scripts": {}
|
|
41
48
|
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { JsonSchemaConverter, AnySchema, JsonSchemaConverterDirection, JsonSchema } from '@orpc/json-schema';
|
|
2
|
-
import { ToJSONSchemaParams } from 'zod/v4/core';
|
|
3
|
-
|
|
4
|
-
interface ZodToJsonSchemaConverterOptions extends Omit<ToJSONSchemaParams, 'target' | 'io'> {
|
|
5
|
-
}
|
|
6
|
-
declare class ZodToJsonSchemaConverter implements JsonSchemaConverter {
|
|
7
|
-
private readonly options;
|
|
8
|
-
constructor(options?: ZodToJsonSchemaConverterOptions);
|
|
9
|
-
condition(schema: AnySchema | undefined, _direction: JsonSchemaConverterDirection): boolean;
|
|
10
|
-
convert(schema: AnySchema | undefined, direction: JsonSchemaConverterDirection): [jsonSchema: JsonSchema, optional: boolean];
|
|
11
|
-
private convertZod;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export { ZodToJsonSchemaConverter };
|
|
15
|
-
export type { ZodToJsonSchemaConverterOptions };
|
package/dist/index.mjs
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { JsonSchemaXNativeType, JsonSchemaFormat } from '@orpc/json-schema';
|
|
2
|
-
import { toJSONSchema } from 'zod/v4/core';
|
|
3
|
-
|
|
4
|
-
class ZodToJsonSchemaConverter {
|
|
5
|
-
constructor(options = {}) {
|
|
6
|
-
this.options = options;
|
|
7
|
-
}
|
|
8
|
-
condition(schema, _direction) {
|
|
9
|
-
return schema?.["~standard"].vendor === "zod";
|
|
10
|
-
}
|
|
11
|
-
convert(schema, direction) {
|
|
12
|
-
const zodSchema = schema;
|
|
13
|
-
const jsonSchema = this.convertZod(zodSchema, direction);
|
|
14
|
-
let optional = false;
|
|
15
|
-
try {
|
|
16
|
-
const result = zodSchema["~standard"].validate(void 0);
|
|
17
|
-
if (!(result instanceof Promise) && !result.issues) {
|
|
18
|
-
optional = direction === "input" ? true : result.value === void 0;
|
|
19
|
-
}
|
|
20
|
-
} catch {
|
|
21
|
-
}
|
|
22
|
-
return [jsonSchema, optional];
|
|
23
|
-
}
|
|
24
|
-
convertZod(schema, direction) {
|
|
25
|
-
const jsonSchema = toJSONSchema(schema, {
|
|
26
|
-
unrepresentable: "any",
|
|
27
|
-
...this.options,
|
|
28
|
-
target: "draft-2020-12",
|
|
29
|
-
io: direction,
|
|
30
|
-
override: (ctx) => {
|
|
31
|
-
const def = ctx.zodSchema._zod.def;
|
|
32
|
-
if (def.type === "bigint") {
|
|
33
|
-
ctx.jsonSchema.type = "string";
|
|
34
|
-
ctx.jsonSchema.pattern = "^-?[0-9]+$";
|
|
35
|
-
ctx.jsonSchema["x-native-type"] = JsonSchemaXNativeType.BigInt;
|
|
36
|
-
} else if (def.type === "date") {
|
|
37
|
-
ctx.jsonSchema.type = "string";
|
|
38
|
-
ctx.jsonSchema.format = JsonSchemaFormat.DateTime;
|
|
39
|
-
ctx.jsonSchema["x-native-type"] = JsonSchemaXNativeType.Date;
|
|
40
|
-
} else if (def.type === "set") {
|
|
41
|
-
ctx.jsonSchema.type = "array";
|
|
42
|
-
ctx.jsonSchema.uniqueItems = true;
|
|
43
|
-
ctx.jsonSchema.items = this.convertZod(def.valueType, direction);
|
|
44
|
-
ctx.jsonSchema["x-native-type"] = JsonSchemaXNativeType.Set;
|
|
45
|
-
} else if (def.type === "map") {
|
|
46
|
-
ctx.jsonSchema.type = "array";
|
|
47
|
-
ctx.jsonSchema.items = {
|
|
48
|
-
type: "array",
|
|
49
|
-
prefixItems: [
|
|
50
|
-
this.convertZod(def.keyType, direction),
|
|
51
|
-
this.convertZod(def.valueType, direction)
|
|
52
|
-
],
|
|
53
|
-
maxItems: 2,
|
|
54
|
-
minItems: 2
|
|
55
|
-
};
|
|
56
|
-
ctx.jsonSchema["x-native-type"] = JsonSchemaXNativeType.Map;
|
|
57
|
-
}
|
|
58
|
-
this.options.override?.(ctx);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
const { $schema, ...rest } = jsonSchema;
|
|
62
|
-
return rest;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export { ZodToJsonSchemaConverter };
|