@orpc/zod 2.0.0-beta.47 → 2.0.0-beta.49

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
@@ -5,7 +5,7 @@
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="weekly downloads" src="https://img.shields.io/npm/dw/%40orpc%2Fzod?logo=npm" />
8
+ <img alt="monthly downloads" src="https://img.shields.io/npm/dm/%40orpc%2Fzod?logo=npm" />
9
9
  </a>
10
10
  <a href="https://app.codspeed.io/middleapi/orpc?utm_source=badge">
11
11
  <img alt="CodSpeed" src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" />
@@ -41,10 +41,11 @@ export const router = {
41
41
  Then call them from a client that knows every input and output, without generating anything:
42
42
 
43
43
  ```ts
44
- import type { RouterClient } from '@orpc/server'
45
- import type { router } from './router'
46
44
  import { createORPCClient } from '@orpc/client'
47
45
  import { RPCLink } from '@orpc/client/fetch'
46
+ import type { RouterClient } from '@orpc/server'
47
+
48
+ import type { router } from './router'
48
49
 
49
50
  const link = new RPCLink({ origin: 'http://localhost:3000', url: '/rpc' })
50
51
  const client: RouterClient<typeof router> = createORPCClient(link)
@@ -191,15 +192,14 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
191
192
  <td align="center"><a href="https://kellychan.im/?ref=middleapi&amp;utm_source=middleapi&amp;utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&amp;v=4" width="139" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
192
193
  <td align="center"><a href="https://guyariely.com/?ref=middleapi&amp;utm_source=middleapi&amp;utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Guy Ariely"><img src="https://avatars.githubusercontent.com/u/42813496?u=edb6b7f563bf28e160a290832e7da57c0506f8ca&amp;v=4" width="139" alt="Guy Ariely"/><br />Guy Ariely</a></td>
193
194
  <td align="center"><a href="https://paulsenon.com/?ref=middleapi&amp;utm_source=middleapi&amp;utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="PaulSenon"><img src="https://avatars.githubusercontent.com/u/19531087?u=6385741eb91d200b8c513ec6045482e301767ca6&amp;v=4" width="139" alt="PaulSenon"/><br />PaulSenon</a></td>
194
- <td align="center"><a href="https://nakasyou.how/?ref=middleapi&amp;utm_source=middleapi&amp;utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Shotaro Nakamura"><img src="https://avatars.githubusercontent.com/u/79000684?u=f644df3f29f0e8677a90967115774564f1d9d6ab&amp;v=4" width="139" alt="Shotaro Nakamura"/><br />Shotaro Nakamura</a></td>
195
+ <td align="center"><a href="https://piscis.dev/?ref=middleapi&amp;utm_source=middleapi&amp;utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&amp;v=4" width="139" alt="Alex"/><br />Alex</a></td>
195
196
  </tr>
196
197
  <tr>
197
- <td align="center"><a href="https://piscis.dev/?ref=middleapi&amp;utm_source=middleapi&amp;utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&amp;v=4" width="139" alt="Alex"/><br />Alex</a></td>
198
198
  <td align="center"><a href="https://opensource.gubanov.eu/?ref=middleapi&amp;utm_source=middleapi&amp;utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Andrey Gubanov"><img src="https://avatars.githubusercontent.com/u/1082083?u=c5f2daf7ebece498e85c83367bb37b4e10e2649d&amp;v=4" width="139" alt="Andrey Gubanov"/><br />Andrey Gubanov</a></td>
199
199
  </tr>
200
200
  </table>
201
201
 
202
- With thanks to [39 past sponsors](https://orpc.dev/sponsors#past-sponsors) who helped get oRPC here.
202
+ With thanks to [40 past sponsors](https://orpc.dev/sponsors#past-sponsors) who helped get oRPC here.
203
203
 
204
204
  ## Open Source Programs
205
205
 
@@ -209,7 +209,6 @@ With thanks to [39 past sponsors](https://orpc.dev/sponsors#past-sponsors) who h
209
209
  <tr>
210
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
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&amp;v=4" width="64" alt="Pullfrog"/><br />Pullfrog</a></td>
212
- <td align="center"><a href="https://macroscope.com/open-source" target="_blank" rel="noopener" title="Macroscope for Open Source"><img src="https://avatars.githubusercontent.com/in/900172?s=128&amp;v=4" width="64" alt="Macroscope"/><br />Macroscope</a></td>
213
212
  </tr>
214
213
  </table>
215
214
 
@@ -0,0 +1,30 @@
1
+ import type { AnySchema, JsonSchema, JsonSchemaConverter, JsonSchemaConverterDirection } from '@orpc/json-schema';
2
+ import type { 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,123 @@
1
+ import { isStandardSchemaOptional, JsonSchemaFormat, JsonSchemaXNativeType, } from '@orpc/json-schema';
2
+ import { process as processZodSchema, toJSONSchema } from 'zod/v4/core';
3
+ import { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, } from './registries.js';
4
+ /**
5
+ * Converts Zod schemas into JSON Schema using Zod's built-in `toJSONSchema`,
6
+ * with additional support for types such as `z.bigint()`, `z.date()`, `z.set()`, and `z.map()`.
7
+ *
8
+ * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
9
+ */
10
+ export class ZodToJsonSchemaConverter {
11
+ toJSONSchemaParams;
12
+ cache;
13
+ constructor({ cache, ...toJSONSchemaParams } = {}) {
14
+ this.toJSONSchemaParams = toJSONSchemaParams;
15
+ if (cache) {
16
+ this.cache = { input: new WeakMap(), output: new WeakMap() };
17
+ }
18
+ }
19
+ condition(schema, _direction) {
20
+ return schema?.['~standard'].vendor === 'zod';
21
+ }
22
+ convert(schema, direction) {
23
+ const zodSchema = schema;
24
+ if (this.cache) {
25
+ const cached = this.cache[direction].get(zodSchema);
26
+ if (cached) {
27
+ return cached;
28
+ }
29
+ }
30
+ const result = this.convertUncached(zodSchema, direction);
31
+ if (this.cache) {
32
+ this.cache[direction].set(zodSchema, result);
33
+ }
34
+ return result;
35
+ }
36
+ convertUncached(zodSchema, direction) {
37
+ const jsonSchema = this.convertZod(zodSchema, direction);
38
+ return [jsonSchema, isStandardSchemaOptional(zodSchema, direction)];
39
+ }
40
+ convertZod(schema, direction) {
41
+ const { unrepresentable = 'any' } = this.toJSONSchemaParams;
42
+ const jsonSchema = toJSONSchema(schema, {
43
+ ...this.toJSONSchemaParams,
44
+ target: 'draft-2020-12',
45
+ io: direction,
46
+ unrepresentable(info) {
47
+ return (convertNativeType(this, info.zodSchema, info.path) ??
48
+ (typeof unrepresentable === 'function' ? unrepresentable(info) : unrepresentable));
49
+ },
50
+ override: (ctx) => {
51
+ const customJsonSchema = this.getCustomJsonSchema(ctx.zodSchema, direction);
52
+ if (customJsonSchema) {
53
+ Object.assign(ctx.jsonSchema, customJsonSchema);
54
+ }
55
+ this.toJSONSchemaParams.override?.(ctx);
56
+ },
57
+ });
58
+ // Since the default oRPC format is always draft/2020-12,
59
+ // `$schema` can be safely omitted here.
60
+ const { $schema: _schema, ...rest } = jsonSchema;
61
+ return rest;
62
+ }
63
+ getCustomJsonSchema(schema, direction) {
64
+ const general = JSON_SCHEMA_REGISTRY.get(schema);
65
+ const directional = direction === 'input'
66
+ ? JSON_SCHEMA_INPUT_REGISTRY.get(schema)
67
+ : JSON_SCHEMA_OUTPUT_REGISTRY.get(schema);
68
+ if (general === undefined && directional === undefined) {
69
+ return undefined;
70
+ }
71
+ return { ...general, ...directional };
72
+ }
73
+ }
74
+ function convertNativeType(ctx, zodSchema, path) {
75
+ const def = zodSchema._zod.def;
76
+ switch (def.type) {
77
+ case 'bigint':
78
+ return {
79
+ 'type': 'string',
80
+ 'pattern': '^-?[0-9]+$',
81
+ 'x-native-type': JsonSchemaXNativeType.BigInt,
82
+ };
83
+ case 'date':
84
+ return {
85
+ 'type': 'string',
86
+ 'format': JsonSchemaFormat.DateTime,
87
+ 'x-native-type': JsonSchemaXNativeType.Date,
88
+ };
89
+ case 'set':
90
+ case 'map': {
91
+ const schemaPath = [];
92
+ for (const [seenSchema, seen] of ctx.seen) {
93
+ if (seen.path &&
94
+ seen.path.length <= path.length &&
95
+ seen.path.every((segment, i) => segment === path[i])) {
96
+ schemaPath.push(seenSchema);
97
+ }
98
+ }
99
+ const processItems = (schema, ...segments) => processZodSchema(schema, ctx, { path: [...path, 'items', ...segments], schemaPath });
100
+ return def.type === 'set'
101
+ ? {
102
+ 'type': 'array',
103
+ 'uniqueItems': true,
104
+ 'items': processItems(def.valueType),
105
+ 'x-native-type': JsonSchemaXNativeType.Set,
106
+ }
107
+ : {
108
+ 'type': 'array',
109
+ 'items': {
110
+ type: 'array',
111
+ prefixItems: [
112
+ processItems(def.keyType, 'prefixItems', 0),
113
+ processItems(def.valueType, 'prefixItems', 1),
114
+ ],
115
+ maxItems: 2,
116
+ minItems: 2,
117
+ },
118
+ 'x-native-type': JsonSchemaXNativeType.Map,
119
+ };
120
+ }
121
+ }
122
+ return undefined;
123
+ }
package/dist/index.d.ts CHANGED
@@ -1,98 +1,3 @@
1
- import { JsonSchemaConverter, AnySchema, JsonSchemaConverterDirection, JsonSchema } from '@orpc/json-schema';
2
- export { JsonSchema } from '@orpc/json-schema';
3
- import * as zod_v4_core from 'zod/v4/core';
4
- import { ToJSONSchemaParams, $input, $output } from 'zod/v4/core';
5
- import * as _openapi_spec_types_v3_2 from '@openapi-spec/types/v3.2';
6
-
7
- interface ZodToJsonSchemaConverterOptions extends Omit<ToJSONSchemaParams, 'target' | 'io'> {
8
- /**
9
- * Caches conversion results in a WeakMap keyed by the Zod schema instance,
10
- * so converting the same schema again is free.
11
- *
12
- * When enabled, repeated conversions return the same JSON schema object,
13
- * so treat returned schemas as immutable.
14
- *
15
- * @default false
16
- */
17
- cache?: boolean | undefined;
18
- }
19
- /**
20
- * Converts Zod schemas into JSON Schema using Zod's built-in `toJSONSchema`,
21
- * with additional support for types such as `z.bigint()`, `z.date()`, `z.set()`, and `z.map()`.
22
- *
23
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
24
- */
25
- declare class ZodToJsonSchemaConverter implements JsonSchemaConverter {
26
- private readonly toJSONSchemaParams;
27
- private readonly cache;
28
- constructor({ cache, ...toJSONSchemaParams }?: ZodToJsonSchemaConverterOptions);
29
- condition(schema: AnySchema | undefined, _direction: JsonSchemaConverterDirection): boolean;
30
- convert(schema: AnySchema | undefined, direction: JsonSchemaConverterDirection): [jsonSchema: JsonSchema, optional: boolean];
31
- private convertUncached;
32
- private convertZod;
33
- private getCustomJsonSchema;
34
- }
35
-
36
- /**
37
- * Zod registry for customizing generated JSON schema, can use both for .input and .output
38
- *
39
- * @example
40
- * ```ts
41
- * import { JSON_SCHEMA_REGISTRY } from '@orpc/zod'
42
- *
43
- * const user = z.object({
44
- * name: z.string(),
45
- * age: z.number(),
46
- * })
47
- *
48
- * JSON_SCHEMA_REGISTRY.add(user, {
49
- * examples: [{ name: 'John', age: 20 }],
50
- * })
51
- * ```
52
- *
53
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
54
- */
55
- declare const JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<_openapi_spec_types_v3_2.SchemaObjectFields<typeof $input | typeof $output>, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
56
- /**
57
- * Zod registry for customizing generated JSON schema, only useful for .input
58
- *
59
- * @example
60
- * ```ts
61
- * import { JSON_SCHEMA_INPUT_REGISTRY } from '@orpc/zod'
62
- *
63
- * const user = z.object({
64
- * name: z.string(),
65
- * age: z.string().transform(v => Number(v)),
66
- * })
67
- *
68
- * JSON_SCHEMA_INPUT_REGISTRY.add(user, {
69
- * examples: [{ name: 'John', age: "20" }],
70
- * })
71
- * ```
72
- *
73
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
74
- */
75
- declare const JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<_openapi_spec_types_v3_2.SchemaObjectFields<typeof $input>, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
76
- /**
77
- * Zod registry for customizing generated JSON schema, only useful for .output
78
- *
79
- * @example
80
- * ```ts
81
- * import { JSON_SCHEMA_OUTPUT_REGISTRY } from '@orpc/zod'
82
- *
83
- * const user = z.object({
84
- * name: z.string(),
85
- * age: z.string().transform(v => Number(v)),
86
- * })
87
- *
88
- * JSON_SCHEMA_OUTPUT_REGISTRY.add(user, {
89
- * examples: [{ name: 'John', age: 20 }],
90
- * })
91
- * ```
92
- *
93
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
94
- */
95
- declare const JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<_openapi_spec_types_v3_2.SchemaObjectFields<typeof $output>, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
96
-
97
- export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter };
98
- export type { ZodToJsonSchemaConverterOptions };
1
+ export * from './converter.ts';
2
+ export * from './registries.ts';
3
+ export type { JsonSchema } from '@orpc/json-schema';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './converter.js';
2
+ export * from './registries.js';
@@ -0,0 +1,62 @@
1
+ import type { JsonSchema } from '@orpc/json-schema';
2
+ import type { $input, $output, $ZodRegistry } 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,64 @@
1
+ import { registry } from 'zod/v4/core';
2
+ /**
3
+ * Zod registry for customizing generated JSON schema, can use both for .input and .output
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { JSON_SCHEMA_REGISTRY } from '@orpc/zod'
8
+ *
9
+ * const user = z.object({
10
+ * name: z.string(),
11
+ * age: z.number(),
12
+ * })
13
+ *
14
+ * JSON_SCHEMA_REGISTRY.add(user, {
15
+ * examples: [{ name: 'John', age: 20 }],
16
+ * })
17
+ * ```
18
+ *
19
+ * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
20
+ */
21
+ export const JSON_SCHEMA_REGISTRY =
22
+ /* @__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
+ export const JSON_SCHEMA_INPUT_REGISTRY =
43
+ /* @__PURE__ */ registry();
44
+ /**
45
+ * Zod registry for customizing generated JSON schema, only useful for .output
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * import { JSON_SCHEMA_OUTPUT_REGISTRY } from '@orpc/zod'
50
+ *
51
+ * const user = z.object({
52
+ * name: z.string(),
53
+ * age: z.string().transform(v => Number(v)),
54
+ * })
55
+ *
56
+ * JSON_SCHEMA_OUTPUT_REGISTRY.add(user, {
57
+ * examples: [{ name: 'John', age: 20 }],
58
+ * })
59
+ * ```
60
+ *
61
+ * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
62
+ */
63
+ export const JSON_SCHEMA_OUTPUT_REGISTRY =
64
+ /* @__PURE__ */ registry();
package/package.json CHANGED
@@ -1,51 +1,48 @@
1
1
  {
2
2
  "name": "@orpc/zod",
3
- "type": "module",
4
- "version": "2.0.0-beta.47",
3
+ "version": "2.0.0-beta.49",
5
4
  "description": "Zod integration for oRPC: convert Zod schemas into JSON Schema for OpenAPI generation",
6
- "license": "MIT",
7
- "funding": [
8
- "https://github.com/sponsors/dinwwwh",
9
- "https://opencollective.com/middleapi"
5
+ "keywords": [
6
+ "json-schema",
7
+ "openapi",
8
+ "orpc",
9
+ "typesafe",
10
+ "typescript",
11
+ "validation",
12
+ "zod"
10
13
  ],
11
14
  "homepage": "https://orpc.dev",
15
+ "license": "MIT",
12
16
  "repository": {
13
17
  "type": "git",
14
18
  "url": "git+https://github.com/middleapi/orpc.git",
15
19
  "directory": "packages/zod"
16
20
  },
17
- "keywords": [
18
- "orpc",
19
- "zod",
20
- "json-schema",
21
- "openapi",
22
- "validation",
23
- "typescript",
24
- "typesafe"
21
+ "funding": [
22
+ "https://github.com/sponsors/dinwwwh",
23
+ "https://opencollective.com/middleapi"
25
24
  ],
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "type": "module",
26
29
  "sideEffects": false,
27
30
  "exports": {
28
31
  "./package.json": "./package.json",
29
32
  ".": {
30
- "types": "./dist/index.d.mts",
31
- "import": "./dist/index.mjs",
32
- "default": "./dist/index.mjs"
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.js",
35
+ "default": "./dist/index.js"
33
36
  }
34
37
  },
35
- "files": [
36
- "dist"
37
- ],
38
- "peerDependencies": {
39
- "zod": ">=4.5.0"
40
- },
41
38
  "dependencies": {
42
- "@openapi-spec/types": "~0.4.0",
43
- "@orpc/json-schema": "2.0.0-beta.47"
39
+ "@orpc/json-schema": "2.0.0-beta.49"
44
40
  },
45
41
  "devDependencies": {
46
42
  "zod": "^4.6.7"
47
43
  },
48
- "scripts": {
49
- "type:check": "tsc -b"
50
- }
44
+ "peerDependencies": {
45
+ "zod": ">=4.5.0"
46
+ },
47
+ "scripts": {}
51
48
  }
package/dist/index.d.mts DELETED
@@ -1,98 +0,0 @@
1
- import { JsonSchemaConverter, AnySchema, JsonSchemaConverterDirection, JsonSchema } from '@orpc/json-schema';
2
- export { JsonSchema } from '@orpc/json-schema';
3
- import * as zod_v4_core from 'zod/v4/core';
4
- import { ToJSONSchemaParams, $input, $output } from 'zod/v4/core';
5
- import * as _openapi_spec_types_v3_2 from '@openapi-spec/types/v3.2';
6
-
7
- interface ZodToJsonSchemaConverterOptions extends Omit<ToJSONSchemaParams, 'target' | 'io'> {
8
- /**
9
- * Caches conversion results in a WeakMap keyed by the Zod schema instance,
10
- * so converting the same schema again is free.
11
- *
12
- * When enabled, repeated conversions return the same JSON schema object,
13
- * so treat returned schemas as immutable.
14
- *
15
- * @default false
16
- */
17
- cache?: boolean | undefined;
18
- }
19
- /**
20
- * Converts Zod schemas into JSON Schema using Zod's built-in `toJSONSchema`,
21
- * with additional support for types such as `z.bigint()`, `z.date()`, `z.set()`, and `z.map()`.
22
- *
23
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
24
- */
25
- declare class ZodToJsonSchemaConverter implements JsonSchemaConverter {
26
- private readonly toJSONSchemaParams;
27
- private readonly cache;
28
- constructor({ cache, ...toJSONSchemaParams }?: ZodToJsonSchemaConverterOptions);
29
- condition(schema: AnySchema | undefined, _direction: JsonSchemaConverterDirection): boolean;
30
- convert(schema: AnySchema | undefined, direction: JsonSchemaConverterDirection): [jsonSchema: JsonSchema, optional: boolean];
31
- private convertUncached;
32
- private convertZod;
33
- private getCustomJsonSchema;
34
- }
35
-
36
- /**
37
- * Zod registry for customizing generated JSON schema, can use both for .input and .output
38
- *
39
- * @example
40
- * ```ts
41
- * import { JSON_SCHEMA_REGISTRY } from '@orpc/zod'
42
- *
43
- * const user = z.object({
44
- * name: z.string(),
45
- * age: z.number(),
46
- * })
47
- *
48
- * JSON_SCHEMA_REGISTRY.add(user, {
49
- * examples: [{ name: 'John', age: 20 }],
50
- * })
51
- * ```
52
- *
53
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
54
- */
55
- declare const JSON_SCHEMA_REGISTRY: zod_v4_core.$ZodRegistry<_openapi_spec_types_v3_2.SchemaObjectFields<typeof $input | typeof $output>, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
56
- /**
57
- * Zod registry for customizing generated JSON schema, only useful for .input
58
- *
59
- * @example
60
- * ```ts
61
- * import { JSON_SCHEMA_INPUT_REGISTRY } from '@orpc/zod'
62
- *
63
- * const user = z.object({
64
- * name: z.string(),
65
- * age: z.string().transform(v => Number(v)),
66
- * })
67
- *
68
- * JSON_SCHEMA_INPUT_REGISTRY.add(user, {
69
- * examples: [{ name: 'John', age: "20" }],
70
- * })
71
- * ```
72
- *
73
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
74
- */
75
- declare const JSON_SCHEMA_INPUT_REGISTRY: zod_v4_core.$ZodRegistry<_openapi_spec_types_v3_2.SchemaObjectFields<typeof $input>, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
76
- /**
77
- * Zod registry for customizing generated JSON schema, only useful for .output
78
- *
79
- * @example
80
- * ```ts
81
- * import { JSON_SCHEMA_OUTPUT_REGISTRY } from '@orpc/zod'
82
- *
83
- * const user = z.object({
84
- * name: z.string(),
85
- * age: z.string().transform(v => Number(v)),
86
- * })
87
- *
88
- * JSON_SCHEMA_OUTPUT_REGISTRY.add(user, {
89
- * examples: [{ name: 'John', age: 20 }],
90
- * })
91
- * ```
92
- *
93
- * @see {@link https://orpc.dev/docs/integrations/zod | Zod Integration}
94
- */
95
- declare const JSON_SCHEMA_OUTPUT_REGISTRY: zod_v4_core.$ZodRegistry<_openapi_spec_types_v3_2.SchemaObjectFields<typeof $output>, zod_v4_core.$ZodType<unknown, unknown, zod_v4_core.$ZodTypeInternals<unknown, unknown>>>;
96
-
97
- export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter };
98
- export type { ZodToJsonSchemaConverterOptions };
package/dist/index.mjs DELETED
@@ -1,97 +0,0 @@
1
- import { isStandardSchemaOptional, JsonSchemaXNativeType, JsonSchemaFormat } from '@orpc/json-schema';
2
- import { registry, toJSONSchema, process } from 'zod/v4/core';
3
-
4
- const JSON_SCHEMA_REGISTRY = registry();
5
- const JSON_SCHEMA_INPUT_REGISTRY = registry();
6
- const JSON_SCHEMA_OUTPUT_REGISTRY = registry();
7
-
8
- class ZodToJsonSchemaConverter {
9
- toJSONSchemaParams;
10
- cache;
11
- constructor({ cache, ...toJSONSchemaParams } = {}) {
12
- this.toJSONSchemaParams = toJSONSchemaParams;
13
- if (cache) {
14
- this.cache = { input: /* @__PURE__ */ new WeakMap(), output: /* @__PURE__ */ new WeakMap() };
15
- }
16
- }
17
- condition(schema, _direction) {
18
- return schema?.["~standard"].vendor === "zod";
19
- }
20
- convert(schema, direction) {
21
- const zodSchema = schema;
22
- if (this.cache) {
23
- const cached = this.cache[direction].get(zodSchema);
24
- if (cached) {
25
- return cached;
26
- }
27
- }
28
- const result = this.convertUncached(zodSchema, direction);
29
- if (this.cache) {
30
- this.cache[direction].set(zodSchema, result);
31
- }
32
- return result;
33
- }
34
- convertUncached(zodSchema, direction) {
35
- const jsonSchema = this.convertZod(zodSchema, direction);
36
- return [jsonSchema, isStandardSchemaOptional(zodSchema, direction)];
37
- }
38
- convertZod(schema, direction) {
39
- const { unrepresentable = "any" } = this.toJSONSchemaParams;
40
- const jsonSchema = toJSONSchema(schema, {
41
- ...this.toJSONSchemaParams,
42
- target: "draft-2020-12",
43
- io: direction,
44
- unrepresentable(info) {
45
- return convertNativeType(this, info.zodSchema, info.path) ?? (typeof unrepresentable === "function" ? unrepresentable(info) : unrepresentable);
46
- },
47
- override: (ctx) => {
48
- const customJsonSchema = this.getCustomJsonSchema(ctx.zodSchema, direction);
49
- if (customJsonSchema) {
50
- Object.assign(ctx.jsonSchema, customJsonSchema);
51
- }
52
- this.toJSONSchemaParams.override?.(ctx);
53
- }
54
- });
55
- const { $schema, ...rest } = jsonSchema;
56
- return rest;
57
- }
58
- getCustomJsonSchema(schema, direction) {
59
- const general = JSON_SCHEMA_REGISTRY.get(schema);
60
- const directional = direction === "input" ? JSON_SCHEMA_INPUT_REGISTRY.get(schema) : JSON_SCHEMA_OUTPUT_REGISTRY.get(schema);
61
- if (general === void 0 && directional === void 0) {
62
- return void 0;
63
- }
64
- return { ...general, ...directional };
65
- }
66
- }
67
- function convertNativeType(ctx, zodSchema, path) {
68
- const def = zodSchema._zod.def;
69
- switch (def.type) {
70
- case "bigint":
71
- return { "type": "string", "pattern": "^-?[0-9]+$", "x-native-type": JsonSchemaXNativeType.BigInt };
72
- case "date":
73
- return { "type": "string", "format": JsonSchemaFormat.DateTime, "x-native-type": JsonSchemaXNativeType.Date };
74
- case "set":
75
- case "map": {
76
- const schemaPath = [];
77
- for (const [seenSchema, seen] of ctx.seen) {
78
- if (seen.path && seen.path.length <= path.length && seen.path.every((segment, i) => segment === path[i])) {
79
- schemaPath.push(seenSchema);
80
- }
81
- }
82
- const processItems = (schema, ...segments) => process(schema, ctx, { path: [...path, "items", ...segments], schemaPath });
83
- return def.type === "set" ? { "type": "array", "uniqueItems": true, "items": processItems(def.valueType), "x-native-type": JsonSchemaXNativeType.Set } : {
84
- "type": "array",
85
- "items": {
86
- type: "array",
87
- prefixItems: [processItems(def.keyType, "prefixItems", 0), processItems(def.valueType, "prefixItems", 1)],
88
- maxItems: 2,
89
- minItems: 2
90
- },
91
- "x-native-type": JsonSchemaXNativeType.Map
92
- };
93
- }
94
- }
95
- }
96
-
97
- export { JSON_SCHEMA_INPUT_REGISTRY, JSON_SCHEMA_OUTPUT_REGISTRY, JSON_SCHEMA_REGISTRY, ZodToJsonSchemaConverter };