@orpc/zod 0.0.0-next.371be67 → 0.0.0-next.3764ef9
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 +43 -30
- package/dist/index.d.mts +22 -13
- package/dist/index.d.ts +22 -13
- package/dist/index.mjs +79 -46
- package/dist/zod4/index.d.mts +314 -0
- package/dist/zod4/index.d.ts +314 -0
- package/dist/zod4/index.mjs +686 -0
- package/package.json +16 -11
package/README.md
CHANGED
|
@@ -1,63 +1,68 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<image align="center" src="https://orpc.
|
|
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/
|
|
9
|
-
<img alt="codecov" src="https://codecov.io/gh/
|
|
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/
|
|
15
|
-
<img alt="MIT License" src="https://img.shields.io/github/license/
|
|
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>
|
|
23
26
|
|
|
24
|
-
**oRPC is a powerful combination of RPC and OpenAPI**, makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards
|
|
27
|
+
**oRPC is a powerful combination of RPC and OpenAPI**, makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards
|
|
25
28
|
|
|
26
29
|
---
|
|
27
30
|
|
|
28
31
|
## Highlights
|
|
29
32
|
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
- **Reusability 🔄**: Write once and reuse your code across multiple purposes effortlessly.
|
|
43
|
-
- **Extendability 🔌**: Easily enhance oRPC with plugins, middleware, and interceptors.
|
|
44
|
-
- **Reliability 🛡️**: Well-tested, fully TypeScript, production-ready, and MIT licensed for peace of mind.
|
|
45
|
-
- **Simplicity 💡**: Enjoy straightforward, clean code with no hidden magic.
|
|
33
|
+
- **🔗 End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server.
|
|
34
|
+
- **📘 First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard.
|
|
35
|
+
- **📝 Contract-First Development**: Optionally define your API contract before implementation.
|
|
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.
|
|
38
|
+
- **🚀 Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
|
|
39
|
+
- **🔠 Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
|
|
40
|
+
- **🗃️ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more.
|
|
41
|
+
- **⏱️ Lazy Router**: Enhance cold start times with our lazy routing feature.
|
|
42
|
+
- **📡 SSE & Streaming**: Enjoy full type-safe support for SSE and streaming.
|
|
43
|
+
- **🌍 Multi-Runtime Support**: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond.
|
|
44
|
+
- **🔌 Extendability**: Easily extend functionality with plugins, middleware, and interceptors.
|
|
46
45
|
|
|
47
46
|
## Documentation
|
|
48
47
|
|
|
49
|
-
You can find the full documentation [here](https://orpc.
|
|
48
|
+
You can find the full documentation [here](https://orpc.dev).
|
|
50
49
|
|
|
51
50
|
## Packages
|
|
52
51
|
|
|
53
52
|
- [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Build your API contract.
|
|
54
53
|
- [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build your API or implement API contract.
|
|
55
54
|
- [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety.
|
|
56
|
-
- [@orpc/react-query](https://www.npmjs.com/package/@orpc/react-query): Integration with [React Query](https://tanstack.com/query/latest/docs/framework/react/overview).
|
|
57
|
-
- [@orpc/vue-query](https://www.npmjs.com/package/@orpc/vue-query): Integration with [Vue Query](https://tanstack.com/query/latest/docs/framework/vue/overview).
|
|
58
|
-
- [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
|
|
59
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.
|
|
57
|
+
- [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
|
|
58
|
+
- [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
|
|
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.
|
|
61
|
+
- [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
|
|
62
|
+
- [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
|
|
60
63
|
- [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
|
|
64
|
+
- [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): OpenAPI spec generation from [Valibot](https://valibot.dev/).
|
|
65
|
+
- [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): OpenAPI spec generation from [ArkType](https://arktype.io/).
|
|
61
66
|
|
|
62
67
|
## `@orpc/zod`
|
|
63
68
|
|
|
@@ -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
|
|
119
|
+
import * as z from 'zod'
|
|
115
120
|
|
|
116
121
|
const InputSchema = oz.openapi(
|
|
117
122
|
z.object({
|
|
@@ -127,6 +132,14 @@ const InputSchema = oz.openapi(
|
|
|
127
132
|
)
|
|
128
133
|
```
|
|
129
134
|
|
|
135
|
+
## Sponsors
|
|
136
|
+
|
|
137
|
+
<p align="center">
|
|
138
|
+
<a href="https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg">
|
|
139
|
+
<img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg'/>
|
|
140
|
+
</a>
|
|
141
|
+
</p>
|
|
142
|
+
|
|
130
143
|
## License
|
|
131
144
|
|
|
132
|
-
Distributed under the MIT License. See [LICENSE](https://github.com/
|
|
145
|
+
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,9 +1,8 @@
|
|
|
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
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { Schema } from '@orpc/contract';
|
|
4
|
+
import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
|
|
5
|
+
import { AnySchema } from '@orpc/contract';
|
|
7
6
|
|
|
8
7
|
declare function getCustomJsonSchema(def: ZodTypeDef, options: {
|
|
9
8
|
strategy: 'input' | 'output' | 'both';
|
|
@@ -35,40 +34,49 @@ declare function regexp(params?: string | CustomParams | ((input: unknown) => Cu
|
|
|
35
34
|
|
|
36
35
|
declare function url(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<URL, ZodTypeDef, URL>;
|
|
37
36
|
|
|
38
|
-
declare class ZodSmartCoercionPlugin<TContext extends Context> implements
|
|
37
|
+
declare class ZodSmartCoercionPlugin<TContext extends Context> implements StandardHandlerPlugin<TContext> {
|
|
39
38
|
init(options: StandardHandlerOptions<TContext>): void;
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
interface ZodToJsonSchemaOptions {
|
|
43
42
|
/**
|
|
44
|
-
* Max depth of lazy type
|
|
43
|
+
* Max depth of lazy type
|
|
45
44
|
*
|
|
46
|
-
* Used `{}` when
|
|
45
|
+
* Used `{}` when exceed max depth
|
|
47
46
|
*
|
|
48
47
|
* @default 3
|
|
49
48
|
*/
|
|
50
49
|
maxLazyDepth?: number;
|
|
51
50
|
/**
|
|
52
|
-
*
|
|
51
|
+
* Max depth of nested types
|
|
53
52
|
*
|
|
54
|
-
*
|
|
53
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
|
54
|
+
*
|
|
55
|
+
* @default 10
|
|
55
56
|
*/
|
|
56
|
-
|
|
57
|
+
maxStructureDepth?: number;
|
|
57
58
|
/**
|
|
58
59
|
* The schema to be used to represent the any | unknown type.
|
|
59
60
|
*
|
|
60
61
|
* @default { }
|
|
61
62
|
*/
|
|
62
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>;
|
|
63
70
|
}
|
|
64
71
|
declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
|
|
65
72
|
#private;
|
|
66
73
|
private readonly maxLazyDepth;
|
|
74
|
+
private readonly maxStructureDepth;
|
|
67
75
|
private readonly unsupportedJsonSchema;
|
|
68
76
|
private readonly anyJsonSchema;
|
|
69
77
|
constructor(options?: ZodToJsonSchemaOptions);
|
|
70
|
-
condition(schema:
|
|
71
|
-
convert(schema:
|
|
78
|
+
condition(schema: AnySchema | undefined): boolean;
|
|
79
|
+
convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean, structureDepth?: number): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
|
72
80
|
}
|
|
73
81
|
|
|
74
82
|
declare const oz: {
|
|
@@ -79,4 +87,5 @@ declare const oz: {
|
|
|
79
87
|
openapi: typeof customJsonSchema;
|
|
80
88
|
};
|
|
81
89
|
|
|
82
|
-
export {
|
|
90
|
+
export { ZodSmartCoercionPlugin, ZodToJsonSchemaConverter, blob, composeParams, customJsonSchema, file, getCustomJsonSchema, getCustomZodDef, oz, regexp, setCustomZodDef, url };
|
|
91
|
+
export type { CustomParams, CustomZodDef, ZodToJsonSchemaOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
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
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { Schema } from '@orpc/contract';
|
|
4
|
+
import { StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
|
|
5
|
+
import { AnySchema } from '@orpc/contract';
|
|
7
6
|
|
|
8
7
|
declare function getCustomJsonSchema(def: ZodTypeDef, options: {
|
|
9
8
|
strategy: 'input' | 'output' | 'both';
|
|
@@ -35,40 +34,49 @@ declare function regexp(params?: string | CustomParams | ((input: unknown) => Cu
|
|
|
35
34
|
|
|
36
35
|
declare function url(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<URL, ZodTypeDef, URL>;
|
|
37
36
|
|
|
38
|
-
declare class ZodSmartCoercionPlugin<TContext extends Context> implements
|
|
37
|
+
declare class ZodSmartCoercionPlugin<TContext extends Context> implements StandardHandlerPlugin<TContext> {
|
|
39
38
|
init(options: StandardHandlerOptions<TContext>): void;
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
interface ZodToJsonSchemaOptions {
|
|
43
42
|
/**
|
|
44
|
-
* Max depth of lazy type
|
|
43
|
+
* Max depth of lazy type
|
|
45
44
|
*
|
|
46
|
-
* Used `{}` when
|
|
45
|
+
* Used `{}` when exceed max depth
|
|
47
46
|
*
|
|
48
47
|
* @default 3
|
|
49
48
|
*/
|
|
50
49
|
maxLazyDepth?: number;
|
|
51
50
|
/**
|
|
52
|
-
*
|
|
51
|
+
* Max depth of nested types
|
|
53
52
|
*
|
|
54
|
-
*
|
|
53
|
+
* Used anyJsonSchema (`{}`) when exceed max depth
|
|
54
|
+
*
|
|
55
|
+
* @default 10
|
|
55
56
|
*/
|
|
56
|
-
|
|
57
|
+
maxStructureDepth?: number;
|
|
57
58
|
/**
|
|
58
59
|
* The schema to be used to represent the any | unknown type.
|
|
59
60
|
*
|
|
60
61
|
* @default { }
|
|
61
62
|
*/
|
|
62
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>;
|
|
63
70
|
}
|
|
64
71
|
declare class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
|
|
65
72
|
#private;
|
|
66
73
|
private readonly maxLazyDepth;
|
|
74
|
+
private readonly maxStructureDepth;
|
|
67
75
|
private readonly unsupportedJsonSchema;
|
|
68
76
|
private readonly anyJsonSchema;
|
|
69
77
|
constructor(options?: ZodToJsonSchemaOptions);
|
|
70
|
-
condition(schema:
|
|
71
|
-
convert(schema:
|
|
78
|
+
condition(schema: AnySchema | undefined): boolean;
|
|
79
|
+
convert(schema: AnySchema | undefined, options: SchemaConvertOptions, lazyDepth?: number, isHandledCustomJSONSchema?: boolean, isHandledZodDescription?: boolean, structureDepth?: number): [required: boolean, jsonSchema: Exclude<JSONSchema, boolean>];
|
|
72
80
|
}
|
|
73
81
|
|
|
74
82
|
declare const oz: {
|
|
@@ -79,4 +87,5 @@ declare const oz: {
|
|
|
79
87
|
openapi: typeof customJsonSchema;
|
|
80
88
|
};
|
|
81
89
|
|
|
82
|
-
export {
|
|
90
|
+
export { ZodSmartCoercionPlugin, ZodToJsonSchemaConverter, blob, composeParams, customJsonSchema, file, getCustomJsonSchema, getCustomZodDef, oz, regexp, setCustomZodDef, url };
|
|
91
|
+
export type { CustomParams, CustomZodDef, ZodToJsonSchemaOptions };
|
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
|
|
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 = {
|
|
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 = {
|
|
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: {
|
|
@@ -591,7 +615,7 @@ class ZodToJsonSchemaConverter {
|
|
|
591
615
|
const schema_ = schema;
|
|
592
616
|
const def2 = schema_._def;
|
|
593
617
|
const json = { type: "array" };
|
|
594
|
-
const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false);
|
|
618
|
+
const [itemRequired, itemJson] = this.convert(def2.type, options, lazyDepth, false, false, structureDepth + 1);
|
|
595
619
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
|
596
620
|
if (def2.exactLength) {
|
|
597
621
|
json.maxItems = def2.exactLength.value;
|
|
@@ -610,7 +634,7 @@ class ZodToJsonSchemaConverter {
|
|
|
610
634
|
const prefixItems = [];
|
|
611
635
|
const json = { type: "array" };
|
|
612
636
|
for (const item of schema_._def.items) {
|
|
613
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
|
637
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
|
|
614
638
|
prefixItems.push(
|
|
615
639
|
this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy)
|
|
616
640
|
);
|
|
@@ -619,7 +643,7 @@ class ZodToJsonSchemaConverter {
|
|
|
619
643
|
json.prefixItems = prefixItems;
|
|
620
644
|
}
|
|
621
645
|
if (schema_._def.rest) {
|
|
622
|
-
const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false);
|
|
646
|
+
const [itemRequired, itemJson] = this.convert(schema_._def.rest, options, lazyDepth, false, false, structureDepth + 1);
|
|
623
647
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
|
624
648
|
}
|
|
625
649
|
return [true, json];
|
|
@@ -630,7 +654,7 @@ class ZodToJsonSchemaConverter {
|
|
|
630
654
|
const properties = {};
|
|
631
655
|
const required = [];
|
|
632
656
|
for (const [key, value] of Object.entries(schema_.shape)) {
|
|
633
|
-
const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false);
|
|
657
|
+
const [itemRequired, itemJson] = this.convert(value, options, lazyDepth, false, false, structureDepth + 1);
|
|
634
658
|
properties[key] = itemJson;
|
|
635
659
|
if (itemRequired) {
|
|
636
660
|
required.push(key);
|
|
@@ -648,7 +672,7 @@ class ZodToJsonSchemaConverter {
|
|
|
648
672
|
json.additionalProperties = false;
|
|
649
673
|
}
|
|
650
674
|
} else {
|
|
651
|
-
const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false);
|
|
675
|
+
const [_, addJson] = this.convert(schema_._def.catchall, options, lazyDepth, false, false, structureDepth + 1);
|
|
652
676
|
json.additionalProperties = addJson;
|
|
653
677
|
}
|
|
654
678
|
return [true, json];
|
|
@@ -656,29 +680,32 @@ class ZodToJsonSchemaConverter {
|
|
|
656
680
|
case ZodFirstPartyTypeKind.ZodRecord: {
|
|
657
681
|
const schema_ = schema;
|
|
658
682
|
const json = { type: "object" };
|
|
659
|
-
const
|
|
660
|
-
if (
|
|
661
|
-
const [_2, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
|
|
683
|
+
const [__, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
|
|
684
|
+
if (Object.entries(keyJson).some(([k, v]) => k !== "type" || v !== "string")) {
|
|
662
685
|
json.propertyNames = keyJson;
|
|
663
686
|
}
|
|
664
|
-
const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
|
|
687
|
+
const [_, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
|
665
688
|
json.additionalProperties = itemJson;
|
|
666
689
|
return [true, json];
|
|
667
690
|
}
|
|
668
691
|
case ZodFirstPartyTypeKind.ZodSet: {
|
|
669
692
|
const schema_ = schema;
|
|
670
|
-
const json = {
|
|
671
|
-
|
|
693
|
+
const json = {
|
|
694
|
+
"type": "array",
|
|
695
|
+
"uniqueItems": true,
|
|
696
|
+
"x-native-type": JsonSchemaXNativeType.Set
|
|
697
|
+
};
|
|
698
|
+
const [itemRequired, itemJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
|
672
699
|
json.items = this.#toArrayItemJsonSchema(itemRequired, itemJson, options.strategy);
|
|
673
700
|
return [true, json];
|
|
674
701
|
}
|
|
675
702
|
case ZodFirstPartyTypeKind.ZodMap: {
|
|
676
703
|
const schema_ = schema;
|
|
677
|
-
const [keyRequired, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false);
|
|
678
|
-
const [valueRequired, valueJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false);
|
|
679
|
-
|
|
680
|
-
type: "array",
|
|
681
|
-
items: {
|
|
704
|
+
const [keyRequired, keyJson] = this.convert(schema_._def.keyType, options, lazyDepth, false, false, structureDepth + 1);
|
|
705
|
+
const [valueRequired, valueJson] = this.convert(schema_._def.valueType, options, lazyDepth, false, false, structureDepth + 1);
|
|
706
|
+
const json = {
|
|
707
|
+
"type": "array",
|
|
708
|
+
"items": {
|
|
682
709
|
type: "array",
|
|
683
710
|
prefixItems: [
|
|
684
711
|
this.#toArrayItemJsonSchema(keyRequired, keyJson, options.strategy),
|
|
@@ -686,8 +713,10 @@ class ZodToJsonSchemaConverter {
|
|
|
686
713
|
],
|
|
687
714
|
maxItems: 2,
|
|
688
715
|
minItems: 2
|
|
689
|
-
}
|
|
690
|
-
|
|
716
|
+
},
|
|
717
|
+
"x-native-type": JsonSchemaXNativeType.Map
|
|
718
|
+
};
|
|
719
|
+
return [true, json];
|
|
691
720
|
}
|
|
692
721
|
case ZodFirstPartyTypeKind.ZodUnion:
|
|
693
722
|
case ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
|
|
@@ -695,7 +724,7 @@ class ZodToJsonSchemaConverter {
|
|
|
695
724
|
const anyOf = [];
|
|
696
725
|
let required = true;
|
|
697
726
|
for (const item of schema_._def.options) {
|
|
698
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
|
727
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
|
|
699
728
|
if (!itemRequired) {
|
|
700
729
|
required = false;
|
|
701
730
|
if (itemJson !== this.unsupportedJsonSchema) {
|
|
@@ -705,9 +734,6 @@ class ZodToJsonSchemaConverter {
|
|
|
705
734
|
anyOf.push(itemJson);
|
|
706
735
|
}
|
|
707
736
|
}
|
|
708
|
-
if (anyOf.length === 1) {
|
|
709
|
-
return [required, anyOf[0]];
|
|
710
|
-
}
|
|
711
737
|
return [required, { anyOf }];
|
|
712
738
|
}
|
|
713
739
|
case ZodFirstPartyTypeKind.ZodIntersection: {
|
|
@@ -715,7 +741,7 @@ class ZodToJsonSchemaConverter {
|
|
|
715
741
|
const allOf = [];
|
|
716
742
|
let required = false;
|
|
717
743
|
for (const item of [schema_._def.left, schema_._def.right]) {
|
|
718
|
-
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false);
|
|
744
|
+
const [itemRequired, itemJson] = this.convert(item, options, lazyDepth, false, false, structureDepth + 1);
|
|
719
745
|
allOf.push(itemJson);
|
|
720
746
|
if (itemRequired) {
|
|
721
747
|
required = true;
|
|
@@ -724,25 +750,26 @@ class ZodToJsonSchemaConverter {
|
|
|
724
750
|
return [required, { allOf }];
|
|
725
751
|
}
|
|
726
752
|
case ZodFirstPartyTypeKind.ZodLazy: {
|
|
727
|
-
|
|
753
|
+
const currentLazyDepth = lazyDepth + 1;
|
|
754
|
+
if (currentLazyDepth > this.maxLazyDepth) {
|
|
728
755
|
return [false, this.anyJsonSchema];
|
|
729
756
|
}
|
|
730
757
|
const schema_ = schema;
|
|
731
|
-
return this.convert(schema_._def.getter(), options,
|
|
758
|
+
return this.convert(schema_._def.getter(), options, currentLazyDepth, false, false, structureDepth);
|
|
732
759
|
}
|
|
733
760
|
case ZodFirstPartyTypeKind.ZodOptional: {
|
|
734
761
|
const schema_ = schema;
|
|
735
|
-
const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
|
762
|
+
const [_, inner] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
|
736
763
|
return [false, inner];
|
|
737
764
|
}
|
|
738
765
|
case ZodFirstPartyTypeKind.ZodReadonly: {
|
|
739
766
|
const schema_ = schema;
|
|
740
|
-
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
|
767
|
+
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
|
741
768
|
return [required, { ...json, readOnly: true }];
|
|
742
769
|
}
|
|
743
770
|
case ZodFirstPartyTypeKind.ZodDefault: {
|
|
744
771
|
const schema_ = schema;
|
|
745
|
-
const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
|
772
|
+
const [_, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
|
746
773
|
return [false, { default: schema_._def.defaultValue(), ...json }];
|
|
747
774
|
}
|
|
748
775
|
case ZodFirstPartyTypeKind.ZodEffects: {
|
|
@@ -750,15 +777,15 @@ class ZodToJsonSchemaConverter {
|
|
|
750
777
|
if (schema_._def.effect.type === "transform" && options.strategy === "output") {
|
|
751
778
|
return [false, this.anyJsonSchema];
|
|
752
779
|
}
|
|
753
|
-
return this.convert(schema_._def.schema, options, lazyDepth, false, false);
|
|
780
|
+
return this.convert(schema_._def.schema, options, lazyDepth, false, false, structureDepth);
|
|
754
781
|
}
|
|
755
782
|
case ZodFirstPartyTypeKind.ZodCatch: {
|
|
756
783
|
const schema_ = schema;
|
|
757
|
-
return this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
|
784
|
+
return this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
|
758
785
|
}
|
|
759
786
|
case ZodFirstPartyTypeKind.ZodBranded: {
|
|
760
787
|
const schema_ = schema;
|
|
761
|
-
return this.convert(schema_._def.type, options, lazyDepth, false, false);
|
|
788
|
+
return this.convert(schema_._def.type, options, lazyDepth, false, false, structureDepth);
|
|
762
789
|
}
|
|
763
790
|
case ZodFirstPartyTypeKind.ZodPipeline: {
|
|
764
791
|
const schema_ = schema;
|
|
@@ -767,13 +794,14 @@ class ZodToJsonSchemaConverter {
|
|
|
767
794
|
options,
|
|
768
795
|
lazyDepth,
|
|
769
796
|
false,
|
|
770
|
-
false
|
|
797
|
+
false,
|
|
798
|
+
structureDepth
|
|
771
799
|
);
|
|
772
800
|
}
|
|
773
801
|
case ZodFirstPartyTypeKind.ZodNullable: {
|
|
774
802
|
const schema_ = schema;
|
|
775
|
-
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false);
|
|
776
|
-
return [required, { anyOf: [{ type: "null" }
|
|
803
|
+
const [required, json] = this.convert(schema_._def.innerType, options, lazyDepth, false, false, structureDepth);
|
|
804
|
+
return [required, { anyOf: [json, { type: "null" }] }];
|
|
777
805
|
}
|
|
778
806
|
}
|
|
779
807
|
return [true, this.unsupportedJsonSchema];
|
|
@@ -792,12 +820,17 @@ class ZodToJsonSchemaConverter {
|
|
|
792
820
|
}
|
|
793
821
|
case "regexp": {
|
|
794
822
|
return {
|
|
795
|
-
type: "string",
|
|
796
|
-
pattern: "^\\/(.*)\\/([a-z]*)$"
|
|
823
|
+
"type": "string",
|
|
824
|
+
"pattern": "^\\/(.*)\\/([a-z]*)$",
|
|
825
|
+
"x-native-type": JsonSchemaXNativeType.RegExp
|
|
797
826
|
};
|
|
798
827
|
}
|
|
799
828
|
case "url": {
|
|
800
|
-
return {
|
|
829
|
+
return {
|
|
830
|
+
"type": "string",
|
|
831
|
+
"format": JSONSchemaFormat.URI,
|
|
832
|
+
"x-native-type": JsonSchemaXNativeType.Url
|
|
833
|
+
};
|
|
801
834
|
}
|
|
802
835
|
}
|
|
803
836
|
}
|