schema-components 1.18.1 → 1.19.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.
Files changed (49) hide show
  1. package/dist/core/adapter.d.mts +1 -1
  2. package/dist/core/adapter.mjs +77 -14
  3. package/dist/core/constraints.d.mts +1 -1
  4. package/dist/core/diagnostics.d.mts +1 -1
  5. package/dist/core/errors.d.mts +1 -1
  6. package/dist/core/errors.mjs +7 -1
  7. package/dist/core/formats.mjs +9 -1
  8. package/dist/core/merge.d.mts +1 -1
  9. package/dist/core/normalise.d.mts +38 -5
  10. package/dist/core/normalise.mjs +2 -2
  11. package/dist/core/openapi30.d.mts +33 -4
  12. package/dist/core/openapi30.mjs +2 -2
  13. package/dist/core/ref.d.mts +1 -1
  14. package/dist/core/renderer.d.mts +1 -1
  15. package/dist/core/renderer.mjs +7 -2
  16. package/dist/core/swagger2.d.mts +1 -1
  17. package/dist/core/swagger2.mjs +1 -1
  18. package/dist/core/version.d.mts +2 -2
  19. package/dist/core/version.mjs +19 -9
  20. package/dist/core/walkBuilders.d.mts +2 -2
  21. package/dist/{diagnostics-BYk63jsC.d.mts → diagnostics-VgEKI_Ct.d.mts} +1 -1
  22. package/dist/{errors-C5zRC2PU.d.mts → errors-CnGjT1cg.d.mts} +7 -2
  23. package/dist/html/a11y.d.mts +1 -1
  24. package/dist/html/renderToHtml.d.mts +1 -1
  25. package/dist/html/renderToHtmlStream.d.mts +1 -1
  26. package/dist/html/renderers.d.mts +1 -1
  27. package/dist/html/renderers.mjs +28 -0
  28. package/dist/html/streamRenderers.d.mts +1 -1
  29. package/dist/{normalise-tL9FckAk.mjs → normalise-C0ofw3W6.mjs} +418 -97
  30. package/dist/openapi/components.mjs +4 -0
  31. package/dist/openapi/parser.mjs +4 -1
  32. package/dist/openapi/resolve.d.mts +6 -5
  33. package/dist/openapi/resolve.mjs +7 -6
  34. package/dist/react/SchemaComponent.d.mts +3 -3
  35. package/dist/react/SchemaComponent.mjs +3 -13
  36. package/dist/react/SchemaView.d.mts +2 -2
  37. package/dist/react/SchemaView.mjs +1 -0
  38. package/dist/react/headless.d.mts +7 -1
  39. package/dist/react/headless.mjs +13 -1
  40. package/dist/react/headlessRenderers.d.mts +53 -2
  41. package/dist/react/headlessRenderers.mjs +139 -1
  42. package/dist/{ref-Ckt5liZs.d.mts → ref-Bb43ZURY.d.mts} +1 -1
  43. package/dist/{renderer-BAGoX4AK.d.mts → renderer-BQqiXUYP.d.mts} +8 -2
  44. package/dist/themes/mantine.d.mts +1 -1
  45. package/dist/themes/mui.d.mts +1 -1
  46. package/dist/themes/radix.d.mts +1 -1
  47. package/dist/themes/shadcn.d.mts +1 -1
  48. package/dist/{version-B5NV-35j.d.mts → version-XNH7PRGP.d.mts} +8 -1
  49. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { T as SchemaMeta, m as JsonObject } from "../types-D_5ST7SS.mjs";
2
- import { i as DiagnosticsOptions } from "../diagnostics-BYk63jsC.mjs";
2
+ import { i as DiagnosticsOptions } from "../diagnostics-VgEKI_Ct.mjs";
3
3
 
4
4
  //#region src/core/adapter.d.ts
5
5
  type SchemaInput = Record<string, unknown>;
@@ -1,8 +1,9 @@
1
1
  import { getProperty, hasProperty, isObject } from "./guards.mjs";
2
+ import { SchemaNormalisationError } from "./errors.mjs";
2
3
  import { emitDiagnostic } from "./diagnostics.mjs";
3
4
  import { dereference } from "./ref.mjs";
4
- import { detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraftWithReason, isSwagger2 } from "./version.mjs";
5
- import { i as normaliseOpenApiSchemas, r as normaliseJsonSchema$1 } from "../normalise-tL9FckAk.mjs";
5
+ import { detectOpenApiVersion, inferJsonSchemaDraftWithReason, isSwagger2, matchJsonSchemaDraftUri } from "./version.mjs";
6
+ import { a as normaliseOpenApiSchemas, i as normaliseJsonSchema$1 } from "../normalise-C0ofw3W6.mjs";
6
7
  import { z } from "zod";
7
8
  //#region src/core/adapter.ts
