schema-components 1.12.11 → 1.13.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 (63) hide show
  1. package/README.md +31 -0
  2. package/dist/core/adapter.d.mts +1 -1
  3. package/dist/core/adapter.mjs +37 -8
  4. package/dist/core/constraints.d.mts +16 -0
  5. package/dist/core/constraints.mjs +138 -0
  6. package/dist/core/merge.d.mts +32 -0
  7. package/dist/core/merge.mjs +96 -0
  8. package/dist/core/normalise.d.mts +40 -0
  9. package/dist/core/normalise.mjs +171 -0
  10. package/dist/core/openapi30.d.mts +38 -0
  11. package/dist/core/openapi30.mjs +223 -0
  12. package/dist/core/ref.d.mts +25 -0
  13. package/dist/core/ref.mjs +86 -0
  14. package/dist/core/renderer.d.mts +2 -2
  15. package/dist/core/renderer.mjs +8 -0
  16. package/dist/core/swagger2.d.mts +10 -0
  17. package/dist/core/swagger2.mjs +294 -0
  18. package/dist/core/typeInference.d.mts +2 -0
  19. package/dist/core/typeInference.mjs +1 -0
  20. package/dist/core/types.d.mts +2 -3
  21. package/dist/core/types.mjs +55 -2
  22. package/dist/core/version.d.mts +2 -0
  23. package/dist/core/version.mjs +79 -0
  24. package/dist/core/walkBuilders.d.mts +52 -0
  25. package/dist/core/walkBuilders.mjs +152 -0
  26. package/dist/core/walker.d.mts +3 -10
  27. package/dist/core/walker.mjs +143 -231
  28. package/dist/html/a11y.d.mts +5 -4
  29. package/dist/html/renderToHtml.d.mts +3 -3
  30. package/dist/html/renderToHtml.mjs +23 -379
  31. package/dist/html/renderToHtmlStream.d.mts +29 -47
  32. package/dist/html/renderToHtmlStream.mjs +33 -305
  33. package/dist/html/renderers.d.mts +14 -0
  34. package/dist/html/renderers.mjs +406 -0
  35. package/dist/html/streamRenderers.d.mts +13 -0
  36. package/dist/html/streamRenderers.mjs +243 -0
  37. package/dist/openapi/components.d.mts +2 -1
  38. package/dist/openapi/parser.d.mts +59 -2
  39. package/dist/openapi/parser.mjs +189 -8
  40. package/dist/react/SchemaComponent.d.mts +4 -2
  41. package/dist/react/SchemaComponent.mjs +39 -85
  42. package/dist/react/SchemaView.d.mts +2 -1
  43. package/dist/react/SchemaView.mjs +21 -9
  44. package/dist/react/fieldPath.d.mts +20 -0
  45. package/dist/react/fieldPath.mjs +81 -0
  46. package/dist/react/headless.d.mts +2 -4
  47. package/dist/react/headless.mjs +3 -492
  48. package/dist/react/headlessRenderers.d.mts +23 -0
  49. package/dist/react/headlessRenderers.mjs +507 -0
  50. package/dist/renderer-DseHeliw.d.mts +160 -0
  51. package/dist/themes/mantine.d.mts +1 -1
  52. package/dist/themes/mantine.mjs +2 -1
  53. package/dist/themes/mui.d.mts +1 -1
  54. package/dist/themes/mui.mjs +2 -1
  55. package/dist/themes/radix.d.mts +1 -1
  56. package/dist/themes/radix.mjs +2 -1
  57. package/dist/themes/shadcn.d.mts +1 -1
  58. package/dist/themes/shadcn.mjs +10 -6
  59. package/dist/typeInference-CRPqVwKu.d.mts +299 -0
  60. package/dist/types-ag2jYLqQ.d.mts +261 -0
  61. package/dist/version-CLchheaH.d.mts +40 -0
  62. package/package.json +1 -1
  63. package/dist/types-BJzEgJdX.d.mts +0 -335
@@ -1,4 +1,4 @@
1
- import { b as ComponentResolver } from "../types-BJzEgJdX.mjs";
1
+ import { r as ComponentResolver } from "../renderer-DseHeliw.mjs";
2
2
 
3
3
  //#region src/themes/radix.d.ts
4
4
  /**
@@ -1,5 +1,6 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
- import { headlessResolver, toReactNode } from "../react/headless.mjs";
2
+ import { toReactNode } from "../react/headlessRenderers.mjs";
3
+ import { headlessResolver } from "../react/headless.mjs";
3
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
5
  //#region src/themes/radix.tsx
5
6
  function getLabel(props) {
@@ -1,4 +1,4 @@
1
- import { b as ComponentResolver } from "../types-BJzEgJdX.mjs";
1
+ import { r as ComponentResolver } from "../renderer-DseHeliw.mjs";
2
2
 
3
3
  //#region src/themes/shadcn.d.ts
4
4
  declare const shadcnResolver: ComponentResolver;
@@ -1,5 +1,6 @@
1
1
  import { toRecord } from "../core/guards.mjs";
2
- import { headlessResolver, toReactNode } from "../react/headless.mjs";
2
+ import { toReactNode } from "../react/headlessRenderers.mjs";
3
+ import { headlessResolver } from "../react/headless.mjs";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  //#region src/themes/shadcn.tsx
5
6
  function isString(value) {
@@ -138,11 +139,14 @@ function renderEnumInput(props) {
138
139
  },
139
140
  children: [/* @__PURE__ */ jsx("option", {
140
141
  value: "",
141
- children: "Select"
142
- }), props.enumValues?.map((v) => /* @__PURE__ */ jsx("option", {
143
- value: v,
144
- children: v
145
- }, v))]
142
+ children: "Select\\u2026"
143
+ }), props.enumValues?.map((v) => {
144
+ const display = v === null ? "null" : typeof v === "string" ? v : String(v);
145
+ return /* @__PURE__ */ jsx("option", {
146
+ value: display,
147
+ children: display
148
+ }, display);
149
+ })]
146
150
  });
