schema-components 1.21.0 → 1.23.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/README.md +3 -1
- package/dist/core/adapter.d.mts +115 -4
- package/dist/core/adapter.mjs +405 -75
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/constraints.mjs +0 -7
- package/dist/core/cssClasses.d.mts +52 -0
- package/dist/core/cssClasses.mjs +51 -0
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +5 -13
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +30 -2
- package/dist/core/formats.mjs +33 -1
- package/dist/core/idPath.d.mts +54 -0
- package/dist/core/idPath.mjs +66 -0
- package/dist/core/limits.d.mts +2 -0
- package/dist/core/limits.mjs +23 -0
- package/dist/core/merge.d.mts +10 -1
- package/dist/core/merge.mjs +49 -10
- package/dist/core/normalise.d.mts +40 -3
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.d.mts +15 -1
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/openapiConstants.d.mts +67 -0
- package/dist/core/openapiConstants.mjs +90 -0
- package/dist/core/ref.d.mts +2 -2
- package/dist/core/ref.mjs +85 -6
- package/dist/core/refChain.d.mts +70 -0
- package/dist/core/refChain.mjs +44 -0
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/renderer.mjs +0 -2
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/typeInference.d.mts +982 -2
- package/dist/core/types.d.mts +2 -2
- package/dist/core/types.mjs +1 -4
- package/dist/core/unionMatch.d.mts +36 -0
- package/dist/core/unionMatch.mjs +53 -0
- package/dist/core/version.d.mts +1 -1
- package/dist/core/version.mjs +29 -17
- package/dist/core/walkBuilders.d.mts +23 -4
- package/dist/core/walkBuilders.mjs +27 -7
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +123 -47
- package/dist/{diagnostics-CbBPsxSt.d.mts → diagnostics-BS2kaUyE.d.mts} +1 -1
- package/dist/{errors-QEwOtQAA.d.mts → errors-g_MCTQel.d.mts} +10 -16
- package/dist/html/a11y.d.mts +9 -4
- package/dist/html/a11y.mjs +10 -12
- package/dist/html/renderToHtml.d.mts +10 -3
- package/dist/html/renderToHtml.mjs +13 -3
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderToHtmlStream.mjs +12 -1
- package/dist/html/renderers.d.mts +43 -8
- package/dist/html/renderers.mjs +136 -116
- package/dist/html/streamRenderers.d.mts +6 -6
- package/dist/html/streamRenderers.mjs +129 -89
- package/dist/limits-Cw5QZND8.d.mts +29 -0
- package/dist/{normalise-DaSrnr8g.mjs → normalise-DCYp06Sr.mjs} +770 -227
- package/dist/openapi/ApiCallbacks.d.mts +1 -1
- package/dist/openapi/ApiLinks.d.mts +1 -1
- package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
- package/dist/openapi/ApiSecurity.d.mts +1 -1
- package/dist/openapi/ApiSecurity.mjs +16 -2
- package/dist/openapi/components.d.mts +234 -23
- package/dist/openapi/components.mjs +183 -52
- package/dist/openapi/parser.d.mts +9 -8
- package/dist/openapi/parser.mjs +252 -70
- package/dist/openapi/resolve.d.mts +31 -15
- package/dist/openapi/resolve.mjs +260 -40
- package/dist/react/SchemaComponent.d.mts +126 -36
- package/dist/react/SchemaComponent.mjs +95 -57
- package/dist/react/SchemaView.d.mts +30 -10
- package/dist/react/SchemaView.mjs +2 -2
- package/dist/react/a11y.d.mts +21 -0
- package/dist/react/a11y.mjs +24 -0
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headless.mjs +1 -2
- package/dist/react/headlessRenderers.d.mts +9 -11
- package/dist/react/headlessRenderers.mjs +51 -102
- package/dist/{ref-si8ViYun.d.mts → ref-DjLEKa_E.d.mts} +38 -3
- package/dist/{renderer-DI6ZYf7a.d.mts → renderer-CXJ8y0qw.d.mts} +2 -2
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/themes/shadcn.mjs +2 -1
- package/dist/{types-BnxPEElk.d.mts → types-BTB73MB8.d.mts} +35 -14
- package/dist/{version-D-u7aMfy.d.mts → version-BFTVLsdb.d.mts} +7 -1
- package/package.json +1 -3
- package/dist/typeInference-Bxw3NOG1.d.mts +0 -647
package/dist/core/adapter.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getProperty, hasProperty, isObject } from "./guards.mjs";
|
|
2
|
+
import "./limits.mjs";
|
|
2
3
|
import { SchemaNormalisationError } from "./errors.mjs";
|
|
3
|
-
import { emitDiagnostic } from "./diagnostics.mjs";
|
|
4
|
+
import { appendPointer, emitDiagnostic } from "./diagnostics.mjs";
|
|
4
5
|
import { dereference } from "./ref.mjs";
|
|
5
6
|
import { detectOpenApiVersion, inferJsonSchemaDraftWithReason, isSwagger2, matchJsonSchemaDraftUri } from "./version.mjs";
|
|
6
|
-
import { a as
|
|
7
|
+
import { a as normaliseJsonSchema$1, o as normaliseOpenApiSchemas } from "../normalise-DCYp06Sr.mjs";
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
//#region src/core/adapter.ts
|
|
9
10
|
/**
|
|
@@ -18,60 +19,295 @@ import { z } from "zod";
|
|
|
18
19
|
* All narrowing uses type guards — no type assertions.
|
|
19
20
|
*/
|
|
20
21
|
const schemaCache = /* @__PURE__ */ new WeakMap();
|
|
22
|
+
/**
|
|
23
|
+
* Classify the input schema by its structural markers.
|
|
24
|
+
*
|
|
25
|
+
* - `zod4` — has a `_zod` marker (further validation that `_zod.def` is a
|
|
26
|
+
* non-null object happens inside `normaliseZod4`).
|
|
27
|
+
* - `zod3` — has `_def` and no `_zod`. The `typeName` field is no longer
|
|
28
|
+
* required: any `_def` without `_zod` is treated as a probable Zod 3
|
|
29
|
+
* schema. Third-party libraries that expose `_def` without `_zod` are
|
|
30
|
+
* nearly always Zod 3 forks; surfacing the migration message is the
|
|
31
|
+
* correct response.
|
|
32
|
+
* - `openapi` — has `openapi` or `swagger` at the root.
|
|
33
|
+
* - `unsupported-schema-lib` — has `parse` and `safeParse` callables but
|
|
34
|
+
* no `_zod` and no `_def` marker. This catches Standard Schema
|
|
35
|
+
* implementations (valibot, arktype, etc.) that would otherwise flow
|
|
36
|
+
* through as "malformed JSON Schema".
|
|
37
|
+
* - `jsonSchema` — fallback for anything that does not match the above.
|
|
38
|
+
*/
|
|
21
39
|
function detectSchemaKind(input) {
|
|
22
40
|
if (hasProperty(input, "_zod")) return "zod4";
|
|
23
41
|
if (hasProperty(input, "_def") && !hasProperty(input, "_zod")) return "zod3";
|
|
24
42
|
if (hasProperty(input, "openapi") || hasProperty(input, "swagger")) return "openapi";
|
|
43
|
+
if (isLikelyOtherSchemaLib(input)) return "unsupported-schema-lib";
|
|
25
44
|
return "jsonSchema";
|
|
26
45
|
}
|
|
27
46
|
/**
|
|
28
|
-
*
|
|
47
|
+
* Heuristic: a non-Zod object that exposes either a Standard Schema
|
|
48
|
+
* `~standard.validate` entry point (valibot, arktype, and any pure
|
|
49
|
+
* Standard-Schema-conformant library) or both legacy `.parse`/`.safeParse`
|
|
50
|
+
* callables is almost certainly an instance of a competing schema
|
|
51
|
+
* library. schema-components requires Zod 4 throughout — surfacing the
|
|
52
|
+
* unsupported library by name beats letting the input drop through to
|
|
53
|
+
* the JSON Schema branch where it would fail as "malformed JSON Schema"
|
|
54
|
+
* without explanation.
|
|
55
|
+
*
|
|
56
|
+
* Standard Schema detection takes priority: the spec mandates a
|
|
57
|
+
* `~standard` property carrying `{ validate, vendor, version }`. Pure
|
|
58
|
+
* Standard Schema implementations may not expose any `.parse`/`.safeParse`
|
|
59
|
+
* surface (those are a Zod / convenience API, not part of the spec), so
|
|
60
|
+
* the legacy heuristic alone would miss them. See
|
|
61
|
+
* https://standardschema.dev/ for the contract.
|
|
62
|
+
*/
|
|
63
|
+
function isLikelyOtherSchemaLib(input) {
|
|
64
|
+
if (!isObject(input)) return false;
|
|
65
|
+
if (hasProperty(input, "_zod") || hasProperty(input, "_def")) return false;
|
|
66
|
+
if (isObject(input["~standard"])) return true;
|
|
67
|
+
const parse = input.parse;
|
|
68
|
+
const safeParse = input.safeParse;
|
|
69
|
+
return typeof parse === "function" && typeof safeParse === "function";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract the Standard Schema vendor string from a non-Zod input, when
|
|
73
|
+
* present. Returns `undefined` if the input does not advertise itself
|
|
74
|
+
* via the `~standard.vendor` field. Used to enrich the
|
|
75
|
+
* `unsupported-schema` error message with the library name so the
|
|
76
|
+
* consumer knows whether they have valibot, arktype, or another
|
|
77
|
+
* implementation in front of them.
|
|
78
|
+
*/
|
|
79
|
+
function extractStandardSchemaVendor(input) {
|
|
80
|
+
const vendor = getProperty(getProperty(input, "~standard"), "vendor");
|
|
81
|
+
return typeof vendor === "string" && vendor.length > 0 ? vendor : void 0;
|
|
82
|
+
}
|
|
83
|
+
function callToJsonSchema(schema, io = "output") {
|
|
84
|
+
try {
|
|
85
|
+
return z.toJSONSchema(schema, {
|
|
86
|
+
target: "draft-2020-12",
|
|
87
|
+
unrepresentable: "throw",
|
|
88
|
+
cycles: "ref",
|
|
89
|
+
io
|
|
90
|
+
});
|
|
91
|
+
} catch (err) {
|
|
92
|
+
throw classifyZodConversionError(err, schema);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Zod `def.type` tags that have no useful JSON Schema representation but
|
|
97
|
+
* do NOT throw when passed through `z.toJSONSchema`. Each tag is handled
|
|
98
|
+
* by Zod with a processor that silently rewrites the output:
|
|
99
|
+
*
|
|
100
|
+
* - `promise` — `promiseProcessor` unwraps the inner type, dropping the
|
|
101
|
+
* `Promise<...>` wrapper without any error. (`json-schema-processors.ts`,
|
|
102
|
+
* the body of `promiseProcessor` calls `process(def.innerType, ...)`.)
|
|
103
|
+
* schema-components considers this a silent shape mismatch — the input
|
|
104
|
+
* tree advertised a `Promise<T>` and the consumer would render `T`
|
|
105
|
+
* without ever being told the wrapping was lost.
|
|
106
|
+
*
|
|
107
|
+
* Detection happens BEFORE the call to `z.toJSONSchema` so the response is
|
|
108
|
+
* an immediate `SchemaNormalisationError` with `kind:
|
|
109
|
+
* "zod-type-unrepresentable"`, matching the philosophy of
|
|
110
|
+
* `UnrepresentableZodType` in `typeInference.ts` — these types are
|
|
111
|
+
* rejected, not coerced.
|
|
112
|
+
*/
|
|
113
|
+
const PRECONVERSION_UNREPRESENTABLE_TAGS = new Map([["promise", "z.promise(T) cannot be represented in JSON Schema. Zod silently unwraps it to the inner type, which would leave the rendered schema out of sync with the source. Resolve the promise at the data boundary before passing the value to the component."]]);
|
|
114
|
+
/**
|
|
115
|
+
* Pre-conversion screening. Walks the entire Zod schema tree looking for
|
|
116
|
+
* silently-misrendered or caveat-bearing constructs and surfaces each as
|
|
117
|
+
* either a hard rejection (raised as a `SchemaNormalisationError`) or a
|
|
118
|
+
* diagnostic on the configured sink:
|
|
119
|
+
*
|
|
120
|
+
* - `z.promise(T)` at any depth → rejection (see
|
|
121
|
+
* {@link PRECONVERSION_UNREPRESENTABLE_TAGS}). Each nested occurrence
|
|
122
|
+
* first emits a `zod-promise-nested-unwrap` diagnostic so consumers
|
|
123
|
+
* with a sink see every offending location before the throw fires.
|
|
124
|
+
* The root occurrence still throws via the same path so behaviour is
|
|
125
|
+
* uniform regardless of position in the tree.
|
|
126
|
+
* - `z.codec(...)` at the root → `zod-codec-output-only` diagnostic.
|
|
127
|
+
* - `z.codec(...)` nested below the root →
|
|
128
|
+
* `zod-codec-nested-output-only` diagnostic per occurrence.
|
|
129
|
+
* - `z.preprocess(...)` at any depth → `zod-preprocess-output-only`
|
|
130
|
+
* diagnostic per occurrence. Preprocess never throws inside Zod (it
|
|
131
|
+
* silently rewrites to the output side), so the diagnostic is the
|
|
132
|
+
* only consumer-visible signal.
|
|
133
|
+
*
|
|
134
|
+
* Detection is structural — `_zod.def.type` plus `_zod.traits` (where
|
|
135
|
+
* present) — and is depth-capped via {@link MAX_REF_DEPTH} with a
|
|
136
|
+
* `visited` set to defend against cyclic graphs. JSON-pointer fragments
|
|
137
|
+
* are accumulated as the walk descends so diagnostics report the exact
|
|
138
|
+
* subschema location rather than `""`.
|
|
139
|
+
*
|
|
140
|
+
* Design choice: `z.never()` is NOT classified here. The Zod processor
|
|
141
|
+
* for `never` already produces `{ not: {} }`, which the walker
|
|
142
|
+
* understands via its `walkBooleanSchema(false)` branch (`walker.ts`
|
|
143
|
+
* boolean-schema handling). Throwing a `zod-type-unrepresentable` for
|
|
144
|
+
* `never` would break the legitimate "this field cannot hold any value"
|
|
145
|
+
* use case that the walker already supports. Documented for posterity
|
|
146
|
+
* so future passes do not "fix" it.
|
|
147
|
+
*/
|
|
148
|
+
function screenPreConversion(input, diagnostics) {
|
|
149
|
+
let rejection;
|
|
150
|
+
screenPreConversionWalk(input, "", 0, true, /* @__PURE__ */ new Set(), diagnostics, (err) => {
|
|
151
|
+
rejection ??= err;
|
|
152
|
+
});
|
|
153
|
+
if (rejection !== void 0) throw rejection;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Inner recursion for {@link screenPreConversion}. Visits every Zod
|
|
157
|
+
* node reachable from `node`, emitting diagnostics and capturing
|
|
158
|
+
* rejections through `recordRejection`. The walk is targeted: only
|
|
159
|
+
* `_zod.def` is descended into (sibling `_zod.*` members are
|
|
160
|
+
* implementation surface and never carry user schemas — same rule as
|
|
161
|
+
* {@link containsNestedZod3Inner}).
|
|
29
162
|
*
|
|
30
|
-
* The
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
163
|
+
* The `pointer` parameter tracks the JSON Pointer to the current
|
|
164
|
+
* subschema so diagnostics carry an accurate location. The `isRoot`
|
|
165
|
+
* flag distinguishes the entry call from recursive descents so
|
|
166
|
+
* `zod-codec-output-only` (root) and `zod-codec-nested-output-only`
|
|
167
|
+
* (nested) fire from the same code path.
|
|
168
|
+
*/
|
|
169
|
+
function screenPreConversionWalk(node, pointer, depth, isRoot, visited, diagnostics, recordRejection) {
|
|
170
|
+
if (depth >= 64) return;
|
|
171
|
+
if (!isObject(node)) return;
|
|
172
|
+
if (visited.has(node)) return;
|
|
173
|
+
visited.add(node);
|
|
174
|
+
const zod = getProperty(node, "_zod");
|
|
175
|
+
if (!isObject(zod)) return;
|
|
176
|
+
const def = getProperty(zod, "def");
|
|
177
|
+
if (!isObject(def)) return;
|
|
178
|
+
const tag = def.type;
|
|
179
|
+
if (typeof tag === "string") {
|
|
180
|
+
const unrepresentableMessage = PRECONVERSION_UNREPRESENTABLE_TAGS.get(tag);
|
|
181
|
+
if (unrepresentableMessage !== void 0) {
|
|
182
|
+
if (tag === "promise") emitDiagnostic(diagnostics, {
|
|
183
|
+
code: "zod-promise-nested-unwrap",
|
|
184
|
+
message: `z.promise(...) detected at ${formatPointer(pointer)}. Zod silently unwraps it to the inner type, which would leave the rendered schema out of sync with the source. Resolve the promise at the data boundary before passing the value to the component.`,
|
|
185
|
+
pointer,
|
|
186
|
+
detail: { zodType: "promise" }
|
|
187
|
+
});
|
|
188
|
+
recordRejection(new SchemaNormalisationError(unrepresentableMessage, node, "zod-type-unrepresentable", tag));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (tag === "pipe" && hasTrait(zod, "$ZodCodec")) if (isRoot) emitDiagnostic(diagnostics, {
|
|
192
|
+
code: "zod-codec-output-only",
|
|
193
|
+
message: "z.codec(...) was passed at the schema root. Only the OUTPUT side is rendered by schema-components; the input side may differ. If you intend to render the input side instead, restructure the codec so the input type is the rendered shape.",
|
|
194
|
+
pointer,
|
|
195
|
+
detail: { zodType: "codec" }
|
|
196
|
+
});
|
|
197
|
+
else emitDiagnostic(diagnostics, {
|
|
198
|
+
code: "zod-codec-nested-output-only",
|
|
199
|
+
message: `z.codec(...) detected at ${formatPointer(pointer)}. Only the OUTPUT side is rendered by schema-components; the input side is invisible to the converted schema even though safeParse still consumes the input shape.`,
|
|
200
|
+
pointer,
|
|
201
|
+
detail: { zodType: "codec" }
|
|
202
|
+
});
|
|
203
|
+
if (tag === "pipe" && hasTrait(zod, "$ZodPreprocess")) emitDiagnostic(diagnostics, {
|
|
204
|
+
code: "zod-preprocess-output-only",
|
|
205
|
+
message: `z.preprocess(...) detected at ${formatPointer(pointer)}. Zod silently renders the OUTPUT-side schema; the preprocess function and its input shape are invisible to the rendered schema. If you need the input shape, restructure the schema to declare it directly.`,
|
|
206
|
+
pointer,
|
|
207
|
+
detail: { zodType: "preprocess" }
|
|
208
|
+
});
|
|
209
|
+
screenPreConversionDescend(def, pointer, depth + 1, visited, diagnostics, recordRejection);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Descend into the values of a Zod `def` object, visiting every nested
|
|
213
|
+
* Zod schema. `def` shapes are heterogeneous, so we walk recursively
|
|
214
|
+
* through plain objects and arrays until we find a value with a
|
|
215
|
+
* `_zod.def` marker — those nodes are the user-supplied sub-schemas.
|
|
34
216
|
*
|
|
35
|
-
*
|
|
36
|
-
* SchemaNormalisationError so the caller does not have to re-parse error
|
|
37
|
-
* message strings. The classification covers:
|
|
217
|
+
* Pointer accumulation:
|
|
38
218
|
*
|
|
39
|
-
* -
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* -
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* compile-time guard.)
|
|
50
|
-
* - Dynamic catch values whose handler throws → zod-type-unrepresentable
|
|
51
|
-
* with zodType "dynamic-catch".
|
|
52
|
-
* - Unrepresentable types — bigint, date, map, set, symbol, function, custom,
|
|
53
|
-
* undefined, void, NaN, and the literal-only forms `z.literal(undefined)`
|
|
54
|
-
* ("undefined-literal") and `z.literal(<bigint>)` ("bigint-literal") →
|
|
55
|
-
* zod-type-unrepresentable.
|
|
56
|
-
* - The catch-all "Non-representable type encountered: <type>" fallback Zod
|
|
57
|
-
* emits for any new schema kind without a registered processor →
|
|
58
|
-
* zod-type-unrepresentable with zodType set to the offending def.type.
|
|
59
|
-
* - Cycle detected (`cycles: "throw"`) → zod-cycle-detected.
|
|
60
|
-
* - Duplicate schema id → zod-duplicate-id.
|
|
61
|
-
* - "Unprocessed schema. This is a bug in Zod." → zod-conversion-bug.
|
|
62
|
-
* - "Error converting schema to JSON." → zod-conversion-failed (explicit
|
|
63
|
-
* classification rather than the generic fallback so the contract test
|
|
64
|
-
* protects the prefix from drift).
|
|
65
|
-
* - Anything else → zod-conversion-failed.
|
|
219
|
+
* - For `def.shape.<key>` we emit pointers of the form
|
|
220
|
+
* `/properties/<key>`, matching the JSON Schema rendering of an
|
|
221
|
+
* object's properties so diagnostics line up with what consumers see
|
|
222
|
+
* in the rendered output.
|
|
223
|
+
* - For `def.items[<i>]` we emit `/items/<i>`.
|
|
224
|
+
* - For `def.options[<i>]` we emit `/anyOf/<i>` so union members line
|
|
225
|
+
* up with their JSON Schema position.
|
|
226
|
+
* - For pipe `def.in` / `def.out` we emit `/in` / `/out`.
|
|
227
|
+
* - Everything else descends without extending the pointer (the
|
|
228
|
+
* diagnostic stays anchored at the parent location).
|
|
66
229
|
*
|
|
67
|
-
* The
|
|
68
|
-
*
|
|
230
|
+
* The pointer scheme is deliberately conservative — it errs on the
|
|
231
|
+
* side of "parent-anchored" when the JSON Schema name for a Zod field
|
|
232
|
+
* is ambiguous, rather than fabricating a synthetic location.
|
|
69
233
|
*/
|
|
70
|
-
function
|
|
234
|
+
function screenPreConversionDescend(def, parentPointer, depth, visited, diagnostics, recordRejection) {
|
|
235
|
+
if (depth >= 64) return;
|
|
236
|
+
const shape = getProperty(def, "shape");
|
|
237
|
+
if (isObject(shape)) {
|
|
238
|
+
const shapeBase = appendPointer(parentPointer, "properties");
|
|
239
|
+
for (const [key, value] of Object.entries(shape)) screenPreConversionWalk(value, appendPointer(shapeBase, key), depth + 1, false, visited, diagnostics, recordRejection);
|
|
240
|
+
}
|
|
241
|
+
const items = getProperty(def, "items");
|
|
242
|
+
if (Array.isArray(items)) {
|
|
243
|
+
const itemsBase = appendPointer(parentPointer, "items");
|
|
244
|
+
items.forEach((item, index) => {
|
|
245
|
+
screenPreConversionWalk(item, appendPointer(itemsBase, String(index)), depth + 1, false, visited, diagnostics, recordRejection);
|
|
246
|
+
});
|
|
247
|
+
} else if (isObject(items)) screenPreConversionWalk(items, appendPointer(parentPointer, "items"), depth + 1, false, visited, diagnostics, recordRejection);
|
|
248
|
+
const options = getProperty(def, "options");
|
|
249
|
+
if (Array.isArray(options)) {
|
|
250
|
+
const optionsBase = appendPointer(parentPointer, "anyOf");
|
|
251
|
+
options.forEach((option, index) => {
|
|
252
|
+
screenPreConversionWalk(option, appendPointer(optionsBase, String(index)), depth + 1, false, visited, diagnostics, recordRejection);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const inSide = getProperty(def, "in");
|
|
256
|
+
if (isObject(inSide)) screenPreConversionWalk(inSide, appendPointer(parentPointer, "in"), depth + 1, false, visited, diagnostics, recordRejection);
|
|
257
|
+
const outSide = getProperty(def, "out");
|
|
258
|
+
if (isObject(outSide)) screenPreConversionWalk(outSide, appendPointer(parentPointer, "out"), depth + 1, false, visited, diagnostics, recordRejection);
|
|
259
|
+
const innerType = getProperty(def, "innerType");
|
|
260
|
+
if (isObject(innerType)) screenPreConversionWalk(innerType, parentPointer, depth + 1, false, visited, diagnostics, recordRejection);
|
|
261
|
+
const valueType = getProperty(def, "valueType");
|
|
262
|
+
if (isObject(valueType)) screenPreConversionWalk(valueType, appendPointer(parentPointer, "additionalProperties"), depth + 1, false, visited, diagnostics, recordRejection);
|
|
263
|
+
const inner = safeCallNoArgs(getProperty(def, "getter"));
|
|
264
|
+
if (isObject(inner)) screenPreConversionWalk(inner, parentPointer, depth + 1, false, visited, diagnostics, recordRejection);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Format an empty pointer as `<root>` so error messages do not contain
|
|
268
|
+
* a stray bare `""`. Non-empty pointers are returned verbatim.
|
|
269
|
+
*/
|
|
270
|
+
function formatPointer(pointer) {
|
|
271
|
+
return pointer === "" ? "<root>" : pointer;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* True when a Zod node's `_zod.traits` set contains the named marker.
|
|
275
|
+
* Returns false when traits is absent or not a Set — Zod always
|
|
276
|
+
* populates it on real schemas, so the missing-Set case is treated as
|
|
277
|
+
* "marker not present".
|
|
278
|
+
*/
|
|
279
|
+
function hasTrait(zod, traitName) {
|
|
280
|
+
const traits = zod.traits;
|
|
281
|
+
if (traits instanceof Set) return traits.has(traitName);
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Type guard narrowing `unknown` to a zero-argument function returning
|
|
286
|
+
* `unknown`. The narrowing is genuinely structural: `typeof === "function"`
|
|
287
|
+
* at runtime is exactly the membership test we want, and Zod has no
|
|
288
|
+
* way to make a getter "have the wrong arity" without breaking its own
|
|
289
|
+
* lazy implementation. Surfacing the narrowing through a guard means
|
|
290
|
+
* the call site can invoke `fn()` without an `as` assertion and the
|
|
291
|
+
* boundary lives in one named, documented location.
|
|
292
|
+
*/
|
|
293
|
+
function isNoArgFunction(value) {
|
|
294
|
+
return typeof value === "function";
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Invoke a value as a zero-argument function safely, returning whatever
|
|
298
|
+
* the function returns or `undefined` if it throws or is not callable.
|
|
299
|
+
* Centralises the lazy-schema getter invocation that both
|
|
300
|
+
* {@link containsNestedZod3Inner} and {@link screenPreConversionDescend}
|
|
301
|
+
* need; the throw is swallowed because the absence of a materialisable
|
|
302
|
+
* inner is not a screening concern — downstream `z.toJSONSchema` will
|
|
303
|
+
* surface any genuine construction failure with its own message.
|
|
304
|
+
*/
|
|
305
|
+
function safeCallNoArgs(candidate) {
|
|
306
|
+
if (!isNoArgFunction(candidate)) return void 0;
|
|
71
307
|
try {
|
|
72
|
-
return
|
|
73
|
-
} catch
|
|
74
|
-
|
|
308
|
+
return candidate();
|
|
309
|
+
} catch {
|
|
310
|
+
return;
|
|
75
311
|
}
|
|
76
312
|
}
|
|
77
313
|
/**
|
|
@@ -106,14 +342,27 @@ function unrepresentableMessage(typeName, fullMessage) {
|
|
|
106
342
|
* test suite asserts no two `prefix` values are prefixes of each other —
|
|
107
343
|
* any future rule that breaks the invariant fails the build.
|
|
108
344
|
*
|
|
109
|
-
* Verbatim sources (kept aligned with `tests/zod-error-wording-contract.unit.test.ts`)
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* - zod/src/v4/core/
|
|
115
|
-
*
|
|
116
|
-
*
|
|
345
|
+
* Verbatim sources (kept aligned with `tests/zod-error-wording-contract.unit.test.ts`).
|
|
346
|
+
* Source files are referenced by message-content anchors rather than line
|
|
347
|
+
* numbers — line numbers drift across Zod patch releases but the message
|
|
348
|
+
* strings themselves are stable and protected by the contract test suite:
|
|
349
|
+
*
|
|
350
|
+
* - `zod/src/v4/core/json-schema-processors.ts` — emits `BigInt cannot be
|
|
351
|
+
* represented`, `Symbols cannot be represented`, `Undefined cannot be
|
|
352
|
+
* represented`, `Void cannot be represented`, `Date cannot be
|
|
353
|
+
* represented`, `Literal \`undefined\` cannot be represented`,
|
|
354
|
+
* `BigInt literals cannot be represented`, `NaN cannot be represented`,
|
|
355
|
+
* `Custom types cannot be represented`, `Function types cannot be
|
|
356
|
+
* represented`, `Transforms cannot be represented`, `Map cannot be
|
|
357
|
+
* represented`, `Set cannot be represented`, `Dynamic catch values are
|
|
358
|
+
* not supported`.
|
|
359
|
+
* - `zod/src/v4/core/to-json-schema.ts` — emits `[toJSONSchema]:
|
|
360
|
+
* Non-representable type encountered: ${def.type}` (the catch-all
|
|
361
|
+
* fallback), `Unprocessed schema. This is a bug in Zod.` (the
|
|
362
|
+
* internal-bug branch), `Duplicate schema id "${id}" detected during
|
|
363
|
+
* JSON Schema conversion.` (the duplicate-id branch), `Cycle detected:
|
|
364
|
+
* ` (the cycle-throw branch), and `Error converting schema to JSON.`
|
|
365
|
+
* (the Standard Schema boundary wrapper).
|
|
117
366
|
*/
|
|
118
367
|
const CLASSIFIER_RULES = [
|
|
119
368
|
{
|
|
@@ -203,8 +452,11 @@ const CLASSIFIER_RULES = [
|
|
|
203
452
|
prefix: "[toJSONSchema]: Non-representable type encountered:",
|
|
204
453
|
kind: "zod-type-unrepresentable",
|
|
205
454
|
build: (match, cause, schema, full) => {
|
|
206
|
-
const trailing = match[1]
|
|
207
|
-
|
|
455
|
+
const trailing = match[1];
|
|
456
|
+
if (trailing === void 0) return describeUnparsableZodWording("Non-representable type prefix matched but no trailing capture", full, schema, cause);
|
|
457
|
+
const trimmed = trailing.trim();
|
|
458
|
+
const firstToken = trimmed.length > 0 ? trimmed.split(/\s+/)[0] : void 0;
|
|
459
|
+
const typeName = firstToken !== void 0 && firstToken.length > 0 ? firstToken : void 0;
|
|
208
460
|
return new SchemaNormalisationError(`Zod encountered a schema kind${typeName !== void 0 ? ` "${typeName}"` : ""} with no JSON Schema processor registered. This usually means Zod added a new schema type that schema-components does not yet support. Original message: ${full}`, schema, "zod-type-unrepresentable", typeName, cause);
|
|
209
461
|
}
|
|
210
462
|
},
|
|
@@ -212,16 +464,22 @@ const CLASSIFIER_RULES = [
|
|
|
212
464
|
prefix: "Cycle detected: ",
|
|
213
465
|
kind: "zod-cycle-detected",
|
|
214
466
|
build: (match, cause, schema, full) => {
|
|
215
|
-
|
|
467
|
+
const trailing = match[1];
|
|
468
|
+
if (trailing === void 0) return describeUnparsableZodWording("Cycle detected prefix matched but no trailing capture", full, schema, cause);
|
|
469
|
+
const path = trailing.split(/\s+/)[0];
|
|
470
|
+
if (path === void 0 || path.length === 0) return describeUnparsableZodWording("Cycle detected message contained no pointer token", full, schema, cause);
|
|
471
|
+
return new SchemaNormalisationError(`Zod detected a cycle in the schema graph at ${path}. schema-components calls z.toJSONSchema with { cycles: "ref" } so legitimate cyclic graphs convert to $ref pairs; this error surfaces only when Zod is unable to break the cycle even under the "ref" policy. Restructure the schema to break the cycle, or use an explicit $ref-based definition. Original message: ${full}`, schema, "zod-cycle-detected", void 0, cause);
|
|
216
472
|
}
|
|
217
473
|
},
|
|
218
474
|
{
|
|
219
475
|
prefix: "Duplicate schema id \"",
|
|
220
476
|
kind: "zod-duplicate-id",
|
|
221
477
|
build: (match, cause, schema, full) => {
|
|
222
|
-
const trailing = match[1]
|
|
478
|
+
const trailing = match[1];
|
|
479
|
+
if (trailing === void 0) return describeUnparsableZodWording("Duplicate schema id prefix matched but no trailing capture", full, schema, cause);
|
|
223
480
|
const closing = trailing.indexOf("\"");
|
|
224
|
-
|
|
481
|
+
if (closing === -1) return describeUnparsableZodWording("Duplicate schema id message had no closing quote", full, schema, cause);
|
|
482
|
+
return new SchemaNormalisationError(`Two different Zod schemas share the same id "${trailing.slice(0, closing)}". JSON Schema requires distinct ids when multiple schemas are bundled together. Give each schema its own .meta({ id: ... }) or remove the duplicate. Original message: ${full}`, schema, "zod-duplicate-id", void 0, cause);
|
|
225
483
|
}
|
|
226
484
|
},
|
|
227
485
|
{
|
|
@@ -244,33 +502,79 @@ const COMPILED_CLASSIFIER_RULES = CLASSIFIER_RULES.map((rule) => ({
|
|
|
244
502
|
pattern: anchored(rule.prefix)
|
|
245
503
|
}));
|
|
246
504
|
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
505
|
+
* Build a structured `zod-conversion-failed` error for the case where a
|
|
506
|
+
* classifier rule's prefix matched but the trailing capture or follow-on
|
|
507
|
+
* parsing could not extract the expected payload (cycle pointer,
|
|
508
|
+
* duplicate id, non-representable type name, ...).
|
|
509
|
+
*
|
|
510
|
+
* This replaces the previous pattern of substituting an empty string
|
|
511
|
+
* fallback — `match[1] ?? ""` would silently produce error messages like
|
|
512
|
+
* `"Zod detected a cycle in the schema graph at ."` whenever Zod's
|
|
513
|
+
* wording drifted, hiding the regression behind a misleading message.
|
|
514
|
+
* Raising a wording-regression error instead surfaces the drift loudly
|
|
515
|
+
* so the classifier rule (and its contract test) can be repaired.
|
|
516
|
+
*/
|
|
517
|
+
function describeUnparsableZodWording(reason, fullMessage, schema, cause) {
|
|
518
|
+
return new SchemaNormalisationError(`Zod error matched a classifier prefix but the trailing message could not be parsed (${reason}). This usually means Zod has reworded the error since the classifier was last updated — the matching rule in adapter.ts CLASSIFIER_RULES needs to be revised to track the new wording. Original message: ${fullMessage}`, schema, "zod-conversion-failed", void 0, cause);
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Maximum recursion depth for {@link containsNestedZod3}. Reuses the
|
|
522
|
+
* shared {@link MAX_REF_DEPTH} so the runtime walk and the compile-time
|
|
523
|
+
* `DEFAULT_MAX_DEPTH` (type-aliased to the same value) stay in lockstep.
|
|
524
|
+
*/
|
|
525
|
+
/**
|
|
526
|
+
* Walk an arbitrary value looking for Zod 3 markers (`_def` without
|
|
527
|
+
* `_zod`). Zod 4 schemas always carry `_zod.def`; Zod 3 schemas carry
|
|
528
|
+
* `_def` (with or without a `typeName` field — third-party Zod-3-style
|
|
529
|
+
* libraries occasionally omit `typeName`). Presence of `_def` without
|
|
530
|
+
* `_zod` anywhere in the tree means a Zod 3 (or Zod-3-like) schema was
|
|
531
|
+
* nested inside a Zod 4 input, which is what trips the V8
|
|
532
|
+
* `"Cannot read properties of undefined"` failure.
|
|
252
533
|
*
|
|
253
534
|
* Engine-agnostic by construction — the detector inspects schema shape
|
|
254
535
|
* instead of pattern-matching against the runtime's TypeError message,
|
|
255
536
|
* so it works equivalently under V8, JavaScriptCore (Bun/Safari), and
|
|
256
537
|
* SpiderMonkey (Firefox) — none of which agree on the wording.
|
|
257
538
|
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
539
|
+
* Performance shortcuts:
|
|
540
|
+
*
|
|
541
|
+
* - **Targeted descent into Zod 4 nodes.** Once a node is identified as a
|
|
542
|
+
* Zod 4 schema (`_zod.def` is an object), the only branch that can
|
|
543
|
+
* carry user-supplied sub-schemas is `_zod.def` itself. Zod's other
|
|
544
|
+
* internal members (`_zod.traits`, `_zod.parse`, `_zod.bag`, etc.) are
|
|
545
|
+
* implementation surface and never contain user schemas, so walking
|
|
546
|
+
* them on every conversion failure is wasted work. Switching to a
|
|
547
|
+
* targeted descent (only `_zod.def` plus the schema root's `_def`
|
|
548
|
+
* field) trims the walk dramatically.
|
|
549
|
+
* - **Depth cap.** Recursion is bounded by {@link MAX_REF_DEPTH}
|
|
550
|
+
* so a pathological schema graph cannot cause stack overflow. The
|
|
551
|
+
* `visited` set still defends against cyclic references; the depth
|
|
552
|
+
* cap defends against deep-but-acyclic trees.
|
|
261
553
|
*/
|
|
262
554
|
function containsNestedZod3(value, visited) {
|
|
555
|
+
return containsNestedZod3Inner(value, visited, 0);
|
|
556
|
+
}
|
|
557
|
+
function containsNestedZod3Inner(value, visited, depth) {
|
|
558
|
+
if (depth >= 64) return false;
|
|
263
559
|
if (value === null || typeof value !== "object") return false;
|
|
264
560
|
if (visited.has(value)) return false;
|
|
265
561
|
visited.add(value);
|
|
266
562
|
if (Array.isArray(value)) {
|
|
267
|
-
for (const item of value) if (
|
|
563
|
+
for (const item of value) if (containsNestedZod3Inner(item, visited, depth + 1)) return true;
|
|
268
564
|
return false;
|
|
269
565
|
}
|
|
270
566
|
if (!isObject(value)) return false;
|
|
271
567
|
const def = value._def;
|
|
272
|
-
|
|
273
|
-
|
|
568
|
+
const zod = value._zod;
|
|
569
|
+
if (zod === void 0 && isObject(def)) return true;
|
|
570
|
+
if (isObject(zod) && isObject(zod.def)) {
|
|
571
|
+
const def4 = zod.def;
|
|
572
|
+
if (def4.type === "lazy") {
|
|
573
|
+
if (containsNestedZod3Inner(safeCallNoArgs(def4.getter), visited, depth + 1)) return true;
|
|
574
|
+
}
|
|
575
|
+
return containsNestedZod3Inner(def4, visited, depth + 1);
|
|
576
|
+
}
|
|
577
|
+
for (const key of Object.keys(value)) if (containsNestedZod3Inner(value[key], visited, depth + 1)) return true;
|
|
274
578
|
return false;
|
|
275
579
|
}
|
|
276
580
|
function classifyZodConversionError(err, schema) {
|
|
@@ -288,7 +592,9 @@ function classifyZodConversionError(err, schema) {
|
|
|
288
592
|
*/
|
|
289
593
|
const __CLASSIFIER_RULES_FOR_TEST = CLASSIFIER_RULES;
|
|
290
594
|
function normaliseSchema(input, ref, options) {
|
|
291
|
-
|
|
595
|
+
const usesDiagnostics = options?.diagnostics !== void 0;
|
|
596
|
+
const cacheEligible = ref === void 0 && isObject(input) && !usesDiagnostics;
|
|
597
|
+
if (cacheEligible) {
|
|
292
598
|
const cached = schemaCache.get(input);
|
|
293
599
|
if (cached !== void 0) return cached;
|
|
294
600
|
}
|
|
@@ -296,11 +602,15 @@ function normaliseSchema(input, ref, options) {
|
|
|
296
602
|
let result;
|
|
297
603
|
switch (kind) {
|
|
298
604
|
case "zod4":
|
|
299
|
-
result = normaliseZod4(input);
|
|
605
|
+
result = normaliseZod4(input, options?.diagnostics);
|
|
300
606
|
break;
|
|
301
607
|
case "zod3":
|
|
302
608
|
result = normaliseZod3(input);
|
|
303
609
|
break;
|
|
610
|
+
case "unsupported-schema-lib": {
|
|
611
|
+
const vendor = extractStandardSchemaVendor(input);
|
|
612
|
+
throw new SchemaNormalisationError(`Input looks like a schema from a non-Zod library — ${vendor !== void 0 ? `it self-identifies as the Standard Schema implementation "${vendor}"` : "it exposes `parse` and `safeParse` but carries no Zod 4 (`_zod`) or Zod 3 (`_def`) marker"}. schema-components requires a Zod 4 schema. Convert the schema with the equivalent Zod 4 builder, or feed schema-components a JSON Schema / OpenAPI document instead. See the Zod 4 contract at https://zod.dev/v4 or run: pnpm add zod@^4`, input, "unsupported-schema");
|
|
613
|
+
}
|
|
304
614
|
case "openapi":
|
|
305
615
|
if (!isObject(input)) throw new SchemaNormalisationError("Invalid OpenAPI document", input, "openapi-invalid");
|
|
306
616
|
result = normaliseOpenApi(input, ref, options);
|
|
@@ -310,13 +620,14 @@ function normaliseSchema(input, ref, options) {
|
|
|
310
620
|
result = normaliseJsonSchema(input, options?.diagnostics);
|
|
311
621
|
break;
|
|
312
622
|
}
|
|
313
|
-
if (
|
|
623
|
+
if (cacheEligible) schemaCache.set(input, result);
|
|
314
624
|
return result;
|
|
315
625
|
}
|
|
316
|
-
function normaliseZod4(input) {
|
|
626
|
+
function normaliseZod4(input, diagnostics) {
|
|
317
627
|
const zod = getProperty(input, "_zod");
|
|
318
|
-
if (!isObject(zod)) throw new SchemaNormalisationError("
|
|
319
|
-
if (!("def"
|
|
628
|
+
if (!isObject(zod)) throw new SchemaNormalisationError("Input is not a valid Zod 4 schema: `_zod` is present but is not an object. schema-components expected a Zod 4 schema produced by the `zod` package version 4 or later. See the Zod 4 migration guide at https://zod.dev/v4/migration or run: pnpm add zod@^4", input, "unsupported-schema");
|
|
629
|
+
if (!isObject(getProperty(zod, "def"))) throw new SchemaNormalisationError("Input is not a valid Zod 4 schema: `_zod.def` is missing or not an object. schema-components expected a Zod 4 schema produced by the `zod` package version 4 or later. See the Zod 4 migration guide at https://zod.dev/v4/migration or run: pnpm add zod@^4", input, "unsupported-schema");
|
|
630
|
+
screenPreConversion(input, diagnostics);
|
|
320
631
|
const jsonSchema = callToJsonSchema(input);
|
|
321
632
|
if (!isObject(jsonSchema)) throw new SchemaNormalisationError("z.toJSONSchema() did not produce an object", input, "invalid-zod");
|
|
322
633
|
return {
|
|
@@ -436,10 +747,27 @@ function resolveOpenApiRef(doc, ref) {
|
|
|
436
747
|
}
|
|
437
748
|
if (ref.startsWith("#/")) {
|
|
438
749
|
const resolved = dereference(ref, doc);
|
|
439
|
-
if (resolved !== void 0) return resolved;
|
|
750
|
+
if (resolved !== void 0 && typeof resolved !== "boolean") return resolved;
|
|
440
751
|
}
|
|
441
752
|
throw new Error(`Unsupported OpenAPI ref format: ${ref}`);
|
|
442
753
|
}
|
|
754
|
+
/**
|
|
755
|
+
* Surface root-level metadata from the JSON Schema into the `rootMeta`
|
|
756
|
+
* shape consumed by the walker. Pulls `readOnly`, `writeOnly`,
|
|
757
|
+
* `description`, `title`, `deprecated`, `examples`, and `default`
|
|
758
|
+
* directly from the schema root.
|
|
759
|
+
*
|
|
760
|
+
* `examples` is forwarded only when present as an array (per JSON Schema
|
|
761
|
+
* Draft 2020-12 — Draft 04's `example` singular is normalised upstream).
|
|
762
|
+
* `default` is forwarded for any value the schema declares (any JSON
|
|
763
|
+
* value, including `null` and `false`); the presence check uses `in`
|
|
764
|
+
* so a literal `false` or `null` default is preserved.
|
|
765
|
+
*
|
|
766
|
+
* `examples` and `default` ride on the `[key: string]: unknown` index
|
|
767
|
+
* signature of {@link SchemaMeta}. They are not declared as named fields
|
|
768
|
+
* on `SchemaMeta` because that type lives in `types.ts` and is shared
|
|
769
|
+
* with the walker; the index signature is the agreed extension point.
|
|
770
|
+
*/
|
|
443
771
|
function extractRootMetaFromJson(jsonSchema) {
|
|
444
772
|
const meta = {};
|
|
445
773
|
if (jsonSchema.readOnly === true) meta.readOnly = true;
|
|
@@ -447,7 +775,9 @@ function extractRootMetaFromJson(jsonSchema) {
|
|
|
447
775
|
if (typeof jsonSchema.description === "string") meta.description = jsonSchema.description;
|
|
448
776
|
if (typeof jsonSchema.title === "string") meta.title = jsonSchema.title;
|
|
449
777
|
if (typeof jsonSchema.deprecated === "boolean") meta.deprecated = jsonSchema.deprecated;
|
|
778
|
+
if (Array.isArray(jsonSchema.examples)) meta.examples = jsonSchema.examples;
|
|
779
|
+
if ("default" in jsonSchema) meta.default = jsonSchema.default;
|
|
450
780
|
return Object.keys(meta).length > 0 ? meta : void 0;
|
|
451
781
|
}
|
|
452
782
|
//#endregion
|
|
453
|
-
export { __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, normaliseSchema };
|
|
783
|
+
export { __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, extractRootMetaFromJson, normaliseSchema };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as DiagnosticsOptions } from "../diagnostics-
|
|
1
|
+
import { E as StringConstraints, f as FileConstraints, t as ArrayConstraints, x as ObjectConstraints, y as NumberConstraints } from "../types-BTB73MB8.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-BS2kaUyE.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/core/constraints.d.ts
|
|
5
5
|
declare function extractStringConstraints(schema: Record<string, unknown>, diagnostics?: DiagnosticsOptions, pointer?: string): StringConstraints;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { isObject } from "./guards.mjs";
|
|
2
1
|
import { emitDiagnostic } from "./diagnostics.mjs";
|
|
3
2
|
import { FORMAT_PATTERNS } from "./formats.mjs";
|
|
4
3
|
//#region src/core/constraints.ts
|
|
@@ -10,10 +9,6 @@ function getNumber(obj, key) {
|
|
|
10
9
|
const value = obj[key];
|
|
11
10
|
return typeof value === "number" ? value : void 0;
|
|
12
11
|
}
|
|
13
|
-
function getObject(obj, key) {
|
|
14
|
-
const value = obj[key];
|
|
15
|
-
return isObject(value) ? value : void 0;
|
|
16
|
-
}
|
|
17
12
|
function extractStringConstraints(schema, diagnostics, pointer = "") {
|
|
18
13
|
const c = {};
|
|
19
14
|
const minLength = getNumber(schema, "minLength");
|
|
@@ -65,8 +60,6 @@ function extractArrayConstraints(schema) {
|
|
|
65
60
|
if (minContains !== void 0) c.minContains = minContains;
|
|
66
61
|
const maxContains = getNumber(schema, "maxContains");
|
|
67
62
|
if (maxContains !== void 0) c.maxContains = maxContains;
|
|
68
|
-
const unevaluatedItems = getObject(schema, "unevaluatedItems");
|
|
69
|
-
if (unevaluatedItems !== void 0) c.unevaluatedItems = unevaluatedItems;
|
|
70
63
|
return c;
|
|
71
64
|
}
|
|
72
65
|
function extractObjectConstraints(schema) {
|