@orpc/zod 0.0.0-next.aa57fb6 → 0.0.0-next.c29cb6d

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -1,4 +1,362 @@
1
- // src/index.ts
1
+ // ../../node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/getType.js
2
+ function getType(payload) {
3
+ return Object.prototype.toString.call(payload).slice(8, -1);
4
+ }
5
+
6
+ // ../../node_modules/.pnpm/is-what@5.0.2/node_modules/is-what/dist/isPlainObject.js
7
+ function isPlainObject(payload) {
8
+ if (getType(payload) !== "Object")
9
+ return false;
10
+ const prototype = Object.getPrototypeOf(payload);
11
+ return !!prototype && prototype.constructor === Object && prototype === Object.prototype;
12
+ }
13
+
14
+ // ../../node_modules/.pnpm/radash@12.1.0/node_modules/radash/dist/esm/async.mjs
15
+ var guard = (func, shouldGuard) => {
16
+ const _guard = (err) => {
17
+ if (shouldGuard && !shouldGuard(err))
18
+ throw err;
19
+ return void 0;
20
+ };
21
+ const isPromise2 = (result) => result instanceof Promise;
22
+ try {
23
+ const result = func();
24
+ return isPromise2(result) ? result.catch(_guard) : result;
25
+ } catch (err) {
26
+ return _guard(err);
27
+ }
28
+ };
29
+
30
+ // src/coercer.ts
31
+ import {
32
+ ZodFirstPartyTypeKind
33
+ } from "zod";
34
+ var ZodCoercer = class {
35
+ coerce(schema, value) {
36
+ if (!schema || schema["~standard"].vendor !== "zod") {
37
+ return value;
38
+ }
39
+ const zodSchema = schema;
40
+ const coerced = zodCoerceInternal(zodSchema, value, { bracketNotation: true });
41
+ return coerced;
42
+ }
43
+ };
44
+ function zodCoerceInternal(schema, value, options) {
45
+ const isRoot = options?.isRoot ?? true;
46
+ const options_ = { ...options, isRoot: false };
47
+ if (isRoot && options?.bracketNotation && Array.isArray(value) && value.length === 1) {
48
+ const newValue = zodCoerceInternal(schema, value[0], options_);
49
+ if (schema.safeParse(newValue).success) {
50
+ return newValue;
51
+ }
52
+ return zodCoerceInternal(schema, value, options_);
53
+ }
54
+ const customType = getCustomZodType(schema._def);
55
+ if (customType === "Invalid Date") {
56
+ if (typeof value === "string" && value.toLocaleLowerCase() === "invalid date") {
57
+ return /* @__PURE__ */ new Date("Invalid Date");
58
+ }
59
+ } else if (customType === "RegExp") {
60
+ if (typeof value === "string" && value.startsWith("/")) {
61
+ const match = value.match(/^\/(.*)\/([a-z]*)$/);
62
+ if (match) {
63
+ const [, pattern, flags] = match;
64
+ return new RegExp(pattern, flags);
65
+ }
66
+ }
67
+ } else if (customType === "URL") {
68
+ if (typeof value === "string") {
69
+ const url2 = guard(() => new URL(value));
70
+ if (url2 !== void 0) {
71
+ return url2;
72
+ }
73
+ }
74
+ }
75
+ if (schema._def.typeName === void 0) {
76
+ return value;
77
+ }
78
+ const typeName = schema._def.typeName;
79
+ if (typeName === ZodFirstPartyTypeKind.ZodNumber) {
80
+ if (options_?.bracketNotation && typeof value === "string") {
81
+ const num = Number(value);
82
+ if (!Number.isNaN(num)) {
83
+ return num;
84
+ }
85
+ }
86
+ } else if (typeName === ZodFirstPartyTypeKind.ZodNaN) {
87
+ if (typeof value === "string" && value.toLocaleLowerCase() === "nan") {
88
+ return Number.NaN;
89
+ }
90
+ } else if (typeName === ZodFirstPartyTypeKind.ZodBoolean) {
91
+ if (options_?.bracketNotation && typeof value === "string") {
92
+ const lower = value.toLowerCase();
93
+ if (lower === "false" || lower === "off" || lower === "f") {
94
+ return false;
95
+ }
96
+ if (lower === "true" || lower === "on" || lower === "t") {
97
+ return true;
98
+ }
99
+ }
100
+ } else if (typeName === ZodFirstPartyTypeKind.ZodNull) {
101
+ if (options_?.bracketNotation && typeof value === "string" && value.toLowerCase() === "null") {
102
+ return null;
103
+ }
104
+ } else if (typeName === ZodFirstPartyTypeKind.ZodUndefined || typeName === ZodFirstPartyTypeKind.ZodVoid) {
105
+ if (typeof value === "string" && value.toLowerCase() === "undefined") {
106
+ return void 0;
107
+ }
108
+ } else if (typeName === ZodFirstPartyTypeKind.ZodDate) {
109
+ if (typeof value === "string" && (value.includes("-") || value.includes(":") || value.toLocaleLowerCase() === "invalid date")) {
110
+ return new Date(value);
111
+ }
112
+ } else if (typeName === ZodFirstPartyTypeKind.ZodBigInt) {
113
+ if (typeof value === "string") {
114
+ const num = guard(() => BigInt(value));
115
+ if (num !== void 0) {
116
+ return num;
117
+ }
118
+ }
119
+ } else if (typeName === ZodFirstPartyTypeKind.ZodArray || typeName === ZodFirstPartyTypeKind.ZodTuple) {
120
+ const schema_ = schema;
121
+ if (Array.isArray(value)) {
122
+ return value.map((v) => zodCoerceInternal(schema_._def.type, v, options_));
123
+ }
124
+ if (options_?.bracketNotation) {
125
+ if (value === void 0) {
126
+ return [];
127
+ }
128
+ if (isPlainObject(value) && Object.keys(value).every((k) => /^[1-9]\d*$/.test(k) || k === "0")) {
129
+ const indexes = Object.keys(value).map((k) => Number(k)).sort((a, b) => a - b);
130
+ const arr = Array.from({ length: (indexes.at(-1) ?? -1) + 1 });
131
+ for (const i of indexes) {
132
+ arr[i] = zodCoerceInternal(schema_._def.type, value[i], options_);
133
+ }
134
+ return arr;
135
+ }
136
+ }
137
+ } else if (typeName === ZodFirstPartyTypeKind.ZodObject) {
138
+ const schema_ = schema;
139
+ if (isPlainObject(value)) {
140
+ const newObj = {};
141
+ const keys = /* @__PURE__ */ new Set([
142
+ ...Object.keys(value),
143
+ ...Object.keys(schema_.shape)
144
+ ]);
145
+ for (const k of keys) {
146
+ if (!(k in value))
147
+ continue;
148
+ const v = value[k];
149
+ newObj[k] = zodCoerceInternal(
150
+ schema_.shape[k] ?? schema_._def.catchall,
151
+ v,
152
+ options_
153
+ );
154
+ }
155
+ return newObj;
156
+ }
157
+ if (options_?.bracketNotation) {
158
+ if (value === void 0) {
159
+ return {};
160
+ }
161
+ if (Array.isArray(value) && value.length === 1) {
162
+ const emptySchema = schema_.shape[""] ?? schema_._def.catchall;
163
+ return { "": zodCoerceInternal(emptySchema, value[0], options_) };
164
+ }
165
+ }
166
+ } else if (typeName === ZodFirstPartyTypeKind.ZodSet) {
167
+ const schema_ = schema;
168
+ if (Array.isArray(value)) {
169
+ return new Set(
170
+ value.map((v) => zodCoerceInternal(schema_._def.valueType, v, options_))
171
+ );
172
+ }
173
+ if (options_?.bracketNotation) {
174
+ if (value === void 0) {
175
+ return /* @__PURE__ */ new Set();
176
+ }
177
+ if (isPlainObject(value) && Object.keys(value).every((k) => /^[1-9]\d*$/.test(k) || k === "0")) {
178
+ const indexes = Object.keys(value).map((k) => Number(k)).sort((a, b) => a - b);
179
+ const arr = Array.from({ length: (indexes.at(-1) ?? -1) + 1 });
180
+ for (const i of indexes) {
181
+ arr[i] = zodCoerceInternal(schema_._def.valueType, value[i], options_);
182
+ }
183
+ return new Set(arr);
184
+ }
185
+ }
186
+ } else if (typeName === ZodFirstPartyTypeKind.ZodMap) {
187
+ const schema_ = schema;
188
+ if (Array.isArray(value) && value.every((i) => Array.isArray(i) && i.length === 2)) {
189
+ return new Map(
190
+ value.map(([k, v]) => [
191
+ zodCoerceInternal(schema_._def.keyType, k, options_),
192
+ zodCoerceInternal(schema_._def.valueType, v, options_)
193
+ ])
194
+ );
195
+ }
196
+ if (options_?.bracketNotation) {
197
+ if (value === void 0) {
198
+ return /* @__PURE__ */ new Map();
199
+ }
200
+ if (isPlainObject(value)) {
201
+ const arr = Array.from({ length: Object.keys(value).length }).fill(void 0).map(
202
+ (_, i) => isPlainObject(value[i]) && Object.keys(value[i]).length === 2 && "0" in value[i] && "1" in value[i] ? [value[i]["0"], value[i]["1"]] : void 0
203
+ );
204
+ if (arr.every((v) => !!v)) {
205
+ return new Map(
206
+ arr.map(([k, v]) => [
207
+ zodCoerceInternal(schema_._def.keyType, k, options_),
208
+ zodCoerceInternal(schema_._def.valueType, v, options_)
209
+ ])
210
+ );
211
+ }
212
+ }
213
+ }
214
+ } else if (typeName === ZodFirstPartyTypeKind.ZodRecord) {
215
+ const schema_ = schema;
216
+ if (isPlainObject(value)) {
217
+ const newObj = {};
218
+ for (const [k, v] of Object.entries(value)) {
219
+ const key = zodCoerceInternal(schema_._def.keyType, k, options_);
220
+ const val = zodCoerceInternal(schema_._def.valueType, v, options_);
221
+ newObj[key] = val;
222
+ }
223
+ return newObj;
224
+ }
225
+ } else if (typeName === ZodFirstPartyTypeKind.ZodUnion || typeName === ZodFirstPartyTypeKind.ZodDiscriminatedUnion) {
226
+ const schema_ = schema;
227
+ if (schema_.safeParse(value).success) {
228
+ return value;
229
+ }
230
+ const results = [];
231
+ for (const s of schema_._def.options) {
232
+ const newValue = zodCoerceInternal(s, value, { ...options_, isRoot });
233
+ if (newValue === value)
234
+ continue;
235
+ const result = schema_.safeParse(newValue);
236
+ if (result.success) {
237
+ return newValue;
238
+ }
239
+ results.push([newValue, result.error.issues.length]);
240
+ }
241
+ if (results.length === 0) {
242
+ return value;
243
+ }
244
+ return results.sort((a, b) => a[1] - b[1])[0]?.[0];
245
+ } else if (typeName === ZodFirstPartyTypeKind.ZodIntersection) {
246
+ const schema_ = schema;
247
+ return zodCoerceInternal(
248
+ schema_._def.right,
249
+ zodCoerceInternal(schema_._def.left, value, { ...options_, isRoot }),
250
+ { ...options_, isRoot }
251
+ );
252
+ } else if (typeName === ZodFirstPartyTypeKind.ZodReadonly) {
253
+ const schema_ = schema;
254
+ return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
255
+ } else if (typeName === ZodFirstPartyTypeKind.ZodPipeline) {
256
+ const schema_ = schema;
257
+ return zodCoerceInternal(schema_._def.in, value, { ...options_, isRoot });
258
+ } else if (typeName === ZodFirstPartyTypeKind.ZodLazy) {
259
+ const schema_ = schema;
260
+ return zodCoerceInternal(schema_._def.getter(), value, { ...options_, isRoot });
261
+ } else if (typeName === ZodFirstPartyTypeKind.ZodEffects) {
262
+ const schema_ = schema;
263
+ return zodCoerceInternal(schema_._def.schema, value, { ...options_, isRoot });
264
+ } else if (typeName === ZodFirstPartyTypeKind.ZodBranded) {
265
+ const schema_ = schema;
266
+ return zodCoerceInternal(schema_._def.type, value, { ...options_, isRoot });
267
+ } else if (typeName === ZodFirstPartyTypeKind.ZodCatch) {
268
+ const schema_ = schema;
269
+ return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
270
+ } else if (typeName === ZodFirstPartyTypeKind.ZodDefault) {
271
+ const schema_ = schema;
272
+ return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
273
+ } else if (typeName === ZodFirstPartyTypeKind.ZodNullable) {
274
+ const schema_ = schema;
275
+ if (value === null) {
276
+ return null;
277
+ }
278
+ if (typeof value === "string" && value.toLowerCase() === "null") {
279
+ return schema_.safeParse(value).success ? value : null;
280
+ }
281
+ return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
282
+ } else if (typeName === ZodFirstPartyTypeKind.ZodOptional) {
283
+ const schema_ = schema;
284
+ if (value === void 0) {
285
+ return void 0;
286
+ }
287
+ if (typeof value === "string" && value.toLowerCase() === "undefined") {
288
+ return schema_.safeParse(value).success ? value : void 0;
289
+ }
290
+ return zodCoerceInternal(schema_._def.innerType, value, { ...options_, isRoot });
291
+ } else if (typeName === ZodFirstPartyTypeKind.ZodNativeEnum) {
292
+ const schema_ = schema;
293
+ if (Object.values(schema_._def.values).includes(value)) {
294
+ return value;
295
+ }
296
+ if (options?.bracketNotation && typeof value === "string") {
297
+ for (const expectedValue of Object.values(schema_._def.values)) {
298
+ if (expectedValue.toString() === value) {
299
+ return expectedValue;
300
+ }
301
+ }
302
+ }
303
+ } else if (typeName === ZodFirstPartyTypeKind.ZodLiteral) {
304
+ const schema_ = schema;
305
+ const expectedValue = schema_._def.value;
306
+ if (typeof value === "string" && typeof expectedValue !== "string") {
307
+ if (typeof expectedValue === "bigint") {
308
+ const num = guard(() => BigInt(value));
309
+ if (num !== void 0) {
310
+ return num;
311
+ }
312
+ } else if (expectedValue === void 0) {
313
+ if (value.toLocaleLowerCase() === "undefined") {
314
+ return void 0;
315
+ }
316
+ } else if (options?.bracketNotation) {
317
+ if (typeof expectedValue === "number") {
318
+ const num = Number(value);
319
+ if (!Number.isNaN(num)) {
320
+ return num;
321
+ }
322
+ } else if (typeof expectedValue === "boolean") {
323
+ const lower = value.toLowerCase();
324
+ if (lower === "false" || lower === "off" || lower === "f") {
325
+ return false;
326
+ }
327
+ if (lower === "true" || lower === "on" || lower === "t") {
328
+ return true;
329
+ }
330
+ } else if (expectedValue === null) {
331
+ if (value.toLocaleLowerCase() === "null") {
332
+ return null;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ } else {
338
+ const _expected = typeName;
339
+ }
340
+ return value;
341
+ }
342
+
343
+ // src/converter.ts
344
+ import { JSONSchemaFormat } from "@orpc/openapi";
345
+
346
+ // ../../node_modules/.pnpm/escape-string-regexp@5.0.0/node_modules/escape-string-regexp/index.js
347
+ function escapeStringRegexp(string) {
348
+ if (typeof string !== "string") {
349
+ throw new TypeError("Expected a string");
350
+ }
351
+ return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
352
+ }
353
+
354
+ // src/converter.ts
355
+ import {
356
+ ZodFirstPartyTypeKind as ZodFirstPartyTypeKind2
357
+ } from "zod";
358
+
359
+ // src/schemas.ts
2
360
  import wcmatch from "wildcard-match";
3
361
  import {
4
362
  custom
@@ -133,7 +491,463 @@ var oz = {
133
491
  regexp,
134
492
  url
135
493
  };
494
+
495
+ // src/converter.ts
496
+ var NON_LOGIC_KEYWORDS = [
497
+ // Core Documentation Keywords
498
+ "$anchor",
499
+ "$comment",
500
+ "$defs",
501
+ "$id",
502
+ "title",
503
+ "description",
504
+ // Value Keywords
505
+ "default",
506
+ "deprecated",
507
+ "examples",
508
+ // Metadata Keywords
509
+ "$schema",
510
+ "definitions",
511
+ // Legacy, but still used
512
+ "readOnly",
513
+ "writeOnly",
514
+ // Display and UI Hints
515
+ "contentMediaType",
516
+ "contentEncoding",
517
+ "format",
518
+ // Custom Extensions
519
+ "$vocabulary",
520
+ "$dynamicAnchor",
521
+ "$dynamicRef"
522
+ ];
523
+ var UNSUPPORTED_JSON_SCHEMA = { not: {} };
524
+ var UNDEFINED_JSON_SCHEMA = { const: "undefined" };
525
+ function zodToJsonSchema(schema, options) {
526
+ if (schema["~standard"].vendor !== "zod") {
527
+ console.warn(`Generate JSON schema not support ${schema["~standard"].vendor} yet`);
528
+ return {};
529
+ }
530
+ const schema__ = schema;
531
+ if (!options?.isHandledCustomJSONSchema) {
532
+ const customJSONSchema = getCustomJSONSchema(schema__._def, options);
533
+ if (customJSONSchema) {
534
+ const json = zodToJsonSchema(schema__, {
535
+ ...options,
536
+ isHandledCustomJSONSchema: true
537
+ });
538
+ return {
539
+ ...json,
540
+ ...customJSONSchema
541
+ };
542
+ }
543
+ }
544
+ const childOptions = { ...options, isHandledCustomJSONSchema: false };
545
+ const customType = getCustomZodType(schema__._def);
546
+ switch (customType) {
547
+ case "Blob": {
548
+ return { type: "string", contentMediaType: "*/*" };
549
+ }
550
+ case "File": {
551
+ const mimeType = getCustomZodFileMimeType(schema__._def) ?? "*/*";
552
+ return { type: "string", contentMediaType: mimeType };
553
+ }
554
+ case "Invalid Date": {
555
+ return { const: "Invalid Date" };
556
+ }
557
+ case "RegExp": {
558
+ return {
559
+ type: "string",
560
+ pattern: "^\\/(.*)\\/([a-z]*)$"
561
+ };
562
+ }
563
+ case "URL": {
564
+ return { type: "string", format: JSONSchemaFormat.URI };
565
+ }
566
+ }
567
+ const _expectedCustomType = customType;
568
+ const typeName = schema__._def.typeName;
569
+ switch (typeName) {
570
+ case ZodFirstPartyTypeKind2.ZodString: {
571
+ const schema_ = schema__;
572
+ const json = { type: "string" };
573
+ for (const check of schema_._def.checks) {
574
+ switch (check.kind) {
575
+ case "base64":
576
+ json.contentEncoding = "base64";
577
+ break;
578
+ case "cuid":
579
+ json.pattern = "^[0-9A-HJKMNP-TV-Z]{26}$";
580
+ break;
581
+ case "email":
582
+ json.format = JSONSchemaFormat.Email;
583
+ break;
584
+ case "url":
585
+ json.format = JSONSchemaFormat.URI;
586
+ break;
587
+ case "uuid":
588
+ json.format = JSONSchemaFormat.UUID;
589
+ break;
590
+ case "regex":
591
+ json.pattern = check.regex.source;
592
+ break;
593
+ case "min":
594
+ json.minLength = check.value;
595
+ break;
596
+ case "max":
597
+ json.maxLength = check.value;
598
+ break;
599
+ case "length":
600
+ json.minLength = check.value;
601
+ json.maxLength = check.value;
602
+ break;
603
+ case "includes":
604
+ json.pattern = escapeStringRegexp(check.value);
605
+ break;
606
+ case "startsWith":
607
+ json.pattern = `^${escapeStringRegexp(check.value)}`;
608
+ break;
609
+ case "endsWith":
610
+ json.pattern = `${escapeStringRegexp(check.value)}$`;
611
+ break;
612
+ case "emoji":
613
+ json.pattern = "^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";
614
+ break;
615
+ case "nanoid":
616
+ json.pattern = "^[a-zA-Z0-9_-]{21}$";
617
+ break;
618
+ case "cuid2":
619
+ json.pattern = "^[0-9a-z]+$";
620
+ break;
621
+ case "ulid":
622
+ json.pattern = "^[0-9A-HJKMNP-TV-Z]{26}$";
623
+ break;
624
+ case "datetime":
625
+ json.format = JSONSchemaFormat.DateTime;
626
+ break;
627
+ case "date":
628
+ json.format = JSONSchemaFormat.Date;
629
+ break;
630
+ case "time":
631
+ json.format = JSONSchemaFormat.Time;
632
+ break;
633
+ case "duration":
634
+ json.format = JSONSchemaFormat.Duration;
635
+ break;
636
+ case "ip":
637
+ json.format = JSONSchemaFormat.IPv4;
638
+ break;
639
+ case "jwt":
640
+ json.pattern = "^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$";
641
+ break;
642
+ case "base64url":
643
+ json.pattern = "^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$";
644
+ break;
645
+ default: {
646
+ const _expect = check.kind;
647
+ }
648
+ }
649
+ }
650
+ return json;
651
+ }
652
+ case ZodFirstPartyTypeKind2.ZodNumber: {
653
+ const schema_ = schema__;
654
+ const json = { type: "number" };
655
+ for (const check of schema_._def.checks) {
656
+ switch (check.kind) {
657
+ case "int":
658
+ json.type = "integer";
659
+ break;
660
+ case "min":
661
+ json.minimum = check.value;
662
+ break;
663
+ case "max":
664
+ json.maximum = check.value;
665
+ break;
666
+ case "multipleOf":
667
+ json.multipleOf = check.value;
668
+ break;
669
+ default: {
670
+ const _expect = check.kind;
671
+ }
672
+ }
673
+ }
674
+ return json;
675
+ }
676
+ case ZodFirstPartyTypeKind2.ZodNaN: {
677
+ return { const: "NaN" };
678
+ }
679
+ case ZodFirstPartyTypeKind2.ZodBigInt: {
680
+ const json = { type: "string", pattern: "^-?[0-9]+$" };
681
+ return json;
682
+ }
683
+ case ZodFirstPartyTypeKind2.ZodBoolean: {
684
+ return { type: "boolean" };
685
+ }
686
+ case ZodFirstPartyTypeKind2.ZodDate: {
687
+ const schema2 = { type: "string", format: JSONSchemaFormat.Date };
688
+ return schema2;
689
+ }
690
+ case ZodFirstPartyTypeKind2.ZodNull: {
691
+ return { type: "null" };
692
+ }
693
+ case ZodFirstPartyTypeKind2.ZodVoid:
694
+ case ZodFirstPartyTypeKind2.ZodUndefined: {
695
+ return UNDEFINED_JSON_SCHEMA;
696
+ }
697
+ case ZodFirstPartyTypeKind2.ZodLiteral: {
698
+ const schema_ = schema__;
699
+ return { const: schema_._def.value };
700
+ }
701
+ case ZodFirstPartyTypeKind2.ZodEnum: {
702
+ const schema_ = schema__;
703
+ return {
704
+ enum: schema_._def.values
705
+ };
706
+ }
707
+ case ZodFirstPartyTypeKind2.ZodNativeEnum: {
708
+ const schema_ = schema__;
709
+ return {
710
+ enum: Object.values(schema_._def.values)
711
+ };
712
+ }
713
+ case ZodFirstPartyTypeKind2.ZodArray: {
714
+ const schema_ = schema__;
715
+ const def = schema_._def;
716
+ const json = { type: "array" };
717
+ if (def.exactLength) {
718
+ json.maxItems = def.exactLength.value;
719
+ json.minItems = def.exactLength.value;
720
+ }
721
+ if (def.minLength) {
722
+ json.minItems = def.minLength.value;
723
+ }
724
+ if (def.maxLength) {
725
+ json.maxItems = def.maxLength.value;
726
+ }
727
+ return json;
728
+ }
729
+ case ZodFirstPartyTypeKind2.ZodTuple: {
730
+ const schema_ = schema__;
731
+ const prefixItems = [];
732
+ const json = { type: "array" };
733
+ for (const item of schema_._def.items) {
734
+ prefixItems.push(zodToJsonSchema(item, childOptions));
735
+ }
736
+ if (prefixItems?.length) {
737
+ json.prefixItems = prefixItems;
738
+ }
739
+ if (schema_._def.rest) {
740
+ const items = zodToJsonSchema(schema_._def.rest, childOptions);
741
+ if (items) {
742
+ json.items = items;
743
+ }
744
+ }
745
+ return json;
746
+ }
747
+ case ZodFirstPartyTypeKind2.ZodObject: {
748
+ const schema_ = schema__;
749
+ const json = { type: "object" };
750
+ const properties = {};
751
+ const required = [];
752
+ for (const [key, value] of Object.entries(schema_.shape)) {
753
+ const { schema: schema2, matches } = extractJSONSchema(
754
+ zodToJsonSchema(value, childOptions),
755
+ (schema3) => schema3 === UNDEFINED_JSON_SCHEMA
756
+ );
757
+ if (schema2) {
758
+ properties[key] = schema2;
759
+ }
760
+ if (matches.length === 0) {
761
+ required.push(key);
762
+ }
763
+ }
764
+ if (Object.keys(properties).length) {
765
+ json.properties = properties;
766
+ }
767
+ if (required.length) {
768
+ json.required = required;
769
+ }
770
+ const additionalProperties = zodToJsonSchema(
771
+ schema_._def.catchall,
772
+ childOptions
773
+ );
774
+ if (schema_._def.unknownKeys === "strict") {
775
+ json.additionalProperties = additionalProperties === UNSUPPORTED_JSON_SCHEMA ? false : additionalProperties;
776
+ } else {
777
+ if (additionalProperties && additionalProperties !== UNSUPPORTED_JSON_SCHEMA) {
778
+ json.additionalProperties = additionalProperties;
779
+ }
780
+ }
781
+ return json;
782
+ }
783
+ case ZodFirstPartyTypeKind2.ZodRecord: {
784
+ const schema_ = schema__;
785
+ const json = { type: "object" };
786
+ json.additionalProperties = zodToJsonSchema(
787
+ schema_._def.valueType,
788
+ childOptions
789
+ );
790
+ return json;
791
+ }
792
+ case ZodFirstPartyTypeKind2.ZodSet: {
793
+ const schema_ = schema__;
794
+ return {
795
+ type: "array",
796
+ items: zodToJsonSchema(schema_._def.valueType, childOptions)
797
+ };
798
+ }
799
+ case ZodFirstPartyTypeKind2.ZodMap: {
800
+ const schema_ = schema__;
801
+ return {
802
+ type: "array",
803
+ items: {
804
+ type: "array",
805
+ prefixItems: [
806
+ zodToJsonSchema(schema_._def.keyType, childOptions),
807
+ zodToJsonSchema(schema_._def.valueType, childOptions)
808
+ ],
809
+ maxItems: 2,
810
+ minItems: 2
811
+ }
812
+ };
813
+ }
814
+ case ZodFirstPartyTypeKind2.ZodUnion:
815
+ case ZodFirstPartyTypeKind2.ZodDiscriminatedUnion: {
816
+ const schema_ = schema__;
817
+ const anyOf = [];
818
+ for (const s of schema_._def.options) {
819
+ anyOf.push(zodToJsonSchema(s, childOptions));
820
+ }
821
+ return { anyOf };
822
+ }
823
+ case ZodFirstPartyTypeKind2.ZodIntersection: {
824
+ const schema_ = schema__;
825
+ const allOf = [];
826
+ for (const s of [schema_._def.left, schema_._def.right]) {
827
+ allOf.push(zodToJsonSchema(s, childOptions));
828
+ }
829
+ return { allOf };
830
+ }
831
+ case ZodFirstPartyTypeKind2.ZodLazy: {
832
+ const schema_ = schema__;
833
+ const maxLazyDepth = childOptions?.maxLazyDepth ?? 5;
834
+ const lazyDepth = childOptions?.lazyDepth ?? 0;
835
+ if (lazyDepth > maxLazyDepth) {
836
+ return {};
837
+ }
838
+ return zodToJsonSchema(schema_._def.getter(), {
839
+ ...childOptions,
840
+ lazyDepth: lazyDepth + 1
841
+ });
842
+ }
843
+ case ZodFirstPartyTypeKind2.ZodUnknown:
844
+ case ZodFirstPartyTypeKind2.ZodAny:
845
+ case void 0: {
846
+ return {};
847
+ }
848
+ case ZodFirstPartyTypeKind2.ZodOptional: {
849
+ const schema_ = schema__;
850
+ const inner = zodToJsonSchema(schema_._def.innerType, childOptions);
851
+ return {
852
+ anyOf: [UNDEFINED_JSON_SCHEMA, inner]
853
+ };
854
+ }
855
+ case ZodFirstPartyTypeKind2.ZodReadonly: {
856
+ const schema_ = schema__;
857
+ return zodToJsonSchema(schema_._def.innerType, childOptions);
858
+ }
859
+ case ZodFirstPartyTypeKind2.ZodDefault: {
860
+ const schema_ = schema__;
861
+ return zodToJsonSchema(schema_._def.innerType, childOptions);
862
+ }
863
+ case ZodFirstPartyTypeKind2.ZodEffects: {
864
+ const schema_ = schema__;
865
+ if (schema_._def.effect.type === "transform" && childOptions?.mode === "output") {
866
+ return {};
867
+ }
868
+ return zodToJsonSchema(schema_._def.schema, childOptions);
869
+ }
870
+ case ZodFirstPartyTypeKind2.ZodCatch: {
871
+ const schema_ = schema__;
872
+ return zodToJsonSchema(schema_._def.innerType, childOptions);
873
+ }
874
+ case ZodFirstPartyTypeKind2.ZodBranded: {
875
+ const schema_ = schema__;
876
+ return zodToJsonSchema(schema_._def.type, childOptions);
877
+ }
878
+ case ZodFirstPartyTypeKind2.ZodPipeline: {
879
+ const schema_ = schema__;
880
+ return zodToJsonSchema(
881
+ childOptions?.mode === "output" ? schema_._def.out : schema_._def.in,
882
+ childOptions
883
+ );
884
+ }
885
+ case ZodFirstPartyTypeKind2.ZodNullable: {
886
+ const schema_ = schema__;
887
+ const inner = zodToJsonSchema(schema_._def.innerType, childOptions);
888
+ return {
889
+ anyOf: [{ type: "null" }, inner]
890
+ };
891
+ }
892
+ }
893
+ const _expected = typeName;
894
+ return UNSUPPORTED_JSON_SCHEMA;
895
+ }
896
+ function extractJSONSchema(schema, check, matches = []) {
897
+ if (check(schema)) {
898
+ matches.push(schema);
899
+ return { schema: void 0, matches };
900
+ }
901
+ if (typeof schema === "boolean") {
902
+ return { schema, matches };
903
+ }
904
+ if (schema.anyOf && Object.keys(schema).every(
905
+ (k) => k === "anyOf" || NON_LOGIC_KEYWORDS.includes(k)
906
+ )) {
907
+ const anyOf = schema.anyOf.map((s) => extractJSONSchema(s, check, matches).schema).filter((v) => !!v);
908
+ if (anyOf.length === 1 && typeof anyOf[0] === "object") {
909
+ return { schema: { ...schema, anyOf: void 0, ...anyOf[0] }, matches };
910
+ }
911
+ return {
912
+ schema: {
913
+ ...schema,
914
+ anyOf
915
+ },
916
+ matches
917
+ };
918
+ }
919
+ if (schema.oneOf && Object.keys(schema).every(
920
+ (k) => k === "oneOf" || NON_LOGIC_KEYWORDS.includes(k)
921
+ )) {
922
+ const oneOf = schema.oneOf.map((s) => extractJSONSchema(s, check, matches).schema).filter((v) => !!v);
923
+ if (oneOf.length === 1 && typeof oneOf[0] === "object") {
924
+ return { schema: { ...schema, oneOf: void 0, ...oneOf[0] }, matches };
925
+ }
926
+ return {
927
+ schema: {
928
+ ...schema,
929
+ oneOf
930
+ },
931
+ matches
932
+ };
933
+ }
934
+ return { schema, matches };
935
+ }
936
+ var ZodToJsonSchemaConverter = class {
937
+ condition(schema) {
938
+ return Boolean(schema && schema["~standard"].vendor === "zod");
939
+ }
940
+ convert(schema, options) {
941
+ const jsonSchema = schema;
942
+ return zodToJsonSchema(jsonSchema, { mode: options.strategy });
943
+ }
944
+ };
136
945
  export {
946
+ NON_LOGIC_KEYWORDS,
947
+ UNDEFINED_JSON_SCHEMA,
948
+ UNSUPPORTED_JSON_SCHEMA,
949
+ ZodCoercer,
950
+ ZodToJsonSchemaConverter,
137
951
  blob,
138
952
  file,
139
953
  getCustomJSONSchema,
@@ -143,6 +957,7 @@ export {
143
957
  openapi,
144
958
  oz,
145
959
  regexp,
146
- url
960
+ url,
961
+ zodToJsonSchema
147
962
  };
148
963
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,6 @@
1
+ import type { Schema } from '@orpc/contract';
2
+ import type { SchemaCoercer } from '@orpc/openapi/fetch';
3
+ export declare class ZodCoercer implements SchemaCoercer {
4
+ coerce(schema: Schema, value: unknown): unknown;
5
+ }
6
+ //# sourceMappingURL=coercer.d.ts.map
@@ -0,0 +1,44 @@
1
+ import type { Schema } from '@orpc/contract';
2
+ import type { JSONSchema, SchemaConverter, SchemaConvertOptions } from '@orpc/openapi';
3
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
4
+ export declare const NON_LOGIC_KEYWORDS: ("$anchor" | "$comment" | "$defs" | "$dynamicAnchor" | "$dynamicRef" | "$id" | "$schema" | "$vocabulary" | "contentEncoding" | "contentMediaType" | "default" | "definitions" | "deprecated" | "description" | "examples" | "format" | "readOnly" | "title" | "writeOnly")[];
5
+ export declare const UNSUPPORTED_JSON_SCHEMA: {
6
+ not: {};
7
+ };
8
+ export declare const UNDEFINED_JSON_SCHEMA: {
9
+ const: string;
10
+ };
11
+ export interface ZodToJsonSchemaOptions {
12
+ /**
13
+ * Max depth of lazy type, if it exceeds.
14
+ *
15
+ * Used `{}` when reach max depth
16
+ *
17
+ * @default 5
18
+ */
19
+ maxLazyDepth?: number;
20
+ /**
21
+ * The length used to track the depth of lazy type
22
+ *
23
+ * @internal
24
+ */
25
+ lazyDepth?: number;
26
+ /**
27
+ * The expected json schema for input or output zod schema
28
+ *
29
+ * @default input
30
+ */
31
+ mode?: 'input' | 'output';
32
+ /**
33
+ * Track if current level schema is handled custom json schema to prevent recursive
34
+ *
35
+ * @internal
36
+ */
37
+ isHandledCustomJSONSchema?: boolean;
38
+ }
39
+ export declare function zodToJsonSchema(schema: StandardSchemaV1, options?: ZodToJsonSchemaOptions): Exclude<JSONSchema.JSONSchema, boolean>;
40
+ export declare class ZodToJsonSchemaConverter implements SchemaConverter {
41
+ condition(schema: Schema): boolean;
42
+ convert(schema: Schema, options: SchemaConvertOptions): JSONSchema.JSONSchema;
43
+ }
44
+ //# sourceMappingURL=converter.d.ts.map
@@ -1,31 +1,4 @@
1
- import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
2
- import { type CustomErrorParams, type input, type output, type ZodEffects, type ZodType, type ZodTypeAny, type ZodTypeDef } from 'zod';
3
- export type CustomZodType = 'File' | 'Blob' | 'Invalid Date' | 'RegExp' | 'URL';
4
- type CustomParams = CustomErrorParams & {
5
- fatal?: boolean;
6
- };
7
- export declare function getCustomZodType(def: ZodTypeDef): CustomZodType | undefined;
8
- export declare function getCustomZodFileMimeType(def: ZodTypeDef): string | undefined;
9
- export declare function getCustomJSONSchema(def: ZodTypeDef, options?: {
10
- mode?: 'input' | 'output';
11
- }): Exclude<JSONSchema, boolean> | undefined;
12
- export declare function file(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<InstanceType<typeof File>, ZodTypeDef, InstanceType<typeof File>> & {
13
- type: (mimeType: string, params?: string | CustomParams | ((input: unknown) => CustomParams)) => ZodEffects<ZodType<InstanceType<typeof File>, ZodTypeDef, InstanceType<typeof File>>, InstanceType<typeof File>, InstanceType<typeof File>>;
14
- };
15
- export declare function blob(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<InstanceType<typeof Blob>, ZodTypeDef, InstanceType<typeof Blob>>;
16
- export declare function invalidDate(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<Date, ZodTypeDef, Date>;
17
- export declare function regexp(options?: CustomParams): ZodType<RegExp, ZodTypeDef, RegExp>;
18
- export declare function url(options?: CustomParams): ZodType<URL, ZodTypeDef, URL>;
19
- export declare function openapi<T extends ZodTypeAny, TMode extends 'input' | 'output' | 'both' = 'both'>(schema: T, custom: Exclude<JSONSchema<TMode extends 'input' ? input<T> : TMode extends 'output' ? output<T> : input<T> & output<T>>, boolean>, options?: {
20
- mode: TMode;
21
- }): ReturnType<T['refine']>;
22
- export declare const oz: {
23
- openapi: typeof openapi;
24
- file: typeof file;
25
- blob: typeof blob;
26
- invalidDate: typeof invalidDate;
27
- regexp: typeof regexp;
28
- url: typeof url;
29
- };
30
- export {};
1
+ export * from './coercer';
2
+ export * from './converter';
3
+ export * from './schemas';
31
4
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,31 @@
1
+ import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
2
+ import { type CustomErrorParams, type input, type output, type ZodEffects, type ZodType, type ZodTypeAny, type ZodTypeDef } from 'zod';
3
+ export type CustomZodType = 'File' | 'Blob' | 'Invalid Date' | 'RegExp' | 'URL';
4
+ type CustomParams = CustomErrorParams & {
5
+ fatal?: boolean;
6
+ };
7
+ export declare function getCustomZodType(def: ZodTypeDef): CustomZodType | undefined;
8
+ export declare function getCustomZodFileMimeType(def: ZodTypeDef): string | undefined;
9
+ export declare function getCustomJSONSchema(def: ZodTypeDef, options?: {
10
+ mode?: 'input' | 'output';
11
+ }): Exclude<JSONSchema, boolean> | undefined;
12
+ export declare function file(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<InstanceType<typeof File>, ZodTypeDef, InstanceType<typeof File>> & {
13
+ type: (mimeType: string, params?: string | CustomParams | ((input: unknown) => CustomParams)) => ZodEffects<ZodType<InstanceType<typeof File>, ZodTypeDef, InstanceType<typeof File>>, InstanceType<typeof File>, InstanceType<typeof File>>;
14
+ };
15
+ export declare function blob(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<InstanceType<typeof Blob>, ZodTypeDef, InstanceType<typeof Blob>>;
16
+ export declare function invalidDate(params?: string | CustomParams | ((input: unknown) => CustomParams)): ZodType<Date, ZodTypeDef, Date>;
17
+ export declare function regexp(options?: CustomParams): ZodType<RegExp, ZodTypeDef, RegExp>;
18
+ export declare function url(options?: CustomParams): ZodType<URL, ZodTypeDef, URL>;
19
+ export declare function openapi<T extends ZodTypeAny, TMode extends 'input' | 'output' | 'both' = 'both'>(schema: T, custom: Exclude<JSONSchema<TMode extends 'input' ? input<T> : TMode extends 'output' ? output<T> : input<T> & output<T>>, boolean>, options?: {
20
+ mode: TMode;
21
+ }): ReturnType<T['refine']>;
22
+ export declare const oz: {
23
+ openapi: typeof openapi;
24
+ file: typeof file;
25
+ blob: typeof blob;
26
+ invalidDate: typeof invalidDate;
27
+ regexp: typeof regexp;
28
+ url: typeof url;
29
+ };
30
+ export {};
31
+ //# sourceMappingURL=schemas.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/zod",
3
3
  "type": "module",
4
- "version": "0.0.0-next.aa57fb6",
4
+ "version": "0.0.0-next.c29cb6d",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -28,10 +28,13 @@
28
28
  "!**/*.tsbuildinfo",
29
29
  "dist"
30
30
  ],
31
+ "peerDependencies": {
32
+ "@orpc/openapi": "0.0.0-next.c29cb6d"
33
+ },
31
34
  "dependencies": {
32
35
  "json-schema-typed": "^8.0.1",
33
36
  "wildcard-match": "^5.1.3",
34
- "zod": "^3.23.8"
37
+ "zod": "^3.24.1"
35
38
  },
36
39
  "scripts": {
37
40
  "build": "tsup --clean --sourcemap --entry.index=src/index.ts --format=esm --onSuccess='tsc -b --noCheck'",