schema-components 1.22.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 +97 -3
- package/dist/core/adapter.mjs +260 -111
- 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 +9 -2
- package/dist/core/formats.mjs +12 -1
- package/dist/core/idPath.d.mts +54 -0
- package/dist/core/idPath.mjs +66 -0
- package/dist/core/merge.d.mts +10 -1
- package/dist/core/merge.mjs +49 -10
- package/dist/core/normalise.d.mts +14 -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 +84 -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/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 +1 -1
- 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 +44 -45
- package/dist/{diagnostics-D0QCYGv0.d.mts → diagnostics-BS2kaUyE.d.mts} +1 -1
- package/dist/{errors-DpFwqs5C.d.mts → errors-g_MCTQel.d.mts} +9 -15
- package/dist/html/a11y.d.mts +9 -4
- package/dist/html/a11y.mjs +10 -19
- package/dist/html/renderToHtml.d.mts +2 -2
- 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 -111
- package/dist/html/streamRenderers.d.mts +4 -5
- package/dist/html/streamRenderers.mjs +40 -61
- package/dist/{normalise-DVEJQmF7.mjs → normalise-DCYp06Sr.mjs} +352 -162
- 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/components.d.mts +116 -37
- package/dist/openapi/components.mjs +54 -37
- package/dist/openapi/parser.d.mts +9 -8
- package/dist/openapi/parser.mjs +234 -84
- package/dist/openapi/resolve.d.mts +20 -11
- package/dist/openapi/resolve.mjs +133 -73
- package/dist/react/SchemaComponent.d.mts +32 -7
- package/dist/react/SchemaComponent.mjs +45 -21
- package/dist/react/SchemaView.d.mts +30 -10
- 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/headlessRenderers.d.mts +8 -9
- package/dist/react/headlessRenderers.mjs +41 -72
- package/dist/{ref-D-_JBZkF.d.mts → ref-DjLEKa_E.d.mts} +38 -3
- package/dist/{renderer-BaRlQIuN.d.mts → renderer-CXJ8y0qw.d.mts} +1 -1
- 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-BrRMV0en.d.mts → types-BTB73MB8.d.mts} +32 -4
- package/dist/{version-D2jfdX6E.d.mts → version-BFTVLsdb.d.mts} +7 -1
- package/package.json +1 -1
- package/dist/typeInference-DkcUHfaM.d.mts +0 -982
package/README.md
CHANGED
|
@@ -16,7 +16,9 @@ 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). Zod 3 schemas are detected structurally — any object exposing `_def` without the Zod 4 `_zod` marker is classified as Zod 3, with or without the historical `_def.typeName` field. (Some third-party Zod-3-style libraries omit `typeName`; the detector keys on the presence of `_def` alone.) A descriptive `SchemaNormalisationError` is raised pointing at the Zod 4 migration guide.
|
|
20
|
+
|
|
21
|
+
Schemas from other libraries that conform to the [Standard Schema](https://standardschema.dev/) spec (valibot, arktype, ...) are also detected and rejected. When the input advertises a `~standard.vendor` field, the error message includes the vendor name so consumers know which library produced the input.
|
|
20
22
|
|
|
21
23
|
## `SchemaComponent`
|
|
22
24
|
|
package/dist/core/adapter.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { m as JsonObject, w as SchemaMeta } from "../types-
|
|
2
|
-
import { i as DiagnosticsOptions } from "../diagnostics-
|
|
1
|
+
import { m as JsonObject, w as SchemaMeta } from "../types-BTB73MB8.mjs";
|
|
2
|
+
import { i as DiagnosticsOptions } from "../diagnostics-BS2kaUyE.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/core/adapter.d.ts
|
|
5
5
|
type SchemaInput = Record<string, unknown>;
|
|
@@ -22,6 +22,82 @@ type SchemaKind = "zod4" | "zod3" | "jsonSchema" | "openapi" | "unsupported-sche
|
|
|
22
22
|
* - `jsonSchema` — fallback for anything that does not match the above.
|
|
23
23
|
*/
|
|
24
24
|
declare function detectSchemaKind(input: unknown): SchemaKind;
|
|
25
|
+
/**
|
|
26
|
+
* Wraps z.toJSONSchema() for a runtime-validated Zod schema.
|
|
27
|
+
*
|
|
28
|
+
* The _zod guard in normaliseZod4 has confirmed this is a valid Zod schema,
|
|
29
|
+
* but TypeScript cannot represent "has _zod.def" as the $ZodType parameter
|
|
30
|
+
* that z.toJSONSchema expects. This is the library boundary equivalent of
|
|
31
|
+
* object → Record<string, unknown> — the type mismatch is genuinely unavoidable.
|
|
32
|
+
*
|
|
33
|
+
* # Options
|
|
34
|
+
*
|
|
35
|
+
* `z.toJSONSchema` is invoked with an explicit options object rather than
|
|
36
|
+
* Zod's defaults so the conversion contract is pinned and stable:
|
|
37
|
+
*
|
|
38
|
+
* - `target: "draft-2020-12"` — matches the walker's draft target.
|
|
39
|
+
* - `unrepresentable: "throw"` — keeps the unrepresentable-type rules in
|
|
40
|
+
* the classifier table firing instead of silently emitting `{}`.
|
|
41
|
+
* - `cycles: "ref"` — converts cyclic graphs into $ref pairs rather than
|
|
42
|
+
* throwing. Cycles in user schemas surface through the walker's $ref
|
|
43
|
+
* resolution rather than the adapter.
|
|
44
|
+
* - `io` — selects which side of every transform / pipe / codec is
|
|
45
|
+
* converted. Defaults to `"output"` (the OUTPUT side); pass `"input"`
|
|
46
|
+
* to render the INPUT side instead. The input side is invisible to
|
|
47
|
+
* the converted schema when `io: "output"` is in force, even though
|
|
48
|
+
* `safeParse` on the same Zod schema consumes the input shape. For
|
|
49
|
+
* transforms this divergence is fatal and the call throws via
|
|
50
|
+
* `Transforms cannot be represented`; for `z.codec(...)` the call
|
|
51
|
+
* succeeds but only the selected side is rendered. Consumers receive
|
|
52
|
+
* a `zod-codec-output-only` diagnostic in the codec case so the
|
|
53
|
+
* asymmetry is visible — see `screenPreConversion`.
|
|
54
|
+
*
|
|
55
|
+
* # Error classification
|
|
56
|
+
*
|
|
57
|
+
* Any exception thrown by z.toJSONSchema is classified into a
|
|
58
|
+
* SchemaNormalisationError so the caller does not have to re-parse error
|
|
59
|
+
* message strings. The classification covers:
|
|
60
|
+
*
|
|
61
|
+
* - Nested Zod 3 schemas inside a Zod 4 tree → zod3-unsupported.
|
|
62
|
+
* Detected structurally (presence of `_def.typeName` markers anywhere
|
|
63
|
+
* in the schema tree) so the check works across V8, JavaScriptCore,
|
|
64
|
+
* and SpiderMonkey, none of which agree on the wording of
|
|
65
|
+
* "Cannot read properties of undefined".
|
|
66
|
+
* - Transforms → zod-transform-unsupported. This also catches `z.codec(…)`
|
|
67
|
+
* because Zod implements codecs as a pipe + transform internally, so
|
|
68
|
+
* they trip the same processor when round-tripping is forced. (Plain
|
|
69
|
+
* `z.toJSONSchema(codec)` itself does NOT throw because Zod picks one
|
|
70
|
+
* side of the codec; the static rejection in `typeInference.ts` is the
|
|
71
|
+
* compile-time guard.)
|
|
72
|
+
* - Dynamic catch values whose handler throws → zod-type-unrepresentable
|
|
73
|
+
* with zodType "dynamic-catch".
|
|
74
|
+
* - Unrepresentable types — bigint, date, map, set, symbol, function, custom,
|
|
75
|
+
* undefined, void, NaN, and the literal-only forms `z.literal(undefined)`
|
|
76
|
+
* ("undefined-literal") and `z.literal(<bigint>)` ("bigint-literal") →
|
|
77
|
+
* zod-type-unrepresentable.
|
|
78
|
+
* - The catch-all "Non-representable type encountered: <type>" fallback Zod
|
|
79
|
+
* emits for any new schema kind without a registered processor →
|
|
80
|
+
* zod-type-unrepresentable with zodType set to the offending def.type.
|
|
81
|
+
* - Cycle detected (`cycles: "throw"`) → zod-cycle-detected.
|
|
82
|
+
* - Duplicate schema id → zod-duplicate-id.
|
|
83
|
+
* - "Unprocessed schema. This is a bug in Zod." → zod-conversion-bug.
|
|
84
|
+
* - "Error converting schema to JSON." → zod-conversion-failed (explicit
|
|
85
|
+
* classification rather than the generic fallback so the contract test
|
|
86
|
+
* protects the prefix from drift).
|
|
87
|
+
* - Anything else → zod-conversion-failed.
|
|
88
|
+
*
|
|
89
|
+
* The original error is preserved on each classified error via the `cause`
|
|
90
|
+
* field so consumers can still inspect the Zod stack trace.
|
|
91
|
+
*/
|
|
92
|
+
/**
|
|
93
|
+
* IO side passed to {@link callToJsonSchema}. The Zod runtime accepts
|
|
94
|
+
* `"input" | "output"` for the corresponding `io` option on
|
|
95
|
+
* `z.toJSONSchema`. Defaults to `"output"` everywhere in the adapter
|
|
96
|
+
* pipeline; the parameter exists so a future renderer or component
|
|
97
|
+
* (currently SchemaComponent — see TODO below) can request the input
|
|
98
|
+
* side without forking the helper.
|
|
99
|
+
*/
|
|
100
|
+
type SchemaIoSide = "input" | "output";
|
|
25
101
|
/**
|
|
26
102
|
* Exposed for unit testing — lets the contract test enumerate every rule's
|
|
27
103
|
* `prefix` value and assert mutual non-prefixing.
|
|
@@ -44,5 +120,23 @@ interface NormaliseOptions {
|
|
|
44
120
|
diagnostics?: DiagnosticsOptions;
|
|
45
121
|
}
|
|
46
122
|
declare function normaliseSchema(input: unknown, ref?: string, options?: NormaliseOptions): NormalisedSchema;
|
|
123
|
+
/**
|
|
124
|
+
* Surface root-level metadata from the JSON Schema into the `rootMeta`
|
|
125
|
+
* shape consumed by the walker. Pulls `readOnly`, `writeOnly`,
|
|
126
|
+
* `description`, `title`, `deprecated`, `examples`, and `default`
|
|
127
|
+
* directly from the schema root.
|
|
128
|
+
*
|
|
129
|
+
* `examples` is forwarded only when present as an array (per JSON Schema
|
|
130
|
+
* Draft 2020-12 — Draft 04's `example` singular is normalised upstream).
|
|
131
|
+
* `default` is forwarded for any value the schema declares (any JSON
|
|
132
|
+
* value, including `null` and `false`); the presence check uses `in`
|
|
133
|
+
* so a literal `false` or `null` default is preserved.
|
|
134
|
+
*
|
|
135
|
+
* `examples` and `default` ride on the `[key: string]: unknown` index
|
|
136
|
+
* signature of {@link SchemaMeta}. They are not declared as named fields
|
|
137
|
+
* on `SchemaMeta` because that type lives in `types.ts` and is shared
|
|
138
|
+
* with the walker; the index signature is the agreed extension point.
|
|
139
|
+
*/
|
|
140
|
+
declare function extractRootMetaFromJson(jsonSchema: JsonObject): SchemaMeta | undefined;
|
|
47
141
|
//#endregion
|
|
48
|
-
export { type JsonObject, NormaliseOptions, NormalisedSchema, SchemaInput, SchemaKind, type SchemaMeta, __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, normaliseSchema };
|
|
142
|
+
export { type JsonObject, NormaliseOptions, NormalisedSchema, SchemaInput, SchemaIoSide, SchemaKind, type SchemaMeta, __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, extractRootMetaFromJson, normaliseSchema };
|
package/dist/core/adapter.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { getProperty, hasProperty, isObject } from "./guards.mjs";
|
|
2
2
|
import "./limits.mjs";
|
|
3
3
|
import { SchemaNormalisationError } from "./errors.mjs";
|
|
4
|
-
import { emitDiagnostic } from "./diagnostics.mjs";
|
|
4
|
+
import { appendPointer, emitDiagnostic } from "./diagnostics.mjs";
|
|
5
5
|
import { dereference } from "./ref.mjs";
|
|
6
6
|
import { detectOpenApiVersion, inferJsonSchemaDraftWithReason, isSwagger2, matchJsonSchemaDraftUri } from "./version.mjs";
|
|
7
|
-
import { a as
|
|
7
|
+
import { a as normaliseJsonSchema$1, o as normaliseOpenApiSchemas } from "../normalise-DCYp06Sr.mjs";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
//#region src/core/adapter.ts
|
|
10
10
|
/**
|
|
@@ -44,92 +44,49 @@ function detectSchemaKind(input) {
|
|
|
44
44
|
return "jsonSchema";
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Heuristic: a non-Zod object
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
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.
|
|
53
62
|
*/
|
|
54
63
|
function isLikelyOtherSchemaLib(input) {
|
|
55
64
|
if (!isObject(input)) return false;
|
|
56
65
|
if (hasProperty(input, "_zod") || hasProperty(input, "_def")) return false;
|
|
66
|
+
if (isObject(input["~standard"])) return true;
|
|
57
67
|
const parse = input.parse;
|
|
58
68
|
const safeParse = input.safeParse;
|
|
59
69
|
return typeof parse === "function" && typeof safeParse === "function";
|
|
60
70
|
}
|
|
61
71
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
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
|
-
*
|
|
91
|
-
* Any exception thrown by z.toJSONSchema is classified into a
|
|
92
|
-
* SchemaNormalisationError so the caller does not have to re-parse error
|
|
93
|
-
* message strings. The classification covers:
|
|
94
|
-
*
|
|
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".
|
|
108
|
-
* - Unrepresentable types — bigint, date, map, set, symbol, function, custom,
|
|
109
|
-
* undefined, void, NaN, and the literal-only forms `z.literal(undefined)`
|
|
110
|
-
* ("undefined-literal") and `z.literal(<bigint>)` ("bigint-literal") →
|
|
111
|
-
* zod-type-unrepresentable.
|
|
112
|
-
* - The catch-all "Non-representable type encountered: <type>" fallback Zod
|
|
113
|
-
* emits for any new schema kind without a registered processor →
|
|
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.
|
|
122
|
-
*
|
|
123
|
-
* The original error is preserved on each classified error via the `cause`
|
|
124
|
-
* field so consumers can still inspect the Zod stack trace.
|
|
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.
|
|
125
78
|
*/
|
|
126
|
-
function
|
|
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") {
|
|
127
84
|
try {
|
|
128
85
|
return z.toJSONSchema(schema, {
|
|
129
86
|
target: "draft-2020-12",
|
|
130
87
|
unrepresentable: "throw",
|
|
131
88
|
cycles: "ref",
|
|
132
|
-
io
|
|
89
|
+
io
|
|
133
90
|
});
|
|
134
91
|
} catch (err) {
|
|
135
92
|
throw classifyZodConversionError(err, schema);
|
|
@@ -155,46 +112,205 @@ function callToJsonSchema(schema) {
|
|
|
155
112
|
*/
|
|
156
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."]]);
|
|
157
114
|
/**
|
|
158
|
-
* Pre-conversion screening.
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
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.
|
|
163
133
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
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.
|
|
171
147
|
*/
|
|
172
|
-
function screenPreConversion(input,
|
|
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}).
|
|
162
|
+
*
|
|
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;
|
|
173
178
|
const tag = def.type;
|
|
174
|
-
if (typeof tag
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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, {
|
|
178
192
|
code: "zod-codec-output-only",
|
|
179
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.",
|
|
180
|
-
pointer
|
|
194
|
+
pointer,
|
|
181
195
|
detail: { zodType: "codec" }
|
|
182
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.
|
|
216
|
+
*
|
|
217
|
+
* Pointer accumulation:
|
|
218
|
+
*
|
|
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).
|
|
229
|
+
*
|
|
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.
|
|
233
|
+
*/
|
|
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);
|
|
183
265
|
}
|
|
184
266
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* own `isTransforming` helper uses to distinguish codecs from generic
|
|
188
|
-
* pipes.
|
|
267
|
+
* Format an empty pointer as `<root>` so error messages do not contain
|
|
268
|
+
* a stray bare `""`. Non-empty pointers are returned verbatim.
|
|
189
269
|
*/
|
|
190
|
-
function
|
|
191
|
-
|
|
192
|
-
|
|
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) {
|
|
193
280
|
const traits = zod.traits;
|
|
194
|
-
if (traits instanceof Set) return traits.has(
|
|
281
|
+
if (traits instanceof Set) return traits.has(traitName);
|
|
195
282
|
return false;
|
|
196
283
|
}
|
|
197
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;
|
|
307
|
+
try {
|
|
308
|
+
return candidate();
|
|
309
|
+
} catch {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
198
314
|
* Escape a string for inclusion in a `RegExp`. Required because Zod
|
|
199
315
|
* messages contain `[`, `]`, `.`, `(`, and `)` characters which have regex
|
|
200
316
|
* meaning. The set covers every character with special meaning in a
|
|
@@ -336,8 +452,11 @@ const CLASSIFIER_RULES = [
|
|
|
336
452
|
prefix: "[toJSONSchema]: Non-representable type encountered:",
|
|
337
453
|
kind: "zod-type-unrepresentable",
|
|
338
454
|
build: (match, cause, schema, full) => {
|
|
339
|
-
const trailing = match[1]
|
|
340
|
-
|
|
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;
|
|
341
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);
|
|
342
461
|
}
|
|
343
462
|
},
|
|
@@ -345,16 +464,22 @@ const CLASSIFIER_RULES = [
|
|
|
345
464
|
prefix: "Cycle detected: ",
|
|
346
465
|
kind: "zod-cycle-detected",
|
|
347
466
|
build: (match, cause, schema, full) => {
|
|
348
|
-
|
|
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);
|
|
349
472
|
}
|
|
350
473
|
},
|
|
351
474
|
{
|
|
352
475
|
prefix: "Duplicate schema id \"",
|
|
353
476
|
kind: "zod-duplicate-id",
|
|
354
477
|
build: (match, cause, schema, full) => {
|
|
355
|
-
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);
|
|
356
480
|
const closing = trailing.indexOf("\"");
|
|
357
|
-
|
|
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);
|
|
358
483
|
}
|
|
359
484
|
},
|
|
360
485
|
{
|
|
@@ -377,6 +502,22 @@ const COMPILED_CLASSIFIER_RULES = CLASSIFIER_RULES.map((rule) => ({
|
|
|
377
502
|
pattern: anchored(rule.prefix)
|
|
378
503
|
}));
|
|
379
504
|
/**
|
|
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
|
+
/**
|
|
380
521
|
* Maximum recursion depth for {@link containsNestedZod3}. Reuses the
|
|
381
522
|
* shared {@link MAX_REF_DEPTH} so the runtime walk and the compile-time
|
|
382
523
|
* `DEFAULT_MAX_DEPTH` (type-aliased to the same value) stay in lockstep.
|
|
@@ -426,7 +567,13 @@ function containsNestedZod3Inner(value, visited, depth) {
|
|
|
426
567
|
const def = value._def;
|
|
427
568
|
const zod = value._zod;
|
|
428
569
|
if (zod === void 0 && isObject(def)) return true;
|
|
429
|
-
if (isObject(zod) && isObject(zod.def))
|
|
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
|
+
}
|
|
430
577
|
for (const key of Object.keys(value)) if (containsNestedZod3Inner(value[key], visited, depth + 1)) return true;
|
|
431
578
|
return false;
|
|
432
579
|
}
|
|
@@ -460,7 +607,10 @@ function normaliseSchema(input, ref, options) {
|
|
|
460
607
|
case "zod3":
|
|
461
608
|
result = normaliseZod3(input);
|
|
462
609
|
break;
|
|
463
|
-
case "unsupported-schema-lib":
|
|
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
|
+
}
|
|
464
614
|
case "openapi":
|
|
465
615
|
if (!isObject(input)) throw new SchemaNormalisationError("Invalid OpenAPI document", input, "openapi-invalid");
|
|
466
616
|
result = normaliseOpenApi(input, ref, options);
|
|
@@ -476,9 +626,8 @@ function normaliseSchema(input, ref, options) {
|
|
|
476
626
|
function normaliseZod4(input, diagnostics) {
|
|
477
627
|
const zod = getProperty(input, "_zod");
|
|
478
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");
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
screenPreConversion(input, def, diagnostics);
|
|
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);
|
|
482
631
|
const jsonSchema = callToJsonSchema(input);
|
|
483
632
|
if (!isObject(jsonSchema)) throw new SchemaNormalisationError("z.toJSONSchema() did not produce an object", input, "invalid-zod");
|
|
484
633
|
return {
|
|
@@ -598,7 +747,7 @@ function resolveOpenApiRef(doc, ref) {
|
|
|
598
747
|
}
|
|
599
748
|
if (ref.startsWith("#/")) {
|
|
600
749
|
const resolved = dereference(ref, doc);
|
|
601
|
-
if (resolved !== void 0) return resolved;
|
|
750
|
+
if (resolved !== void 0 && typeof resolved !== "boolean") return resolved;
|
|
602
751
|
}
|
|
603
752
|
throw new Error(`Unsupported OpenAPI ref format: ${ref}`);
|
|
604
753
|
}
|
|
@@ -631,4 +780,4 @@ function extractRootMetaFromJson(jsonSchema) {
|
|
|
631
780
|
return Object.keys(meta).length > 0 ? meta : void 0;
|
|
632
781
|
}
|
|
633
782
|
//#endregion
|
|
634
|
-
export { __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, normaliseSchema };
|
|
783
|
+
export { __CLASSIFIER_RULES_FOR_TEST, detectSchemaKind, extractRootMetaFromJson, normaliseSchema };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as StringConstraints, f as FileConstraints, t as ArrayConstraints, x as ObjectConstraints, y as NumberConstraints } from "../types-
|
|
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) {
|