schema-components 1.20.0 → 1.22.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 +1 -1
- package/dist/core/adapter.d.mts +28 -4
- package/dist/core/adapter.mjs +408 -71
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/constraints.mjs +0 -2
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +9 -15
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +22 -1
- package/dist/core/formats.mjs +21 -0
- package/dist/core/limits.d.mts +2 -0
- package/dist/core/limits.mjs +23 -0
- package/dist/core/merge.d.mts +11 -2
- package/dist/core/merge.mjs +11 -0
- package/dist/core/normalise.d.mts +36 -4
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.d.mts +24 -1
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/ref.mjs +35 -9
- 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 +2 -2
- package/dist/core/types.d.mts +2 -2
- package/dist/core/types.mjs +1 -4
- package/dist/core/version.d.mts +1 -1
- package/dist/core/walkBuilders.d.mts +13 -5
- package/dist/core/walkBuilders.mjs +11 -3
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +110 -26
- package/dist/{diagnostics-CbBPsxSt.d.mts → diagnostics-D0QCYGv0.d.mts} +1 -1
- package/dist/{errors-C2iABcn9.d.mts → errors-DpFwqs5C.d.mts} +7 -11
- package/dist/html/a11y.d.mts +2 -2
- package/dist/html/a11y.mjs +10 -3
- 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/renderers.d.mts +2 -2
- package/dist/html/renderers.mjs +1 -6
- package/dist/html/streamRenderers.d.mts +5 -4
- package/dist/html/streamRenderers.mjs +91 -30
- package/dist/limits-Cw5QZND8.d.mts +29 -0
- package/dist/{normalise-CMMEl4cd.mjs → normalise-DVEJQmF7.mjs} +791 -141
- 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 +127 -7
- package/dist/openapi/components.d.mts +175 -21
- package/dist/openapi/components.mjs +145 -21
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +74 -7
- package/dist/openapi/resolve.d.mts +70 -12
- package/dist/openapi/resolve.mjs +265 -42
- package/dist/react/SchemaComponent.d.mts +100 -35
- package/dist/react/SchemaComponent.mjs +66 -24
- package/dist/react/SchemaView.d.mts +3 -3
- package/dist/react/SchemaView.mjs +2 -2
- 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 +3 -4
- package/dist/react/headlessRenderers.mjs +11 -31
- package/dist/{ref-C8JbwfiS.d.mts → ref-D-_JBZkF.d.mts} +7 -2
- package/dist/{renderer-SOIbJBtk.d.mts → renderer-BaRlQIuN.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/typeInference-DkcUHfaM.d.mts +982 -0
- package/dist/{types-C9zw9wbX.d.mts → types-BrRMV0en.d.mts} +15 -12
- package/package.json +1 -3
- package/dist/typeInference-CDoD_LZ_.d.mts +0 -533
- /package/dist/{version-D-u7aMfy.d.mts → version-D2jfdX6E.d.mts} +0 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Peer dependencies: `zod@^4.0.0`, `react@^18.0.0 || ^19.0.0`.
|
|
|
16
16
|
|
|
17
17
|
### Zod version requirement
|
|
18
18
|
|
|
19
|
-
schema-components requires **Zod 4**. If you are on Zod 3, see the [Zod 4 migration guide](https://zod.dev/v4/migration).
|
|
19
|
+
schema-components requires **Zod 4**. If you are on Zod 3, see the [Zod 4 migration guide](https://zod.dev/v4/migration). If a Zod 3 schema is passed (detected via `_def.typeName`), a descriptive `SchemaNormalisationError` is raised pointing at the Zod 4 migration guide. Schemas from other Standard Schema libraries are not currently supported.
|
|
20
20
|
|
|
21
21
|
## `SchemaComponent`
|
|
22
22
|
|
package/dist/core/adapter.d.mts
CHANGED
|
@@ -1,10 +1,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as DiagnosticsOptions } from "../diagnostics-
|
|
1
|
+
import { m as JsonObject, w as SchemaMeta } from "../types-BrRMV0en.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/core/adapter.d.ts
|
|
5
5
|
type SchemaInput = Record<string, unknown>;
|
|
6
|
-
type SchemaKind = "zod4" | "zod3" | "jsonSchema" | "openapi";
|
|
6
|
+
type SchemaKind = "zod4" | "zod3" | "jsonSchema" | "openapi" | "unsupported-schema-lib";
|
|
7
|
+
/**
|
|
8
|
+
* Classify the input schema by its structural markers.
|
|
9
|
+
*
|
|
10
|
+
* - `zod4` — has a `_zod` marker (further validation that `_zod.def` is a
|
|
11
|
+
* non-null object happens inside `normaliseZod4`).
|
|
12
|
+
* - `zod3` — has `_def` and no `_zod`. The `typeName` field is no longer
|
|
13
|
+
* required: any `_def` without `_zod` is treated as a probable Zod 3
|
|
14
|
+
* schema. Third-party libraries that expose `_def` without `_zod` are
|
|
15
|
+
* nearly always Zod 3 forks; surfacing the migration message is the
|
|
16
|
+
* correct response.
|
|
17
|
+
* - `openapi` — has `openapi` or `swagger` at the root.
|
|
18
|
+
* - `unsupported-schema-lib` — has `parse` and `safeParse` callables but
|
|
19
|
+
* no `_zod` and no `_def` marker. This catches Standard Schema
|
|
20
|
+
* implementations (valibot, arktype, etc.) that would otherwise flow
|
|
21
|
+
* through as "malformed JSON Schema".
|
|
22
|
+
* - `jsonSchema` — fallback for anything that does not match the above.
|
|
23
|
+
*/
|
|
7
24
|
declare function detectSchemaKind(input: unknown): SchemaKind;
|
|
25
|
+
/**
|
|
26
|
+
* Exposed for unit testing — lets the contract test enumerate every rule's
|
|
27
|
+
* `prefix` value and assert mutual non-prefixing.
|
|
28
|
+
*/
|
|
29
|
+
declare const __CLASSIFIER_RULES_FOR_TEST: readonly {
|
|
30
|
+
readonly prefix: string;
|
|
31
|
+
}[];
|
|
8
32
|
interface NormalisedSchema {
|
|
9
33
|
/** JSON Schema object — the authoritative schema for rendering. */
|
|
10
34
|
jsonSchema: JsonObject;
|
|
@@ -21,4 +45,4 @@ interface NormaliseOptions {
|
|
|
21
45
|
}
|
|
22
46
|
declare function normaliseSchema(input: unknown, ref?: string, options?: NormaliseOptions): NormalisedSchema;
|
|
23
47
|
//#endregion
|
|
24
|
-
export { type JsonObject, NormaliseOptions, NormalisedSchema, SchemaInput, SchemaKind, type SchemaMeta, detectSchemaKind, normaliseSchema };
|
|
48
|
+
export { type JsonObject, NormaliseOptions, NormalisedSchema, SchemaInput, SchemaKind, type SchemaMeta, __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, normaliseSchema };
|
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
4
|
import { 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 normaliseOpenApiSchemas, i as normaliseJsonSchema$1 } from "../normalise-
|
|
7
|
+
import { a as normaliseOpenApiSchemas, i as normaliseJsonSchema$1 } from "../normalise-DVEJQmF7.mjs";
|
|
7
8
|
import { z } from "zod";
|
|
8
9
|
//#region src/core/adapter.ts
|
|
9
10
|
/**
|
|
@@ -18,13 +19,46 @@ 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
|
/**
|
|
47
|
+
* Heuristic: a non-Zod object exposing both `.parse` and `.safeParse` as
|
|
48
|
+
* callables is almost certainly an instance of a competing schema library
|
|
49
|
+
* (Standard Schema, valibot, arktype, etc.). schema-components requires
|
|
50
|
+
* Zod 4 throughout — surfacing the unsupported library by name beats
|
|
51
|
+
* letting the input drop through to the JSON Schema branch where it
|
|
52
|
+
* would fail as "malformed JSON Schema" without explanation.
|
|
53
|
+
*/
|
|
54
|
+
function isLikelyOtherSchemaLib(input) {
|
|
55
|
+
if (!isObject(input)) return false;
|
|
56
|
+
if (hasProperty(input, "_zod") || hasProperty(input, "_def")) return false;
|
|
57
|
+
const parse = input.parse;
|
|
58
|
+
const safeParse = input.safeParse;
|
|
59
|
+
return typeof parse === "function" && typeof safeParse === "function";
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
28
62
|
* Wraps z.toJSONSchema() for a runtime-validated Zod schema.
|
|
29
63
|
*
|
|
30
64
|
* The _zod guard in normaliseZod4 has confirmed this is a valid Zod schema,
|
|
@@ -32,107 +66,388 @@ function detectSchemaKind(input) {
|
|
|
32
66
|
* that z.toJSONSchema expects. This is the library boundary equivalent of
|
|
33
67
|
* object → Record<string, unknown> — the type mismatch is genuinely unavoidable.
|
|
34
68
|
*
|
|
69
|
+
* # Options
|
|
70
|
+
*
|
|
71
|
+
* `z.toJSONSchema` is invoked with an explicit options object rather than
|
|
72
|
+
* Zod's defaults so the conversion contract is pinned and stable:
|
|
73
|
+
*
|
|
74
|
+
* - `target: "draft-2020-12"` — matches the walker's draft target.
|
|
75
|
+
* - `unrepresentable: "throw"` — keeps the unrepresentable-type rules in
|
|
76
|
+
* the classifier table firing instead of silently emitting `{}`.
|
|
77
|
+
* - `cycles: "ref"` — converts cyclic graphs into $ref pairs rather than
|
|
78
|
+
* throwing. Cycles in user schemas surface through the walker's $ref
|
|
79
|
+
* resolution rather than the adapter.
|
|
80
|
+
* - `io: "output"` — convert the OUTPUT side of every transform / pipe /
|
|
81
|
+
* codec. The input side is invisible to the converted schema, even
|
|
82
|
+
* though `safeParse` on the same Zod schema consumes the input shape.
|
|
83
|
+
* For transforms this divergence is fatal and the call throws via
|
|
84
|
+
* `Transforms cannot be represented`; for `z.codec(...)` the call
|
|
85
|
+
* succeeds but only the output side is rendered. Consumers receive a
|
|
86
|
+
* `zod-codec-output-only` diagnostic in the codec case so the
|
|
87
|
+
* asymmetry is visible — see `screenPreConversion`.
|
|
88
|
+
*
|
|
89
|
+
* # Error classification
|
|
90
|
+
*
|
|
35
91
|
* Any exception thrown by z.toJSONSchema is classified into a
|
|
36
92
|
* SchemaNormalisationError so the caller does not have to re-parse error
|
|
37
93
|
* message strings. The classification covers:
|
|
38
94
|
*
|
|
39
|
-
* - Nested Zod 3 schemas inside a Zod 4 tree
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
95
|
+
* - Nested Zod 3 schemas inside a Zod 4 tree → zod3-unsupported.
|
|
96
|
+
* Detected structurally (presence of `_def.typeName` markers anywhere
|
|
97
|
+
* in the schema tree) so the check works across V8, JavaScriptCore,
|
|
98
|
+
* and SpiderMonkey, none of which agree on the wording of
|
|
99
|
+
* "Cannot read properties of undefined".
|
|
100
|
+
* - Transforms → zod-transform-unsupported. This also catches `z.codec(…)`
|
|
101
|
+
* because Zod implements codecs as a pipe + transform internally, so
|
|
102
|
+
* they trip the same processor when round-tripping is forced. (Plain
|
|
103
|
+
* `z.toJSONSchema(codec)` itself does NOT throw because Zod picks one
|
|
104
|
+
* side of the codec; the static rejection in `typeInference.ts` is the
|
|
105
|
+
* compile-time guard.)
|
|
106
|
+
* - Dynamic catch values whose handler throws → zod-type-unrepresentable
|
|
107
|
+
* with zodType "dynamic-catch".
|
|
44
108
|
* - Unrepresentable types — bigint, date, map, set, symbol, function, custom,
|
|
45
109
|
* undefined, void, NaN, and the literal-only forms `z.literal(undefined)`
|
|
46
110
|
* ("undefined-literal") and `z.literal(<bigint>)` ("bigint-literal") →
|
|
47
|
-
* zod-type-unrepresentable
|
|
111
|
+
* zod-type-unrepresentable.
|
|
48
112
|
* - The catch-all "Non-representable type encountered: <type>" fallback Zod
|
|
49
113
|
* emits for any new schema kind without a registered processor →
|
|
50
|
-
* zod-type-unrepresentable with zodType set to the offending def.type
|
|
51
|
-
* -
|
|
114
|
+
* zod-type-unrepresentable with zodType set to the offending def.type.
|
|
115
|
+
* - Cycle detected (`cycles: "throw"`) → zod-cycle-detected.
|
|
116
|
+
* - Duplicate schema id → zod-duplicate-id.
|
|
117
|
+
* - "Unprocessed schema. This is a bug in Zod." → zod-conversion-bug.
|
|
118
|
+
* - "Error converting schema to JSON." → zod-conversion-failed (explicit
|
|
119
|
+
* classification rather than the generic fallback so the contract test
|
|
120
|
+
* protects the prefix from drift).
|
|
121
|
+
* - Anything else → zod-conversion-failed.
|
|
52
122
|
*
|
|
53
123
|
* The original error is preserved on each classified error via the `cause`
|
|
54
124
|
* field so consumers can still inspect the Zod stack trace.
|
|
55
125
|
*/
|
|
56
126
|
function callToJsonSchema(schema) {
|
|
57
127
|
try {
|
|
58
|
-
return z.toJSONSchema(schema
|
|
128
|
+
return z.toJSONSchema(schema, {
|
|
129
|
+
target: "draft-2020-12",
|
|
130
|
+
unrepresentable: "throw",
|
|
131
|
+
cycles: "ref",
|
|
132
|
+
io: "output"
|
|
133
|
+
});
|
|
59
134
|
} catch (err) {
|
|
60
135
|
throw classifyZodConversionError(err, schema);
|
|
61
136
|
}
|
|
62
137
|
}
|
|
63
138
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* Sources (verbatim message prefixes):
|
|
69
|
-
* - zod/src/v4/core/json-schema-processors.ts L104 (bigint), L110 (symbol),
|
|
70
|
-
* L126 (undefined), L132 (void), L150 (date), L169 (literal-undefined),
|
|
71
|
-
* L175 (literal-bigint), L204 (NaN), L246 (custom), L252 (function),
|
|
72
|
-
* L264 (map), L270 (set), L521 (dynamic catch).
|
|
73
|
-
* - zod/src/v4/core/to-json-schema.ts L182 (non-representable type fallback).
|
|
139
|
+
* Zod `def.type` tags that have no useful JSON Schema representation but
|
|
140
|
+
* do NOT throw when passed through `z.toJSONSchema`. Each tag is handled
|
|
141
|
+
* by Zod with a processor that silently rewrites the output:
|
|
74
142
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
143
|
+
* - `promise` — `promiseProcessor` unwraps the inner type, dropping the
|
|
144
|
+
* `Promise<...>` wrapper without any error. (`json-schema-processors.ts`,
|
|
145
|
+
* the body of `promiseProcessor` calls `process(def.innerType, ...)`.)
|
|
146
|
+
* schema-components considers this a silent shape mismatch — the input
|
|
147
|
+
* tree advertised a `Promise<T>` and the consumer would render `T`
|
|
148
|
+
* without ever being told the wrapping was lost.
|
|
79
149
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
150
|
+
* Detection happens BEFORE the call to `z.toJSONSchema` so the response is
|
|
151
|
+
* an immediate `SchemaNormalisationError` with `kind:
|
|
152
|
+
* "zod-type-unrepresentable"`, matching the philosophy of
|
|
153
|
+
* `UnrepresentableZodType` in `typeInference.ts` — these types are
|
|
154
|
+
* rejected, not coerced.
|
|
84
155
|
*/
|
|
85
|
-
const
|
|
86
|
-
["Literal `undefined` cannot be represented", "undefined-literal"],
|
|
87
|
-
["BigInt literals cannot be represented", "bigint-literal"],
|
|
88
|
-
["BigInt cannot be represented", "bigint"],
|
|
89
|
-
["Date cannot be represented", "date"],
|
|
90
|
-
["Map cannot be represented", "map"],
|
|
91
|
-
["Set cannot be represented", "set"],
|
|
92
|
-
["Symbols cannot be represented", "symbol"],
|
|
93
|
-
["Function types cannot be represented", "function"],
|
|
94
|
-
["Custom types cannot be represented", "custom"],
|
|
95
|
-
["Undefined cannot be represented", "undefined"],
|
|
96
|
-
["Void cannot be represented", "void"],
|
|
97
|
-
["NaN cannot be represented", "nan"]
|
|
98
|
-
];
|
|
156
|
+
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."]]);
|
|
99
157
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
158
|
+
* Pre-conversion screening. Inspects the root `_zod.def.type` tag for
|
|
159
|
+
* known-problematic types that either silently misrender (handled via
|
|
160
|
+
* {@link PRECONVERSION_UNREPRESENTABLE_TAGS}, raising a
|
|
161
|
+
* `SchemaNormalisationError`) or render correctly but with consumer-visible
|
|
162
|
+
* caveats (codecs, raising a `zod-codec-output-only` diagnostic).
|
|
102
163
|
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
164
|
+
* Design choice: `z.never()` is NOT classified here. The Zod processor for
|
|
165
|
+
* `never` already produces `{ not: {} }`, which the walker understands via
|
|
166
|
+
* its `walkBooleanSchema(false)` branch (`walker.ts` boolean-schema
|
|
167
|
+
* handling). Throwing a `zod-type-unrepresentable` for `never` would break
|
|
168
|
+
* the legitimate "this field cannot hold any value" use case that the
|
|
169
|
+
* walker already supports. Documented for posterity so future passes do
|
|
170
|
+
* not "fix" it.
|
|
105
171
|
*/
|
|
106
|
-
|
|
172
|
+
function screenPreConversion(input, def, diagnostics) {
|
|
173
|
+
const tag = def.type;
|
|
174
|
+
if (typeof tag !== "string") return;
|
|
175
|
+
const unrepresentableMessage = PRECONVERSION_UNREPRESENTABLE_TAGS.get(tag);
|
|
176
|
+
if (unrepresentableMessage !== void 0) throw new SchemaNormalisationError(unrepresentableMessage, input, "zod-type-unrepresentable", tag);
|
|
177
|
+
if (tag === "pipe" && isCodecSchema(input)) emitDiagnostic(diagnostics, {
|
|
178
|
+
code: "zod-codec-output-only",
|
|
179
|
+
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.",
|
|
180
|
+
pointer: "",
|
|
181
|
+
detail: { zodType: "codec" }
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* True when `input` is a `z.codec(...)` instance. Detection looks for the
|
|
186
|
+
* `$ZodCodec` entry in `_zod.traits` — the same marker `z.toJSONSchema`'s
|
|
187
|
+
* own `isTransforming` helper uses to distinguish codecs from generic
|
|
188
|
+
* pipes.
|
|
189
|
+
*/
|
|
190
|
+
function isCodecSchema(input) {
|
|
191
|
+
const zod = getProperty(input, "_zod");
|
|
192
|
+
if (!isObject(zod)) return false;
|
|
193
|
+
const traits = zod.traits;
|
|
194
|
+
if (traits instanceof Set) return traits.has("$ZodCodec");
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Escape a string for inclusion in a `RegExp`. Required because Zod
|
|
199
|
+
* messages contain `[`, `]`, `.`, `(`, and `)` characters which have regex
|
|
200
|
+
* meaning. The set covers every character with special meaning in a
|
|
201
|
+
* JavaScript regular-expression source — RegExp.escape is not yet widely
|
|
202
|
+
* available so we escape manually.
|
|
203
|
+
*/
|
|
204
|
+
function escapeRegExp(literal) {
|
|
205
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Compile a prefix into an anchored regex that captures any trailing text
|
|
209
|
+
* (used by rules that need to extract dynamic data such as the duplicate id
|
|
210
|
+
* or the def.type that tripped the non-representable fallback).
|
|
211
|
+
*/
|
|
212
|
+
function anchored(prefix) {
|
|
213
|
+
return new RegExp(`^${escapeRegExp(prefix)}(.*)$`, "s");
|
|
214
|
+
}
|
|
107
215
|
/**
|
|
108
|
-
*
|
|
109
|
-
|
|
216
|
+
* Build the message body shared by every unrepresentable-type rule.
|
|
217
|
+
*/
|
|
218
|
+
function unrepresentableMessage(typeName, fullMessage) {
|
|
219
|
+
return `Zod type ${typeName} cannot be represented in JSON Schema and is not supported by schema-components. Original message: ${fullMessage}`;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Classifier rules ordered most-specific first. Order is load-bearing:
|
|
223
|
+
* `Literal \`undefined\` cannot be represented` must precede the broader
|
|
224
|
+
* `Undefined cannot be represented` so the literal classification wins
|
|
225
|
+
* even when both share a leading word. A consistency check in the unit
|
|
226
|
+
* test suite asserts no two `prefix` values are prefixes of each other —
|
|
227
|
+
* any future rule that breaks the invariant fails the build.
|
|
228
|
+
*
|
|
229
|
+
* Verbatim sources (kept aligned with `tests/zod-error-wording-contract.unit.test.ts`).
|
|
230
|
+
* Source files are referenced by message-content anchors rather than line
|
|
231
|
+
* numbers — line numbers drift across Zod patch releases but the message
|
|
232
|
+
* strings themselves are stable and protected by the contract test suite:
|
|
110
233
|
*
|
|
111
|
-
*
|
|
234
|
+
* - `zod/src/v4/core/json-schema-processors.ts` — emits `BigInt cannot be
|
|
235
|
+
* represented`, `Symbols cannot be represented`, `Undefined cannot be
|
|
236
|
+
* represented`, `Void cannot be represented`, `Date cannot be
|
|
237
|
+
* represented`, `Literal \`undefined\` cannot be represented`,
|
|
238
|
+
* `BigInt literals cannot be represented`, `NaN cannot be represented`,
|
|
239
|
+
* `Custom types cannot be represented`, `Function types cannot be
|
|
240
|
+
* represented`, `Transforms cannot be represented`, `Map cannot be
|
|
241
|
+
* represented`, `Set cannot be represented`, `Dynamic catch values are
|
|
242
|
+
* not supported`.
|
|
243
|
+
* - `zod/src/v4/core/to-json-schema.ts` — emits `[toJSONSchema]:
|
|
244
|
+
* Non-representable type encountered: ${def.type}` (the catch-all
|
|
245
|
+
* fallback), `Unprocessed schema. This is a bug in Zod.` (the
|
|
246
|
+
* internal-bug branch), `Duplicate schema id "${id}" detected during
|
|
247
|
+
* JSON Schema conversion.` (the duplicate-id branch), `Cycle detected:
|
|
248
|
+
* ` (the cycle-throw branch), and `Error converting schema to JSON.`
|
|
249
|
+
* (the Standard Schema boundary wrapper).
|
|
250
|
+
*/
|
|
251
|
+
const CLASSIFIER_RULES = [
|
|
252
|
+
{
|
|
253
|
+
prefix: "Literal `undefined` cannot be represented",
|
|
254
|
+
kind: "zod-type-unrepresentable",
|
|
255
|
+
zodType: "undefined-literal",
|
|
256
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("undefined-literal", full), schema, "zod-type-unrepresentable", "undefined-literal", cause)
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
prefix: "BigInt literals cannot be represented",
|
|
260
|
+
kind: "zod-type-unrepresentable",
|
|
261
|
+
zodType: "bigint-literal",
|
|
262
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("bigint-literal", full), schema, "zod-type-unrepresentable", "bigint-literal", cause)
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
prefix: "BigInt cannot be represented",
|
|
266
|
+
kind: "zod-type-unrepresentable",
|
|
267
|
+
zodType: "bigint",
|
|
268
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("bigint", full), schema, "zod-type-unrepresentable", "bigint", cause)
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
prefix: "Date cannot be represented",
|
|
272
|
+
kind: "zod-type-unrepresentable",
|
|
273
|
+
zodType: "date",
|
|
274
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("date", full), schema, "zod-type-unrepresentable", "date", cause)
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
prefix: "Map cannot be represented",
|
|
278
|
+
kind: "zod-type-unrepresentable",
|
|
279
|
+
zodType: "map",
|
|
280
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("map", full), schema, "zod-type-unrepresentable", "map", cause)
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
prefix: "Set cannot be represented",
|
|
284
|
+
kind: "zod-type-unrepresentable",
|
|
285
|
+
zodType: "set",
|
|
286
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("set", full), schema, "zod-type-unrepresentable", "set", cause)
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
prefix: "Symbols cannot be represented",
|
|
290
|
+
kind: "zod-type-unrepresentable",
|
|
291
|
+
zodType: "symbol",
|
|
292
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("symbol", full), schema, "zod-type-unrepresentable", "symbol", cause)
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
prefix: "Function types cannot be represented",
|
|
296
|
+
kind: "zod-type-unrepresentable",
|
|
297
|
+
zodType: "function",
|
|
298
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("function", full), schema, "zod-type-unrepresentable", "function", cause)
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
prefix: "Custom types cannot be represented",
|
|
302
|
+
kind: "zod-type-unrepresentable",
|
|
303
|
+
zodType: "custom",
|
|
304
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("custom", full), schema, "zod-type-unrepresentable", "custom", cause)
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
prefix: "Undefined cannot be represented",
|
|
308
|
+
kind: "zod-type-unrepresentable",
|
|
309
|
+
zodType: "undefined",
|
|
310
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("undefined", full), schema, "zod-type-unrepresentable", "undefined", cause)
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
prefix: "Void cannot be represented",
|
|
314
|
+
kind: "zod-type-unrepresentable",
|
|
315
|
+
zodType: "void",
|
|
316
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("void", full), schema, "zod-type-unrepresentable", "void", cause)
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
prefix: "NaN cannot be represented",
|
|
320
|
+
kind: "zod-type-unrepresentable",
|
|
321
|
+
zodType: "nan",
|
|
322
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(unrepresentableMessage("nan", full), schema, "zod-type-unrepresentable", "nan", cause)
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
prefix: "Transforms cannot be represented",
|
|
326
|
+
kind: "zod-transform-unsupported",
|
|
327
|
+
build: (_m, cause, schema) => new SchemaNormalisationError("Zod transforms cannot be represented in JSON Schema. Remove the .transform() call, or pre-transform the input before passing it to the component. (Note: z.codec(...) is implemented as a transform internally — codecs that force round-tripping trip this same rule.)", schema, "zod-transform-unsupported", void 0, cause)
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
prefix: "Dynamic catch values are not supported",
|
|
331
|
+
kind: "zod-type-unrepresentable",
|
|
332
|
+
zodType: "dynamic-catch",
|
|
333
|
+
build: (_m, cause, schema) => new SchemaNormalisationError("Zod catch values that depend on runtime computation cannot be represented in JSON Schema. Provide a static catch value or remove the .catch() call.", schema, "zod-type-unrepresentable", "dynamic-catch", cause)
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
prefix: "[toJSONSchema]: Non-representable type encountered:",
|
|
337
|
+
kind: "zod-type-unrepresentable",
|
|
338
|
+
build: (match, cause, schema, full) => {
|
|
339
|
+
const trailing = match[1]?.trim() ?? "";
|
|
340
|
+
const typeName = trailing.length > 0 ? trailing.split(/\s+/)[0] : void 0;
|
|
341
|
+
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);
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
prefix: "Cycle detected: ",
|
|
346
|
+
kind: "zod-cycle-detected",
|
|
347
|
+
build: (match, cause, schema, full) => {
|
|
348
|
+
return new SchemaNormalisationError(`Zod detected a cycle in the schema graph at ${(match[1] ?? "").split(/\s+/)[0] ?? ""}. 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);
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
prefix: "Duplicate schema id \"",
|
|
353
|
+
kind: "zod-duplicate-id",
|
|
354
|
+
build: (match, cause, schema, full) => {
|
|
355
|
+
const trailing = match[1] ?? "";
|
|
356
|
+
const closing = trailing.indexOf("\"");
|
|
357
|
+
return new SchemaNormalisationError(`Two different Zod schemas share the same id "${closing === -1 ? trailing : 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);
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
prefix: "Unprocessed schema. This is a bug in Zod.",
|
|
362
|
+
kind: "zod-conversion-bug",
|
|
363
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(`Zod failed to process this schema during JSON Schema conversion and reports it as an internal bug. File an issue on the Zod tracker with a reproduction. Original message: ${full}`, schema, "zod-conversion-bug", void 0, cause)
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
prefix: "Error converting schema to JSON.",
|
|
367
|
+
kind: "zod-conversion-failed",
|
|
368
|
+
build: (_m, cause, schema, full) => new SchemaNormalisationError(`z.toJSONSchema() failed to produce a Standard Schema payload. Inspect the underlying cause for the original error. Original message: ${full}`, schema, "zod-conversion-failed", void 0, cause)
|
|
369
|
+
}
|
|
370
|
+
];
|
|
371
|
+
/**
|
|
372
|
+
* Compiled regex form of {@link CLASSIFIER_RULES} — built once at module
|
|
373
|
+
* load. Avoids per-error compilation.
|
|
374
|
+
*/
|
|
375
|
+
const COMPILED_CLASSIFIER_RULES = CLASSIFIER_RULES.map((rule) => ({
|
|
376
|
+
rule,
|
|
377
|
+
pattern: anchored(rule.prefix)
|
|
378
|
+
}));
|
|
379
|
+
/**
|
|
380
|
+
* Maximum recursion depth for {@link containsNestedZod3}. Reuses the
|
|
381
|
+
* shared {@link MAX_REF_DEPTH} so the runtime walk and the compile-time
|
|
382
|
+
* `DEFAULT_MAX_DEPTH` (type-aliased to the same value) stay in lockstep.
|
|
112
383
|
*/
|
|
113
|
-
const DYNAMIC_CATCH_MARKER = "Dynamic catch values are not supported";
|
|
114
384
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
385
|
+
* Walk an arbitrary value looking for Zod 3 markers (`_def` without
|
|
386
|
+
* `_zod`). Zod 4 schemas always carry `_zod.def`; Zod 3 schemas carry
|
|
387
|
+
* `_def` (with or without a `typeName` field — third-party Zod-3-style
|
|
388
|
+
* libraries occasionally omit `typeName`). Presence of `_def` without
|
|
389
|
+
* `_zod` anywhere in the tree means a Zod 3 (or Zod-3-like) schema was
|
|
390
|
+
* nested inside a Zod 4 input, which is what trips the V8
|
|
391
|
+
* `"Cannot read properties of undefined"` failure.
|
|
392
|
+
*
|
|
393
|
+
* Engine-agnostic by construction — the detector inspects schema shape
|
|
394
|
+
* instead of pattern-matching against the runtime's TypeError message,
|
|
395
|
+
* so it works equivalently under V8, JavaScriptCore (Bun/Safari), and
|
|
396
|
+
* SpiderMonkey (Firefox) — none of which agree on the wording.
|
|
397
|
+
*
|
|
398
|
+
* Performance shortcuts:
|
|
399
|
+
*
|
|
400
|
+
* - **Targeted descent into Zod 4 nodes.** Once a node is identified as a
|
|
401
|
+
* Zod 4 schema (`_zod.def` is an object), the only branch that can
|
|
402
|
+
* carry user-supplied sub-schemas is `_zod.def` itself. Zod's other
|
|
403
|
+
* internal members (`_zod.traits`, `_zod.parse`, `_zod.bag`, etc.) are
|
|
404
|
+
* implementation surface and never contain user schemas, so walking
|
|
405
|
+
* them on every conversion failure is wasted work. Switching to a
|
|
406
|
+
* targeted descent (only `_zod.def` plus the schema root's `_def`
|
|
407
|
+
* field) trims the walk dramatically.
|
|
408
|
+
* - **Depth cap.** Recursion is bounded by {@link MAX_REF_DEPTH}
|
|
409
|
+
* so a pathological schema graph cannot cause stack overflow. The
|
|
410
|
+
* `visited` set still defends against cyclic references; the depth
|
|
411
|
+
* cap defends against deep-but-acyclic trees.
|
|
118
412
|
*/
|
|
119
|
-
|
|
413
|
+
function containsNestedZod3(value, visited) {
|
|
414
|
+
return containsNestedZod3Inner(value, visited, 0);
|
|
415
|
+
}
|
|
416
|
+
function containsNestedZod3Inner(value, visited, depth) {
|
|
417
|
+
if (depth >= 64) return false;
|
|
418
|
+
if (value === null || typeof value !== "object") return false;
|
|
419
|
+
if (visited.has(value)) return false;
|
|
420
|
+
visited.add(value);
|
|
421
|
+
if (Array.isArray(value)) {
|
|
422
|
+
for (const item of value) if (containsNestedZod3Inner(item, visited, depth + 1)) return true;
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
if (!isObject(value)) return false;
|
|
426
|
+
const def = value._def;
|
|
427
|
+
const zod = value._zod;
|
|
428
|
+
if (zod === void 0 && isObject(def)) return true;
|
|
429
|
+
if (isObject(zod) && isObject(zod.def)) return containsNestedZod3Inner(zod.def, visited, depth + 1);
|
|
430
|
+
for (const key of Object.keys(value)) if (containsNestedZod3Inner(value[key], visited, depth + 1)) return true;
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
120
433
|
function classifyZodConversionError(err, schema) {
|
|
121
434
|
const message = err instanceof Error ? err.message : String(err);
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const nonReprIndex = message.indexOf(NON_REPRESENTABLE_TYPE_MARKER);
|
|
127
|
-
if (nonReprIndex !== -1) {
|
|
128
|
-
const trailing = message.slice(nonReprIndex + 51).trim();
|
|
129
|
-
const typeName = trailing.length > 0 ? trailing.split(/\s+/)[0] : void 0;
|
|
130
|
-
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: ${message}`, schema, "zod-type-unrepresentable", typeName, err);
|
|
435
|
+
if (containsNestedZod3(schema, /* @__PURE__ */ new Set())) return new SchemaNormalisationError("A nested Zod 3 schema was found inside a Zod 4 schema. schema-components requires Zod 4 throughout the schema tree. See the Zod 4 migration guide at https://zod.dev/v4/migration or run: pnpm add zod@^4", schema, "zod3-unsupported", void 0, err);
|
|
436
|
+
for (const { rule, pattern } of COMPILED_CLASSIFIER_RULES) {
|
|
437
|
+
const match = pattern.exec(message);
|
|
438
|
+
if (match !== null) return rule.build(match, err, schema, message);
|
|
131
439
|
}
|
|
132
440
|
return new SchemaNormalisationError(`z.toJSONSchema() failed: ${message}`, schema, "zod-conversion-failed", void 0, err);
|
|
133
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Exposed for unit testing — lets the contract test enumerate every rule's
|
|
444
|
+
* `prefix` value and assert mutual non-prefixing.
|
|
445
|
+
*/
|
|
446
|
+
const __CLASSIFIER_RULES_FOR_TEST = CLASSIFIER_RULES;
|
|
134
447
|
function normaliseSchema(input, ref, options) {
|
|
135
|
-
|
|
448
|
+
const usesDiagnostics = options?.diagnostics !== void 0;
|
|
449
|
+
const cacheEligible = ref === void 0 && isObject(input) && !usesDiagnostics;
|
|
450
|
+
if (cacheEligible) {
|
|
136
451
|
const cached = schemaCache.get(input);
|
|
137
452
|
if (cached !== void 0) return cached;
|
|
138
453
|
}
|
|
@@ -140,11 +455,12 @@ function normaliseSchema(input, ref, options) {
|
|
|
140
455
|
let result;
|
|
141
456
|
switch (kind) {
|
|
142
457
|
case "zod4":
|
|
143
|
-
result = normaliseZod4(input);
|
|
458
|
+
result = normaliseZod4(input, options?.diagnostics);
|
|
144
459
|
break;
|
|
145
460
|
case "zod3":
|
|
146
461
|
result = normaliseZod3(input);
|
|
147
462
|
break;
|
|
463
|
+
case "unsupported-schema-lib": throw new SchemaNormalisationError("Input looks like a schema from a non-Zod library — 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");
|
|
148
464
|
case "openapi":
|
|
149
465
|
if (!isObject(input)) throw new SchemaNormalisationError("Invalid OpenAPI document", input, "openapi-invalid");
|
|
150
466
|
result = normaliseOpenApi(input, ref, options);
|
|
@@ -154,13 +470,15 @@ function normaliseSchema(input, ref, options) {
|
|
|
154
470
|
result = normaliseJsonSchema(input, options?.diagnostics);
|
|
155
471
|
break;
|
|
156
472
|
}
|
|
157
|
-
if (
|
|
473
|
+
if (cacheEligible) schemaCache.set(input, result);
|
|
158
474
|
return result;
|
|
159
475
|
}
|
|
160
|
-
function normaliseZod4(input) {
|
|
476
|
+
function normaliseZod4(input, diagnostics) {
|
|
161
477
|
const zod = getProperty(input, "_zod");
|
|
162
|
-
if (!isObject(zod)) throw new SchemaNormalisationError("
|
|
163
|
-
|
|
478
|
+
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");
|
|
479
|
+
const def = getProperty(zod, "def");
|
|
480
|
+
if (!isObject(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");
|
|
481
|
+
screenPreConversion(input, def, diagnostics);
|
|
164
482
|
const jsonSchema = callToJsonSchema(input);
|
|
165
483
|
if (!isObject(jsonSchema)) throw new SchemaNormalisationError("z.toJSONSchema() did not produce an object", input, "invalid-zod");
|
|
166
484
|
return {
|
|
@@ -284,6 +602,23 @@ function resolveOpenApiRef(doc, ref) {
|
|
|
284
602
|
}
|
|
285
603
|
throw new Error(`Unsupported OpenAPI ref format: ${ref}`);
|
|
286
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* Surface root-level metadata from the JSON Schema into the `rootMeta`
|
|
607
|
+
* shape consumed by the walker. Pulls `readOnly`, `writeOnly`,
|
|
608
|
+
* `description`, `title`, `deprecated`, `examples`, and `default`
|
|
609
|
+
* directly from the schema root.
|
|
610
|
+
*
|
|
611
|
+
* `examples` is forwarded only when present as an array (per JSON Schema
|
|
612
|
+
* Draft 2020-12 — Draft 04's `example` singular is normalised upstream).
|
|
613
|
+
* `default` is forwarded for any value the schema declares (any JSON
|
|
614
|
+
* value, including `null` and `false`); the presence check uses `in`
|
|
615
|
+
* so a literal `false` or `null` default is preserved.
|
|
616
|
+
*
|
|
617
|
+
* `examples` and `default` ride on the `[key: string]: unknown` index
|
|
618
|
+
* signature of {@link SchemaMeta}. They are not declared as named fields
|
|
619
|
+
* on `SchemaMeta` because that type lives in `types.ts` and is shared
|
|
620
|
+
* with the walker; the index signature is the agreed extension point.
|
|
621
|
+
*/
|
|
287
622
|
function extractRootMetaFromJson(jsonSchema) {
|
|
288
623
|
const meta = {};
|
|
289
624
|
if (jsonSchema.readOnly === true) meta.readOnly = true;
|
|
@@ -291,7 +626,9 @@ function extractRootMetaFromJson(jsonSchema) {
|
|
|
291
626
|
if (typeof jsonSchema.description === "string") meta.description = jsonSchema.description;
|
|
292
627
|
if (typeof jsonSchema.title === "string") meta.title = jsonSchema.title;
|
|
293
628
|
if (typeof jsonSchema.deprecated === "boolean") meta.deprecated = jsonSchema.deprecated;
|
|
629
|
+
if (Array.isArray(jsonSchema.examples)) meta.examples = jsonSchema.examples;
|
|
630
|
+
if ("default" in jsonSchema) meta.default = jsonSchema.default;
|
|
294
631
|
return Object.keys(meta).length > 0 ? meta : void 0;
|
|
295
632
|
}
|
|
296
633
|
//#endregion
|
|
297
|
-
export { detectSchemaKind, normaliseSchema };
|
|
634
|
+
export { __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, 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-BrRMV0en.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.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;
|