8
9
  /**
@@ -30,9 +31,55 @@ function detectSchemaKind(input) {
30
31
  * but TypeScript cannot represent "has _zod.def" as the $ZodType parameter
31
32
  * that z.toJSONSchema expects. This is the library boundary equivalent of
32
33
  * object → Record<string, unknown> — the type mismatch is genuinely unavoidable.
34
+ *
35
+ * Any exception thrown by z.toJSONSchema is classified into a
36
+ * SchemaNormalisationError so the caller does not have to re-parse error
37
+ * message strings. The classification covers:
38
+ *
39
+ * - Nested Zod 3 schemas inside a Zod 4 tree (which surface as
40
+ * "Cannot read properties of undefined (reading 'def')") → zod3-unsupported
41
+ * - Transforms ("Transforms cannot be represented") → zod-transform-unsupported
42
+ * - Unrepresentable types ("BigInt cannot be represented", "Date cannot be
43
+ * represented", etc.) → zod-type-unrepresentable
44
+ * - Anything else → zod-conversion-failed
33
45
  */
34
46
  function callToJsonSchema(schema) {
35
- return z.toJSONSchema(schema);
47
+ try {
48
+ return z.toJSONSchema(schema);
49
+ } catch (err) {
50
+ throw classifyZodConversionError(err, schema);
51
+ }
52
+ }
53
+ /**
54
+ * Error messages emitted by Zod 4's z.toJSONSchema for unrepresentable types.
55
+ * Mapping is exact-prefix on the message and the corresponding Zod type name
56
+ * surfaced to the consumer via SchemaNormalisationError.zodType.
57
+ *
58
+ * Source: zod/src/v4/core/to-json-schema.ts ("cannot be represented" messages).
59
+ */
60
+ const UNREPRESENTABLE_ZOD_TYPES = [
61
+ ["BigInt cannot be represented", "bigint"],
62
+ ["Date cannot be represented", "date"],
63
+ ["Map cannot be represented", "map"],
64
+ ["Set cannot be represented", "set"],
65
+ ["Symbols cannot be represented", "symbol"],
66
+ ["Function types cannot be represented", "function"],
67
+ ["Undefined cannot be represented", "undefined"],
68
+ ["Void cannot be represented", "void"],
69
+ ["NaN cannot be represented", "nan"]
70
+ ];
71
+ /**
72
+ * The cryptic error produced when z.toJSONSchema encounters a nested Zod 3
73
+ * schema (one without `_zod.def`). Reproduced verbatim from Node's TypeError
74
+ * for property access on undefined.
75
+ */
76
+ const NESTED_ZOD3_MARKER = "Cannot read properties of undefined";
77
+ function classifyZodConversionError(err, schema) {
78
+ const message = err instanceof Error ? err.message : String(err);
79
+ if (message.includes(NESTED_ZOD3_MARKER)) 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");
80
+ if (message.includes("Transforms cannot be represented")) return 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.", schema, "zod-transform-unsupported");
81
+ for (const [prefix, typeName] of UNREPRESENTABLE_ZOD_TYPES) if (message.includes(prefix)) return new SchemaNormalisationError(`Zod type ${typeName} cannot be represented in JSON Schema and is not supported by schema-components. Original message: ${message}`, schema, "zod-type-unrepresentable", typeName);
82
+ return new SchemaNormalisationError(`z.toJSONSchema() failed: ${message}`, schema, "zod-conversion-failed");
36
83
  }
