zod 4.5.3 → 4.6.0
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/compile.cjs +19 -0
- package/index.cjs +19 -0
- package/locales/index.cjs +19 -0
- package/mini/index.cjs +19 -0
- package/package.json +8 -7
- package/src/v3/helpers/errorUtil.ts +1 -1
- package/src/v4/classic/checks.ts +0 -1
- package/src/v4/classic/external.ts +2 -0
- package/src/v4/classic/from-json-schema.ts +248 -25
- package/src/v4/classic/schemas.ts +255 -164
- package/src/v4/classic/tests/assignability.test.ts +59 -9
- package/src/v4/classic/tests/bigint.test.ts +6 -0
- package/src/v4/classic/tests/continuability.test.ts +2 -2
- package/src/v4/classic/tests/cyclic-data.test.ts +316 -0
- package/src/v4/classic/tests/default.test.ts +46 -0
- package/src/v4/classic/tests/enum.test.ts +9 -0
- package/src/v4/classic/tests/error.test.ts +130 -1
- package/src/v4/classic/tests/firstparty.test.ts +4 -0
- package/src/v4/classic/tests/from-json-schema.test.ts +157 -0
- package/src/v4/classic/tests/iban.test.ts +81 -0
- package/src/v4/classic/tests/instance-footprint.test.ts +18 -2
- package/src/v4/classic/tests/instanceof.test.ts +27 -7
- package/src/v4/classic/tests/issue-schema.test.ts +88 -56
- package/src/v4/classic/tests/object.test.ts +56 -0
- package/src/v4/classic/tests/optin-ladder.test.ts +3 -2
- package/src/v4/classic/tests/properties.test.ts +225 -0
- package/src/v4/classic/tests/recursive-types.test.ts +1 -1
- package/src/v4/classic/tests/standard-schema.test.ts +19 -0
- package/src/v4/classic/tests/string.test.ts +25 -0
- package/src/v4/classic/tests/template-literal.test.ts +33 -1
- package/src/v4/classic/tests/to-json-schema.test.ts +147 -3
- package/src/v4/classic/tests/validate.test.ts +569 -0
- package/src/v4/core/api.ts +30 -6
- package/src/v4/core/checks.ts +1 -101
- package/src/v4/core/compile.ts +193 -81
- package/src/v4/core/doc.ts +6 -2
- package/src/v4/core/errors.ts +3 -6
- package/src/v4/core/json-schema-generator.ts +2 -2
- package/src/v4/core/json-schema-processors.ts +226 -68
- package/src/v4/core/memoizer.ts +162 -36
- package/src/v4/core/parse.ts +37 -16
- package/src/v4/core/regexes.ts +10 -4
- package/src/v4/core/schemas.ts +314 -83
- package/src/v4/core/tests/cached.test.ts +54 -0
- package/src/v4/core/tests/compile-generative.test.ts +445 -0
- package/src/v4/core/tests/compile.test.ts +222 -2
- package/src/v4/core/tests/email-regex.test.ts +140 -0
- package/src/v4/core/tests/polyfill-collision.test.ts +46 -0
- package/src/v4/core/to-json-schema.ts +10 -8
- package/src/v4/core/util.ts +222 -147
- package/src/v4/core/versions.ts +2 -2
- package/src/v4/core/visit.ts +11 -0
- package/src/v4/locales/ar.ts +1 -0
- package/src/v4/locales/az.ts +1 -0
- package/src/v4/locales/be.ts +1 -0
- package/src/v4/locales/bg.ts +1 -0
- package/src/v4/locales/bn.ts +1 -0
- package/src/v4/locales/ca.ts +1 -0
- package/src/v4/locales/ckb.ts +1 -0
- package/src/v4/locales/cs.ts +1 -0
- package/src/v4/locales/da.ts +1 -0
- package/src/v4/locales/de.ts +1 -0
- package/src/v4/locales/el.ts +1 -0
- package/src/v4/locales/en.ts +1 -0
- package/src/v4/locales/eo.ts +1 -0
- package/src/v4/locales/es.ts +1 -0
- package/src/v4/locales/fa.ts +1 -0
- package/src/v4/locales/fi.ts +1 -0
- package/src/v4/locales/fr-CA.ts +1 -0
- package/src/v4/locales/fr.ts +1 -0
- package/src/v4/locales/gu.ts +1 -0
- package/src/v4/locales/he.ts +1 -0
- package/src/v4/locales/hi.ts +1 -0
- package/src/v4/locales/hr.ts +1 -0
- package/src/v4/locales/hu.ts +1 -0
- package/src/v4/locales/hy.ts +1 -0
- package/src/v4/locales/id.ts +1 -0
- package/src/v4/locales/is.ts +1 -0
- package/src/v4/locales/it.ts +1 -0
- package/src/v4/locales/ja.ts +1 -0
- package/src/v4/locales/ka.ts +1 -0
- package/src/v4/locales/km.ts +1 -0
- package/src/v4/locales/kn.ts +1 -0
- package/src/v4/locales/ko.ts +1 -0
- package/src/v4/locales/lt.ts +1 -0
- package/src/v4/locales/mk.ts +1 -0
- package/src/v4/locales/ms.ts +1 -0
- package/src/v4/locales/ne.ts +1 -0
- package/src/v4/locales/nl.ts +1 -0
- package/src/v4/locales/nn.ts +1 -0
- package/src/v4/locales/no.ts +1 -0
- package/src/v4/locales/ota.ts +1 -0
- package/src/v4/locales/pl.ts +1 -0
- package/src/v4/locales/ps.ts +1 -0
- package/src/v4/locales/pt-BR.ts +1 -0
- package/src/v4/locales/pt.ts +1 -0
- package/src/v4/locales/ro.ts +1 -0
- package/src/v4/locales/ru.ts +1 -0
- package/src/v4/locales/sk.ts +1 -0
- package/src/v4/locales/sl.ts +1 -0
- package/src/v4/locales/sv.ts +1 -0
- package/src/v4/locales/ta.ts +1 -0
- package/src/v4/locales/th.ts +1 -0
- package/src/v4/locales/tk.ts +1 -0
- package/src/v4/locales/tr.ts +1 -0
- package/src/v4/locales/uk.ts +1 -0
- package/src/v4/locales/ur.ts +1 -0
- package/src/v4/locales/uz.ts +1 -0
- package/src/v4/locales/vi.ts +1 -0
- package/src/v4/locales/yo.ts +1 -0
- package/src/v4/locales/zh-CN.ts +1 -0
- package/src/v4/locales/zh-TW.ts +1 -0
- package/src/v4/mini/checks.ts +0 -1
- package/src/v4/mini/external.ts +2 -0
- package/src/v4/mini/schemas.ts +38 -2
- package/src/v4/mini/tests/checks.test.ts +1 -1
- package/src/v4/mini/tests/computed.test.ts +11 -17
- package/src/v4/mini/tests/index.test.ts +8 -0
- package/src/v4/mini/tests/string.test.ts +16 -0
- package/v3/ZodError.cjs +19 -0
- package/v3/errors.cjs +19 -0
- package/v3/external.cjs +19 -0
- package/v3/helpers/enumUtil.cjs +19 -0
- package/v3/helpers/errorUtil.cjs +20 -1
- package/v3/helpers/errorUtil.js +1 -1
- package/v3/helpers/parseUtil.cjs +19 -0
- package/v3/helpers/partialUtil.cjs +19 -0
- package/v3/helpers/typeAliases.cjs +19 -0
- package/v3/helpers/util.cjs +19 -0
- package/v3/index.cjs +19 -0
- package/v3/standard-schema.cjs +19 -0
- package/v3/types.cjs +19 -0
- package/v4/classic/checks.cjs +20 -2
- 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/coerce.cjs +19 -0
- package/v4/classic/compat.cjs +19 -0
- package/v4/classic/deep-partial.cjs +19 -0
- package/v4/classic/errors.cjs +19 -0
- package/v4/classic/external.cjs +22 -1
- package/v4/classic/external.d.cts +1 -1
- package/v4/classic/external.d.ts +1 -1
- package/v4/classic/external.js +1 -1
- package/v4/classic/from-json-schema.cjs +264 -24
- package/v4/classic/from-json-schema.js +245 -24
- package/v4/classic/in-out.cjs +19 -0
- package/v4/classic/index.cjs +19 -0
- package/v4/classic/iso.cjs +19 -0
- package/v4/classic/parse.cjs +19 -0
- package/v4/classic/schemas.cjs +100 -31
- package/v4/classic/schemas.d.cts +17 -1
- package/v4/classic/schemas.d.ts +17 -1
- package/v4/classic/schemas.js +77 -29
- package/v4/core/api.cjs +37 -2
- package/v4/core/api.d.cts +6 -4
- package/v4/core/api.d.ts +6 -4
- package/v4/core/api.js +17 -2
- package/v4/core/checks.cjs +19 -96
- package/v4/core/checks.d.cts +1 -1
- package/v4/core/checks.d.ts +1 -1
- package/v4/core/checks.js +0 -96
- package/v4/core/compile.cjs +164 -65
- package/v4/core/compile.d.cts +18 -4
- package/v4/core/compile.d.ts +18 -4
- package/v4/core/compile.js +145 -66
- package/v4/core/core.cjs +19 -0
- package/v4/core/doc.cjs +26 -2
- package/v4/core/doc.js +7 -2
- package/v4/core/errors.cjs +21 -5
- package/v4/core/errors.js +2 -5
- package/v4/core/index.cjs +19 -0
- package/v4/core/json-schema-generator.cjs +20 -1
- package/v4/core/json-schema-generator.js +2 -2
- package/v4/core/json-schema-processors.cjs +215 -63
- package/v4/core/json-schema-processors.d.cts +17 -0
- package/v4/core/json-schema-processors.d.ts +17 -0
- package/v4/core/json-schema-processors.js +195 -64
- package/v4/core/json-schema.cjs +19 -0
- package/v4/core/memoizer.cjs +204 -36
- package/v4/core/memoizer.js +162 -36
- package/v4/core/parse.cjs +56 -16
- package/v4/core/parse.js +37 -16
- package/v4/core/regexes.cjs +29 -6
- package/v4/core/regexes.d.cts +2 -0
- package/v4/core/regexes.d.ts +2 -0
- package/v4/core/regexes.js +8 -4
- package/v4/core/registries.cjs +19 -0
- package/v4/core/schemas.cjs +285 -66
- package/v4/core/schemas.d.cts +34 -3
- package/v4/core/schemas.d.ts +34 -3
- package/v4/core/schemas.js +264 -65
- package/v4/core/standard-schema.cjs +19 -0
- package/v4/core/to-json-schema.cjs +29 -7
- package/v4/core/to-json-schema.d.cts +7 -3
- package/v4/core/to-json-schema.d.ts +7 -3
- package/v4/core/to-json-schema.js +8 -7
- package/v4/core/util.cjs +181 -143
- package/v4/core/util.d.cts +25 -4
- package/v4/core/util.d.ts +25 -4
- package/v4/core/util.js +160 -143
- package/v4/core/versions.cjs +21 -2
- package/v4/core/versions.d.cts +1 -1
- package/v4/core/versions.d.ts +1 -1
- package/v4/core/versions.js +2 -2
- package/v4/core/visit.cjs +31 -0
- package/v4/core/visit.js +12 -0
- package/v4/index.cjs +19 -0
- package/v4/locales/ar.cjs +1 -0
- package/v4/locales/ar.js +1 -0
- package/v4/locales/az.cjs +1 -0
- package/v4/locales/az.js +1 -0
- package/v4/locales/be.cjs +1 -0
- package/v4/locales/be.js +1 -0
- package/v4/locales/bg.cjs +1 -0
- package/v4/locales/bg.js +1 -0
- package/v4/locales/bn.cjs +1 -0
- package/v4/locales/bn.js +1 -0
- package/v4/locales/ca.cjs +1 -0
- package/v4/locales/ca.js +1 -0
- package/v4/locales/ckb.cjs +1 -0
- package/v4/locales/ckb.js +1 -0
- package/v4/locales/cs.cjs +1 -0
- package/v4/locales/cs.js +1 -0
- package/v4/locales/da.cjs +1 -0
- package/v4/locales/da.js +1 -0
- package/v4/locales/de.cjs +1 -0
- package/v4/locales/de.js +1 -0
- package/v4/locales/el.cjs +1 -0
- package/v4/locales/el.js +1 -0
- package/v4/locales/en.cjs +1 -0
- package/v4/locales/en.js +1 -0
- package/v4/locales/eo.cjs +1 -0
- package/v4/locales/eo.js +1 -0
- package/v4/locales/es.cjs +1 -0
- package/v4/locales/es.js +1 -0
- package/v4/locales/fa.cjs +1 -0
- package/v4/locales/fa.js +1 -0
- package/v4/locales/fi.cjs +1 -0
- package/v4/locales/fi.js +1 -0
- package/v4/locales/fr-CA.cjs +1 -0
- package/v4/locales/fr-CA.js +1 -0
- package/v4/locales/fr.cjs +1 -0
- package/v4/locales/fr.js +1 -0
- package/v4/locales/gu.cjs +1 -0
- package/v4/locales/gu.js +1 -0
- package/v4/locales/he.cjs +1 -0
- package/v4/locales/he.js +1 -0
- package/v4/locales/hi.cjs +1 -0
- package/v4/locales/hi.js +1 -0
- package/v4/locales/hr.cjs +1 -0
- package/v4/locales/hr.js +1 -0
- package/v4/locales/hu.cjs +1 -0
- package/v4/locales/hu.js +1 -0
- package/v4/locales/hy.cjs +1 -0
- package/v4/locales/hy.js +1 -0
- package/v4/locales/id.cjs +1 -0
- package/v4/locales/id.js +1 -0
- package/v4/locales/index.cjs +19 -0
- package/v4/locales/is.cjs +1 -0
- package/v4/locales/is.js +1 -0
- package/v4/locales/it.cjs +1 -0
- package/v4/locales/it.js +1 -0
- package/v4/locales/ja.cjs +1 -0
- package/v4/locales/ja.js +1 -0
- package/v4/locales/ka.cjs +1 -0
- package/v4/locales/ka.js +1 -0
- package/v4/locales/km.cjs +1 -0
- package/v4/locales/km.js +1 -0
- package/v4/locales/kn.cjs +1 -0
- package/v4/locales/kn.js +1 -0
- package/v4/locales/ko.cjs +1 -0
- package/v4/locales/ko.js +1 -0
- package/v4/locales/lt.cjs +1 -0
- package/v4/locales/lt.js +1 -0
- package/v4/locales/mk.cjs +1 -0
- package/v4/locales/mk.js +1 -0
- package/v4/locales/ms.cjs +1 -0
- package/v4/locales/ms.js +1 -0
- package/v4/locales/ne.cjs +1 -0
- package/v4/locales/ne.js +1 -0
- package/v4/locales/nl.cjs +1 -0
- package/v4/locales/nl.js +1 -0
- package/v4/locales/nn.cjs +1 -0
- package/v4/locales/nn.js +1 -0
- package/v4/locales/no.cjs +1 -0
- package/v4/locales/no.js +1 -0
- package/v4/locales/ota.cjs +1 -0
- package/v4/locales/ota.js +1 -0
- package/v4/locales/pl.cjs +1 -0
- package/v4/locales/pl.js +1 -0
- package/v4/locales/ps.cjs +1 -0
- package/v4/locales/ps.js +1 -0
- package/v4/locales/pt-BR.cjs +1 -0
- package/v4/locales/pt-BR.js +1 -0
- package/v4/locales/pt.cjs +1 -0
- package/v4/locales/pt.js +1 -0
- package/v4/locales/ro.cjs +1 -0
- package/v4/locales/ro.js +1 -0
- package/v4/locales/ru.cjs +1 -0
- package/v4/locales/ru.js +1 -0
- package/v4/locales/sk.cjs +1 -0
- package/v4/locales/sk.js +1 -0
- package/v4/locales/sl.cjs +1 -0
- package/v4/locales/sl.js +1 -0
- package/v4/locales/sv.cjs +1 -0
- package/v4/locales/sv.js +1 -0
- package/v4/locales/ta.cjs +1 -0
- package/v4/locales/ta.js +1 -0
- package/v4/locales/th.cjs +1 -0
- package/v4/locales/th.js +1 -0
- package/v4/locales/tk.cjs +1 -0
- package/v4/locales/tk.js +1 -0
- package/v4/locales/tr.cjs +1 -0
- package/v4/locales/tr.js +1 -0
- package/v4/locales/uk.cjs +1 -0
- package/v4/locales/uk.js +1 -0
- package/v4/locales/ur.cjs +1 -0
- package/v4/locales/ur.js +1 -0
- package/v4/locales/uz.cjs +1 -0
- package/v4/locales/uz.js +1 -0
- package/v4/locales/vi.cjs +1 -0
- package/v4/locales/vi.js +1 -0
- package/v4/locales/yo.cjs +1 -0
- package/v4/locales/yo.js +1 -0
- package/v4/locales/zh-CN.cjs +1 -0
- package/v4/locales/zh-CN.js +1 -0
- package/v4/locales/zh-TW.cjs +1 -0
- package/v4/locales/zh-TW.js +1 -0
- package/v4/mini/checks.cjs +20 -2
- package/v4/mini/checks.d.cts +1 -1
- package/v4/mini/checks.d.ts +1 -1
- package/v4/mini/checks.js +1 -1
- package/v4/mini/coerce.cjs +19 -0
- package/v4/mini/deep-partial.cjs +19 -0
- package/v4/mini/external.cjs +22 -1
- package/v4/mini/external.d.cts +1 -1
- package/v4/mini/external.d.ts +1 -1
- package/v4/mini/external.js +1 -1
- package/v4/mini/in-out.cjs +19 -0
- package/v4/mini/index.cjs +19 -0
- package/v4/mini/iso.cjs +19 -0
- package/v4/mini/parse.cjs +19 -0
- package/v4/mini/schemas.cjs +42 -4
- package/v4/mini/schemas.d.cts +8 -0
- package/v4/mini/schemas.d.ts +8 -0
- package/v4/mini/schemas.js +19 -2
- package/v4-mini/index.cjs +19 -0
|
@@ -2,6 +2,7 @@ import type * as checks from "./checks.js";
|
|
|
2
2
|
import type * as JSONSchema from "./json-schema.js";
|
|
3
3
|
import * as regexes from "./regexes.js";
|
|
4
4
|
import type { $ZodRegistry } from "./registries.js";
|
|
5
|
+
import { base64Charset, base64urlCharset } from "./schemas.js";
|
|
5
6
|
import type * as schemas from "./schemas.js";
|
|
6
7
|
import {
|
|
7
8
|
type ProcessParams,
|
|
@@ -15,9 +16,116 @@ import {
|
|
|
15
16
|
finalize,
|
|
16
17
|
handleUnrepresentable,
|
|
17
18
|
initializeContext,
|
|
18
|
-
|
|
19
|
+
isTransforming,
|
|
20
|
+
processSchema,
|
|
19
21
|
} from "./to-json-schema.js";
|
|
20
|
-
import { assignProp, getEnumValues } from "./util.js";
|
|
22
|
+
import { BIGINT_FORMAT_RANGES, NUMBER_FORMAT_RANGES, assignProp, getEnumValues } from "./util.js";
|
|
23
|
+
|
|
24
|
+
// ==================== CHECK AGGREGATION ====================
|
|
25
|
+
|
|
26
|
+
// constraint metadata comes from folding `def.checks` here, not from trusting `_zod.bag`: the bag is written by each check's own `onattach` in chain order, which has repeatedly produced order-dependent and lossy values (#6550). runtime checks are a conjunction, so every merge below is the conjunction's — tightest bound wins, patterns union, divisors collect, mime lists intersect
|
|
27
|
+
type Bound = number | bigint | Date;
|
|
28
|
+
|
|
29
|
+
interface CheckAggregate<N extends Bound = Bound> {
|
|
30
|
+
minimum?: N;
|
|
31
|
+
maximum?: N;
|
|
32
|
+
exclusiveMinimum?: N;
|
|
33
|
+
exclusiveMaximum?: N;
|
|
34
|
+
multipleOf?: number[];
|
|
35
|
+
format?: string;
|
|
36
|
+
// ORed across formats: any integer format keeps the conjunction integer, whatever format lands last
|
|
37
|
+
isInt?: boolean;
|
|
38
|
+
patterns?: Set<RegExp>;
|
|
39
|
+
mime?: string[];
|
|
40
|
+
contentEncoding?: string;
|
|
41
|
+
// a datetime that drops the offset or the seconds accepts what `date-time` forbids, so the keyword is withheld
|
|
42
|
+
laxFormat?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const narrowMin = (agg: CheckAggregate, key: "minimum" | "exclusiveMinimum", value: Bound): void => {
|
|
46
|
+
if (agg[key] === undefined || value > agg[key]) agg[key] = value;
|
|
47
|
+
};
|
|
48
|
+
const narrowMax = (agg: CheckAggregate, key: "maximum" | "exclusiveMaximum", value: Bound): void => {
|
|
49
|
+
if (agg[key] === undefined || value < agg[key]) agg[key] = value;
|
|
50
|
+
};
|
|
51
|
+
const narrowBoth = (agg: CheckAggregate, value: number): void => {
|
|
52
|
+
narrowMin(agg, "minimum", value);
|
|
53
|
+
narrowMax(agg, "maximum", value);
|
|
54
|
+
};
|
|
55
|
+
const addDivisor = (agg: CheckAggregate, value: number): void => {
|
|
56
|
+
agg.multipleOf ??= [];
|
|
57
|
+
if (!agg.multipleOf.includes(value)) agg.multipleOf.push(value);
|
|
58
|
+
};
|
|
59
|
+
const addPattern = (agg: CheckAggregate, pattern: RegExp): void => {
|
|
60
|
+
agg.patterns ??= new Set();
|
|
61
|
+
agg.patterns.add(pattern);
|
|
62
|
+
};
|
|
63
|
+
const intersectMime = (agg: CheckAggregate, mime: string[]): void => {
|
|
64
|
+
agg.mime = agg.mime ? agg.mime.filter((m) => mime.includes(m)) : [...mime];
|
|
65
|
+
};
|
|
66
|
+
// last-wins, matching the bag's historical write order; the flag keeps an integer format from being lost to a later float one
|
|
67
|
+
const setFormat = (agg: CheckAggregate, format: string): void => {
|
|
68
|
+
agg.format = format;
|
|
69
|
+
if (format.includes("int")) agg.isInt = true;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
type Contributor = (agg: CheckAggregate, def: any) => void;
|
|
73
|
+
const minContributor: Contributor = (agg, def) => narrowMin(agg, "minimum", def.minimum);
|
|
74
|
+
const maxContributor: Contributor = (agg, def) => narrowMax(agg, "maximum", def.maximum);
|
|
75
|
+
const formatContributor =
|
|
76
|
+
(ranges: Record<string, [Bound, Bound]>): Contributor =>
|
|
77
|
+
(agg, def) => {
|
|
78
|
+
setFormat(agg, def.format);
|
|
79
|
+
const [minimum, maximum] = ranges[def.format]!;
|
|
80
|
+
narrowMin(agg, "minimum", minimum);
|
|
81
|
+
narrowMax(agg, "maximum", maximum);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const contributors: Record<string, Contributor> = {
|
|
85
|
+
greater_than: (agg, def) => narrowMin(agg, def.inclusive ? "minimum" : "exclusiveMinimum", def.value),
|
|
86
|
+
less_than: (agg, def) => narrowMax(agg, def.inclusive ? "maximum" : "exclusiveMaximum", def.value),
|
|
87
|
+
multiple_of: (agg, def) => addDivisor(agg, def.value),
|
|
88
|
+
number_format: formatContributor(NUMBER_FORMAT_RANGES),
|
|
89
|
+
bigint_format: formatContributor(BIGINT_FORMAT_RANGES),
|
|
90
|
+
min_length: minContributor,
|
|
91
|
+
max_length: maxContributor,
|
|
92
|
+
length_equals: (agg, def) => narrowBoth(agg, def.length),
|
|
93
|
+
min_size: minContributor,
|
|
94
|
+
max_size: maxContributor,
|
|
95
|
+
size_equals: (agg, def) => narrowBoth(agg, def.size),
|
|
96
|
+
string_format: (agg, def) => {
|
|
97
|
+
setFormat(agg, def.format);
|
|
98
|
+
if (def.pattern) addPattern(agg, def.pattern);
|
|
99
|
+
if (def.format === "base64" || def.format === "base64url") agg.contentEncoding = def.format;
|
|
100
|
+
if (def.local || def.precision === -1) agg.laxFormat = true;
|
|
101
|
+
},
|
|
102
|
+
mime_type: (agg, def) => intersectMime(agg, def.mime),
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export function aggregateChecks<N extends Bound = Bound>(schema: schemas.$ZodType): CheckAggregate<N> {
|
|
106
|
+
const agg: CheckAggregate = {};
|
|
107
|
+
const def = schema._zod.def;
|
|
108
|
+
// a format schema is its own first check, same rule as $ZodType init
|
|
109
|
+
const list: checks.$ZodCheck[] = schema._zod.traits.has("$ZodCheck")
|
|
110
|
+
? [schema as unknown as checks.$ZodCheck, ...(def.checks ?? [])]
|
|
111
|
+
: (def.checks ?? []);
|
|
112
|
+
for (const ch of list) contributors[ch._zod.def.check]?.(agg, ch._zod.def);
|
|
113
|
+
|
|
114
|
+
// reconcile with the bag so third-party onattach contributions still land; first-party residue is never tighter than the fold, so merging it back is idempotent for one and additive for the other
|
|
115
|
+
const bag = schema._zod.bag as Omit<CheckAggregate, "multipleOf"> & { multipleOf?: number };
|
|
116
|
+
if (bag.minimum !== undefined) narrowMin(agg, "minimum", bag.minimum);
|
|
117
|
+
if (bag.exclusiveMinimum !== undefined) narrowMin(agg, "exclusiveMinimum", bag.exclusiveMinimum);
|
|
118
|
+
if (bag.maximum !== undefined) narrowMax(agg, "maximum", bag.maximum);
|
|
119
|
+
if (bag.exclusiveMaximum !== undefined) narrowMax(agg, "exclusiveMaximum", bag.exclusiveMaximum);
|
|
120
|
+
if (bag.multipleOf !== undefined) addDivisor(agg, bag.multipleOf);
|
|
121
|
+
if (bag.format !== undefined) {
|
|
122
|
+
agg.format ??= bag.format;
|
|
123
|
+
if (bag.format.includes("int")) agg.isInt = true;
|
|
124
|
+
}
|
|
125
|
+
if (bag.mime) intersectMime(agg, bag.mime);
|
|
126
|
+
for (const pattern of bag.patterns ?? []) addPattern(agg, pattern);
|
|
127
|
+
return agg as CheckAggregate<N>;
|
|
128
|
+
}
|
|
21
129
|
|
|
22
130
|
const formatMap: Partial<Record<checks.$ZodStringFormats, string | undefined>> = {
|
|
23
131
|
guid: "uuid",
|
|
@@ -29,11 +137,17 @@ const formatMap: Partial<Record<checks.$ZodStringFormats, string | undefined>> =
|
|
|
29
137
|
|
|
30
138
|
// ==================== SIMPLE TYPE PROCESSORS ====================
|
|
31
139
|
|
|
140
|
+
// the runtime patterns are lax so parse paths never overflow the regex stack; the emitted schema swaps in the exact block forms, which zod itself never executes
|
|
141
|
+
const exactPatterns: Map<RegExp, RegExp> = new Map([
|
|
142
|
+
[base64Charset, regexes.base64],
|
|
143
|
+
[base64urlCharset, regexes.base64url],
|
|
144
|
+
]);
|
|
145
|
+
const exactPattern = (p: RegExp): RegExp => exactPatterns.get(p) ?? p;
|
|
146
|
+
|
|
32
147
|
export const stringProcessor: Processor<schemas.$ZodString> = (schema, ctx, _json, _params) => {
|
|
33
148
|
const json = _json as JSONSchema.StringSchema;
|
|
34
149
|
json.type = "string";
|
|
35
|
-
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = schema
|
|
36
|
-
.bag as schemas.$ZodStringInternals<unknown>["bag"];
|
|
150
|
+
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
|
|
37
151
|
if (typeof minimum === "number") json.minLength = minimum;
|
|
38
152
|
if (typeof maximum === "number") json.maxLength = maximum;
|
|
39
153
|
// custom pattern overrides format
|
|
@@ -48,7 +162,7 @@ export const stringProcessor: Processor<schemas.$ZodString> = (schema, ctx, _jso
|
|
|
48
162
|
}
|
|
49
163
|
if (contentEncoding) json.contentEncoding = contentEncoding;
|
|
50
164
|
if (patterns && patterns.size > 0) {
|
|
51
|
-
const patternList = [...patterns];
|
|
165
|
+
const patternList = [...patterns].map(exactPattern);
|
|
52
166
|
if (patternList.length === 1) json.pattern = patternList[0]!.source;
|
|
53
167
|
else if (patternList.length > 1) {
|
|
54
168
|
json.allOf = [
|
|
@@ -65,9 +179,8 @@ export const stringProcessor: Processor<schemas.$ZodString> = (schema, ctx, _jso
|
|
|
65
179
|
|
|
66
180
|
export const numberProcessor: Processor<schemas.$ZodNumber> = (schema, ctx, _json, params) => {
|
|
67
181
|
const json = _json as JSONSchema.NumberSchema | JSONSchema.IntegerSchema;
|
|
68
|
-
const { minimum, maximum,
|
|
69
|
-
|
|
70
|
-
else json.type = "number";
|
|
182
|
+
const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt } = aggregateChecks<number>(schema);
|
|
183
|
+
json.type = isInt ? "integer" : "number";
|
|
71
184
|
|
|
72
185
|
// when both minimum and exclusiveMinimum exist, pick the more restrictive one
|
|
73
186
|
const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
|
|
@@ -96,17 +209,24 @@ export const numberProcessor: Processor<schemas.$ZodNumber> = (schema, ctx, _jso
|
|
|
96
209
|
json.maximum = maximum;
|
|
97
210
|
}
|
|
98
211
|
|
|
99
|
-
if (
|
|
212
|
+
if (multipleOf) {
|
|
100
213
|
// JSON Schema requires a divisor strictly greater than zero, and a non-finite one does not survive JSON at all. A negative divisor accepts exactly what its absolute value accepts, so it still maps; zero, NaN and Infinity have no keyword form.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
214
|
+
const divisors = new Set<number>();
|
|
215
|
+
for (const divisor of multipleOf) {
|
|
216
|
+
if (Number.isFinite(divisor) && divisor !== 0) divisors.add(Math.abs(divisor));
|
|
217
|
+
else
|
|
218
|
+
handleUnrepresentable(
|
|
219
|
+
schema,
|
|
220
|
+
ctx,
|
|
221
|
+
json,
|
|
222
|
+
params,
|
|
223
|
+
`A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
// chained divisors are a conjunction the keyword cannot carry alone, so extras ride an allOf, same as stacked patterns
|
|
227
|
+
const [first, ...rest] = divisors;
|
|
228
|
+
if (first !== undefined) json.multipleOf = first;
|
|
229
|
+
if (rest.length) json.allOf = [...(json.allOf ?? []), ...rest.map((m) => ({ multipleOf: m }))];
|
|
110
230
|
}
|
|
111
231
|
};
|
|
112
232
|
|
|
@@ -229,26 +349,19 @@ export const templateLiteralProcessor: Processor<schemas.$ZodTemplateLiteral> =
|
|
|
229
349
|
|
|
230
350
|
export const fileProcessor: Processor<schemas.$ZodFile> = (schema, _ctx, json, _params) => {
|
|
231
351
|
const _json = json as JSONSchema.StringSchema;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
contentEncoding: "binary",
|
|
236
|
-
};
|
|
352
|
+
_json.type = "string";
|
|
353
|
+
_json.format = "binary";
|
|
354
|
+
_json.contentEncoding = "binary";
|
|
237
355
|
|
|
238
|
-
const { minimum, maximum, mime } = schema
|
|
239
|
-
if (minimum !== undefined)
|
|
240
|
-
if (maximum !== undefined)
|
|
241
|
-
if (mime)
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
_json.anyOf = mime.map((m) => ({ contentMediaType: m })); // only contentMediaType differs
|
|
248
|
-
}
|
|
249
|
-
} else {
|
|
250
|
-
Object.assign(_json, file);
|
|
251
|
-
}
|
|
356
|
+
const { minimum, maximum, mime } = aggregateChecks<number>(schema);
|
|
357
|
+
if (minimum !== undefined) _json.minLength = minimum;
|
|
358
|
+
if (maximum !== undefined) _json.maxLength = maximum;
|
|
359
|
+
if (!mime) return;
|
|
360
|
+
// an empty intersection means the mime checks share no value, so nothing passes at runtime; `anyOf` must be non-empty, so the false schema is `not: {}`
|
|
361
|
+
if (mime.length === 0) _json.not = {};
|
|
362
|
+
else if (mime.length === 1) _json.contentMediaType = mime[0]!;
|
|
363
|
+
// only contentMediaType differs, so the shared props stay at the root
|
|
364
|
+
else _json.anyOf = mime.map((m) => ({ contentMediaType: m }));
|
|
252
365
|
};
|
|
253
366
|
|
|
254
367
|
export const successProcessor: Processor<schemas.$ZodSuccess> = (_schema, _ctx, json, _params) => {
|
|
@@ -280,12 +393,12 @@ export const setProcessor: Processor<schemas.$ZodSet> = (schema, ctx, json, para
|
|
|
280
393
|
export const arrayProcessor: Processor<schemas.$ZodArray> = (schema, ctx, _json, params) => {
|
|
281
394
|
const json = _json as JSONSchema.ArraySchema;
|
|
282
395
|
const def = schema._zod.def as schemas.$ZodArrayDef;
|
|
283
|
-
const { minimum, maximum } = schema
|
|
396
|
+
const { minimum, maximum } = aggregateChecks(schema);
|
|
284
397
|
if (typeof minimum === "number") json.minItems = minimum;
|
|
285
398
|
if (typeof maximum === "number") json.maxItems = maximum;
|
|
286
399
|
|
|
287
400
|
json.type = "array";
|
|
288
|
-
json.items =
|
|
401
|
+
json.items = processSchema(def.element, ctx as any, {
|
|
289
402
|
...params,
|
|
290
403
|
path: [...params.path, "items"],
|
|
291
404
|
});
|
|
@@ -329,7 +442,7 @@ export const objectProcessor: Processor<schemas.$ZodObject> = (schema, ctx, _jso
|
|
|
329
442
|
assignProp(
|
|
330
443
|
json.properties,
|
|
331
444
|
key,
|
|
332
|
-
|
|
445
|
+
processSchema(shape[key]!, ctx as any, {
|
|
333
446
|
...params,
|
|
334
447
|
path: [...params.path, "properties", key],
|
|
335
448
|
})
|
|
@@ -361,19 +474,67 @@ export const objectProcessor: Processor<schemas.$ZodObject> = (schema, ctx, _jso
|
|
|
361
474
|
// regular
|
|
362
475
|
if (ctx.io === "output") json.additionalProperties = false;
|
|
363
476
|
} else if (def.catchall) {
|
|
364
|
-
json.additionalProperties =
|
|
477
|
+
json.additionalProperties = processSchema(def.catchall, ctx as any, {
|
|
365
478
|
...params,
|
|
366
479
|
path: [...params.path, "additionalProperties"],
|
|
367
480
|
});
|
|
368
481
|
}
|
|
369
482
|
};
|
|
370
483
|
|
|
484
|
+
// asserts named properties in place and passes everything else through, so no additionalProperties constraint is emitted
|
|
485
|
+
export const propertiesProcessor: Processor<schemas.$ZodProperties> = (schema, ctx, _json, params) => {
|
|
486
|
+
const json = _json as JSONSchema.ObjectSchema;
|
|
487
|
+
const def = schema._zod.def;
|
|
488
|
+
|
|
489
|
+
// dropping a symbol key silently would emit a schema that asserts less than this one does
|
|
490
|
+
if (
|
|
491
|
+
Object.getOwnPropertySymbols(def.shape).length &&
|
|
492
|
+
handleUnrepresentable(schema, ctx, json, params, "Symbol keys cannot be represented in JSON Schema")
|
|
493
|
+
) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// the parsed value is the input, so an output-mode emission would describe a transformed value this schema never returns
|
|
498
|
+
if (ctx.io === "output") {
|
|
499
|
+
for (const key in def.shape) {
|
|
500
|
+
if (
|
|
501
|
+
isTransforming(def.shape[key]!) &&
|
|
502
|
+
handleUnrepresentable(
|
|
503
|
+
schema,
|
|
504
|
+
ctx,
|
|
505
|
+
json,
|
|
506
|
+
params,
|
|
507
|
+
`z.properties() returns its input, so the output of a transforming schema at key "${key}" cannot be represented in JSON Schema`
|
|
508
|
+
)
|
|
509
|
+
) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
json.type = "object";
|
|
516
|
+
json.properties = {};
|
|
517
|
+
for (const key in def.shape) {
|
|
518
|
+
assignProp(
|
|
519
|
+
json.properties,
|
|
520
|
+
key,
|
|
521
|
+
processSchema(def.shape[key]!, ctx as any, {
|
|
522
|
+
...params,
|
|
523
|
+
path: [...params.path, "properties", key],
|
|
524
|
+
})
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
// input-side optionality in both modes: the parsed value is the input, so a defaulted key that stays absent must not be required of the output either
|
|
528
|
+
const required = Object.keys(def.shape).filter((key) => inputOptin(def.shape[key]!) === undefined);
|
|
529
|
+
if (required.length > 0) json.required = required;
|
|
530
|
+
};
|
|
531
|
+
|
|
371
532
|
export const unionProcessor: Processor<schemas.$ZodUnion> = (schema, ctx, json, params) => {
|
|
372
533
|
const def = schema._zod.def as schemas.$ZodUnionDef;
|
|
373
534
|
// Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches). This includes both z.xor() and discriminated unions
|
|
374
535
|
const isExclusive = def.inclusive === false;
|
|
375
536
|
const options = def.options.map((x, i) =>
|
|
376
|
-
|
|
537
|
+
processSchema(x, ctx as any, {
|
|
377
538
|
...params,
|
|
378
539
|
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i],
|
|
379
540
|
})
|
|
@@ -387,11 +548,11 @@ export const unionProcessor: Processor<schemas.$ZodUnion> = (schema, ctx, json,
|
|
|
387
548
|
|
|
388
549
|
export const intersectionProcessor: Processor<schemas.$ZodIntersection> = (schema, ctx, json, params) => {
|
|
389
550
|
const def = schema._zod.def as schemas.$ZodIntersectionDef;
|
|
390
|
-
const a =
|
|
551
|
+
const a = processSchema(def.left, ctx as any, {
|
|
391
552
|
...params,
|
|
392
553
|
path: [...params.path, "allOf", 0],
|
|
393
554
|
});
|
|
394
|
-
const b =
|
|
555
|
+
const b = processSchema(def.right, ctx as any, {
|
|
395
556
|
...params,
|
|
396
557
|
path: [...params.path, "allOf", 1],
|
|
397
558
|
});
|
|
@@ -416,13 +577,13 @@ export const tupleProcessor: Processor<schemas.$ZodTuple> = (schema, ctx, _json,
|
|
|
416
577
|
ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
|
|
417
578
|
|
|
418
579
|
const prefixItems = def.items.map((x, i) =>
|
|
419
|
-
|
|
580
|
+
processSchema(x, ctx as any, {
|
|
420
581
|
...params,
|
|
421
582
|
path: [...params.path, prefixPath, i],
|
|
422
583
|
})
|
|
423
584
|
);
|
|
424
585
|
const rest = def.rest
|
|
425
|
-
?
|
|
586
|
+
? processSchema(def.rest, ctx as any, {
|
|
426
587
|
...params,
|
|
427
588
|
path: [...params.path, restPath, ...(ctx.target === "openapi-3.0" ? [def.items.length] : [])],
|
|
428
589
|
})
|
|
@@ -469,10 +630,7 @@ export const tupleProcessor: Processor<schemas.$ZodTuple> = (schema, ctx, _json,
|
|
|
469
630
|
}
|
|
470
631
|
|
|
471
632
|
// explicit user-defined length checks take precedence
|
|
472
|
-
const { minimum, maximum } = schema
|
|
473
|
-
minimum?: number;
|
|
474
|
-
maximum?: number;
|
|
475
|
-
};
|
|
633
|
+
const { minimum, maximum } = aggregateChecks(schema);
|
|
476
634
|
if (typeof minimum === "number") json.minItems = minimum;
|
|
477
635
|
if (typeof maximum === "number") json.maxItems = maximum;
|
|
478
636
|
};
|
|
@@ -563,23 +721,22 @@ export const recordProcessor: Processor<schemas.$ZodRecord> = (schema, ctx, _jso
|
|
|
563
721
|
|
|
564
722
|
// For looseRecord with regex patterns, use patternProperties. This correctly represents "only validate keys matching the pattern" semantics and composes well with allOf (intersections)
|
|
565
723
|
const keyType = def.keyType as schemas.$ZodTypes;
|
|
566
|
-
const
|
|
567
|
-
const patterns = keyBag?.patterns;
|
|
724
|
+
const patterns = aggregateChecks(keyType).patterns;
|
|
568
725
|
|
|
569
726
|
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
570
727
|
// Use patternProperties for looseRecord with regex patterns
|
|
571
|
-
const valueSchema =
|
|
728
|
+
const valueSchema = processSchema(def.valueType, ctx as any, {
|
|
572
729
|
...params,
|
|
573
730
|
path: [...params.path, "patternProperties", "*"],
|
|
574
731
|
});
|
|
575
732
|
json.patternProperties = {};
|
|
576
733
|
for (const pattern of patterns) {
|
|
577
|
-
assignProp(json.patternProperties, pattern.source, valueSchema);
|
|
734
|
+
assignProp(json.patternProperties, exactPattern(pattern).source, valueSchema);
|
|
578
735
|
}
|
|
579
736
|
} else {
|
|
580
737
|
// Default behavior: use propertyNames + additionalProperties
|
|
581
738
|
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
582
|
-
json.propertyNames =
|
|
739
|
+
json.propertyNames = processSchema(def.keyType, ctx as any, {
|
|
583
740
|
...params,
|
|
584
741
|
path: [...params.path, "propertyNames"],
|
|
585
742
|
});
|
|
@@ -591,7 +748,7 @@ export const recordProcessor: Processor<schemas.$ZodRecord> = (schema, ctx, _jso
|
|
|
591
748
|
}
|
|
592
749
|
pending.push(schema);
|
|
593
750
|
}
|
|
594
|
-
json.additionalProperties =
|
|
751
|
+
json.additionalProperties = processSchema(def.valueType, ctx as any, {
|
|
595
752
|
...params,
|
|
596
753
|
path: [...params.path, "additionalProperties"],
|
|
597
754
|
});
|
|
@@ -614,7 +771,7 @@ export const recordProcessor: Processor<schemas.$ZodRecord> = (schema, ctx, _jso
|
|
|
614
771
|
|
|
615
772
|
export const nullableProcessor: Processor<schemas.$ZodNullable> = (schema, ctx, json, params) => {
|
|
616
773
|
const def = schema._zod.def as schemas.$ZodNullableDef;
|
|
617
|
-
const inner =
|
|
774
|
+
const inner = processSchema(def.innerType, ctx as any, params);
|
|
618
775
|
const seen = ctx.seen.get(schema)!;
|
|
619
776
|
if (ctx.target === "openapi-3.0") {
|
|
620
777
|
seen.ref = def.innerType;
|
|
@@ -626,7 +783,7 @@ export const nullableProcessor: Processor<schemas.$ZodNullable> = (schema, ctx,
|
|
|
626
783
|
|
|
627
784
|
export const nonoptionalProcessor: Processor<schemas.$ZodNonOptional> = (schema, ctx, _json, params) => {
|
|
628
785
|
const def = schema._zod.def as schemas.$ZodNonOptionalDef;
|
|
629
|
-
|
|
786
|
+
processSchema(def.innerType, ctx as any, params);
|
|
630
787
|
const seen = ctx.seen.get(schema)!;
|
|
631
788
|
seen.ref = def.innerType;
|
|
632
789
|
};
|
|
@@ -655,7 +812,7 @@ function serializeDefaultValue(
|
|
|
655
812
|
|
|
656
813
|
export const defaultProcessor: Processor<schemas.$ZodDefault> = (schema, ctx, json, params) => {
|
|
657
814
|
const def = schema._zod.def as schemas.$ZodDefaultDef;
|
|
658
|
-
|
|
815
|
+
processSchema(def.innerType, ctx as any, params);
|
|
659
816
|
const seen = ctx.seen.get(schema)!;
|
|
660
817
|
seen.ref = def.innerType;
|
|
661
818
|
const value = serializeDefaultValue(def.defaultValue, schema, ctx as ToJSONSchemaContext, json, params);
|
|
@@ -664,7 +821,7 @@ export const defaultProcessor: Processor<schemas.$ZodDefault> = (schema, ctx, js
|
|
|
664
821
|
|
|
665
822
|
export const prefaultProcessor: Processor<schemas.$ZodPrefault> = (schema, ctx, json, params) => {
|
|
666
823
|
const def = schema._zod.def as schemas.$ZodPrefaultDef;
|
|
667
|
-
|
|
824
|
+
processSchema(def.innerType, ctx as any, params);
|
|
668
825
|
const seen = ctx.seen.get(schema)!;
|
|
669
826
|
seen.ref = def.innerType;
|
|
670
827
|
if (ctx.io !== "input") return;
|
|
@@ -674,7 +831,7 @@ export const prefaultProcessor: Processor<schemas.$ZodPrefault> = (schema, ctx,
|
|
|
674
831
|
|
|
675
832
|
export const catchProcessor: Processor<schemas.$ZodCatch> = (schema, ctx, json, params) => {
|
|
676
833
|
const def = schema._zod.def as schemas.$ZodCatchDef;
|
|
677
|
-
|
|
834
|
+
processSchema(def.innerType, ctx as any, params);
|
|
678
835
|
const seen = ctx.seen.get(schema)!;
|
|
679
836
|
seen.ref = def.innerType;
|
|
680
837
|
let catchValue: any;
|
|
@@ -691,14 +848,14 @@ export const pipeProcessor: Processor<schemas.$ZodPipe> = (schema, ctx, _json, p
|
|
|
691
848
|
const def = schema._zod.def as schemas.$ZodPipeDef;
|
|
692
849
|
const inIsTransform = def.in._zod.traits.has("$ZodTransform");
|
|
693
850
|
const innerType = ctx.io === "input" ? (inIsTransform ? def.out : def.in) : def.out;
|
|
694
|
-
|
|
851
|
+
processSchema(innerType, ctx as any, params);
|
|
695
852
|
const seen = ctx.seen.get(schema)!;
|
|
696
853
|
seen.ref = innerType;
|
|
697
854
|
};
|
|
698
855
|
|
|
699
856
|
export const readonlyProcessor: Processor<schemas.$ZodReadonly> = (schema, ctx, json, params) => {
|
|
700
857
|
const def = schema._zod.def as schemas.$ZodReadonlyDef;
|
|
701
|
-
|
|
858
|
+
processSchema(def.innerType, ctx as any, params);
|
|
702
859
|
const seen = ctx.seen.get(schema)!;
|
|
703
860
|
seen.ref = def.innerType;
|
|
704
861
|
json.readOnly = true;
|
|
@@ -706,21 +863,21 @@ export const readonlyProcessor: Processor<schemas.$ZodReadonly> = (schema, ctx,
|
|
|
706
863
|
|
|
707
864
|
export const promiseProcessor: Processor<schemas.$ZodPromise> = (schema, ctx, _json, params) => {
|
|
708
865
|
const def = schema._zod.def as schemas.$ZodPromiseDef;
|
|
709
|
-
|
|
866
|
+
processSchema(def.innerType, ctx as any, params);
|
|
710
867
|
const seen = ctx.seen.get(schema)!;
|
|
711
868
|
seen.ref = def.innerType;
|
|
712
869
|
};
|
|
713
870
|
|
|
714
871
|
export const optionalProcessor: Processor<schemas.$ZodOptional> = (schema, ctx, _json, params) => {
|
|
715
872
|
const def = schema._zod.def as schemas.$ZodOptionalDef;
|
|
716
|
-
|
|
873
|
+
processSchema(def.innerType, ctx as any, params);
|
|
717
874
|
const seen = ctx.seen.get(schema)!;
|
|
718
875
|
seen.ref = def.innerType;
|
|
719
876
|
};
|
|
720
877
|
|
|
721
878
|
export const lazyProcessor: Processor<schemas.$ZodLazy> = (schema, ctx, _json, params) => {
|
|
722
879
|
const innerType = (schema as schemas.$ZodLazy)._zod.innerType;
|
|
723
|
-
|
|
880
|
+
processSchema(innerType, ctx as any, params);
|
|
724
881
|
const seen = ctx.seen.get(schema)!;
|
|
725
882
|
seen.ref = innerType;
|
|
726
883
|
};
|
|
@@ -747,6 +904,7 @@ export const allProcessors: Record<string, Processor<any>> = {
|
|
|
747
904
|
file: fileProcessor,
|
|
748
905
|
success: successProcessor,
|
|
749
906
|
custom: customProcessor,
|
|
907
|
+
properties: propertiesProcessor,
|
|
750
908
|
function: functionProcessor,
|
|
751
909
|
transform: transformProcessor,
|
|
752
910
|
map: mapProcessor,
|
|
@@ -792,7 +950,7 @@ export function toJSONSchema(
|
|
|
792
950
|
// First pass: process all schemas to build the seen map
|
|
793
951
|
for (const entry of registry._idmap.entries()) {
|
|
794
952
|
const [_, schema] = entry;
|
|
795
|
-
|
|
953
|
+
processSchema(schema, ctx as any);
|
|
796
954
|
}
|
|
797
955
|
|
|
798
956
|
const schemas: Record<string, JSONSchema.BaseSchema> = {};
|
|
@@ -824,7 +982,7 @@ export function toJSONSchema(
|
|
|
824
982
|
|
|
825
983
|
// Single schema case
|
|
826
984
|
const ctx = initializeContext({ ...params, processors: allProcessors });
|
|
827
|
-
|
|
985
|
+
processSchema(input, ctx as any);
|
|
828
986
|
extractDefs(ctx as any, input);
|
|
829
987
|
return finalize(ctx as any, input);
|
|
830
988
|
}
|