147
151
  }
148
152
  function buildResolver() {
@@ -0,0 +1,299 @@
1
+ import { d as FieldOverrides, u as FieldOverride } from "./types-ag2jYLqQ.mjs";
2
+
3
+ //#region src/core/typeInference.d.ts
4
+ /**
5
+ * Convert a readonly tuple/array of values to a union type.
6
+ * Handles both `as const` readonly tuples and mutable arrays.
7
+ */
8
+ type ArrayToUnion<A> = A extends readonly unknown[] ? A[number] : never;
9
+ /**
10
+ * Maps a JSON Schema structure to a TypeScript type.
11
+ * Works with `as const` literals -- provides full autocomplete for `fields`.
12
+ *
13
+ * Supports all JSON Schema draft versions (04-2020-12) and OpenAPI 3.x:
14
+ * - Primitive types: string, number, integer, boolean, null
15
+ * - type as array: `["string", "null"]` -> `string | null` (nullable)
16
+ * - enum -> union of literal types
17
+ * - const -> literal type
18
+ * - object with properties/required -> specific object type
19
+ * - object with additionalProperties -> Record<string, T>
20
+ * - array with items -> T[]
21
+ * - array with prefixItems -> tuple type
22
+ * - allOf -> intersection type
23
+ * - anyOf -> union type
24
+ * - oneOf -> union type
25
+ * - $ref -> resolved via $defs/definitions/$anchor context
26
+ * - $dynamicRef -> resolved via $dynamicAnchor in definitions
27
+ * - $recursiveRef -> unknown (recursive types not expressible in TS)
28
+ * - if/then/else -> base schema (conditionals not expressible in TS)
29
+ * - not -> unknown (negation not expressible in TS)
30
+ * - patternProperties -> merged into loose index signature
31
+ */
32
+ type FromJSONSchema<S, Defs extends Record<string, unknown> = Record<string, never>> = S extends {
33
+ $ref: infer R extends string;
34
+ } ? ResolveSchemaRef<R, Defs> : S extends {
35
+ $recursiveRef: string;
36
+ } ? unknown : S extends {
37
+ $dynamicRef: infer R extends string;
38
+ } ? ResolveSchemaRef<R, Defs> : S extends {
39
+ allOf: infer A;
40
+ } ? AllOfToType<A, Defs> : S extends {
41
+ anyOf: infer A;
42
+ } ? UnionOfMembers<A, Defs> : S extends {
43
+ oneOf: infer A;
44
+ } ? UnionOfMembers<A, Defs> : S extends {
45
+ if: unknown;
46
+ } ? FromJSONSchema<Omit<S, "if" | "then" | "else">, Defs> : S extends {
47
+ not: unknown;
48
+ } ? unknown : S extends {
49
+ const: infer V;
50
+ } ? V : S extends {
51
+ enum: infer E;
52
+ } ? ArrayToUnion<E> : S extends {
53
+ type: infer T;
54
+ } ? TypeToTs<T, S, Defs> : S extends readonly (infer E)[] ? E : unknown;
55
+ /**
56
+ * Resolve a $ref against the local definitions context.
57
+ * Supports:
58
+ * - `#` (root)
59
+ * - `#/$defs/Name` and `#/definitions/Name` (named definitions)
60
+ * - `#SomeName` ($anchor, $dynamicAnchor resolved from definitions)
61
+ */
62
+ type ResolveSchemaRef<R extends string, Defs extends Record<string, unknown>> = R extends "#" ? unknown : R extends `#/$defs/${infer Name}` ? Name extends keyof Defs ? FromJSONSchema<Defs[Name], Defs> : unknown : R extends `#/definitions/${infer Name}` ? Name extends keyof Defs ? FromJSONSchema<Defs[Name], Defs> : unknown : R extends `#${infer AnchorName}` ? AnchorName extends keyof Defs ? FromJSONSchema<Defs[AnchorName], Defs> : unknown : unknown;
63
+ /**
64
+ * Merge an allOf array into an intersection type.
65
+ */
66
+ type AllOfToType<A, Defs extends Record<string, unknown>> = A extends readonly unknown[] ? UnionToIntersection<FromJSONSchema<A[number], Defs>> : unknown;
67
+ /**
68
+ * Convert an anyOf/oneOf array into a union type.
69
+ * Filters out `{ type: "null" }` members and instead makes the result nullable
70
+ * when at least one null member is present -- mirrors the walker's normaliseAnyOf.
71
+ */
72
+ 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;
73
+ /**
74
+ * Check whether an anyOf/oneOf array contains a `{ type: "null" }` member.
75
+ */
76
+ type HasNullMember<A> = A extends readonly unknown[] ? null extends A[number] ? false : {
77
+ type: "null";
78
+ } extends A[number] ? true : false : false;
79
+ /**
80
+ * Dispatch on a `type` value -- handles single types, type arrays,
81
+ * and delegates to the appropriate type-specific resolver.
82
+ */
83
+ type TypeToTs<T, S, Defs extends Record<string, unknown>> = T extends "string" ? string : T extends "number" | "integer" ? number : T extends "boolean" ? boolean : T extends "null" ? null : T extends "array" ? ArraySchemaToTs<S, Defs> : T extends "object" ? ObjectSchemaToTs<S, Defs> : T extends readonly (infer E)[] ? TypeArrayToTs<E, S, Defs> : unknown;
84
+ /**
85
+ * Handle `type` as an array (Draft 04-07): `["string", "null"]`.
86
+ * Filters out "null" and makes the result nullable.
87
+ */
88
+ type TypeArrayToTs<E, S, Defs extends Record<string, unknown>> = E extends "null" ? null : E extends "string" ? NullableResult<string, S> : E extends "number" | "integer" ? NullableResult<number, S> : E extends "boolean" ? NullableResult<boolean, S> : E extends "array" ? NullableResult<ArraySchemaToTs<OmitArrayHelpers<S>, Defs>, S> : E extends "object" ? NullableResult<ObjectSchemaToTs<OmitArrayHelpers<S>, Defs>, S> : unknown;
89
+ /**
90
+ * Make a type nullable if the original schema `type` array includes "null".
91
+ * Detects nullable from the type array directly.
92
+ */
93
+ type NullableResult<Base, S> = S extends {
94
+ type: readonly (infer T)[];
95
+ } ? "null" extends T ? Base | null : Base : Base;
96
+ /**
97
+ * Omit array-utility keys that interfere with object/array matching
98
+ * when re-parsing a schema for a single type from a type array.
99
+ */
100
+ type OmitArrayHelpers<S> = Omit<S, "prefixItems" | "items" | "additionalProperties">;
101
+ /**
102
+ * Parse an array schema: prefixItems -> tuple, items -> T[], or unknown[].
103
+ *
104
+ * `contains` / `minContains` / `maxContains` constrain elements at runtime
105
+ * but don't change the compile-time array element type.
106
+ */
107
+ type ArraySchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
108
+ prefixItems: infer P;
109
+ } ? PrefixItemsToTuple<P, Defs> : S extends {
110
+ items: infer I;
111
+ } ? FromJSONSchema<I, Defs>[] : unknown[];
112
+ /**
113
+ * Convert a prefixItems array to a TypeScript tuple type.
114
+ */
115
+ type PrefixItemsToTuple<P, Defs extends Record<string, unknown>> = P extends readonly [infer First, ...infer Rest] ? [FromJSONSchema<First, Defs>, ...PrefixItemsToTuple<Rest, Defs>] : [];
116
+ /**
117
+ * Parse an object schema: properties + required -> specific object,
118
+ * additionalProperties -> Record, or empty object.
119
+ *
120
+ * Handles:
121
+ * - `properties` + `required` -> specific object type with required/optional keys
122
+ * - `additionalProperties` as schema -> Record<string, T>
123
+ * - `patternProperties` -> merged into a loose index signature alongside specific props
124
+ * (TypeScript cannot express regex-keyed properties)
125
+ * - `propertyNames` -> ignored at type level (TS cannot validate key shapes)
126
+ * - `dependentSchemas` / `dependentRequired` -> ignored (runtime-only conditionals)
127
+ * - `unevaluatedProperties` -> ignored (runtime-only)
128
+ */
129
+ type ObjectSchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
130
+ type: "object";
131
+ properties: infer P;
132
+ } ? ExtractDefs<S, Defs> extends infer D extends Record<string, unknown> ? MergePatternProps<{ [K in keyof P as K extends RequiredKeysOf<S> ? K : never]: FromJSONSchema<P[K], D> } & { [K in keyof P as K extends RequiredKeysOf<S> ? never : K]?: FromJSONSchema<P[K], D> }, S, D> : never : S extends {
133
+ additionalProperties: infer V;
134
+ } ? Record<string, FromJSONSchema<V, Defs>> : Record<string, unknown>;
135
+ /**
136
+ * If the schema has `patternProperties`, intersect the base object type
137
+ * with a `Record<string, T>` index signature covering all pattern values.
138
+ * If no `patternProperties`, return the base type unchanged.
139
+ */
140
+ type MergePatternProps<Base, S, Defs extends Record<string, unknown>> = S extends {
141
+ patternProperties: infer PP;
142
+ } ? PP extends Record<string, unknown> ? Base & Record<string, UnionOfPatternValues<PP, Defs>> : Base : Base;
143
+ /**
144
+ * Extract the union of all pattern property value types.
145
+ */
146
+ type UnionOfPatternValues<PP extends Record<string, unknown>, Defs extends Record<string, unknown>> = { [K in keyof PP]: FromJSONSchema<PP[K], Defs> }[keyof PP];
147
+ /**
148
+ * Extract the `required` array from a schema as a union of string literals.
149
+ * Handles both readonly `as const` arrays and mutable arrays.
150
+ */
151
+ type RequiredKeysOf<S> = S extends {
152
+ required: infer R;
153
+ } ? R extends readonly string[] ? R[number] : never : never;
154
+ /**
155
+ * Extract $defs / definitions from a schema for $ref resolution context.
156
+ * Also indexes schemas with `$anchor` or `$dynamicAnchor` by their anchor name,
157
+ * enabling `#SomeName` ref resolution.
158
+ * Merges with the existing Defs context from parent schemas.
159
+ */
160
+ type ExtractDefs<S, ParentDefs extends Record<string, unknown>> = ExtractRawDefs<S> extends infer RawDefs extends Record<string, unknown> ? RawDefs & ParentDefs & ExtractAnchors<RawDefs> : ParentDefs;
161
+ /** Extract raw $defs / definitions maps. */
162
+ type ExtractRawDefs<S> = S extends {
163
+ $defs: infer D;
164
+ } ? D extends Record<string, unknown> ? D : Record<string, never> : S extends {
165
+ definitions: infer D;
166
+ } ? D extends Record<string, unknown> ? D : Record<string, never> : Record<string, never>;
167
+ /**
168
+ * Build a map of `$anchor` name -> schema from a definitions block.
169
+ * Scans each definition value for `$anchor` or `$dynamicAnchor` and
170
+ * creates entries like `{ Tree: <schema-with-$anchor-Tree> }`.
171
+ */
172
+ type ExtractAnchors<D extends Record<string, unknown>> = { [K in keyof D as D[K] extends {
173
+ $anchor: infer A extends string;
174
+ } ? A : D[K] extends {
175
+ $dynamicAnchor: infer A extends string;
176
+ } ? A : never]: D[K] };
177
+ /**
178
+ * Convert a union to an intersection.
179
+ * `A | B` -> `A & B`. Used for allOf merging.
180
+ */
181
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
182
+ /**
183
+ * Resolves an OpenAPI `ref` string to its JSON Schema, then parses it.
184
+ *
185
+ * Handles:
186
+ * - `#/components/schemas/Name` (OpenAPI 3.x)
187
+ * - `#/definitions/Name` (Swagger 2.0)
188
+ * - `#/paths/...` (path-based refs, navigating the document tree)
189
+ */
190
+ type ResolveOpenAPIRef<Spec extends Record<string, unknown>, Ref extends string> = Ref extends `#/components/schemas/${infer Name}` ? Spec["components"] extends Record<string, unknown> ? Spec["components"]["schemas"] extends Record<string, unknown> ? Name extends keyof Spec["components"]["schemas"] ? FromJSONSchema<Spec["components"]["schemas"][Name]> : unknown : unknown : unknown : Ref extends `#/definitions/${infer Name}` ? Spec["definitions"] extends Record<string, unknown> ? Name extends keyof Spec["definitions"] ? FromJSONSchema<Spec["definitions"][Name]> : unknown : unknown : Ref extends `#/paths/${infer PathRest}` ? ResolvePathBasedRef<Spec, PathRest> : unknown;
191
+ /**
192
+ * Resolve a path-based $ref after the `#/paths/` prefix.
193
+ * Splits on `/` and navigates the document tree.
194
+ *
195
+ * Note: JSON Pointer tilde encoding (~1 for /, ~0 for ~) is not decoded
196
+ * at the type level. For `as const` literals, use the literal path
197
+ * character directly (e.g. `#/paths//pets/get/...`).
198
+ */
199
+ type ResolvePathBasedRef<Spec extends Record<string, unknown>, PathRest extends string> = Spec["paths"] extends Record<string, unknown> ? ResolvePathSegments<Spec["paths"], SplitPath<PathRest>> : unknown;
200
+ /**
201
+ * Split a path string on `/` into a tuple of segments.
202
+ * The first segment is the path key (may be empty for `/pets` -> `""` / `"pets"`).
203
+ */
204
+ type SplitPath<S extends string> = S extends `${infer Head}/${infer Tail}` ? [Head, ...SplitPath<Tail>] : [S];
205
+ /**
206
+ * Recursively navigate into a document object by path segments.
207
+ */
208
+ type ResolvePathSegments<Doc, Segs extends string[]> = Segs extends [infer Head extends string, ...infer Rest extends string[]] ? Doc extends Record<string, unknown> ? Rest extends [] ? Doc[Head] : ResolvePathSegments<Doc[Head], Rest> : unknown : unknown;
209
+ /** Navigate to a path item in an OpenAPI document. */
210
+ type PathItemOf<Doc, Path extends string> = Doc extends {
211
+ paths: Record<string, unknown>;
212
+ } ? Path extends keyof Doc["paths"] ? Doc["paths"][Path] : unknown : unknown;
213
+ /** Navigate to an operation within a path item. */
214
+ type OperationOf<PathItem, Method extends string> = PathItem extends Record<string, unknown> ? Method extends keyof PathItem ? PathItem[Method] : unknown : unknown;
215
+ /** Extract the schema from request body content (any media type). */
216
+ type RequestBodySchemaOf<Op> = Op extends {
217
+ requestBody: {
218
+ content: Record<string, {
219
+ schema: infer S;
220
+ }>;
221
+ };
222
+ } ? S : Op extends {
223
+ requestBody: {
224
+ content: {
225
+ "application/json": {
226
+ schema: infer S;
227
+ };
228
+ };
229
+ };
230
+ } ? S : unknown;
231
+ /** Extract the schema from response content (any media type). */
232
+ type ResponseSchemaOf<Op, Status extends string> = Op extends {
233
+ responses: Record<string, unknown>;
234
+ } ? Status extends keyof Op["responses"] ? Op["responses"][Status] extends {
235
+ content: Record<string, {
236
+ schema: infer S;
237
+ }>;
238
+ } ? S : Op["responses"][Status] extends {
239
+ content: {
240
+ "application/json": {
241
+ schema: infer S;
242
+ };
243
+ };
244
+ } ? S : unknown : unknown : unknown;
245
+ /** Resolve a schema that may be a $ref pointer. */
246
+ type ResolveMaybeRef<Doc, S> = S extends {
247
+ $ref: infer R extends string;
248
+ } ? ResolveOpenAPIRef<Doc & Record<string, unknown>, R> : S extends {
249
+ nullable: true;
250
+ } & Record<string, unknown> ? FromJSONSchema<Omit<S, "nullable">> | null : S extends Record<string, unknown> ? FromJSONSchema<S> : unknown;
251
+ /** Extract parameter names from an operation. */
252
+ type ParameterNamesOf<Doc, Path extends string, Method extends string> = OperationOf<PathItemOf<Doc, Path>, Method> extends {
253
+ parameters: readonly unknown[];
254
+ } ? OperationOf<PathItemOf<Doc, Path>, Method>["parameters"][number] extends {
255
+ name: infer N;
256
+ } ? N extends string ? N : never : never : never;
257
+ /**
258
+ * Infer the TypeScript type of an OpenAPI operation's request body.
259
+ */
260
+ type OpenAPIRequestBodyType<Doc, Path extends string, Method extends string> = ResolveMaybeRef<Doc, RequestBodySchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>>>;
261
+ /**
262
+ * Infer the TypeScript type of an OpenAPI operation's response.
263
+ */
264
+ type OpenAPIResponseType<Doc, Path extends string, Method extends string, Status extends string> = ResolveMaybeRef<Doc, ResponseSchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>, Status>>;
265
+ /**
266
+ * Infer the fields prop type for ApiRequestBody.
267
+ * Falls back to Record<string, FieldOverride> for runtime documents.
268
+ */
269
+ type InferRequestBodyFields<Doc, Path extends string, Method extends string> = unknown extends OpenAPIRequestBodyType<Doc, Path, Method> ? Record<string, FieldOverride> : FieldOverrides<OpenAPIRequestBodyType<Doc, Path, Method>>;
270
+ /**
271
+ * Infer the fields prop type for ApiResponse.
272
+ * Falls back to Record<string, FieldOverride> for runtime documents.
273
+ */
274
+ type InferResponseFields<Doc, Path extends string, Method extends string, Status extends string> = unknown extends OpenAPIResponseType<Doc, Path, Method, Status> ? Record<string, FieldOverride> : FieldOverrides<OpenAPIResponseType<Doc, Path, Method, Status>>;
275
+ /**
276
+ * Infer the overrides prop type for ApiParameters.
277
+ * Falls back to Record<string, FieldOverride> for runtime documents.
278
+ */
279
+ type InferParameterOverrides<Doc, Path extends string, Method extends string> = string extends ParameterNamesOf<Doc, Path, Method> ? Record<string, FieldOverride> : Partial<Record<ParameterNamesOf<Doc, Path, Method>, FieldOverride>>;
280
+ /**
281
+ * Check if T is a "narrow" type (not wide like object, Record, or unknown).
282
+ * Used to determine if we can enumerate keys for path inference.
283
+ */
284
+ type IsNarrowObject<T> = T extends string | number | boolean | null | undefined | unknown[] ? false : T extends object ? Record<string, never> extends T ? false : true : false;
285
+ /**
286
+ * Extract all valid dot-separated paths from an object type.
287
+ * Produces paths like "name" | "address.city" | "address.postcode".
288
+ * Stops at leaf types (string, number, boolean, null) and arrays.
289
+ * Returns `string` for wide types (object, Record, unknown).
290
+ * Handles optional/nullable fields by unwrapping T | undefined.
291
+ */
292
+ type PathOfType<T, Prefix extends string = ""> = IsNarrowObject<T> extends true ? { [K in keyof T & string]: T[K] extends string | number | boolean | null | undefined ? `${Prefix}${K}` : T[K] extends unknown[] ? `${Prefix}${K}` : T[K] extends object | undefined ? PathOfType<Exclude<T[K], undefined>, `${Prefix}${K}.`> | `${Prefix}${K}` : `${Prefix}${K}` }[keyof T & string] : string;
293
+ /**
294
+ * Extract the type at a given dot-separated path.
295
+ * PathOfType<T> produces valid paths; TypeAtPath resolves the leaf type.
296
+ */
297
+ 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;
298
+ //#endregion
299
+ export { OpenAPIRequestBodyType as a, ResolveOpenAPIRef as c, InferResponseFields as i, TypeAtPath as l, InferParameterOverrides as n, OpenAPIResponseType as o, InferRequestBodyFields as r, PathOfType as s, FromJSONSchema as t };
@@ -0,0 +1,261 @@
1
+ //#region src/core/types.d.ts
2
+ /**
3
+ * Core types for schema-components.
4
+ *
5
+ * These types define the vocabulary shared between the schema walker,
6
+ * component resolver, and React components.
7
+ */
8
+ /** A raw JSON object (JSON Schema or OpenAPI document). */
9
+ type JsonObject = Record<string, unknown>;
10
+ /**
11
+ * Metadata attached to schemas via `.meta()` or passed as props to
12
+ * `<SchemaComponent>`. Every field is also available as a top-level
13
+ * prop on `<SchemaComponent>` (with TypeScript-enforced exclusivity
14
+ * between prop and `meta`).
15
+ */
16
+ interface SchemaMeta {
17
+ readOnly?: boolean;
18
+ writeOnly?: boolean;
19
+ description?: string;
20
+ title?: string;
21
+ deprecated?: boolean;
22
+ /** Component hint — resolved before theme adapter. */
23
+ component?: string;
24
+ /** Sort order for object fields. Lower values render first. */
25
+ order?: number;
26
+ /** Arbitrary UI hints passed through to theme adapters. */
27
+ [key: string]: unknown;
28
+ }
29
+ type Editability = "presentation" | "input" | "editable";
30
+ /**
31
+ * Resolved editability state for a single field.
32
+ *
33
+ * Priority (highest wins):
34
+ * 1. Property-level readOnly → presentation
35
+ * 2. Property-level writeOnly → input
36
+ * 3. Component-level readOnly → presentation
37
+ * 4. Component-level writeOnly → input
38
+ * 5. Schema root readOnly → presentation
39
+ * 6. Schema root writeOnly → input
40
+ * 7. Neither → editable
41
+ */
42
+ declare function resolveEditability(propertyMeta: SchemaMeta | undefined, componentMeta: SchemaMeta | undefined, rootMeta: SchemaMeta | undefined): Editability;
43
+ /**
44
+ * Recursive mapped type that mirrors a schema's shape for per-field
45
+ * overrides. Each leaf accepts schema meta overrides and an optional
46
+ * per-field validation error callback. Objects recurse and also accept
47
+ * their own overrides.
48
+ */
49
+ type FieldOverrides<T> = { [K in keyof T]?: T[K] extends object ? FieldOverrides<T[K]> & FieldOverride : FieldOverride };
50
+ /**
51
+ * Per-field override. Extends SchemaMeta with rendering controls
52
+ * and a per-field validation error callback.
53
+ */
54
+ type FieldOverride = Partial<SchemaMeta> & {
55
+ /** Called with the ZodError when this field fails validation. */onValidationError?: (error: unknown) => void; /** Hide this field when false. Defaults to true (visible). */
56
+ visible?: boolean;
57
+ };
58
+ /**
59
+ * All schema types the walker can produce.
60
+ * Used as the discriminant in the WalkedField tagged union.
61
+ */
62
+ type SchemaType = "string" | "number" | "boolean" | "null" | "enum" | "literal" | "object" | "array" | "tuple" | "record" | "union" | "discriminatedUnion" | "conditional" | "negation" | "recursive" | "file" | "unknown";
63
+ /** Constraints that apply to string schemas. */
64
+ interface StringConstraints {
65
+ minLength?: number;
66
+ maxLength?: number;
67
+ pattern?: string;
68
+ format?: string;
69
+ contentEncoding?: string;
70
+ contentMediaType?: string;
71
+ }
72
+ /** Constraints that apply to number/integer schemas. */
73
+ interface NumberConstraints {
74
+ minimum?: number;
75
+ maximum?: number;
76
+ exclusiveMinimum?: number;
77
+ exclusiveMaximum?: number;
78
+ multipleOf?: number;
79
+ }
80
+ /** Constraints that apply to array schemas. */
81
+ interface ArrayConstraints {
82
+ minItems?: number;
83
+ maxItems?: number;
84
+ uniqueItems?: boolean;
85
+ /** Schema that at least one array item must match. */
86
+ contains?: Record<string, unknown>;
87
+ minContains?: number;
88
+ maxContains?: number;
89
+ /** Constraint schema for unevaluated items. */
90
+ unevaluatedItems?: Record<string, unknown>;
91
+ }
92
+ /** Constraints that apply to object schemas. */
93
+ interface ObjectConstraints {
94
+ minProperties?: number;
95
+ maxProperties?: number;
96
+ }
97
+ /** Constraints that apply to file schemas. */
98
+ interface FileConstraints {
99
+ mimeTypes?: string[];
100
+ }
101
+ /**
102
+ * Union of all constraint types. Renderers can narrow by checking
103
+ * the WalkedField's `type` discriminant.
104
+ */
105
+ type FieldConstraints = StringConstraints | NumberConstraints | ArrayConstraints | ObjectConstraints | FileConstraints | Record<string, never>;
106
+ /**
107
+ * Properties common to every WalkedField variant.
108
+ * The `type` field acts as the discriminant for the tagged union.
109
+ */
110
+ interface FieldBase {
111
+ editability: Editability;
112
+ meta: SchemaMeta;
113
+ /** Whether the field is optional (not in `required`). */
114
+ isOptional?: boolean;
115
+ /** Whether the field is nullable (`anyOf [T, null]` or `type: ["...", "null"]`). */
116
+ isNullable?: boolean;
117
+ /** Default value from the schema's `default` keyword. */
118
+ defaultValue?: unknown;
119
+ /** Example values from the schema's `examples` keyword. */
120
+ examples?: unknown[];
121
+ }
122
+ interface StringField extends FieldBase {
123
+ type: "string";
124
+ constraints: StringConstraints;
125
+ }
126
+ interface NumberField extends FieldBase {
127
+ type: "number";
128
+ constraints: NumberConstraints;
129
+ }
130
+ interface BooleanField extends FieldBase {
131
+ type: "boolean";
132
+ constraints: Record<string, never>;
133
+ }
134
+ interface NullField extends FieldBase {
135
+ type: "null";
136
+ constraints: Record<string, never>;
137
+ }
138
+ interface EnumField extends FieldBase {
139
+ type: "enum";
140
+ constraints: Record<string, never>;
141
+ enumValues: (string | number | boolean | null)[];
142
+ }
143
+ interface LiteralField extends FieldBase {
144
+ type: "literal";
145
+ constraints: Record<string, never>;
146
+ literalValues: (string | number | boolean | null)[];
147
+ }
148
+ interface ObjectField extends FieldBase {
149
+ type: "object";
150
+ constraints: ObjectConstraints;
151
+ /** Map of property name → walked sub-schema. */
152
+ fields: Record<string, WalkedField>;
153
+ /** Property names declared in `required`. */
154
+ requiredFields: string[];
155
+ /** Regex-keyed sub-schemas from `patternProperties`. */
156
+ patternProperties?: Record<string, WalkedField>;
157
+ /** Whether `additionalProperties` is explicitly `false` (closed). */
158
+ additionalPropertiesClosed?: boolean;
159
+ /** Schema for additional properties when not `false` and not a Record. */
160
+ additionalPropertiesSchema?: WalkedField;
161
+ /** Property-presence-activated sub-schemas from `dependentSchemas`. */
162
+ dependentSchemas?: Record<string, WalkedField>;
163
+ /** Property-presence-conditional required fields from `dependentRequired`. */
164
+ dependentRequired?: Record<string, string[]>;
165
+ /** Constraint schema for unevaluated properties. */
166
+ unevaluatedProperties?: WalkedField;
167
+ /** Whether unevaluatedProperties is explicitly `false`. */
168
+ unevaluatedPropertiesClosed?: boolean;
169
+ /** Schema constraining property names (from `propertyNames`). */
170
+ propertyNames?: WalkedField;
171
+ }
172
+ interface ArrayField extends FieldBase {
173
+ type: "array";
174
+ constraints: ArrayConstraints;
175
+ /** The element sub-schema. */
176
+ element?: WalkedField;
177
+ /** Walked schema for unevaluated items. */
178
+ unevaluatedItems?: WalkedField;
179
+ }
180
+ interface TupleField extends FieldBase {
181
+ type: "tuple";
182
+ constraints: ArrayConstraints;
183
+ /** Positional element schemas from `prefixItems`. */
184
+ prefixItems: WalkedField[];
185
+ }
186
+ interface RecordField extends FieldBase {
187
+ type: "record";
188
+ constraints: ObjectConstraints;
189
+ /** Key name validation schema (from `propertyNames`). */
190
+ keyType: WalkedField;
191
+ /** Value schema (from `additionalProperties`). */
192
+ valueType: WalkedField;
193
+ }
194
+ interface UnionField extends FieldBase {
195
+ type: "union";
196
+ constraints: Record<string, never>;
197
+ /** The union options. */
198
+ options: WalkedField[];
199
+ }
200
+ interface DiscriminatedUnionField extends FieldBase {
201
+ type: "discriminatedUnion";
202
+ constraints: Record<string, never>;
203
+ /** The union options. */
204
+ options: WalkedField[];
205
+ /** Property name that discriminates between options. */
206
+ discriminator: string;
207
+ }
208
+ interface ConditionalField extends FieldBase {
209
+ type: "conditional";
210
+ constraints: Record<string, never>;
211
+ /** The `if` sub-schema. */
212
+ ifClause: WalkedField;
213
+ /** The `then` sub-schema. */
214
+ thenClause?: WalkedField;
215
+ /** The `else` sub-schema. */
216
+ elseClause?: WalkedField;
217
+ }
218
+ interface NegationField extends FieldBase {
219
+ type: "negation";
220
+ constraints: Record<string, never>;
221
+ /** The negated sub-schema. */
222
+ negated: WalkedField;
223
+ }
224
+ interface FileField extends FieldBase {
225
+ type: "file";
226
+ constraints: FileConstraints;
227
+ }
228
+ interface RecursiveField extends FieldBase {
229
+ type: "recursive";
230
+ constraints: Record<string, never>;
231
+ /** The $ref string that would create the cycle (e.g. "#" or "#Node"). */
232
+ refTarget: string;
233
+ }
234
+ interface UnknownField extends FieldBase {
235
+ type: "unknown";
236
+ constraints: Record<string, never>;
237
+ }
238
+ /**
239
+ * Tagged union of all schema field types produced by the walker.
240
+ * Use `field.type` to narrow to a specific variant.
241
+ */
242
+ type WalkedField = StringField | NumberField | BooleanField | NullField | EnumField | LiteralField | ObjectField | ArrayField | TupleField | RecordField | UnionField | DiscriminatedUnionField | ConditionalField | NegationField | RecursiveField | FileField | UnknownField;
243
+ declare function isStringField(field: WalkedField): field is StringField;
244
+ declare function isNumberField(field: WalkedField): field is NumberField;
245
+ declare function isBooleanField(field: WalkedField): field is BooleanField;
246
+ declare function isNullField(field: WalkedField): field is NullField;
247
+ declare function isEnumField(field: WalkedField): field is EnumField;
248
+ declare function isLiteralField(field: WalkedField): field is LiteralField;
249
+ declare function isObjectField(field: WalkedField): field is ObjectField;
250
+ declare function isArrayField(field: WalkedField): field is ArrayField;
251
+ declare function isTupleField(field: WalkedField): field is TupleField;
252
+ declare function isRecordField(field: WalkedField): field is RecordField;
253
+ declare function isUnionField(field: WalkedField): field is UnionField;
254
+ declare function isDiscriminatedUnionField(field: WalkedField): field is DiscriminatedUnionField;
255
+ declare function isConditionalField(field: WalkedField): field is ConditionalField;
256
+ declare function isNegationField(field: WalkedField): field is NegationField;
257
+ declare function isFileField(field: WalkedField): field is FileField;
258
+ declare function isRecursiveField(field: WalkedField): field is RecursiveField;
259
+ declare function isUnknownField(field: WalkedField): field is UnknownField;
260
+ //#endregion
261
+ export { UnknownField as A, isNullField as B, RecursiveField as C, StringField as D, StringConstraints as E, isDiscriminatedUnionField as F, isStringField as G, isObjectField as H, isEnumField as I, isUnknownField as J, isTupleField as K, isFileField as L, isArrayField as M, isBooleanField as N, TupleField as O, isConditionalField as P, isLiteralField as R, RecordField as S, SchemaType as T, isRecordField as U, isNumberField as V, isRecursiveField as W, resolveEditability as Y, NullField as _, DiscriminatedUnionField as a, ObjectConstraints as b, FieldBase as c, FieldOverrides as d, FileConstraints as f, NegationField as g, LiteralField as h, ConditionalField as i, WalkedField as j, UnionField as k, FieldConstraints as l, JsonObject as m, ArrayField as n, Editability as o, FileField as p, isUnionField as q, BooleanField as r, EnumField as s, ArrayConstraints as t, FieldOverride as u, NumberConstraints as v, SchemaMeta as w, ObjectField as x, NumberField as y, isNegationField as z };
@@ -0,0 +1,40 @@
1
+ //#region src/core/version.d.ts
2
+ /**
3
+ * JSON Schema draft and OpenAPI version detection.
4
+ *
5
+ * Detects the version from `$schema` URIs and OpenAPI `openapi`/`swagger`
6
+ * fields. Used by the normaliser to apply version-specific transformations
7
+ * before the walker processes the schema.
8
+ */
9
+ type JsonSchemaDraft = "draft-04" | "draft-06" | "draft-07" | "draft-2019-09" | "draft-2020-12";
10
+ /**
11
+ * Detect the JSON Schema draft version from a schema's `$schema` URI.
12
+ * Returns `"draft-2020-12"` as the default when `$schema` is absent —
13
+ * this is the most compatible assumption for modern schemas.
14
+ */
15
+ declare function detectJsonSchemaDraft(schema: Record<string, unknown>): JsonSchemaDraft;
16
+ interface OpenApiVersionInfo {
17
+ major: number;
18
+ minor: number;
19
+ patch: number;
20
+ }
21
+ /**
22
+ * Detect the OpenAPI/Swagger version from a document.
23
+ * Returns `undefined` for documents that are not OpenAPI or Swagger.
24
+ */
25
+ declare function detectOpenApiVersion(doc: Record<string, unknown>): OpenApiVersionInfo | undefined;
26
+ /**
27
+ * Check if an OpenAPI version is 3.0.x (uses modified Draft 04 schemas
28
+ * with `nullable` instead of `anyOf [T, null]`).
29
+ */
30
+ declare function isOpenApi30(version: OpenApiVersionInfo): boolean;
31
+ /**
32
+ * Check if an OpenAPI version is 3.1.x (uses standard Draft 2020-12).
33
+ */
34
+ declare function isOpenApi31(version: OpenApiVersionInfo): boolean;
35
+ /**
36
+ * Check if a document is Swagger 2.0.
37
+ */
38
+ declare function isSwagger2(version: OpenApiVersionInfo): boolean;
39
+ //#endregion
40
+ export { isOpenApi30 as a, detectOpenApiVersion as i, OpenApiVersionInfo as n, isOpenApi31 as o, detectJsonSchemaDraft as r, isSwagger2 as s, JsonSchemaDraft as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schema-components",
3
- "version": "1.12.11",
3
+ "version": "1.13.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",