37
84
  function normaliseSchema(input, ref, options) {
38
85
  if (ref === void 0 && isObject(input)) {
@@ -46,14 +93,14 @@ function normaliseSchema(input, ref, options) {
46
93
  result = normaliseZod4(input);
47
94
  break;
48
95
  case "zod3":
49
- result = normaliseZod3();
96
+ result = normaliseZod3(input);
50
97
  break;
51
98
  case "openapi":
52
- if (!isObject(input)) throw new Error("Invalid OpenAPI document");
99
+ if (!isObject(input)) throw new SchemaNormalisationError("Invalid OpenAPI document", input, "openapi-invalid");
53
100
  result = normaliseOpenApi(input, ref, options);
54
101
  break;
55
102
  case "jsonSchema":
56
- if (!isObject(input)) throw new Error("Invalid JSON Schema");
103
+ if (!isObject(input)) throw new SchemaNormalisationError("Invalid JSON Schema", input, "invalid-json-schema");
57
104
  result = normaliseJsonSchema(input, options?.diagnostics);
58
105
  break;
59
106
  }
@@ -62,10 +109,10 @@ function normaliseSchema(input, ref, options) {
62
109
  }
63
110
  function normaliseZod4(input) {
64
111
  const zod = getProperty(input, "_zod");
65
- if (!isObject(zod)) throw new Error("Invalid Zod 4 schema: missing _zod property");
66
- if (!("def" in zod)) throw new Error("Invalid Zod 4 schema: missing _zod.def");
112
+ if (!isObject(zod)) throw new SchemaNormalisationError("Invalid Zod 4 schema: missing _zod property", input, "invalid-zod");
113
+ if (!("def" in zod)) throw new SchemaNormalisationError("Invalid Zod 4 schema: missing _zod.def", input, "invalid-zod");
67
114
  const jsonSchema = callToJsonSchema(input);
68
- if (!isObject(jsonSchema)) throw new Error("z.toJSONSchema() did not produce an object");
115
+ if (!isObject(jsonSchema)) throw new SchemaNormalisationError("z.toJSONSchema() did not produce an object", input, "invalid-zod");
69
116
  return {
70
117
  jsonSchema,
71
118
  zodSchema: input,
@@ -75,7 +122,8 @@ function normaliseZod4(input) {
75
122
  }
76
123
  function normaliseJsonSchema(jsonSchema, diagnostics) {
77
124
  let draft;
78
- if (typeof jsonSchema.$schema !== "string") {
125
+ const $schema = jsonSchema.$schema;
126
+ if (typeof $schema !== "string") {
79
127
  const inferred = inferJsonSchemaDraftWithReason(jsonSchema);
80
128
  draft = inferred.draft;
81
129
  emitDiagnostic(diagnostics, {
@@ -87,16 +135,31 @@ function normaliseJsonSchema(jsonSchema, diagnostics) {
87
135
  draft: inferred.draft
88
136
  }
89
137
  });
90
- } else draft = detectJsonSchemaDraft(jsonSchema);
91
- const normalised = normaliseJsonSchema$1(jsonSchema, draft);
138
+ } else {
139
+ const matched = matchJsonSchemaDraftUri($schema);
140
+ if (matched === void 0) {
141
+ draft = "draft-2020-12";
142
+ emitDiagnostic(diagnostics, {
143
+ code: "assumed-draft",
144
+ message: `Unknown $schema URI "${$schema}"; assuming draft-2020-12`,
145
+ pointer: "",
146
+ detail: {
147
+ inferredFrom: "unknown-uri",
148
+ draft,
149
+ uri: $schema
150
+ }
151
+ });
152
+ } else draft = matched;
153
+ }
154
+ const normalised = normaliseJsonSchema$1(jsonSchema, draft, diagnostics);
92
155
  return {
93
156
  jsonSchema: normalised,
94
157
  rootMeta: extractRootMetaFromJson(normalised),
95
158
  rootDocument: normalised
96
159
  };
97
160
  }
98
- function normaliseZod3() {
99
- throw new Error("Zod 3 schemas are not supported. schema-components requires Zod 4. Detected: Zod 3 (has _def without _zod). See the Zod 4 migration guide at https://zod.dev/v4/migration or run: pnpm add zod@^4");
161
+ function normaliseZod3(input) {
162
+ throw new SchemaNormalisationError("Zod 3 schemas are not supported. schema-components requires Zod 4. Detected: Zod 3 (has _def without _zod). See the Zod 4 migration guide at https://zod.dev/v4/migration or run: pnpm add zod@^4", input, "zod3-unsupported");
100
163
  }
101
164
  /**
102
165
  * Mapping of Swagger 2.0 $ref prefixes to their OpenAPI 3.x equivalents.
@@ -1,5 +1,5 @@
1
1
  import { D as StringConstraints, f as FileConstraints, t as ArrayConstraints, x as ObjectConstraints, y as NumberConstraints } from "../types-D_5ST7SS.mjs";
2
- import { i as DiagnosticsOptions } from "../diagnostics-BYk63jsC.mjs";
2
+ import { i as DiagnosticsOptions } from "../diagnostics-VgEKI_Ct.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,2 +1,2 @@
1
- import { a as appendPointer, i as DiagnosticsOptions, n as DiagnosticCode, o as emitDiagnostic, r as DiagnosticSink, t as Diagnostic } from "../diagnostics-BYk63jsC.mjs";
1
+ import { a as appendPointer, i as DiagnosticsOptions, n as DiagnosticCode, o as emitDiagnostic, r as DiagnosticSink, t as Diagnostic } from "../diagnostics-VgEKI_Ct.mjs";
2
2
  export { Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticsOptions, appendPointer, emitDiagnostic };
@@ -1,2 +1,2 @@
1
- import { i as SchemaRenderError, n as SchemaFieldError, r as SchemaNormalisationError, t as SchemaError } from "../errors-C5zRC2PU.mjs";
1
+ import { i as SchemaRenderError, n as SchemaFieldError, r as SchemaNormalisationError, t as SchemaError } from "../errors-CnGjT1cg.mjs";
2
2
  export { SchemaError, SchemaFieldError, SchemaNormalisationError, SchemaRenderError };
@@ -32,10 +32,16 @@ var SchemaError = class extends Error {
32
32
  */
33
33
  var SchemaNormalisationError = class extends SchemaError {
34
34
  kind;
35
- constructor(message, schema, kind) {
35
+ /**
36
+ * For `zod-type-unrepresentable`, the offending Zod type name
37
+ * (e.g. "bigint", "date", "map", "set"). `undefined` for other kinds.
38
+ */
39
+ zodType;
40
+ constructor(message, schema, kind, zodType) {
36
41
  super(message, schema);
37
42
  this.name = "SchemaNormalisationError";
38
43
  this.kind = kind;
44
+ this.zodType = zodType;
39
45
  }
40
46
  };
41
47
  /**
@@ -19,7 +19,15 @@ const FORMAT_PATTERNS = {
19
19
  "relative-json-pointer": /^(0|[1-9][0-9]*)(#?([/]([^/~]|~0|~1)*)*)?$/,
20
20
  duration: /^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+(\.\d+)?S)?)?$/,
21
21
  "idn-email": /^[^\s@]+@[^\s@]+\.[^\s@]+$/u,
22
- "idn-hostname": /^[a-z0-9\u00a1-\uffff]([a-z0-9\u00a1-\uffff-]{0,61}[a-z0-9\u00a1-\uffff])?(\.[a-z0-9\u00a1-\uffff]([a-z0-9\u00a1-\uffff-]{0,61}[a-z0-9\u00a1-\uffff])?)*$/iu
22
+ "idn-hostname": /^[a-z0-9\u00a1-\uffff]([a-z0-9\u00a1-\uffff-]{0,61}[a-z0-9\u00a1-\uffff])?(\.[a-z0-9\u00a1-\uffff]([a-z0-9\u00a1-\uffff-]{0,61}[a-z0-9\u00a1-\uffff])?)*$/iu,
23
+ cuid: /^[cC][0-9a-z]{6,}$/,
24
+ cuid2: /^[0-9a-z]+$/,
25
+ nanoid: /^[a-zA-Z0-9_-]{21}$/,
26
+ cidrv4: /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,
27
+ cidrv6: /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,
28
+ base64: /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,
29
+ base64url: /^[A-Za-z0-9_-]*$/,
30
+ e164: /^\+[1-9]\d{6,14}$/
23
31
  };
24
32
  /**
25
33
  * Format validators that use predicate functions instead of regex.
@@ -1,4 +1,4 @@
1
- import { i as DiagnosticsOptions } from "../diagnostics-BYk63jsC.mjs";
1
+ import { i as DiagnosticsOptions } from "../diagnostics-VgEKI_Ct.mjs";
2
2
 
3
3
  //#region src/core/merge.d.ts
4
4
  /**
@@ -1,5 +1,5 @@
1
- import { i as DiagnosticsOptions } from "../diagnostics-BYk63jsC.mjs";
2
- import { n as JsonSchemaDraft, r as OpenApiVersionInfo } from "../version-B5NV-35j.mjs";
1
+ import { i as DiagnosticsOptions } from "../diagnostics-VgEKI_Ct.mjs";
2
+ import { n as JsonSchemaDraft, r as OpenApiVersionInfo } from "../version-XNH7PRGP.mjs";
3
3
 
4
4
  //#region src/core/normalise.d.ts
5
5
  type NodeTransform = (node: Record<string, unknown>) => Record<string, unknown>;
@@ -8,9 +8,32 @@ type NodeTransform = (node: Record<string, unknown>) => Record<string, unknown>;
8
8
  * and recursing into every sub-schema location.
9
9
  */
10
10
  declare function deepNormalise(schema: Record<string, unknown>, transform: NodeTransform): Record<string, unknown>;
11
+ /**
12
+ * Per-node context threaded through `deepNormaliseWithContext`.
13
+ *
14
+ * Carries the diagnostics sink and the JSON Pointer to the current
15
+ * node so per-node transforms can emit pointer-accurate diagnostics
16
+ * when they translate or reject legacy constructs.
17
+ */
18
+ interface NodeContext {
19
+ diagnostics: DiagnosticsOptions | undefined;
20
+ pointer: string;
21
+ }
22
+ type NodeTransformWithContext = (node: Record<string, unknown>, ctx: NodeContext) => Record<string, unknown>;
23
+ /**
24
+ * Deep-normalise a JSON Schema object, threading a context (diagnostics
25
+ * sink + JSON Pointer) through each recursive call. Used by the JSON
26
+ * Schema normalisation path so per-node transforms can emit diagnostics
27
+ * with accurate pointers.
28
+ *
29
+ * Mirrors `deepNormalise` structurally — keep the two in sync when
30
+ * adding new sub-schema locations.
31
+ */
32
+ declare function deepNormaliseWithContext(schema: Record<string, unknown>, transform: NodeTransformWithContext, ctx: NodeContext): Record<string, unknown>;
11
33
  /**
12
34
  * Normalise Draft 04 `exclusiveMinimum`/`exclusiveMaximum` from boolean
13
- * to number form.
35
+ * to number form, plus the other Draft 04 translations applied to a
36
+ * single node.
14
37
  *
15
38
  * In Draft 04:
16
39
  * - `exclusiveMinimum: true` + `minimum: 5` → value must be > 5
@@ -22,13 +45,23 @@ declare function deepNormalise(schema: Record<string, unknown>, transform: NodeT
22
45
  *
23
46
  * The transform converts boolean form to number form so the walker can
24
47
  * treat `exclusiveMinimum`/`exclusiveMaximum` uniformly as numbers.
48
+ *
49
+ * This function preserves the no-context signature for the OpenAPI 3.0
50
+ * and Swagger 2.0 normalisers that compose it directly. The JSON Schema
51
+ * normalisation path uses {@link normaliseDraft04NodeWithContext} via
52
+ * {@link deepNormaliseWithContext} to thread diagnostics.
25
53
  */
26
54
  declare function normaliseDraft04Node(node: Record<string, unknown>): Record<string, unknown>;
27
55
  /**
28
56
  * Normalise a JSON Schema to canonical Draft 2020-12 form.
29
57
  * Deep-clones the input — the original is never mutated.
58
+ *
59
+ * When `diagnostics` is supplied, per-node transforms emit diagnostics
60
+ * for legacy-keyword rewrites and invalid constructs (e.g. `divisibleBy`
61
+ * conflicts, non-string entries in a `dependentRequired` array, legacy
62
+ * `dependencies` reaching the 2020-12 path).
30
63
  */
31
- declare function normaliseJsonSchema(schema: Record<string, unknown>, draft: JsonSchemaDraft): Record<string, unknown>;
64
+ declare function normaliseJsonSchema(schema: Record<string, unknown>, draft: JsonSchemaDraft, diagnostics?: DiagnosticsOptions): Record<string, unknown>;
32
65
  /**
33
66
  * Normalise an OpenAPI document's schemas for walker consumption.
34
67
  * Handles version-specific keyword transformations.
@@ -38,4 +71,4 @@ declare function normaliseJsonSchema(schema: Record<string, unknown>, draft: Jso
38
71
  */
39
72
  declare function normaliseOpenApiSchemas(doc: Record<string, unknown>, version: OpenApiVersionInfo, diagnostics?: DiagnosticsOptions): Record<string, unknown>;
40
73
  //#endregion
41
- export { NodeTransform, deepNormalise, normaliseDraft04Node, normaliseJsonSchema, normaliseOpenApiSchemas };
74
+ export { NodeContext, NodeTransform, NodeTransformWithContext, deepNormalise, deepNormaliseWithContext, normaliseDraft04Node, normaliseJsonSchema, normaliseOpenApiSchemas };
@@ -1,2 +1,2 @@
1
- import { i as normaliseOpenApiSchemas, n as normaliseDraft04Node, r as normaliseJsonSchema, t as deepNormalise } from "../normalise-tL9FckAk.mjs";
2
- export { deepNormalise, normaliseDraft04Node, normaliseJsonSchema, normaliseOpenApiSchemas };
1
+ import { a as normaliseOpenApiSchemas, i as normaliseJsonSchema, n as deepNormaliseWithContext, r as normaliseDraft04Node, t as deepNormalise } from "../normalise-C0ofw3W6.mjs";
2
+ export { deepNormalise, deepNormaliseWithContext, normaliseDraft04Node, normaliseJsonSchema, normaliseOpenApiSchemas };
@@ -32,10 +32,39 @@ declare function normaliseOpenApi30Discriminator(node: Record<string, unknown>):
32
32
  */
33
33
  declare function normaliseOpenApi30Combined(node: Record<string, unknown>): Record<string, unknown>;
34
34
  /**
35
- * Deep-normalise all schemas in an OpenAPI 3.0.x document.
36
- * Walks components/schemas, path operations, parameters, request bodies,
37
- * and responses applying `nullable` normalisation to each schema.
35
+ * Per-schema normaliser supplied by the caller. Given a Schema Object,
36
+ * returns the normalised (deep-cloned) Schema Object. The visitor is
37
+ * agnostic to which transforms run inside.
38
+ */
39
+ type SchemaNormaliser = (schema: Record<string, unknown>) => Record<string, unknown>;
40
+ /**
41
+ * Deep-clone the parent first, then patch back any keys whose values were
42
+ * rewritten by the visitor. This preserves immutability of the original
43
+ * document while keeping the visitor straightforward to write.
44
+ */
45
+ /**
46
+ * Deep-normalise every Schema Object in an OpenAPI document.
47
+ *
48
+ * Walks: `paths.*` (operations + path-level parameters), `webhooks.*`
49
+ * (3.1), `components.schemas`, `components.parameters`,
50
+ * `components.responses`, `components.requestBodies`,
51
+ * `components.headers`, `components.callbacks`, `components.pathItems`
52
+ * (3.1). For each Schema-bearing location, applies the supplied
53
+ * `normaliseSchema` function.
54
+ *
55
+ * The walker is structural (it understands OAS document shapes) and
56
+ * delegates the per-schema transformation. For OAS 3.0 the caller
57
+ * passes a full Draft 04 + nullable + discriminator + example
58
+ * normaliser; for OAS 3.1 the caller passes a discriminator-only
59
+ * normaliser so the walker's discriminated-union detection sees the
60
+ * injected `const`s regardless of OAS minor version.
61
+ */
62
+ declare function deepNormaliseOpenApiDoc(doc: Record<string, unknown>, normaliseSchema: SchemaNormaliser): Record<string, unknown>;
63
+ /**
64
+ * Backwards-compatible wrapper retaining the historic `deepNormalise`
65
+ * signature used by callers in `normalise.ts`. Always applies the full
66
+ * 3.0 combined transform via `deepNormalise(schema, normaliseOpenApi30Combined)`.
38
67
  */
39
68
  declare function deepNormaliseOpenApi30Doc(doc: Record<string, unknown>, deepNormalise: (schema: Record<string, unknown>, transform: NodeTransform) => Record<string, unknown>): Record<string, unknown>;
40
69
  //#endregion
41
- export { deepNormaliseOpenApi30Doc, normaliseOpenApi30Combined, normaliseOpenApi30Discriminator, normaliseOpenApi30Node };
70
+ export { deepNormaliseOpenApi30Doc, deepNormaliseOpenApiDoc, normaliseOpenApi30Combined, normaliseOpenApi30Discriminator, normaliseOpenApi30Node };
@@ -1,2 +1,2 @@
1
- import { c as normaliseOpenApi30Discriminator, l as normaliseOpenApi30Node, o as deepNormaliseOpenApi30Doc, s as normaliseOpenApi30Combined } from "../normalise-tL9FckAk.mjs";
2
- export { deepNormaliseOpenApi30Doc, normaliseOpenApi30Combined, normaliseOpenApi30Discriminator, normaliseOpenApi30Node };
1
+ import { c as deepNormaliseOpenApiDoc, d as normaliseOpenApi30Node, l as normaliseOpenApi30Combined, s as deepNormaliseOpenApi30Doc, u as normaliseOpenApi30Discriminator } from "../normalise-C0ofw3W6.mjs";
2
+ export { deepNormaliseOpenApi30Doc, deepNormaliseOpenApiDoc, normaliseOpenApi30Combined, normaliseOpenApi30Discriminator, normaliseOpenApi30Node };
@@ -1,2 +1,2 @@
1
- import { a as findAnchor, i as dereference, n as RefOptions, o as resolveRef, r as countDistinctRefs, t as ExternalResolver } from "../ref-Ckt5liZs.mjs";
1
+ import { a as findAnchor, i as dereference, n as RefOptions, o as resolveRef, r as countDistinctRefs, t as ExternalResolver } from "../ref-Bb43ZURY.mjs";
2
2
  export { ExternalResolver, RefOptions, countDistinctRefs, dereference, findAnchor, resolveRef };
@@ -1,2 +1,2 @@
1
- import { a as HtmlRenderProps, c as RenderFunction, d as getHtmlRenderFn, f as getRenderFunction, h as typeToKey, i as HtmlRenderFunction, l as RenderProps, m as mergeResolvers, n as BaseFieldProps, o as HtmlResolver, p as mergeHtmlResolvers, r as ComponentResolver, s as RESOLVER_KEYS, t as AllConstraints, u as buildRenderProps } from "../renderer-BAGoX4AK.mjs";
1
+ import { a as HtmlRenderProps, c as RenderFunction, d as getHtmlRenderFn, f as getRenderFunction, h as typeToKey, i as HtmlRenderFunction, l as RenderProps, m as mergeResolvers, n as BaseFieldProps, o as HtmlResolver, p as mergeHtmlResolvers, r as ComponentResolver, s as RESOLVER_KEYS, t as AllConstraints, u as buildRenderProps } from "../renderer-BQqiXUYP.mjs";
2
2
  export { AllConstraints, BaseFieldProps, ComponentResolver, HtmlRenderFunction, HtmlRenderProps, HtmlResolver, RESOLVER_KEYS, RenderFunction, RenderProps, buildRenderProps, getHtmlRenderFn, getRenderFunction, mergeHtmlResolvers, mergeResolvers, typeToKey };
@@ -33,6 +33,7 @@ const RESOLVER_KEYS = [
33
33
  "string",
34
34
  "number",
35
35
  "boolean",
36
+ "null",
36
37
  "enum",
37
38
  "object",
38
39
  "array",
@@ -45,17 +46,21 @@ const RESOLVER_KEYS = [
45
46
  "recursive",
46
47
  "literal",
47
48
  "file",
49
+ "never",
48
50
  "unknown"
49
51
  ];
50
52
  /**
51
53
  * Map a schema type to the resolver key that handles it.
52
- * `discriminatedUnion` `union`. Unknown types `unknown`.
54
+ * Every WalkedField variant has a direct resolver key — exhaustive switch
55
+ * ensures new variants surface as a type error rather than silently
56
+ * falling through to "unknown".
53
57
  */
54
58
  function typeToKey(type) {
55
59
  switch (type) {
56
60
  case "string":
57
61
  case "number":
58
62
  case "boolean":
63
+ case "null":
59
64
  case "enum":
60
65
  case "object":
61
66
  case "array":
@@ -68,8 +73,8 @@ function typeToKey(type) {
68
73
  case "recursive":
69
74
  case "literal":
70
75
  case "file":
76
+ case "never":
71
77
  case "unknown": return type;
72
- default: return "unknown";
73
78
  }
74
79
  }
75
80
  /**
@@ -1,4 +1,4 @@
1
- import { i as DiagnosticsOptions } from "../diagnostics-BYk63jsC.mjs";
1
+ import { i as DiagnosticsOptions } from "../diagnostics-VgEKI_Ct.mjs";
2
2
  import { NodeTransform } from "./normalise.mjs";
3
3
 
4
4
  //#region src/core/swagger2.d.ts
@@ -1,2 +1,2 @@
1
- import { a as normaliseSwagger2Document } from "../normalise-tL9FckAk.mjs";
1
+ import { o as normaliseSwagger2Document } from "../normalise-C0ofw3W6.mjs";
2
2
  export { normaliseSwagger2Document };
@@ -1,2 +1,2 @@
1
- import { a as detectOpenApiVersion, c as isOpenApi30, i as detectJsonSchemaDraft, l as isOpenApi31, n as JsonSchemaDraft, o as inferJsonSchemaDraft, r as OpenApiVersionInfo, s as inferJsonSchemaDraftWithReason, t as InferredDraft, u as isSwagger2 } from "../version-B5NV-35j.mjs";
2
- export { InferredDraft, JsonSchemaDraft, OpenApiVersionInfo, detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2 };
1
+ import { a as detectOpenApiVersion, c as isOpenApi30, d as matchJsonSchemaDraftUri, i as detectJsonSchemaDraft, l as isOpenApi31, n as JsonSchemaDraft, o as inferJsonSchemaDraft, r as OpenApiVersionInfo, s as inferJsonSchemaDraftWithReason, t as InferredDraft, u as isSwagger2 } from "../version-XNH7PRGP.mjs";
2
+ export { InferredDraft, JsonSchemaDraft, OpenApiVersionInfo, detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2, matchJsonSchemaDraftUri };
@@ -15,6 +15,22 @@ const DRAFT_URIS = new Map([
15
15
  ["https://json-schema.org/draft-04/schema#", "draft-04"]
16
16
  ]);
17
17
  /**
18
+ * Match a `$schema` URI string to a known draft. Returns `undefined`
19
+ * when the URI matches none of the documented Draft 04 – Draft 2020-12
20
+ * schema URIs (including the known prefix patterns) — callers can use
21
+ * this to distinguish an authoritative match from a silent fallback.
22
+ */
23
+ function matchJsonSchemaDraftUri(uri) {
24
+ const exact = DRAFT_URIS.get(uri);
25
+ if (exact !== void 0) return exact;
26
+ for (const [draftUri, draft] of DRAFT_URIS) if (uri.startsWith(draftUri) || uri === draftUri) return draft;
27
+ if (uri.includes("/draft/2020-12/")) return "draft-2020-12";
28
+ if (uri.includes("/draft/2019-09/")) return "draft-2019-09";
29
+ if (uri.includes("/draft-07")) return "draft-07";
30
+ if (uri.includes("/draft-06")) return "draft-06";
31
+ if (uri.includes("/draft-04")) return "draft-04";
32
+ }
33
+ /**
18
34
  * Detect the JSON Schema draft version from a schema's `$schema` URI.
19
35
  * When `$schema` is absent, uses heuristic keyword detection via
20
36
  * `inferJsonSchemaDraft` to guess the draft version.
@@ -24,14 +40,8 @@ const DRAFT_URIS = new Map([
24
40
  function detectJsonSchemaDraft(schema) {
25
41
  const $schema = schema.$schema;
26
42
  if (typeof $schema === "string") {
27
- const exact = DRAFT_URIS.get($schema);
28
- if (exact !== void 0) return exact;
29
- for (const [uri, draft] of DRAFT_URIS) if ($schema.startsWith(uri) || $schema === uri) return draft;
30
- if ($schema.includes("/draft/2020-12/")) return "draft-2020-12";
31
- if ($schema.includes("/draft/2019-09/")) return "draft-2019-09";
32
- if ($schema.includes("/draft-07")) return "draft-07";
33
- if ($schema.includes("/draft-06")) return "draft-06";
34
- if ($schema.includes("/draft-04")) return "draft-04";
43
+ const matched = matchJsonSchemaDraftUri($schema);
44
+ if (matched !== void 0) return matched;
35
45
  return "draft-2020-12";
36
46
  }
37
47
  return inferJsonSchemaDraft(schema);
@@ -148,4 +158,4 @@ function isSwagger2(version) {
148
158
  return version.major === 2;
149
159
  }
150
160
  //#endregion
151
- export { detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2 };
161
+ export { detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2, matchJsonSchemaDraftUri };
@@ -1,6 +1,6 @@
1
1
  import { M as WalkedField, O as StringField, T as SchemaMeta, b as NumberField, c as FieldBase, j as UnknownField, o as Editability, p as FileField, r as BooleanField, v as NullField } from "../types-D_5ST7SS.mjs";
2
- import { i as DiagnosticsOptions } from "../diagnostics-BYk63jsC.mjs";
3
- import { t as ExternalResolver } from "../ref-Ckt5liZs.mjs";
2
+ import { i as DiagnosticsOptions } from "../diagnostics-VgEKI_Ct.mjs";
3
+ import { t as ExternalResolver } from "../ref-Bb43ZURY.mjs";
4
4
 
5
5
  //#region src/core/walkBuilders.d.ts
6
6
  declare function getString(obj: Record<string, unknown>, key: string): string | undefined;
@@ -16,7 +16,7 @@
16
16
  * Machine-readable codes identifying each class of diagnostic.
17
17
  * Stable across releases — consumers can pattern-match on these.
18
18
  */
19
- type DiagnosticCode = "unresolved-ref" | "unknown-keyword" | "unknown-format" | "invalid-const" | "unsupported-type" | "dropped-swagger-feature" | "external-ref" | "type-negation-fallback" | "conditional-fallback" | "assumed-draft" | "depth-exceeded" | "allof-conflict" | "discriminator-inconsistent";
19
+ type DiagnosticCode = "unresolved-ref" | "unknown-keyword" | "unknown-format" | "invalid-const" | "unsupported-type" | "dropped-swagger-feature" | "external-ref" | "type-negation-fallback" | "conditional-fallback" | "assumed-draft" | "depth-exceeded" | "allof-conflict" | "discriminator-inconsistent" | "divisible-by-conflict" | "legacy-dependencies-split" | "dependent-required-invalid";
20
20
  /**
21
21
  * A single diagnostic emitted during schema processing.
22
22
  */
@@ -27,8 +27,13 @@ declare class SchemaError extends Error {
27
27
  * JSON Schema, missing OpenAPI ref, unsupported ref format.
28
28
  */
29
29
  declare class SchemaNormalisationError extends SchemaError {
30
- readonly kind: "invalid-zod" | "zod3-unsupported" | "invalid-json-schema" | "openapi-missing-ref" | "openapi-invalid" | "unknown";
31
- constructor(message: string, schema: unknown, kind: SchemaNormalisationError["kind"]);
30
+ readonly kind: "invalid-zod" | "zod3-unsupported" | "zod-transform-unsupported" | "zod-type-unrepresentable" | "zod-conversion-failed" | "invalid-json-schema" | "openapi-missing-ref" | "openapi-invalid" | "unknown";
31
+ /**
32
+ * For `zod-type-unrepresentable`, the offending Zod type name
33
+ * (e.g. "bigint", "date", "map", "set"). `undefined` for other kinds.
34
+ */
35
+ readonly zodType: string | undefined;
36
+ constructor(message: string, schema: unknown, kind: SchemaNormalisationError["kind"], zodType?: string);
32
37
  }
33
38
  /**
34
39
  * A theme adapter's render function threw during rendering.
@@ -1,5 +1,5 @@
1
1
  import { M as WalkedField } from "../types-D_5ST7SS.mjs";
2
- import { t as AllConstraints } from "../renderer-BAGoX4AK.mjs";
2
+ import { t as AllConstraints } from "../renderer-BQqiXUYP.mjs";
3
3
  import { HtmlAttributes, HtmlNode } from "./html.mjs";
4
4
 
5
5
  //#region src/html/a11y.d.ts
@@ -1,5 +1,5 @@
1
1
  import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
2
- import { o as HtmlResolver } from "../renderer-BAGoX4AK.mjs";
2
+ import { o as HtmlResolver } from "../renderer-BQqiXUYP.mjs";
3
3
 
4
4
  //#region src/html/renderToHtml.d.ts
5
5
  interface RenderToHtmlOptions {
@@ -1,5 +1,5 @@
1
1
  import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
2
- import { o as HtmlResolver } from "../renderer-BAGoX4AK.mjs";
2
+ import { o as HtmlResolver } from "../renderer-BQqiXUYP.mjs";
3
3
 
4
4
  //#region src/html/renderToHtmlStream.d.ts
5
5
  interface StreamRenderOptions {
@@ -1,5 +1,5 @@
1
1
  import { M as WalkedField } from "../types-D_5ST7SS.mjs";
2
- import { o as HtmlResolver } from "../renderer-BAGoX4AK.mjs";
2
+ import { o as HtmlResolver } from "../renderer-BQqiXUYP.mjs";
3
3
 
4
4
  //#region src/html/renderers.d.ts
5
5
  declare function dateInputType(format: string | undefined): string | undefined;
@@ -378,6 +378,32 @@ function renderConditionalHtml(props) {
378
378
  function renderNegationHtml(props) {
379
379
  return serialize(h("div", { class: "sc-negation" }, raw("not: ...")));
380
380
  }
381
+ /**
382
+ * Render a null field — `z.null()` or `{ type: "null" }`.
383
+ *
384
+ * The only valid value is `null`, so render an em-dash placeholder.
385
+ */
386
+ function renderNullHtml(props) {
387
+ return serialize(h("span", {
388
+ class: "sc-value sc-value--empty",
389
+ id: fieldId(props.path),
390
+ ...ariaReadonlyAttrs()
391
+ }, "—"));
392
+ }
393
+ /**
394
+ * Render a never field — `z.never()` or a `false` schema.
395
+ *
396
+ * `never` indicates a position that cannot hold any value. Render a
397
+ * visible placeholder rather than throwing because some valid schemas
398
+ * intentionally contain `never` branches.
399
+ */
400
+ function renderNeverHtml(props) {
401
+ return serialize(h("span", {
402
+ class: "sc-value sc-never",
403
+ id: fieldId(props.path),
404
+ ...ariaReadonlyAttrs()
405
+ }, h("em", {}, "never matches")));
406
+ }
381
407
  function matchUnionOption(options, value) {
382
408
  if (typeof value === "string") return options.find((o) => o.type === "string" || o.type === "enum");
383
409
  if (typeof value === "number") return options.find((o) => o.type === "number");
@@ -389,6 +415,7 @@ const defaultHtmlResolver = {
389
415
  string: renderStringHtml,
390
416
  number: renderNumberHtml,
391
417
  boolean: renderBooleanHtml,
418
+ null: renderNullHtml,
392
419
  enum: renderEnumHtml,
393
420
  object: renderObjectHtml,
394
421
  array: renderArrayHtml,
@@ -401,6 +428,7 @@ const defaultHtmlResolver = {
401
428
  negation: renderNegationHtml,
402
429
  recursive: renderRecursiveHtml,
403
430
  file: renderFileHtml,
431
+ never: renderNeverHtml,
404
432
  unknown: renderUnknownHtml
405
433
  };
406
434
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { M as WalkedField } from "../types-D_5ST7SS.mjs";
2
- import { o as HtmlResolver } from "../renderer-BAGoX4AK.mjs";
2
+ import { o as HtmlResolver } from "../renderer-BQqiXUYP.mjs";
3
3
  import { HtmlElement } from "./html.mjs";
4
4
 
5
5
  //#region src/html/streamRenderers.d.ts