zod 3.26.0-canary.20250703T215303 → 3.26.0-canary.20250708T090717
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/index.cjs +2 -2
- package/index.d.cts +2 -2
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/package.json +1 -1
- package/src/index.ts +2 -2
- package/src/v4/classic/schemas.ts +8 -9
- package/src/v4/classic/tests/brand.test.ts +1 -3
- package/src/v4/classic/tests/discriminated-unions.test.ts +27 -0
- package/src/v4/classic/tests/index.test.ts +1 -1
- package/src/v4/classic/tests/object.test.ts +11 -1
- package/src/v4/classic/tests/record.test.ts +11 -1
- package/src/v4/classic/tests/recursive-types.test.ts +33 -2
- package/src/v4/classic/tests/refine.test.ts +109 -0
- package/src/v4/classic/tests/registries.test.ts +9 -0
- package/src/v4/classic/tests/to-json-schema.test.ts +78 -17
- package/src/v4/core/api.ts +2 -0
- package/src/v4/core/checks.ts +8 -10
- package/src/v4/core/errors.ts +4 -0
- package/src/v4/core/registries.ts +11 -1
- package/src/v4/core/schemas.ts +80 -34
- package/src/v4/core/to-json-schema.ts +67 -30
- package/src/v4/mini/schemas.ts +2 -2
- package/src/v4/mini/tests/string.test.ts +6 -0
- package/v4/classic/schemas.cjs +4 -4
- package/v4/classic/schemas.d.cts +4 -3
- package/v4/classic/schemas.d.ts +4 -3
- package/v4/classic/schemas.js +4 -4
- package/v4/core/checks.cjs +18 -12
- package/v4/core/checks.d.cts +2 -1
- package/v4/core/checks.d.ts +2 -1
- package/v4/core/checks.js +18 -12
- package/v4/core/errors.cjs +4 -0
- package/v4/core/errors.js +4 -0
- package/v4/core/registries.cjs +10 -1
- package/v4/core/registries.d.cts +2 -1
- package/v4/core/registries.d.ts +2 -1
- package/v4/core/registries.js +10 -1
- package/v4/core/schemas.cjs +15 -6
- package/v4/core/schemas.d.cts +31 -9
- package/v4/core/schemas.d.ts +31 -9
- package/v4/core/schemas.js +15 -6
- package/v4/core/to-json-schema.cjs +51 -26
- package/v4/core/to-json-schema.d.cts +6 -2
- package/v4/core/to-json-schema.d.ts +6 -2
- package/v4/core/to-json-schema.js +51 -26
- package/v4/mini/schemas.d.cts +1 -1
- package/v4/mini/schemas.d.ts +1 -1
package/v4/core/schemas.d.ts
CHANGED
|
@@ -32,7 +32,6 @@ export interface _$ZodTypeInternals {
|
|
|
32
32
|
/** Schema definition. */
|
|
33
33
|
def: $ZodTypeDef;
|
|
34
34
|
/** @internal Randomly generated ID for this schema. */
|
|
35
|
-
id: string;
|
|
36
35
|
/** @internal List of deferred initializers. */
|
|
37
36
|
deferred: util.AnyFunc[] | undefined;
|
|
38
37
|
/** @internal Parses input and runs all checks (refinements). */
|
|
@@ -516,11 +515,13 @@ export interface $ZodArrayDef<T extends SomeType = $ZodType> extends $ZodTypeDef
|
|
|
516
515
|
type: "array";
|
|
517
516
|
element: T;
|
|
518
517
|
}
|
|
519
|
-
export interface $ZodArrayInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals
|
|
518
|
+
export interface $ZodArrayInternals<T extends SomeType = $ZodType> extends _$ZodTypeInternals {
|
|
520
519
|
def: $ZodArrayDef<T>;
|
|
521
520
|
isst: errors.$ZodIssueInvalidType;
|
|
521
|
+
output: core.output<T>[];
|
|
522
|
+
input: core.input<T>[];
|
|
522
523
|
}
|
|
523
|
-
export interface $ZodArray<T extends SomeType = $ZodType> extends $ZodType<
|
|
524
|
+
export interface $ZodArray<T extends SomeType = $ZodType> extends $ZodType<any, any, $ZodArrayInternals<T>> {
|
|
524
525
|
}
|
|
525
526
|
export declare const $ZodArray: core.$constructor<$ZodArray>;
|
|
526
527
|
type OptionalOutSchema = {
|
|
@@ -533,12 +534,12 @@ type OptionalInSchema = {
|
|
|
533
534
|
optin: "optional";
|
|
534
535
|
};
|
|
535
536
|
};
|
|
536
|
-
export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T ? Record<string, unknown> : keyof (T & Extra) extends never ? Record<string, never> : util.Prettify<{
|
|
537
|
+
export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T ? util.IsAny<T[keyof T]> extends true ? Record<string, unknown> : Record<string, core.output<T[keyof T]>> : keyof (T & Extra) extends never ? Record<string, never> : util.Prettify<{
|
|
537
538
|
-readonly [k in keyof T as T[k] extends OptionalOutSchema ? never : k]: T[k]["_zod"]["output"];
|
|
538
539
|
} & {
|
|
539
540
|
-readonly [k in keyof T as T[k] extends OptionalOutSchema ? k : never]?: T[k]["_zod"]["output"];
|
|
540
541
|
} & Extra>;
|
|
541
|
-
export type $InferObjectInput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T ? Record<string, unknown> : keyof (T & Extra) extends never ? Record<string, never> : util.Prettify<{
|
|
542
|
+
export type $InferObjectInput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T ? util.IsAny<T[keyof T]> extends true ? Record<string, unknown> : Record<string, core.input<T[keyof T]>> : keyof (T & Extra) extends never ? Record<string, never> : util.Prettify<{
|
|
542
543
|
-readonly [k in keyof T as T[k] extends OptionalInSchema ? never : k]: T[k]["_zod"]["input"];
|
|
543
544
|
} & {
|
|
544
545
|
-readonly [k in keyof T as T[k] extends OptionalInSchema ? k : never]?: T[k]["_zod"]["input"];
|
|
@@ -600,14 +601,17 @@ export interface $ZodUnionDef<Options extends readonly SomeType[] = readonly $Zo
|
|
|
600
601
|
}
|
|
601
602
|
type IsOptionalIn<T extends SomeType> = T extends OptionalInSchema ? true : false;
|
|
602
603
|
type IsOptionalOut<T extends SomeType> = T extends OptionalOutSchema ? true : false;
|
|
603
|
-
export interface $ZodUnionInternals<T extends readonly SomeType[] = readonly $ZodType[]> extends $ZodTypeInternals
|
|
604
|
+
export interface $ZodUnionInternals<T extends readonly SomeType[] = readonly $ZodType[]> extends _$ZodTypeInternals {
|
|
604
605
|
def: $ZodUnionDef<T>;
|
|
605
606
|
isst: errors.$ZodIssueInvalidUnion;
|
|
606
607
|
pattern: T[number]["_zod"]["pattern"];
|
|
608
|
+
values: T[number]["_zod"]["values"];
|
|
609
|
+
output: $InferUnionOutput<T[number]>;
|
|
610
|
+
input: $InferUnionInput<T[number]>;
|
|
607
611
|
optin: IsOptionalIn<T[number]> extends false ? "optional" | undefined : "optional";
|
|
608
612
|
optout: IsOptionalOut<T[number]> extends false ? "optional" | undefined : "optional";
|
|
609
613
|
}
|
|
610
|
-
export interface $ZodUnion<T extends readonly SomeType[] = readonly $ZodType[]> extends $ZodType {
|
|
614
|
+
export interface $ZodUnion<T extends readonly SomeType[] = readonly $ZodType[]> extends $ZodType<any, any, $ZodUnionInternals<T>> {
|
|
611
615
|
_zod: $ZodUnionInternals<T>;
|
|
612
616
|
}
|
|
613
617
|
export declare const $ZodUnion: core.$constructor<$ZodUnion>;
|
|
@@ -631,6 +635,8 @@ export interface $ZodIntersectionDef<Left extends SomeType = $ZodType, Right ext
|
|
|
631
635
|
export interface $ZodIntersectionInternals<A extends SomeType = $ZodType, B extends SomeType = $ZodType> extends $ZodTypeInternals<core.output<A> & core.output<B>, core.input<A> & core.input<B>> {
|
|
632
636
|
def: $ZodIntersectionDef<A, B>;
|
|
633
637
|
isst: never;
|
|
638
|
+
optin: A["_zod"]["optin"] | B["_zod"]["optin"];
|
|
639
|
+
optout: A["_zod"]["optout"] | B["_zod"]["optout"];
|
|
634
640
|
}
|
|
635
641
|
export interface $ZodIntersection<A extends SomeType = $ZodType, B extends SomeType = $ZodType> extends $ZodType {
|
|
636
642
|
_zod: $ZodIntersectionInternals<A, B>;
|
|
@@ -677,12 +683,17 @@ export interface $ZodRecordDef<Key extends $ZodRecordKey = $ZodRecordKey, Value
|
|
|
677
683
|
keyType: Key;
|
|
678
684
|
valueType: Value;
|
|
679
685
|
}
|
|
680
|
-
export type $InferZodRecordOutput<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> =
|
|
681
|
-
export type $InferZodRecordInput<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> =
|
|
686
|
+
export type $InferZodRecordOutput<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> = Key extends $partial ? Partial<Record<core.output<Key>, core.output<Value>>> : Record<core.output<Key>, core.output<Value>>;
|
|
687
|
+
export type $InferZodRecordInput<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> = Key extends $partial ? Partial<Record<core.input<Key>, core.input<Value>>> : Record<core.input<Key>, core.input<Value>>;
|
|
682
688
|
export interface $ZodRecordInternals<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> extends $ZodTypeInternals<$InferZodRecordOutput<Key, Value>, $InferZodRecordInput<Key, Value>> {
|
|
683
689
|
def: $ZodRecordDef<Key, Value>;
|
|
684
690
|
isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey<Record<PropertyKey, unknown>>;
|
|
691
|
+
optin?: "optional" | undefined;
|
|
692
|
+
optout?: "optional" | undefined;
|
|
685
693
|
}
|
|
694
|
+
export type $partial = {
|
|
695
|
+
"~~partial": true;
|
|
696
|
+
};
|
|
686
697
|
export interface $ZodRecord<Key extends $ZodRecordKey = $ZodRecordKey, Value extends SomeType = $ZodType> extends $ZodType {
|
|
687
698
|
_zod: $ZodRecordInternals<Key, Value>;
|
|
688
699
|
}
|
|
@@ -695,6 +706,8 @@ export interface $ZodMapDef<Key extends SomeType = $ZodType, Value extends SomeT
|
|
|
695
706
|
export interface $ZodMapInternals<Key extends SomeType = $ZodType, Value extends SomeType = $ZodType> extends $ZodTypeInternals<Map<core.output<Key>, core.output<Value>>, Map<core.input<Key>, core.input<Value>>> {
|
|
696
707
|
def: $ZodMapDef<Key, Value>;
|
|
697
708
|
isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey | errors.$ZodIssueInvalidElement<unknown>;
|
|
709
|
+
optin?: "optional" | undefined;
|
|
710
|
+
optout?: "optional" | undefined;
|
|
698
711
|
}
|
|
699
712
|
export interface $ZodMap<Key extends SomeType = $ZodType, Value extends SomeType = $ZodType> extends $ZodType {
|
|
700
713
|
_zod: $ZodMapInternals<Key, Value>;
|
|
@@ -707,6 +720,8 @@ export interface $ZodSetDef<T extends SomeType = $ZodType> extends $ZodTypeDef {
|
|
|
707
720
|
export interface $ZodSetInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<Set<core.output<T>>, Set<core.input<T>>> {
|
|
708
721
|
def: $ZodSetDef<T>;
|
|
709
722
|
isst: errors.$ZodIssueInvalidType;
|
|
723
|
+
optin?: "optional" | undefined;
|
|
724
|
+
optout?: "optional" | undefined;
|
|
710
725
|
}
|
|
711
726
|
export interface $ZodSet<T extends SomeType = $ZodType> extends $ZodType {
|
|
712
727
|
_zod: $ZodSetInternals<T>;
|
|
@@ -819,6 +834,7 @@ export interface $ZodDefaultDef<T extends SomeType = $ZodType> extends $ZodTypeD
|
|
|
819
834
|
export interface $ZodDefaultInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<util.NoUndefined<core.output<T>>, core.input<T> | undefined> {
|
|
820
835
|
def: $ZodDefaultDef<T>;
|
|
821
836
|
optin: "optional";
|
|
837
|
+
optout?: "optional" | undefined;
|
|
822
838
|
isst: never;
|
|
823
839
|
values: T["_zod"]["values"];
|
|
824
840
|
}
|
|
@@ -835,6 +851,7 @@ export interface $ZodPrefaultDef<T extends SomeType = $ZodType> extends $ZodType
|
|
|
835
851
|
export interface $ZodPrefaultInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<util.NoUndefined<core.output<T>>, core.input<T> | undefined> {
|
|
836
852
|
def: $ZodPrefaultDef<T>;
|
|
837
853
|
optin: "optional";
|
|
854
|
+
optout?: "optional" | undefined;
|
|
838
855
|
isst: never;
|
|
839
856
|
values: T["_zod"]["values"];
|
|
840
857
|
}
|
|
@@ -850,6 +867,8 @@ export interface $ZodNonOptionalInternals<T extends SomeType = $ZodType> extends
|
|
|
850
867
|
def: $ZodNonOptionalDef<T>;
|
|
851
868
|
isst: errors.$ZodIssueInvalidType;
|
|
852
869
|
values: T["_zod"]["values"];
|
|
870
|
+
optin: "optional" | undefined;
|
|
871
|
+
optout: "optional" | undefined;
|
|
853
872
|
}
|
|
854
873
|
export interface $ZodNonOptional<T extends SomeType = $ZodType> extends $ZodType {
|
|
855
874
|
_zod: $ZodNonOptionalInternals<T>;
|
|
@@ -862,6 +881,8 @@ export interface $ZodSuccessDef<T extends SomeType = $ZodType> extends $ZodTypeD
|
|
|
862
881
|
export interface $ZodSuccessInternals<T extends SomeType = $ZodType> extends $ZodTypeInternals<boolean, core.input<T>> {
|
|
863
882
|
def: $ZodSuccessDef<T>;
|
|
864
883
|
isst: never;
|
|
884
|
+
optin: T["_zod"]["optin"];
|
|
885
|
+
optout: "optional" | undefined;
|
|
865
886
|
}
|
|
866
887
|
export interface $ZodSuccess<T extends SomeType = $ZodType> extends $ZodType {
|
|
867
888
|
_zod: $ZodSuccessInternals<T>;
|
|
@@ -928,6 +949,7 @@ export interface $ZodReadonlyInternals<T extends SomeType = $ZodType> extends $Z
|
|
|
928
949
|
optout: T["_zod"]["optout"];
|
|
929
950
|
isst: never;
|
|
930
951
|
propValues: T["_zod"]["propValues"];
|
|
952
|
+
values: T["_zod"]["values"];
|
|
931
953
|
}
|
|
932
954
|
export interface $ZodReadonly<T extends SomeType = $ZodType> extends $ZodType {
|
|
933
955
|
_zod: $ZodReadonlyInternals<T>;
|
package/v4/core/schemas.js
CHANGED
|
@@ -8,8 +8,6 @@ import { version } from "./versions.js";
|
|
|
8
8
|
export const $ZodType = /*@__PURE__*/ core.$constructor("$ZodType", (inst, def) => {
|
|
9
9
|
var _a;
|
|
10
10
|
inst ?? (inst = {});
|
|
11
|
-
// avoids issues with using Math.random() in Next.js caching
|
|
12
|
-
util.defineLazy(inst._zod, "id", () => def.type + "_" + util.randomString(10));
|
|
13
11
|
inst._zod.def = def; // set _def property
|
|
14
12
|
inst._zod.bag = inst._zod.bag || {}; // initialize _bag object
|
|
15
13
|
inst._zod.version = version;
|
|
@@ -37,8 +35,8 @@ export const $ZodType = /*@__PURE__*/ core.$constructor("$ZodType", (inst, def)
|
|
|
37
35
|
let isAborted = util.aborted(payload);
|
|
38
36
|
let asyncResult;
|
|
39
37
|
for (const ch of checks) {
|
|
40
|
-
if (ch._zod.when) {
|
|
41
|
-
const shouldRun = ch._zod.when(payload);
|
|
38
|
+
if (ch._zod.def.when) {
|
|
39
|
+
const shouldRun = ch._zod.def.when(payload);
|
|
42
40
|
if (!shouldRun)
|
|
43
41
|
continue;
|
|
44
42
|
}
|
|
@@ -158,7 +156,9 @@ export const $ZodURL = /*@__PURE__*/ core.$constructor("$ZodURL", (inst, def) =>
|
|
|
158
156
|
$ZodStringFormat.init(inst, def);
|
|
159
157
|
inst._zod.check = (payload) => {
|
|
160
158
|
try {
|
|
161
|
-
const
|
|
159
|
+
const orig = payload.value;
|
|
160
|
+
const url = new URL(orig);
|
|
161
|
+
const href = url.href;
|
|
162
162
|
if (def.hostname) {
|
|
163
163
|
def.hostname.lastIndex = 0;
|
|
164
164
|
if (!def.hostname.test(url.hostname)) {
|
|
@@ -187,6 +187,13 @@ export const $ZodURL = /*@__PURE__*/ core.$constructor("$ZodURL", (inst, def) =>
|
|
|
187
187
|
});
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
|
+
// payload.value = url.href;
|
|
191
|
+
if (!orig.endsWith("/") && href.endsWith("/")) {
|
|
192
|
+
payload.value = href.slice(0, -1);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
payload.value = href;
|
|
196
|
+
}
|
|
190
197
|
return;
|
|
191
198
|
}
|
|
192
199
|
catch (_) {
|
|
@@ -720,8 +727,9 @@ export const $ZodObject = /*@__PURE__*/ core.$constructor("$ZodObject", (inst, d
|
|
|
720
727
|
};
|
|
721
728
|
doc.write(`const input = payload.value;`);
|
|
722
729
|
const ids = Object.create(null);
|
|
730
|
+
let counter = 0;
|
|
723
731
|
for (const key of normalized.keys) {
|
|
724
|
-
ids[key] =
|
|
732
|
+
ids[key] = `key_${counter++}`;
|
|
725
733
|
}
|
|
726
734
|
// A: preserve key order {
|
|
727
735
|
doc.write(`const newResult = {}`);
|
|
@@ -1595,6 +1603,7 @@ function handlePipeResult(left, def, ctx) {
|
|
|
1595
1603
|
export const $ZodReadonly = /*@__PURE__*/ core.$constructor("$ZodReadonly", (inst, def) => {
|
|
1596
1604
|
$ZodType.init(inst, def);
|
|
1597
1605
|
util.defineLazy(inst._zod, "propValues", () => def.innerType._zod.propValues);
|
|
1606
|
+
util.defineLazy(inst._zod, "values", () => def.innerType._zod.values);
|
|
1598
1607
|
util.defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
|
|
1599
1608
|
util.defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
|
|
1600
1609
|
inst._zod.parse = (payload, ctx) => {
|
|
@@ -36,7 +36,7 @@ class JSONSchemaGenerator {
|
|
|
36
36
|
return seen.schema;
|
|
37
37
|
}
|
|
38
38
|
// initialize
|
|
39
|
-
const result = { schema: {}, count: 1, cycle: undefined };
|
|
39
|
+
const result = { schema: {}, count: 1, cycle: undefined, path: _params.path };
|
|
40
40
|
this.seen.set(schema, result);
|
|
41
41
|
// custom method overrides default behavior
|
|
42
42
|
const overrideSchema = schema._zod.toJSONSchema?.();
|
|
@@ -151,9 +151,10 @@ class JSONSchemaGenerator {
|
|
|
151
151
|
case "unknown": {
|
|
152
152
|
break;
|
|
153
153
|
}
|
|
154
|
-
case "undefined":
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
case "undefined": {
|
|
155
|
+
if (this.unrepresentable === "throw") {
|
|
156
|
+
throw new Error("Undefined cannot be represented in JSON Schema");
|
|
157
|
+
}
|
|
157
158
|
break;
|
|
158
159
|
}
|
|
159
160
|
case "void": {
|
|
@@ -162,6 +163,10 @@ class JSONSchemaGenerator {
|
|
|
162
163
|
}
|
|
163
164
|
break;
|
|
164
165
|
}
|
|
166
|
+
case "never": {
|
|
167
|
+
_json.not = {};
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
165
170
|
case "date": {
|
|
166
171
|
if (this.unrepresentable === "throw") {
|
|
167
172
|
throw new Error("Date cannot be represented in JSON Schema");
|
|
@@ -531,6 +536,8 @@ class JSONSchemaGenerator {
|
|
|
531
536
|
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
532
537
|
// initialize result with root schema fields
|
|
533
538
|
// Object.assign(result, seen.cached);
|
|
539
|
+
// returns a ref to the schema
|
|
540
|
+
// defId will be empty if the ref points to an external schema (or #)
|
|
534
541
|
const makeURI = (entry) => {
|
|
535
542
|
// comparing the seen objects because sometimes
|
|
536
543
|
// multiple schemas map to the same seen object.
|
|
@@ -540,12 +547,14 @@ class JSONSchemaGenerator {
|
|
|
540
547
|
if (params.external) {
|
|
541
548
|
const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`;
|
|
542
549
|
// check if schema is in the external registry
|
|
543
|
-
|
|
544
|
-
|
|
550
|
+
const uriGenerator = params.external.uri ?? ((id) => id);
|
|
551
|
+
if (externalId) {
|
|
552
|
+
return { ref: uriGenerator(externalId) };
|
|
553
|
+
}
|
|
545
554
|
// otherwise, add to __shared
|
|
546
555
|
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
|
|
547
|
-
entry[1].defId = id;
|
|
548
|
-
return { defId: id, ref: `${
|
|
556
|
+
entry[1].defId = id; // set defId so it will be reused if needed
|
|
557
|
+
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
|
549
558
|
}
|
|
550
559
|
if (entry[1] === root) {
|
|
551
560
|
return { ref: "#" };
|
|
@@ -559,6 +568,7 @@ class JSONSchemaGenerator {
|
|
|
559
568
|
// stored cached version in `def` property
|
|
560
569
|
// remove all properties, set $ref
|
|
561
570
|
const extractToDef = (entry) => {
|
|
571
|
+
// if the schema is already a reference, do not extract it
|
|
562
572
|
if (entry[1].schema.$ref) {
|
|
563
573
|
return;
|
|
564
574
|
}
|
|
@@ -575,14 +585,24 @@ class JSONSchemaGenerator {
|
|
|
575
585
|
}
|
|
576
586
|
schema.$ref = ref;
|
|
577
587
|
};
|
|
588
|
+
// throw on cycles
|
|
589
|
+
// break cycles
|
|
590
|
+
if (params.cycles === "throw") {
|
|
591
|
+
for (const entry of this.seen.entries()) {
|
|
592
|
+
const seen = entry[1];
|
|
593
|
+
if (seen.cycle) {
|
|
594
|
+
throw new Error("Cycle detected: " +
|
|
595
|
+
`#/${seen.cycle?.join("/")}/<root>` +
|
|
596
|
+
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
578
600
|
// extract schemas into $defs
|
|
579
601
|
for (const entry of this.seen.entries()) {
|
|
580
602
|
const seen = entry[1];
|
|
581
603
|
// convert root schema to # $ref
|
|
582
|
-
// also prevents root schema from being extracted
|
|
583
604
|
if (schema === entry[0]) {
|
|
584
|
-
//
|
|
585
|
-
extractToDef(entry);
|
|
605
|
+
extractToDef(entry); // this has special handling for the root schema
|
|
586
606
|
continue;
|
|
587
607
|
}
|
|
588
608
|
// extract schemas that are in the external registry
|
|
@@ -601,14 +621,8 @@ class JSONSchemaGenerator {
|
|
|
601
621
|
}
|
|
602
622
|
// break cycles
|
|
603
623
|
if (seen.cycle) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
`#/${seen.cycle?.join("/")}/<root>` +
|
|
607
|
-
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
608
|
-
}
|
|
609
|
-
else if (params.cycles === "ref") {
|
|
610
|
-
extractToDef(entry);
|
|
611
|
-
}
|
|
624
|
+
// any
|
|
625
|
+
extractToDef(entry);
|
|
612
626
|
continue;
|
|
613
627
|
}
|
|
614
628
|
// extract reused schemas
|
|
@@ -650,6 +664,7 @@ class JSONSchemaGenerator {
|
|
|
650
664
|
this.override({
|
|
651
665
|
zodSchema: zodSchema,
|
|
652
666
|
jsonSchema: schema,
|
|
667
|
+
path: seen.path ?? [],
|
|
653
668
|
});
|
|
654
669
|
};
|
|
655
670
|
for (const entry of [...this.seen.entries()].reverse()) {
|
|
@@ -665,6 +680,12 @@ class JSONSchemaGenerator {
|
|
|
665
680
|
else {
|
|
666
681
|
console.warn(`Invalid target: ${this.target}`);
|
|
667
682
|
}
|
|
683
|
+
if (params.external?.uri) {
|
|
684
|
+
const id = params.external.registry.get(schema)?.id;
|
|
685
|
+
if (!id)
|
|
686
|
+
throw new Error("Schema is missing an `id` property");
|
|
687
|
+
result.$id = params.external.uri(id);
|
|
688
|
+
}
|
|
668
689
|
Object.assign(result, root.def);
|
|
669
690
|
// build defs object
|
|
670
691
|
const defs = params.external?.defs ?? {};
|
|
@@ -675,12 +696,16 @@ class JSONSchemaGenerator {
|
|
|
675
696
|
}
|
|
676
697
|
}
|
|
677
698
|
// set definitions in result
|
|
678
|
-
if (
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
699
|
+
if (params.external) {
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
if (Object.keys(defs).length > 0) {
|
|
703
|
+
if (this.target === "draft-2020-12") {
|
|
704
|
+
result.$defs = defs;
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
result.definitions = defs;
|
|
708
|
+
}
|
|
684
709
|
}
|
|
685
710
|
}
|
|
686
711
|
try {
|
|
@@ -706,7 +731,7 @@ function toJSONSchema(input, _params) {
|
|
|
706
731
|
const schemas = {};
|
|
707
732
|
const external = {
|
|
708
733
|
registry: input,
|
|
709
|
-
uri: _params?.uri
|
|
734
|
+
uri: _params?.uri,
|
|
710
735
|
defs,
|
|
711
736
|
};
|
|
712
737
|
for (const entry of input._idmap.entries()) {
|
|
@@ -17,9 +17,10 @@ interface JSONSchemaGeneratorParams {
|
|
|
17
17
|
override?: (ctx: {
|
|
18
18
|
zodSchema: schemas.$ZodTypes;
|
|
19
19
|
jsonSchema: JSONSchema.BaseSchema;
|
|
20
|
+
path: (string | number)[];
|
|
20
21
|
}) => void;
|
|
21
22
|
/** Whether to extract the `"input"` or `"output"` type. Relevant to transforms, Error converting schema to JSONz, defaults, coerced primitives, etc.
|
|
22
|
-
* - `"output" —
|
|
23
|
+
* - `"output"` — Default. Convert the output schema.
|
|
23
24
|
* - `"input"` — Convert the input schema. */
|
|
24
25
|
io?: "input" | "output";
|
|
25
26
|
}
|
|
@@ -38,7 +39,7 @@ interface EmitParams {
|
|
|
38
39
|
registry: $ZodRegistry<{
|
|
39
40
|
id?: string | undefined;
|
|
40
41
|
}>;
|
|
41
|
-
uri
|
|
42
|
+
uri?: ((id: string) => string) | undefined;
|
|
42
43
|
defs: Record<string, JSONSchema.BaseSchema>;
|
|
43
44
|
} | undefined;
|
|
44
45
|
}
|
|
@@ -54,6 +55,8 @@ interface Seen {
|
|
|
54
55
|
cycle?: (string | number)[] | undefined;
|
|
55
56
|
isParent?: boolean | undefined;
|
|
56
57
|
ref?: schemas.$ZodType | undefined | null;
|
|
58
|
+
/** JSON Schema property path for this schema */
|
|
59
|
+
path?: (string | number)[] | undefined;
|
|
57
60
|
}
|
|
58
61
|
export declare class JSONSchemaGenerator {
|
|
59
62
|
metadataRegistry: $ZodRegistry<Record<string, any>>;
|
|
@@ -62,6 +65,7 @@ export declare class JSONSchemaGenerator {
|
|
|
62
65
|
override: (ctx: {
|
|
63
66
|
zodSchema: schemas.$ZodTypes;
|
|
64
67
|
jsonSchema: JSONSchema.BaseSchema;
|
|
68
|
+
path: (string | number)[];
|
|
65
69
|
}) => void;
|
|
66
70
|
io: "input" | "output";
|
|
67
71
|
counter: number;
|
|
@@ -17,9 +17,10 @@ interface JSONSchemaGeneratorParams {
|
|
|
17
17
|
override?: (ctx: {
|
|
18
18
|
zodSchema: schemas.$ZodTypes;
|
|
19
19
|
jsonSchema: JSONSchema.BaseSchema;
|
|
20
|
+
path: (string | number)[];
|
|
20
21
|
}) => void;
|
|
21
22
|
/** Whether to extract the `"input"` or `"output"` type. Relevant to transforms, Error converting schema to JSONz, defaults, coerced primitives, etc.
|
|
22
|
-
* - `"output" —
|
|
23
|
+
* - `"output"` — Default. Convert the output schema.
|
|
23
24
|
* - `"input"` — Convert the input schema. */
|
|
24
25
|
io?: "input" | "output";
|
|
25
26
|
}
|
|
@@ -38,7 +39,7 @@ interface EmitParams {
|
|
|
38
39
|
registry: $ZodRegistry<{
|
|
39
40
|
id?: string | undefined;
|
|
40
41
|
}>;
|
|
41
|
-
uri
|
|
42
|
+
uri?: ((id: string) => string) | undefined;
|
|
42
43
|
defs: Record<string, JSONSchema.BaseSchema>;
|
|
43
44
|
} | undefined;
|
|
44
45
|
}
|
|
@@ -54,6 +55,8 @@ interface Seen {
|
|
|
54
55
|
cycle?: (string | number)[] | undefined;
|
|
55
56
|
isParent?: boolean | undefined;
|
|
56
57
|
ref?: schemas.$ZodType | undefined | null;
|
|
58
|
+
/** JSON Schema property path for this schema */
|
|
59
|
+
path?: (string | number)[] | undefined;
|
|
57
60
|
}
|
|
58
61
|
export declare class JSONSchemaGenerator {
|
|
59
62
|
metadataRegistry: $ZodRegistry<Record<string, any>>;
|
|
@@ -62,6 +65,7 @@ export declare class JSONSchemaGenerator {
|
|
|
62
65
|
override: (ctx: {
|
|
63
66
|
zodSchema: schemas.$ZodTypes;
|
|
64
67
|
jsonSchema: JSONSchema.BaseSchema;
|
|
68
|
+
path: (string | number)[];
|
|
65
69
|
}) => void;
|
|
66
70
|
io: "input" | "output";
|
|
67
71
|
counter: number;
|
|
@@ -32,7 +32,7 @@ export class JSONSchemaGenerator {
|
|
|
32
32
|
return seen.schema;
|
|
33
33
|
}
|
|
34
34
|
// initialize
|
|
35
|
-
const result = { schema: {}, count: 1, cycle: undefined };
|
|
35
|
+
const result = { schema: {}, count: 1, cycle: undefined, path: _params.path };
|
|
36
36
|
this.seen.set(schema, result);
|
|
37
37
|
// custom method overrides default behavior
|
|
38
38
|
const overrideSchema = schema._zod.toJSONSchema?.();
|
|
@@ -147,9 +147,10 @@ export class JSONSchemaGenerator {
|
|
|
147
147
|
case "unknown": {
|
|
148
148
|
break;
|
|
149
149
|
}
|
|
150
|
-
case "undefined":
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
case "undefined": {
|
|
151
|
+
if (this.unrepresentable === "throw") {
|
|
152
|
+
throw new Error("Undefined cannot be represented in JSON Schema");
|
|
153
|
+
}
|
|
153
154
|
break;
|
|
154
155
|
}
|
|
155
156
|
case "void": {
|
|
@@ -158,6 +159,10 @@ export class JSONSchemaGenerator {
|
|
|
158
159
|
}
|
|
159
160
|
break;
|
|
160
161
|
}
|
|
162
|
+
case "never": {
|
|
163
|
+
_json.not = {};
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
161
166
|
case "date": {
|
|
162
167
|
if (this.unrepresentable === "throw") {
|
|
163
168
|
throw new Error("Date cannot be represented in JSON Schema");
|
|
@@ -527,6 +532,8 @@ export class JSONSchemaGenerator {
|
|
|
527
532
|
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
528
533
|
// initialize result with root schema fields
|
|
529
534
|
// Object.assign(result, seen.cached);
|
|
535
|
+
// returns a ref to the schema
|
|
536
|
+
// defId will be empty if the ref points to an external schema (or #)
|
|
530
537
|
const makeURI = (entry) => {
|
|
531
538
|
// comparing the seen objects because sometimes
|
|
532
539
|
// multiple schemas map to the same seen object.
|
|
@@ -536,12 +543,14 @@ export class JSONSchemaGenerator {
|
|
|
536
543
|
if (params.external) {
|
|
537
544
|
const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`;
|
|
538
545
|
// check if schema is in the external registry
|
|
539
|
-
|
|
540
|
-
|
|
546
|
+
const uriGenerator = params.external.uri ?? ((id) => id);
|
|
547
|
+
if (externalId) {
|
|
548
|
+
return { ref: uriGenerator(externalId) };
|
|
549
|
+
}
|
|
541
550
|
// otherwise, add to __shared
|
|
542
551
|
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
|
|
543
|
-
entry[1].defId = id;
|
|
544
|
-
return { defId: id, ref: `${
|
|
552
|
+
entry[1].defId = id; // set defId so it will be reused if needed
|
|
553
|
+
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
|
545
554
|
}
|
|
546
555
|
if (entry[1] === root) {
|
|
547
556
|
return { ref: "#" };
|
|
@@ -555,6 +564,7 @@ export class JSONSchemaGenerator {
|
|
|
555
564
|
// stored cached version in `def` property
|
|
556
565
|
// remove all properties, set $ref
|
|
557
566
|
const extractToDef = (entry) => {
|
|
567
|
+
// if the schema is already a reference, do not extract it
|
|
558
568
|
if (entry[1].schema.$ref) {
|
|
559
569
|
return;
|
|
560
570
|
}
|
|
@@ -571,14 +581,24 @@ export class JSONSchemaGenerator {
|
|
|
571
581
|
}
|
|
572
582
|
schema.$ref = ref;
|
|
573
583
|
};
|
|
584
|
+
// throw on cycles
|
|
585
|
+
// break cycles
|
|
586
|
+
if (params.cycles === "throw") {
|
|
587
|
+
for (const entry of this.seen.entries()) {
|
|
588
|
+
const seen = entry[1];
|
|
589
|
+
if (seen.cycle) {
|
|
590
|
+
throw new Error("Cycle detected: " +
|
|
591
|
+
`#/${seen.cycle?.join("/")}/<root>` +
|
|
592
|
+
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
574
596
|
// extract schemas into $defs
|
|
575
597
|
for (const entry of this.seen.entries()) {
|
|
576
598
|
const seen = entry[1];
|
|
577
599
|
// convert root schema to # $ref
|
|
578
|
-
// also prevents root schema from being extracted
|
|
579
600
|
if (schema === entry[0]) {
|
|
580
|
-
//
|
|
581
|
-
extractToDef(entry);
|
|
601
|
+
extractToDef(entry); // this has special handling for the root schema
|
|
582
602
|
continue;
|
|
583
603
|
}
|
|
584
604
|
// extract schemas that are in the external registry
|
|
@@ -597,14 +617,8 @@ export class JSONSchemaGenerator {
|
|
|
597
617
|
}
|
|
598
618
|
// break cycles
|
|
599
619
|
if (seen.cycle) {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
`#/${seen.cycle?.join("/")}/<root>` +
|
|
603
|
-
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
604
|
-
}
|
|
605
|
-
else if (params.cycles === "ref") {
|
|
606
|
-
extractToDef(entry);
|
|
607
|
-
}
|
|
620
|
+
// any
|
|
621
|
+
extractToDef(entry);
|
|
608
622
|
continue;
|
|
609
623
|
}
|
|
610
624
|
// extract reused schemas
|
|
@@ -646,6 +660,7 @@ export class JSONSchemaGenerator {
|
|
|
646
660
|
this.override({
|
|
647
661
|
zodSchema: zodSchema,
|
|
648
662
|
jsonSchema: schema,
|
|
663
|
+
path: seen.path ?? [],
|
|
649
664
|
});
|
|
650
665
|
};
|
|
651
666
|
for (const entry of [...this.seen.entries()].reverse()) {
|
|
@@ -661,6 +676,12 @@ export class JSONSchemaGenerator {
|
|
|
661
676
|
else {
|
|
662
677
|
console.warn(`Invalid target: ${this.target}`);
|
|
663
678
|
}
|
|
679
|
+
if (params.external?.uri) {
|
|
680
|
+
const id = params.external.registry.get(schema)?.id;
|
|
681
|
+
if (!id)
|
|
682
|
+
throw new Error("Schema is missing an `id` property");
|
|
683
|
+
result.$id = params.external.uri(id);
|
|
684
|
+
}
|
|
664
685
|
Object.assign(result, root.def);
|
|
665
686
|
// build defs object
|
|
666
687
|
const defs = params.external?.defs ?? {};
|
|
@@ -671,12 +692,16 @@ export class JSONSchemaGenerator {
|
|
|
671
692
|
}
|
|
672
693
|
}
|
|
673
694
|
// set definitions in result
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
695
|
+
if (params.external) {
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
if (Object.keys(defs).length > 0) {
|
|
699
|
+
if (this.target === "draft-2020-12") {
|
|
700
|
+
result.$defs = defs;
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
result.definitions = defs;
|
|
704
|
+
}
|
|
680
705
|
}
|
|
681
706
|
}
|
|
682
707
|
try {
|
|
@@ -701,7 +726,7 @@ export function toJSONSchema(input, _params) {
|
|
|
701
726
|
const schemas = {};
|
|
702
727
|
const external = {
|
|
703
728
|
registry: input,
|
|
704
|
-
uri: _params?.uri
|
|
729
|
+
uri: _params?.uri,
|
|
705
730
|
defs,
|
|
706
731
|
};
|
|
707
732
|
for (const entry of input._idmap.entries()) {
|
package/v4/mini/schemas.d.cts
CHANGED
|
@@ -234,7 +234,7 @@ export interface ZodMiniRecord<Key extends core.$ZodRecordKey = core.$ZodRecordK
|
|
|
234
234
|
}
|
|
235
235
|
export declare const ZodMiniRecord: core.$constructor<ZodMiniRecord>;
|
|
236
236
|
export declare function record<Key extends core.$ZodRecordKey, Value extends SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodMiniRecord<Key, Value>;
|
|
237
|
-
export declare function partialRecord<Key extends core.$ZodRecordKey, Value extends SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodMiniRecord<
|
|
237
|
+
export declare function partialRecord<Key extends core.$ZodRecordKey, Value extends SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodMiniRecord<Key & core.$partial, Value>;
|
|
238
238
|
export interface ZodMiniMap<Key extends SomeType = core.$ZodType, Value extends SomeType = core.$ZodType> extends _ZodMiniType<core.$ZodMapInternals<Key, Value>> {
|
|
239
239
|
}
|
|
240
240
|
export declare const ZodMiniMap: core.$constructor<ZodMiniMap>;
|
package/v4/mini/schemas.d.ts
CHANGED
|
@@ -234,7 +234,7 @@ export interface ZodMiniRecord<Key extends core.$ZodRecordKey = core.$ZodRecordK
|
|
|
234
234
|
}
|
|
235
235
|
export declare const ZodMiniRecord: core.$constructor<ZodMiniRecord>;
|
|
236
236
|
export declare function record<Key extends core.$ZodRecordKey, Value extends SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodMiniRecord<Key, Value>;
|
|
237
|
-
export declare function partialRecord<Key extends core.$ZodRecordKey, Value extends SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodMiniRecord<
|
|
237
|
+
export declare function partialRecord<Key extends core.$ZodRecordKey, Value extends SomeType>(keyType: Key, valueType: Value, params?: string | core.$ZodRecordParams): ZodMiniRecord<Key & core.$partial, Value>;
|
|
238
238
|
export interface ZodMiniMap<Key extends SomeType = core.$ZodType, Value extends SomeType = core.$ZodType> extends _ZodMiniType<core.$ZodMapInternals<Key, Value>> {
|
|
239
239
|
}
|
|
240
240
|
export declare const ZodMiniMap: core.$constructor<ZodMiniMap>;
|