schema-components 1.17.0 → 1.18.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 (48) hide show
  1. package/dist/core/adapter.d.mts +1 -1
  2. package/dist/core/constraints.d.mts +1 -1
  3. package/dist/core/diagnostics.d.mts +1 -1
  4. package/dist/core/merge.d.mts +14 -8
  5. package/dist/core/merge.mjs +81 -12
  6. package/dist/core/normalise.d.mts +1 -1
  7. package/dist/core/ref.d.mts +1 -1
  8. package/dist/core/renderer.d.mts +2 -2
  9. package/dist/core/renderer.mjs +50 -1
  10. package/dist/core/swagger2.d.mts +1 -1
  11. package/dist/core/typeInference.d.mts +2 -2
  12. package/dist/core/walkBuilders.d.mts +2 -2
  13. package/dist/core/walker.mjs +2 -2
  14. package/dist/{diagnostics-DzbZmcLI.d.mts → diagnostics-BYk63jsC.d.mts} +1 -1
  15. package/dist/html/a11y.d.mts +13 -2
  16. package/dist/html/a11y.mjs +26 -2
  17. package/dist/html/renderToHtml.d.mts +1 -1
  18. package/dist/html/renderToHtml.mjs +5 -3
  19. package/dist/html/renderToHtmlStream.d.mts +1 -1
  20. package/dist/html/renderers.d.mts +4 -3
  21. package/dist/html/renderers.mjs +9 -13
  22. package/dist/html/streamRenderers.d.mts +1 -1
  23. package/dist/openapi/bundle.d.mts +9 -4
  24. package/dist/openapi/bundle.mjs +73 -15
  25. package/dist/openapi/components.d.mts +1 -1
  26. package/dist/openapi/components.mjs +22 -17
  27. package/dist/openapi/parser.mjs +8 -8
  28. package/dist/openapi/resolve.d.mts +13 -2
  29. package/dist/openapi/resolve.mjs +19 -3
  30. package/dist/react/SchemaComponent.d.mts +4 -4
  31. package/dist/react/SchemaComponent.mjs +2 -31
  32. package/dist/react/SchemaView.d.mts +4 -3
  33. package/dist/react/SchemaView.mjs +13 -44
  34. package/dist/react/headless.d.mts +1 -1
  35. package/dist/react/headlessRenderers.d.mts +1 -1
  36. package/dist/react/headlessRenderers.mjs +3 -2
  37. package/dist/{ref-DvWoULcy.d.mts → ref-Ckt5liZs.d.mts} +1 -1
  38. package/dist/{renderer-B3s8o2B8.d.mts → renderer-DXo-rXHJ.d.mts} +18 -1
  39. package/dist/themes/mantine.d.mts +1 -1
  40. package/dist/themes/mantine.mjs +4 -3
  41. package/dist/themes/mui.d.mts +1 -1
  42. package/dist/themes/mui.mjs +6 -5
  43. package/dist/themes/radix.d.mts +1 -1
  44. package/dist/themes/radix.mjs +3 -3
  45. package/dist/themes/shadcn.d.mts +1 -1
  46. package/dist/themes/shadcn.mjs +6 -5
  47. package/dist/{typeInference-k7FXfTVO.d.mts → typeInference-5JiqIZ8t.d.mts} +57 -4
  48. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
2
  import { inputId, toReactNode } from "../react/headlessRenderers.mjs";
3
3
  import { headlessResolver } from "../react/headless.mjs";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
4
  import { isValidElement } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/themes/mui.tsx
7
7
  function ariaRequired(tree) {
8
8
  return { required: tree.isOptional === false };
@@ -117,15 +117,15 @@ function renderEnumInput(props) {
117
117
  children: [/* @__PURE__ */ jsxs(MuiMenuItem, {
118
118
  value: "",
119
119
  children: ["Select", "…"]
120
- }), (props.enumValues ?? []).map((v) => /* @__PURE__ */ jsx(MuiMenuItem, {
120
+ }), (props.tree.type === "enum" ? props.tree.enumValues : []).map((v) => /* @__PURE__ */ jsx(MuiMenuItem, {
121
121
  value: v,
122
122
  children: v
123
123
  }, v))]
124
124
  });
125
125
  }
