zod 4.1.12 → 4.1.13
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/package.json +1 -1
- package/src/v4/classic/checks.ts +1 -0
- package/src/v4/classic/schemas.ts +20 -0
- package/src/v4/classic/tests/continuability.test.ts +22 -0
- package/src/v4/classic/tests/describe-meta-checks.test.ts +27 -0
- package/src/v4/classic/tests/index.test.ts +55 -1
- package/src/v4/classic/tests/promise.test.ts +1 -1
- package/src/v4/classic/tests/readonly.test.ts +1 -1
- package/src/v4/classic/tests/record.test.ts +141 -9
- package/src/v4/classic/tests/registries.test.ts +5 -1
- package/src/v4/classic/tests/string.test.ts +72 -0
- package/src/v4/classic/tests/template-literal.test.ts +8 -0
- package/src/v4/classic/tests/to-json-schema.test.ts +97 -0
- package/src/v4/classic/tests/tuple.test.ts +18 -0
- package/src/v4/classic/tests/url.test.ts +13 -0
- package/src/v4/core/api.ts +45 -0
- package/src/v4/core/core.ts +22 -9
- package/src/v4/core/regexes.ts +6 -1
- package/src/v4/core/registries.ts +12 -1
- package/src/v4/core/schemas.ts +50 -33
- package/src/v4/core/tests/extend.test.ts +42 -1
- package/src/v4/core/tests/locales/he.test.ts +379 -0
- package/src/v4/core/tests/locales/nl.test.ts +46 -0
- package/src/v4/core/tests/record-constructor.test.ts +67 -0
- package/src/v4/core/tests/recursive-tuples.test.ts +45 -0
- package/src/v4/core/to-json-schema.ts +55 -91
- package/src/v4/core/util.ts +11 -0
- package/src/v4/core/versions.ts +1 -1
- package/src/v4/locales/en.ts +1 -0
- package/src/v4/locales/he.ts +202 -71
- package/src/v4/locales/nl.ts +10 -10
- package/src/v4/mini/iso.ts +4 -4
- package/src/v4/mini/schemas.ts +17 -0
- package/src/v4/mini/tests/functions.test.ts +0 -38
- package/src/v4/mini/tests/index.test.ts +24 -1
- package/src/v4/mini/tests/string.test.ts +32 -0
- package/v3/ZodError.d.cts +1 -1
- package/v3/ZodError.d.ts +1 -1
- package/v4/classic/checks.cjs +2 -1
- package/v4/classic/checks.d.cts +1 -1
- package/v4/classic/checks.d.ts +1 -1
- package/v4/classic/checks.js +1 -1
- package/v4/classic/schemas.cjs +15 -2
- package/v4/classic/schemas.d.cts +8 -0
- package/v4/classic/schemas.d.ts +8 -0
- package/v4/classic/schemas.js +12 -0
- package/v4/core/api.cjs +40 -0
- package/v4/core/api.d.cts +7 -0
- package/v4/core/api.d.ts +7 -0
- package/v4/core/api.js +36 -0
- package/v4/core/core.cjs +20 -11
- package/v4/core/core.js +20 -11
- package/v4/core/regexes.cjs +31 -2
- package/v4/core/regexes.d.cts +1 -0
- package/v4/core/regexes.d.ts +1 -0
- package/v4/core/regexes.js +5 -0
- package/v4/core/registries.cjs +3 -1
- package/v4/core/registries.js +3 -1
- package/v4/core/schemas.cjs +32 -33
- package/v4/core/schemas.d.cts +12 -2
- package/v4/core/schemas.d.ts +12 -2
- package/v4/core/schemas.js +30 -31
- package/v4/core/to-json-schema.cjs +55 -92
- package/v4/core/to-json-schema.js +55 -92
- package/v4/core/util.cjs +11 -0
- package/v4/core/util.d.cts +1 -0
- package/v4/core/util.d.ts +1 -0
- package/v4/core/util.js +10 -0
- package/v4/core/versions.cjs +1 -1
- package/v4/core/versions.js +1 -1
- package/v4/locales/en.cjs +1 -0
- package/v4/locales/en.js +1 -0
- package/v4/locales/he.cjs +177 -66
- package/v4/locales/he.js +177 -66
- package/v4/locales/nl.cjs +8 -8
- package/v4/locales/nl.js +8 -8
- package/v4/mini/iso.cjs +4 -4
- package/v4/mini/iso.js +4 -4
- package/v4/mini/schemas.cjs +13 -2
- package/v4/mini/schemas.d.cts +6 -0
- package/v4/mini/schemas.d.ts +6 -0
- package/v4/mini/schemas.js +10 -0
|
@@ -252,11 +252,19 @@ class JSONSchemaGenerator {
|
|
|
252
252
|
}
|
|
253
253
|
case "union": {
|
|
254
254
|
const json = _json;
|
|
255
|
+
// Discriminated unions use oneOf (exactly one match) instead of anyOf (one or more matches)
|
|
256
|
+
// because the discriminator field ensures mutual exclusivity between options in JSON Schema
|
|
257
|
+
const isDiscriminated = def.discriminator !== undefined;
|
|
255
258
|
const options = def.options.map((x, i) => this.process(x, {
|
|
256
259
|
...params,
|
|
257
|
-
path: [...params.path, "anyOf", i],
|
|
260
|
+
path: [...params.path, isDiscriminated ? "oneOf" : "anyOf", i],
|
|
258
261
|
}));
|
|
259
|
-
|
|
262
|
+
if (isDiscriminated) {
|
|
263
|
+
json.oneOf = options;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
json.anyOf = options;
|
|
267
|
+
}
|
|
260
268
|
break;
|
|
261
269
|
}
|
|
262
270
|
case "intersection": {
|
|
@@ -821,100 +829,55 @@ function isTransforming(_schema, _ctx) {
|
|
|
821
829
|
if (ctx.seen.has(_schema))
|
|
822
830
|
return false;
|
|
823
831
|
ctx.seen.add(_schema);
|
|
824
|
-
const
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
}
|
|
855
|
-
case "union": {
|
|
856
|
-
for (const option of def.options) {
|
|
857
|
-
if (isTransforming(option, ctx))
|
|
858
|
-
return true;
|
|
859
|
-
}
|
|
860
|
-
return false;
|
|
861
|
-
}
|
|
862
|
-
case "intersection": {
|
|
863
|
-
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
|
864
|
-
}
|
|
865
|
-
case "tuple": {
|
|
866
|
-
for (const item of def.items) {
|
|
867
|
-
if (isTransforming(item, ctx))
|
|
868
|
-
return true;
|
|
869
|
-
}
|
|
870
|
-
if (def.rest && isTransforming(def.rest, ctx))
|
|
832
|
+
const def = _schema._zod.def;
|
|
833
|
+
if (def.type === "transform")
|
|
834
|
+
return true;
|
|
835
|
+
if (def.type === "array")
|
|
836
|
+
return isTransforming(def.element, ctx);
|
|
837
|
+
if (def.type === "set")
|
|
838
|
+
return isTransforming(def.valueType, ctx);
|
|
839
|
+
if (def.type === "lazy")
|
|
840
|
+
return isTransforming(def.getter(), ctx);
|
|
841
|
+
if (def.type === "promise" ||
|
|
842
|
+
def.type === "optional" ||
|
|
843
|
+
def.type === "nonoptional" ||
|
|
844
|
+
def.type === "nullable" ||
|
|
845
|
+
def.type === "readonly" ||
|
|
846
|
+
def.type === "default" ||
|
|
847
|
+
def.type === "prefault") {
|
|
848
|
+
return isTransforming(def.innerType, ctx);
|
|
849
|
+
}
|
|
850
|
+
if (def.type === "intersection") {
|
|
851
|
+
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
|
852
|
+
}
|
|
853
|
+
if (def.type === "record" || def.type === "map") {
|
|
854
|
+
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
|
855
|
+
}
|
|
856
|
+
if (def.type === "pipe") {
|
|
857
|
+
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
|
858
|
+
}
|
|
859
|
+
if (def.type === "object") {
|
|
860
|
+
for (const key in def.shape) {
|
|
861
|
+
if (isTransforming(def.shape[key], ctx))
|
|
871
862
|
return true;
|
|
872
|
-
return false;
|
|
873
|
-
}
|
|
874
|
-
case "record": {
|
|
875
|
-
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
|
876
863
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
// inner types
|
|
884
|
-
case "promise":
|
|
885
|
-
case "optional":
|
|
886
|
-
case "nonoptional":
|
|
887
|
-
case "nullable":
|
|
888
|
-
case "readonly":
|
|
889
|
-
return isTransforming(def.innerType, ctx);
|
|
890
|
-
case "lazy":
|
|
891
|
-
return isTransforming(def.getter(), ctx);
|
|
892
|
-
case "default": {
|
|
893
|
-
return isTransforming(def.innerType, ctx);
|
|
894
|
-
}
|
|
895
|
-
case "prefault": {
|
|
896
|
-
return isTransforming(def.innerType, ctx);
|
|
864
|
+
return false;
|
|
865
|
+
}
|
|
866
|
+
if (def.type === "union") {
|
|
867
|
+
for (const option of def.options) {
|
|
868
|
+
if (isTransforming(option, ctx))
|
|
869
|
+
return true;
|
|
897
870
|
}
|
|
898
|
-
|
|
899
|
-
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
873
|
+
if (def.type === "tuple") {
|
|
874
|
+
for (const item of def.items) {
|
|
875
|
+
if (isTransforming(item, ctx))
|
|
876
|
+
return true;
|
|
900
877
|
}
|
|
901
|
-
|
|
878
|
+
if (def.rest && isTransforming(def.rest, ctx))
|
|
902
879
|
return true;
|
|
903
|
-
|
|
904
|
-
case "pipe": {
|
|
905
|
-
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
|
906
|
-
}
|
|
907
|
-
case "success": {
|
|
908
|
-
return false;
|
|
909
|
-
}
|
|
910
|
-
case "catch": {
|
|
911
|
-
return false;
|
|
912
|
-
}
|
|
913
|
-
case "function": {
|
|
914
|
-
return false;
|
|
915
|
-
}
|
|
916
|
-
default:
|
|
917
|
-
def;
|
|
880
|
+
return false;
|
|
918
881
|
}
|
|
919
|
-
|
|
882
|
+
return false;
|
|
920
883
|
}
|
|
@@ -248,11 +248,19 @@ export class JSONSchemaGenerator {
|
|
|
248
248
|
}
|
|
249
249
|
case "union": {
|
|
250
250
|
const json = _json;
|
|
251
|
+
// Discriminated unions use oneOf (exactly one match) instead of anyOf (one or more matches)
|
|
252
|
+
// because the discriminator field ensures mutual exclusivity between options in JSON Schema
|
|
253
|
+
const isDiscriminated = def.discriminator !== undefined;
|
|
251
254
|
const options = def.options.map((x, i) => this.process(x, {
|
|
252
255
|
...params,
|
|
253
|
-
path: [...params.path, "anyOf", i],
|
|
256
|
+
path: [...params.path, isDiscriminated ? "oneOf" : "anyOf", i],
|
|
254
257
|
}));
|
|
255
|
-
|
|
258
|
+
if (isDiscriminated) {
|
|
259
|
+
json.oneOf = options;
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
json.anyOf = options;
|
|
263
|
+
}
|
|
256
264
|
break;
|
|
257
265
|
}
|
|
258
266
|
case "intersection": {
|
|
@@ -816,100 +824,55 @@ function isTransforming(_schema, _ctx) {
|
|
|
816
824
|
if (ctx.seen.has(_schema))
|
|
817
825
|
return false;
|
|
818
826
|
ctx.seen.add(_schema);
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
}
|
|
850
|
-
case "union": {
|
|
851
|
-
for (const option of def.options) {
|
|
852
|
-
if (isTransforming(option, ctx))
|
|
853
|
-
return true;
|
|
854
|
-
}
|
|
855
|
-
return false;
|
|
856
|
-
}
|
|
857
|
-
case "intersection": {
|
|
858
|
-
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
|
859
|
-
}
|
|
860
|
-
case "tuple": {
|
|
861
|
-
for (const item of def.items) {
|
|
862
|
-
if (isTransforming(item, ctx))
|
|
863
|
-
return true;
|
|
864
|
-
}
|
|
865
|
-
if (def.rest && isTransforming(def.rest, ctx))
|
|
827
|
+
const def = _schema._zod.def;
|
|
828
|
+
if (def.type === "transform")
|
|
829
|
+
return true;
|
|
830
|
+
if (def.type === "array")
|
|
831
|
+
return isTransforming(def.element, ctx);
|
|
832
|
+
if (def.type === "set")
|
|
833
|
+
return isTransforming(def.valueType, ctx);
|
|
834
|
+
if (def.type === "lazy")
|
|
835
|
+
return isTransforming(def.getter(), ctx);
|
|
836
|
+
if (def.type === "promise" ||
|
|
837
|
+
def.type === "optional" ||
|
|
838
|
+
def.type === "nonoptional" ||
|
|
839
|
+
def.type === "nullable" ||
|
|
840
|
+
def.type === "readonly" ||
|
|
841
|
+
def.type === "default" ||
|
|
842
|
+
def.type === "prefault") {
|
|
843
|
+
return isTransforming(def.innerType, ctx);
|
|
844
|
+
}
|
|
845
|
+
if (def.type === "intersection") {
|
|
846
|
+
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
|
847
|
+
}
|
|
848
|
+
if (def.type === "record" || def.type === "map") {
|
|
849
|
+
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
|
850
|
+
}
|
|
851
|
+
if (def.type === "pipe") {
|
|
852
|
+
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
|
853
|
+
}
|
|
854
|
+
if (def.type === "object") {
|
|
855
|
+
for (const key in def.shape) {
|
|
856
|
+
if (isTransforming(def.shape[key], ctx))
|
|
866
857
|
return true;
|
|
867
|
-
return false;
|
|
868
|
-
}
|
|
869
|
-
case "record": {
|
|
870
|
-
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
|
871
858
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
// inner types
|
|
879
|
-
case "promise":
|
|
880
|
-
case "optional":
|
|
881
|
-
case "nonoptional":
|
|
882
|
-
case "nullable":
|
|
883
|
-
case "readonly":
|
|
884
|
-
return isTransforming(def.innerType, ctx);
|
|
885
|
-
case "lazy":
|
|
886
|
-
return isTransforming(def.getter(), ctx);
|
|
887
|
-
case "default": {
|
|
888
|
-
return isTransforming(def.innerType, ctx);
|
|
889
|
-
}
|
|
890
|
-
case "prefault": {
|
|
891
|
-
return isTransforming(def.innerType, ctx);
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
if (def.type === "union") {
|
|
862
|
+
for (const option of def.options) {
|
|
863
|
+
if (isTransforming(option, ctx))
|
|
864
|
+
return true;
|
|
892
865
|
}
|
|
893
|
-
|
|
894
|
-
|
|
866
|
+
return false;
|
|
867
|
+
}
|
|
868
|
+
if (def.type === "tuple") {
|
|
869
|
+
for (const item of def.items) {
|
|
870
|
+
if (isTransforming(item, ctx))
|
|
871
|
+
return true;
|
|
895
872
|
}
|
|
896
|
-
|
|
873
|
+
if (def.rest && isTransforming(def.rest, ctx))
|
|
897
874
|
return true;
|
|
898
|
-
|
|
899
|
-
case "pipe": {
|
|
900
|
-
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
|
901
|
-
}
|
|
902
|
-
case "success": {
|
|
903
|
-
return false;
|
|
904
|
-
}
|
|
905
|
-
case "catch": {
|
|
906
|
-
return false;
|
|
907
|
-
}
|
|
908
|
-
case "function": {
|
|
909
|
-
return false;
|
|
910
|
-
}
|
|
911
|
-
default:
|
|
912
|
-
def;
|
|
875
|
+
return false;
|
|
913
876
|
}
|
|
914
|
-
|
|
877
|
+
return false;
|
|
915
878
|
}
|
package/v4/core/util.cjs
CHANGED
|
@@ -22,6 +22,7 @@ exports.getElementAtPath = getElementAtPath;
|
|
|
22
22
|
exports.promiseAllObject = promiseAllObject;
|
|
23
23
|
exports.randomString = randomString;
|
|
24
24
|
exports.esc = esc;
|
|
25
|
+
exports.slugify = slugify;
|
|
25
26
|
exports.isObject = isObject;
|
|
26
27
|
exports.isPlainObject = isPlainObject;
|
|
27
28
|
exports.shallowClone = shallowClone;
|
|
@@ -190,6 +191,14 @@ function randomString(length = 10) {
|
|
|
190
191
|
function esc(str) {
|
|
191
192
|
return JSON.stringify(str);
|
|
192
193
|
}
|
|
194
|
+
function slugify(input) {
|
|
195
|
+
return input
|
|
196
|
+
.toLowerCase()
|
|
197
|
+
.trim()
|
|
198
|
+
.replace(/[^\w\s-]/g, "")
|
|
199
|
+
.replace(/[\s_-]+/g, "-")
|
|
200
|
+
.replace(/^-+|-+$/g, "");
|
|
201
|
+
}
|
|
193
202
|
exports.captureStackTrace = ("captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => { });
|
|
194
203
|
function isObject(data) {
|
|
195
204
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
@@ -215,6 +224,8 @@ function isPlainObject(o) {
|
|
|
215
224
|
const ctor = o.constructor;
|
|
216
225
|
if (ctor === undefined)
|
|
217
226
|
return true;
|
|
227
|
+
if (typeof ctor !== "function")
|
|
228
|
+
return true;
|
|
218
229
|
// modified prototype
|
|
219
230
|
const prot = ctor.prototype;
|
|
220
231
|
if (isObject(prot) === false)
|
package/v4/core/util.d.cts
CHANGED
|
@@ -133,6 +133,7 @@ export declare function promiseAllObject<T extends object>(promisesObj: T): Prom
|
|
|
133
133
|
}>;
|
|
134
134
|
export declare function randomString(length?: number): string;
|
|
135
135
|
export declare function esc(str: string): string;
|
|
136
|
+
export declare function slugify(input: string): string;
|
|
136
137
|
export declare const captureStackTrace: (targetObject: object, constructorOpt?: Function) => void;
|
|
137
138
|
export declare function isObject(data: any): data is Record<PropertyKey, unknown>;
|
|
138
139
|
export declare const allowsEval: {
|
package/v4/core/util.d.ts
CHANGED
|
@@ -133,6 +133,7 @@ export declare function promiseAllObject<T extends object>(promisesObj: T): Prom
|
|
|
133
133
|
}>;
|
|
134
134
|
export declare function randomString(length?: number): string;
|
|
135
135
|
export declare function esc(str: string): string;
|
|
136
|
+
export declare function slugify(input: string): string;
|
|
136
137
|
export declare const captureStackTrace: (targetObject: object, constructorOpt?: Function) => void;
|
|
137
138
|
export declare function isObject(data: any): data is Record<PropertyKey, unknown>;
|
|
138
139
|
export declare const allowsEval: {
|
package/v4/core/util.js
CHANGED
|
@@ -135,6 +135,14 @@ export function randomString(length = 10) {
|
|
|
135
135
|
export function esc(str) {
|
|
136
136
|
return JSON.stringify(str);
|
|
137
137
|
}
|
|
138
|
+
export function slugify(input) {
|
|
139
|
+
return input
|
|
140
|
+
.toLowerCase()
|
|
141
|
+
.trim()
|
|
142
|
+
.replace(/[^\w\s-]/g, "")
|
|
143
|
+
.replace(/[\s_-]+/g, "-")
|
|
144
|
+
.replace(/^-+|-+$/g, "");
|
|
145
|
+
}
|
|
138
146
|
export const captureStackTrace = ("captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => { });
|
|
139
147
|
export function isObject(data) {
|
|
140
148
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
@@ -160,6 +168,8 @@ export function isPlainObject(o) {
|
|
|
160
168
|
const ctor = o.constructor;
|
|
161
169
|
if (ctor === undefined)
|
|
162
170
|
return true;
|
|
171
|
+
if (typeof ctor !== "function")
|
|
172
|
+
return true;
|
|
163
173
|
// modified prototype
|
|
164
174
|
const prot = ctor.prototype;
|
|
165
175
|
if (isObject(prot) === false)
|
package/v4/core/versions.cjs
CHANGED
package/v4/core/versions.js
CHANGED
package/v4/locales/en.cjs
CHANGED