126
126
  function renderObjectContainer(props) {
127
- const fields = props.fields;
128
- if (fields === void 0) return null;
127
+ if (props.tree.type !== "object") return null;
128
+ const fields = props.tree.fields;
129
129
  const obj = isObject(props.value) ? props.value : {};
130
130
  return /* @__PURE__ */ jsxs(MuiBox, {
131
131
  sx: {
@@ -150,7 +150,8 @@ function renderObjectContainer(props) {
150
150
  }
151
151
  function renderArrayContainer(props) {
152
152
  const arr = Array.isArray(props.value) ? props.value : [];
153
- const element = props.element;
153
+ if (props.tree.type !== "array") return null;
154
+ const element = props.tree.element;
154
155
  if (element === void 0) return null;
155
156
  return /* @__PURE__ */ jsx(MuiBox, {
156
157
  sx: {
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
1
+ import { r as ComponentResolver } from "../renderer-DXo-rXHJ.mjs";
2
2
 
3
3
  //#region src/themes/radix.d.ts
4
4
  /**
@@ -142,15 +142,15 @@ function renderEnumInput(props) {
142
142
  children: [/* @__PURE__ */ jsx(RadixSelectTrigger, {
143
143
  id,
144
144
  mt: "1"
145
- }), /* @__PURE__ */ jsx(RadixSelectContent, { children: (props.enumValues ?? []).map((value) => /* @__PURE__ */ jsx(RadixSelectItem, {
145
+ }), /* @__PURE__ */ jsx(RadixSelectContent, { children: (props.tree.type === "enum" ? props.tree.enumValues : []).map((value) => /* @__PURE__ */ jsx(RadixSelectItem, {
146
146
  value,
147
147
  children: value
148
148
  }, value)) })]
149
149
  })] });
150
150
  }
151
151
  function renderObjectContainer(props) {
152
- const fields = props.fields;
153
- if (fields === void 0) return null;
152
+ if (props.tree.type !== "object") return null;
153
+ const fields = props.tree.fields;
154
154
  const obj = isObject(props.value) ? props.value : {};
155
155
  return /* @__PURE__ */ jsxs(RadixBox, { children: [typeof props.meta.description === "string" && /* @__PURE__ */ jsx(RadixText, {
156
156
  as: "div",
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
1
+ import { r as ComponentResolver } from "../renderer-DXo-rXHJ.mjs";
2
2
 
3
3
  //#region src/themes/shadcn.d.ts
4
4
  declare const shadcnResolver: ComponentResolver;
@@ -94,8 +94,8 @@ function renderBooleanInput(props) {
94
94
  });
95
95
  }
96
96
  function renderObjectContainer(props) {
97
- const fields = props.fields;
98
- if (fields === void 0) return null;
97
+ if (props.tree.type !== "object") return null;
98
+ const fields = props.tree.fields;
99
99
  const obj = typeof props.value === "object" && props.value !== null && !Array.isArray(props.value) ? props.value : {};
100
100
  return /* @__PURE__ */ jsxs("div", {
101
101
  className: "space-y-4",
@@ -124,7 +124,8 @@ function renderObjectContainer(props) {
124
124
  }
125
125
  function renderArrayContainer(props) {
126
126
  const arr = Array.isArray(props.value) ? props.value : [];
127
- const element = props.element;
127
+ if (props.tree.type !== "array") return null;
128
+ const element = props.tree.element;
128
129
  if (element === void 0) return null;
129
130
  return /* @__PURE__ */ jsx("div", {
130
131
  className: "space-y-2",
@@ -157,13 +158,13 @@ function renderEnumInput(props) {
157
158
  children: [/* @__PURE__ */ jsxs("option", {
158
159
  value: "",
159
160
  children: ["Select", "…"]
160
- }), props.enumValues?.map((v) => {
161
+ }), props.tree.type === "enum" ? props.tree.enumValues.map((v) => {
161
162
  const display = v === null ? "null" : typeof v === "string" ? v : String(v);
162
163
  return /* @__PURE__ */ jsx("option", {
163
164
  value: display,
164
165
  children: display
165
166
  }, display);
166
- })]
167
+ }) : null]
167
168
  });
168
169
  }
169
170
  function buildResolver() {
@@ -84,26 +84,71 @@ type UnsafeFields = Record<string, FieldOverride> & {
84
84
  * Returns the original type when the schema is non-recursive.
85
85
  */
86
86
  type DetectRecursiveFallback<T> = unknown extends T ? __SchemaInferenceFellBack : T;
87
+ /**
88
+ * Type-level recursion bound for $ref resolution.
89
+ *
90
+ * The TypeScript type system imposes its own recursion limit; without an
91
+ * explicit bound a cyclic schema graph would exhaust it and degrade to
92
+ * `any`/`unknown` silently. Ten levels is the runtime walker's parallel
93
+ * — see `countDistinctRefs` in `ref.ts` (lines 52-55), which derives its
94
+ * bound from the number of distinct `$ref` strings in the document.
95
+ *
96
+ * A fixed bound is used here rather than a derived one because the type
97
+ * system has no way to count distinct strings across a recursive `Defs`
98
+ * map without itself recursing — which is the problem the bound exists
99
+ * to solve. Ten covers every realistic schema graph encountered in
100
+ * practice; deeper graphs surface as `__SchemaInferenceFellBack` so
101
+ * consumers can detect the limit explicitly.
102
+ */
103
+ type DEFAULT_MAX_DEPTH = 10;
87
104
  /**
88
105
  * Resolve a $ref against the local definitions context.
106
+ *
107
+ * SOURCE-OF-TRUTH: mirrors runtime `resolveRef` in
108
+ * `packages/core/src/core/ref.ts` (line 90). Any change to the runtime
109
+ * ref-resolution rules (new ref forms, different cycle handling) must be
110
+ * reflected here and pinned in
111
+ * `packages/core/tests/typeInference-walker-parity.test.ts`.
112
+ *
89
113
  * Supports:
90
114
  * - `#` (root)
91
115
  * - `#/$defs/Name` and `#/definitions/Name` (named definitions)
92
116
  * - `#SomeName` ($anchor, $dynamicAnchor resolved from definitions)
93
117
  */
94
- type ResolveSchemaRef<R extends string, Defs extends Record<string, unknown>, Depth extends number = 0> = Depth extends 10 ? __SchemaInferenceFellBack : R extends "#" ? unknown : R extends `#/$defs/${infer Name}` ? Name extends keyof Defs ? DetectRecursiveFallback<FromJSONSchema<Defs[Name], Defs>> : unknown : R extends `#/definitions/${infer Name}` ? Name extends keyof Defs ? DetectRecursiveFallback<FromJSONSchema<Defs[Name], Defs>> : unknown : R extends `#${infer AnchorName}` ? AnchorName extends keyof Defs ? DetectRecursiveFallback<FromJSONSchema<Defs[AnchorName], Defs>> : unknown : unknown;
118
+ type ResolveSchemaRef<R extends string, Defs extends Record<string, unknown>, Depth extends number = 0> = Depth extends DEFAULT_MAX_DEPTH ? __SchemaInferenceFellBack : R extends "#" ? unknown : R extends `#/$defs/${infer Name}` ? Name extends keyof Defs ? DetectRecursiveFallback<FromJSONSchema<Defs[Name], Defs>> : unknown : R extends `#/definitions/${infer Name}` ? Name extends keyof Defs ? DetectRecursiveFallback<FromJSONSchema<Defs[Name], Defs>> : unknown : R extends `#${infer AnchorName}` ? AnchorName extends keyof Defs ? DetectRecursiveFallback<FromJSONSchema<Defs[AnchorName], Defs>> : unknown : unknown;
95
119
  /**
96
120
  * Merge an allOf array into an intersection type.
97
121
  */
98
122
  type AllOfToType<A, Defs extends Record<string, unknown>> = A extends readonly unknown[] ? UnionToIntersection<FromJSONSchema<A[number], Defs>> : unknown;
99
123
  /**
100
124
  * Convert an anyOf/oneOf array into a union type.
101
- * Filters out `{ type: "null" }` members and instead makes the result nullable
102
- * when at least one null member is present -- mirrors the walker's normaliseAnyOf.
125
+ *
126
+ * SOURCE-OF-TRUTH: mirrors runtime `walkUnion` (and the
127
+ * `walkDiscriminatedUnion` fast path) in
128
+ * `packages/core/src/core/walker.ts` (lines 723-752), together with
129
+ * `detectDiscriminated` and `normaliseAnyOf` in
130
+ * `packages/core/src/core/merge.ts` (lines 190-260).
131
+ *
132
+ * Deliberate divergence: the walker collapses qualifying `oneOf` members
133
+ * into a `discriminatedUnion` field at runtime. The type-level helper
134
+ * produces a plain TypeScript union because a discriminated union and a
135
+ * plain union over the same members are structurally indistinguishable
136
+ * at the type level. Parity is pinned in
137
+ * `packages/core/tests/typeInference-walker-parity.test.ts`.
138
+ *
139
+ * Filters out `{ type: "null" }` members and instead makes the result
140
+ * nullable when at least one null member is present — mirrors the
141
+ * walker's `normaliseAnyOf`.
103
142
  */
104
143
  type UnionOfMembers<A, Defs extends Record<string, unknown>> = A extends readonly unknown[] ? HasNullMember<A> extends true ? Exclude<FromJSONSchema<A[number], Defs>, null> | null : FromJSONSchema<A[number], Defs> : unknown;
105
144
  /**
106
145
  * Check whether an anyOf/oneOf array contains a `{ type: "null" }` member.
146
+ *
147
+ * SOURCE-OF-TRUTH: mirrors runtime `normaliseAnyOf` in
148
+ * `packages/core/src/core/merge.ts` (lines 190-209). Both implementations
149
+ * only recognise schema-shaped null members (`{ type: "null" }`); a bare
150
+ * `null` literal in the array is treated as non-nullable. Parity is
151
+ * pinned in `packages/core/tests/typeInference-walker-parity.test.ts`.
107
152
  */
108
153
  type HasNullMember<A> = A extends readonly unknown[] ? null extends A[number] ? false : {
109
154
  type: "null";
@@ -214,6 +259,14 @@ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) exten
214
259
  /**
215
260
  * Resolves an OpenAPI `ref` string to its JSON Schema, then parses it.
216
261
  *
262
+ * SOURCE-OF-TRUTH: mirrors runtime `resolveRef` in
263
+ * `packages/core/src/core/ref.ts` (line 90), which is invoked by the
264
+ * walker entry point in `packages/core/src/core/walker.ts` (lines
265
+ * 144-154) for OpenAPI documents. Any change to the runtime ref-resolution
266
+ * rules (new ref forms, different cycle handling, JSON Pointer decoding)
267
+ * must be reflected here and pinned in
268
+ * `packages/core/tests/typeInference-walker-parity.test.ts`.
269
+ *
217
270
  * Handles:
218
271
  * - `#/components/schemas/Name` (OpenAPI 3.x)
219
272
  * - `#/definitions/Name` (Swagger 2.0)
@@ -332,4 +385,4 @@ type PathOfType<T, Prefix extends string = ""> = IsNarrowObject<T> extends true
332
385
  */
333
386
  type TypeAtPath<T, P extends string> = P extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? TypeAtPath<T[Key], Rest> : unknown : P extends keyof T ? T[P] : unknown;
334
387
  //#endregion
335
- export { OpenAPIRequestBodyType as a, ResolveOpenAPIRef as c, __SchemaInferenceFellBack as d, InferResponseFields as i, TypeAtPath as l, InferParameterOverrides as n, OpenAPIResponseType as o, InferRequestBodyFields as r, PathOfType as s, FromJSONSchema as t, UnsafeFields as u };
388
+ export { InferResponseFields as a, PathOfType as c, UnsafeFields as d, __SchemaInferenceFellBack as f, InferRequestBodyFields as i, ResolveOpenAPIRef as l, FromJSONSchema as n, OpenAPIRequestBodyType as o, InferParameterOverrides as r, OpenAPIResponseType as s, DEFAULT_MAX_DEPTH as t, TypeAtPath as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schema-components",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "React components that render UI from Zod schemas, JSON Schema, and OpenAPI documents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",