schema-components 1.12.11 → 1.14.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 +35 -0
- package/dist/core/adapter.d.mts +8 -3
- package/dist/core/adapter.mjs +58 -14
- package/dist/core/constraints.d.mts +17 -0
- package/dist/core/constraints.mjs +150 -0
- package/dist/core/diagnostics.d.mts +2 -0
- package/dist/core/diagnostics.mjs +33 -0
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/formats.d.mts +33 -0
- package/dist/core/formats.mjs +67 -0
- package/dist/core/merge.d.mts +48 -0
- package/dist/core/merge.mjs +125 -0
- package/dist/core/normalise.d.mts +41 -0
- package/dist/core/normalise.mjs +2 -0
- package/dist/core/openapi30.d.mts +41 -0
- package/dist/core/openapi30.mjs +2 -0
- package/dist/core/ref.d.mts +2 -0
- package/dist/core/ref.mjs +165 -0
- package/dist/core/renderer.d.mts +2 -2
- package/dist/core/renderer.mjs +8 -0
- package/dist/core/swagger2.d.mts +11 -0
- package/dist/core/swagger2.mjs +2 -0
- package/dist/core/typeInference.d.mts +2 -0
- package/dist/core/typeInference.mjs +1 -0
- package/dist/core/types.d.mts +2 -3
- package/dist/core/types.mjs +58 -2
- package/dist/core/version.d.mts +2 -0
- package/dist/core/version.mjs +151 -0
- package/dist/core/walkBuilders.d.mts +66 -0
- package/dist/core/walkBuilders.mjs +152 -0
- package/dist/core/walker.d.mts +3 -10
- package/dist/core/walker.mjs +245 -233
- package/dist/diagnostics-DzbZmcLI.d.mts +64 -0
- package/dist/html/a11y.d.mts +5 -4
- package/dist/html/renderToHtml.d.mts +3 -3
- package/dist/html/renderToHtml.mjs +23 -379
- package/dist/html/renderToHtmlStream.d.mts +29 -47
- package/dist/html/renderToHtmlStream.mjs +33 -305
- package/dist/html/renderers.d.mts +14 -0
- package/dist/html/renderers.mjs +406 -0
- package/dist/html/streamRenderers.d.mts +13 -0
- package/dist/html/streamRenderers.mjs +243 -0
- package/dist/normalise-tL9FckAk.mjs +748 -0
- package/dist/openapi/ApiCallbacks.d.mts +16 -0
- package/dist/openapi/ApiCallbacks.mjs +34 -0
- package/dist/openapi/ApiLinks.d.mts +16 -0
- package/dist/openapi/ApiLinks.mjs +42 -0
- package/dist/openapi/ApiResponseHeaders.d.mts +16 -0
- package/dist/openapi/ApiResponseHeaders.mjs +35 -0
- package/dist/openapi/ApiSecurity.d.mts +19 -0
- package/dist/openapi/ApiSecurity.mjs +33 -0
- package/dist/openapi/bundle.d.mts +47 -0
- package/dist/openapi/bundle.mjs +95 -0
- package/dist/openapi/components.d.mts +7 -1
- package/dist/openapi/components.mjs +30 -6
- package/dist/openapi/parser.d.mts +59 -2
- package/dist/openapi/parser.mjs +189 -8
- package/dist/react/SchemaComponent.d.mts +13 -4
- package/dist/react/SchemaComponent.mjs +51 -91
- package/dist/react/SchemaView.d.mts +10 -2
- package/dist/react/SchemaView.mjs +33 -15
- package/dist/react/fieldPath.d.mts +20 -0
- package/dist/react/fieldPath.mjs +81 -0
- package/dist/react/headless.d.mts +2 -4
- package/dist/react/headless.mjs +3 -492
- package/dist/react/headlessRenderers.d.mts +23 -0
- package/dist/react/headlessRenderers.mjs +507 -0
- package/dist/ref-DvWoULcy.d.mts +44 -0
- package/dist/renderer-BdSqllx5.d.mts +160 -0
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mantine.mjs +2 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/mui.mjs +3 -2
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/radix.mjs +2 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/themes/shadcn.mjs +10 -6
- package/dist/typeInference-k7FXfTVO.d.mts +335 -0
- package/dist/types-D_5ST7SS.d.mts +269 -0
- package/dist/version-B5NV-35j.d.mts +69 -0
- package/package.json +1 -1
- package/dist/types-BJzEgJdX.d.mts +0 -335
- /package/dist/{errors-DIKI2C78.d.mts → errors-C5zRC2PU.d.mts} +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { D as StringConstraints, M as WalkedField, T as SchemaMeta, f as FileConstraints, t as ArrayConstraints, x as ObjectConstraints, y as NumberConstraints } from "./types-D_5ST7SS.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/renderer.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Flat intersection of all constraint types.
|
|
6
|
+
* Used in renderer props where the render function receives the union
|
|
7
|
+
* but knows (by resolver key) which subset applies.
|
|
8
|
+
*
|
|
9
|
+
* The walker's discriminated WalkedField enforces type-correct constraints
|
|
10
|
+
* at construction time; the renderer consumes them as this flat type.
|
|
11
|
+
*/
|
|
12
|
+
type AllConstraints = StringConstraints & NumberConstraints & ArrayConstraints & ObjectConstraints & FileConstraints;
|
|
13
|
+
/**
|
|
14
|
+
* Properties available on every schema field, regardless of rendering target.
|
|
15
|
+
* Both React and HTML renderers receive these.
|
|
16
|
+
*/
|
|
17
|
+
interface BaseFieldProps {
|
|
18
|
+
/** Current field value. */
|
|
19
|
+
value: unknown;
|
|
20
|
+
/** Whether to render as read-only display. */
|
|
21
|
+
readOnly: boolean;
|
|
22
|
+
/** Whether to render as an empty input. */
|
|
23
|
+
writeOnly: boolean;
|
|
24
|
+
/** Schema metadata for this field. */
|
|
25
|
+
meta: SchemaMeta;
|
|
26
|
+
/** Constraints from schema checks. */
|
|
27
|
+
constraints: AllConstraints;
|
|
28
|
+
/** Dot-separated path from root (e.g. "address.city"). */
|
|
29
|
+
path: string;
|
|
30
|
+
/** For enums: the allowed values. */
|
|
31
|
+
enumValues?: (string | number | boolean | null)[];
|
|
32
|
+
/** For arrays: the element schema. */
|
|
33
|
+
element?: WalkedField;
|
|
34
|
+
/** For tuples: positional element schemas from prefixItems. */
|
|
35
|
+
prefixItems?: WalkedField[];
|
|
36
|
+
/** For conditionals: the if/then/else sub-schemas. */
|
|
37
|
+
ifClause?: WalkedField;
|
|
38
|
+
thenClause?: WalkedField;
|
|
39
|
+
elseClause?: WalkedField;
|
|
40
|
+
/** For negations: the negated sub-schema. */
|
|
41
|
+
negated?: WalkedField;
|
|
42
|
+
/** For recursive fields: the $ref string that would create the cycle. */
|
|
43
|
+
refTarget?: string;
|
|
44
|
+
/** For objects: map of field name → WalkedField. */
|
|
45
|
+
fields?: Record<string, WalkedField>;
|
|
46
|
+
/** For unions: the option schemas. */
|
|
47
|
+
options?: WalkedField[];
|
|
48
|
+
/** For discriminated unions: the discriminator key. */
|
|
49
|
+
discriminator?: string;
|
|
50
|
+
/** For records: key and value schemas. */
|
|
51
|
+
keyType?: WalkedField;
|
|
52
|
+
valueType?: WalkedField;
|
|
53
|
+
/** For literals: the literal value(s). */
|
|
54
|
+
literalValues?: (string | number | boolean | null)[];
|
|
55
|
+
/** Example values from the schema's `examples` keyword. */
|
|
56
|
+
examples?: unknown[];
|
|
57
|
+
/** Walked field tree for recursive rendering. */
|
|
58
|
+
tree: WalkedField;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Props for React render functions. Extends BaseFieldProps with:
|
|
62
|
+
* - `onChange` — callback to propagate value changes back to state
|
|
63
|
+
* - `renderChild` — recursively renders a child field, threading onChange
|
|
64
|
+
*/
|
|
65
|
+
interface RenderProps extends BaseFieldProps {
|
|
66
|
+
/** Callback to update the field value. */
|
|
67
|
+
onChange: (value: unknown) => void;
|
|
68
|
+
/**
|
|
69
|
+
* Render a child field. Theme adapters call this to recursively render
|
|
70
|
+
* nested structures (object fields, array elements, union options).
|
|
71
|
+
* The resolver and rendering context are already wired in.
|
|
72
|
+
*/
|
|
73
|
+
renderChild: (tree: WalkedField, value: unknown, onChange: (v: unknown) => void) => unknown;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Props for HTML render functions. Extends BaseFieldProps with:
|
|
77
|
+
* - `renderChild` — recursively renders a child field to HTML string
|
|
78
|
+
*
|
|
79
|
+
* No `onChange` — HTML rendering is pure output with no event handling.
|
|
80
|
+
*/
|
|
81
|
+
interface HtmlRenderProps extends BaseFieldProps {
|
|
82
|
+
/**
|
|
83
|
+
* Render a child field to an HTML string. Theme adapters call this
|
|
84
|
+
* to recursively render nested structures.
|
|
85
|
+
*
|
|
86
|
+
* @param tree - The walked field tree for the child
|
|
87
|
+
* @param value - The child's current value
|
|
88
|
+
* @param pathSuffix - Path segment from the parent (e.g. "city",
|
|
89
|
+
* "[0]"). When omitted, the child's description is used as fallback.
|
|
90
|
+
*/
|
|
91
|
+
renderChild: (tree: WalkedField, value: unknown, pathSuffix?: string) => string;
|
|
92
|
+
}
|
|
93
|
+
type RenderFunction = (props: RenderProps) => unknown;
|
|
94
|
+
interface ComponentResolver {
|
|
95
|
+
string?: RenderFunction;
|
|
96
|
+
number?: RenderFunction;
|
|
97
|
+
boolean?: RenderFunction;
|
|
98
|
+
enum?: RenderFunction;
|
|
99
|
+
object?: RenderFunction;
|
|
100
|
+
array?: RenderFunction;
|
|
101
|
+
tuple?: RenderFunction;
|
|
102
|
+
record?: RenderFunction;
|
|
103
|
+
union?: RenderFunction;
|
|
104
|
+
discriminatedUnion?: RenderFunction;
|
|
105
|
+
conditional?: RenderFunction;
|
|
106
|
+
negation?: RenderFunction;
|
|
107
|
+
recursive?: RenderFunction;
|
|
108
|
+
literal?: RenderFunction;
|
|
109
|
+
file?: RenderFunction;
|
|
110
|
+
unknown?: RenderFunction;
|
|
111
|
+
}
|
|
112
|
+
/** An HTML render function returns a string. */
|
|
113
|
+
type HtmlRenderFunction = (props: HtmlRenderProps) => string;
|
|
114
|
+
/**
|
|
115
|
+
* HTML resolver — maps schema types to HTML string renderers.
|
|
116
|
+
* Structurally mirrors ComponentResolver but produces strings.
|
|
117
|
+
*/
|
|
118
|
+
interface HtmlResolver {
|
|
119
|
+
string?: HtmlRenderFunction;
|
|
120
|
+
number?: HtmlRenderFunction;
|
|
121
|
+
boolean?: HtmlRenderFunction;
|
|
122
|
+
enum?: HtmlRenderFunction;
|
|
123
|
+
object?: HtmlRenderFunction;
|
|
124
|
+
array?: HtmlRenderFunction;
|
|
125
|
+
tuple?: HtmlRenderFunction;
|
|
126
|
+
record?: HtmlRenderFunction;
|
|
127
|
+
union?: HtmlRenderFunction;
|
|
128
|
+
discriminatedUnion?: HtmlRenderFunction;
|
|
129
|
+
conditional?: HtmlRenderFunction;
|
|
130
|
+
negation?: HtmlRenderFunction;
|
|
131
|
+
recursive?: HtmlRenderFunction;
|
|
132
|
+
literal?: HtmlRenderFunction;
|
|
133
|
+
file?: HtmlRenderFunction;
|
|
134
|
+
unknown?: HtmlRenderFunction;
|
|
135
|
+
}
|
|
136
|
+
declare const RESOLVER_KEYS: readonly ["string", "number", "boolean", "enum", "object", "array", "tuple", "record", "union", "discriminatedUnion", "conditional", "negation", "recursive", "literal", "file", "unknown"];
|
|
137
|
+
type ResolverKey = (typeof RESOLVER_KEYS)[number];
|
|
138
|
+
/**
|
|
139
|
+
* Map a schema type to the resolver key that handles it.
|
|
140
|
+
* `discriminatedUnion` → `union`. Unknown types → `unknown`.
|
|
141
|
+
*/
|
|
142
|
+
declare function typeToKey(type: WalkedField["type"]): ResolverKey;
|
|
143
|
+
/**
|
|
144
|
+
* Look up the render function for a schema type in a ComponentResolver.
|
|
145
|
+
*/
|
|
146
|
+
declare function getRenderFunction(type: WalkedField["type"], resolver: ComponentResolver): RenderFunction | undefined;
|
|
147
|
+
/**
|
|
148
|
+
* Look up the render function for a schema type in an HtmlResolver.
|
|
149
|
+
*/
|
|
150
|
+
declare function getHtmlRenderFn(type: WalkedField["type"], resolver: HtmlResolver): HtmlRenderFunction | undefined;
|
|
151
|
+
/**
|
|
152
|
+
* Merge two ComponentResolvers — user values take priority, fallback fills gaps.
|
|
153
|
+
*/
|
|
154
|
+
declare function mergeResolvers(user: ComponentResolver, fallback: ComponentResolver): ComponentResolver;
|
|
155
|
+
/**
|
|
156
|
+
* Merge two HtmlResolvers — user values take priority, fallback fills gaps.
|
|
157
|
+
*/
|
|
158
|
+
declare function mergeHtmlResolvers(user: HtmlResolver, fallback: HtmlResolver): HtmlResolver;
|
|
159
|
+
//#endregion
|
|
160
|
+
export { HtmlRenderProps as a, RenderFunction as c, getRenderFunction as d, mergeHtmlResolvers as f, HtmlRenderFunction as i, RenderProps as l, typeToKey as m, BaseFieldProps as n, HtmlResolver as o, mergeResolvers as p, ComponentResolver as r, RESOLVER_KEYS as s, AllConstraints as t, getHtmlRenderFn as u };
|
package/dist/themes/mantine.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { toReactNode } from "../react/headlessRenderers.mjs";
|
|
3
|
+
import { headlessResolver } from "../react/headless.mjs";
|
|
3
4
|
import { jsx } from "react/jsx-runtime";
|
|
4
5
|
//#region src/themes/mantine.tsx
|
|
5
6
|
function getLabel(props) {
|
package/dist/themes/mui.d.mts
CHANGED
package/dist/themes/mui.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { toReactNode } from "../react/headlessRenderers.mjs";
|
|
3
|
+
import { headlessResolver } from "../react/headless.mjs";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { isValidElement } from "react";
|
|
5
6
|
//#region src/themes/mui.tsx
|
|
6
7
|
function ariaRequired(tree) {
|
|
7
8
|
return { required: tree.isOptional === false };
|
package/dist/themes/radix.d.mts
CHANGED
package/dist/themes/radix.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
-
import {
|
|
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) {
|
package/dist/themes/shadcn.d.mts
CHANGED
package/dist/themes/shadcn.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toRecord } from "../core/guards.mjs";
|
|
2
|
-
import {
|
|
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) =>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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,335 @@
|
|
|
1
|
+
import { d as FieldOverrides, u as FieldOverride } from "./types-D_5ST7SS.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
|
+
* Marker type emitted when OpenAPI $ref resolution hits the type-level
|
|
57
|
+
* recursion depth limit. Instead of silently falling back to
|
|
58
|
+
* `Record<string, FieldOverride>`, produces this branded type so
|
|
59
|
+
* consumers can detect it via conditional types.
|
|
60
|
+
*
|
|
61
|
+
* Usage:
|
|
62
|
+
* ```ts
|
|
63
|
+
* type Fields = InferRequestBodyFields<Doc, "/users", "post">;
|
|
64
|
+
* type IsFallback = Fields extends __SchemaInferenceFellBack ? true : false;
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
interface __SchemaInferenceFellBack {
|
|
68
|
+
readonly __schemaInferenceFallback: unique symbol;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Escape hatch for recursive schemas where type-level inference
|
|
72
|
+
* cannot proceed. Typed as `Record<string, FieldOverride>` but
|
|
73
|
+
* explicitly branded so callers know they are using the unsafe path.
|
|
74
|
+
*
|
|
75
|
+
* JSDoc trade-off note: This bypasses field-level type safety.
|
|
76
|
+
* Prefer restructuring the schema to avoid deep $ref chains
|
|
77
|
+
* when possible.
|
|
78
|
+
*/
|
|
79
|
+
type UnsafeFields = Record<string, FieldOverride> & {
|
|
80
|
+
/** Marks this as the unsafe fallback for recursive schemas. */readonly __unsafe?: true;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Convert a `FromJSONSchema` result to `unknown` when recursion is detected.
|
|
84
|
+
* Returns the original type when the schema is non-recursive.
|
|
85
|
+
*/
|
|
86
|
+
type DetectRecursiveFallback<T> = unknown extends T ? __SchemaInferenceFellBack : T;
|
|
87
|
+
/**
|
|
88
|
+
* Resolve a $ref against the local definitions context.
|
|
89
|
+
* Supports:
|
|
90
|
+
* - `#` (root)
|
|
91
|
+
* - `#/$defs/Name` and `#/definitions/Name` (named definitions)
|
|
92
|
+
* - `#SomeName` ($anchor, $dynamicAnchor resolved from definitions)
|
|
93
|
+
*/
|
|
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;
|
|
95
|
+
/**
|
|
96
|
+
* Merge an allOf array into an intersection type.
|
|
97
|
+
*/
|
|
98
|
+
type AllOfToType<A, Defs extends Record<string, unknown>> = A extends readonly unknown[] ? UnionToIntersection<FromJSONSchema<A[number], Defs>> : unknown;
|
|
99
|
+
/**
|
|
100
|
+
* 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.
|
|
103
|
+
*/
|
|
104
|
+
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
|
+
/**
|
|
106
|
+
* Check whether an anyOf/oneOf array contains a `{ type: "null" }` member.
|
|
107
|
+
*/
|
|
108
|
+
type HasNullMember<A> = A extends readonly unknown[] ? null extends A[number] ? false : {
|
|
109
|
+
type: "null";
|
|
110
|
+
} extends A[number] ? true : false : false;
|
|
111
|
+
/**
|
|
112
|
+
* Dispatch on a `type` value -- handles single types, type arrays,
|
|
113
|
+
* and delegates to the appropriate type-specific resolver.
|
|
114
|
+
*/
|
|
115
|
+
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;
|
|
116
|
+
/**
|
|
117
|
+
* Handle `type` as an array (Draft 04-07): `["string", "null"]`.
|
|
118
|
+
* Filters out "null" and makes the result nullable.
|
|
119
|
+
*/
|
|
120
|
+
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;
|
|
121
|
+
/**
|
|
122
|
+
* Make a type nullable if the original schema `type` array includes "null".
|
|
123
|
+
* Detects nullable from the type array directly.
|
|
124
|
+
*/
|
|
125
|
+
type NullableResult<Base, S> = S extends {
|
|
126
|
+
type: readonly (infer T)[];
|
|
127
|
+
} ? "null" extends T ? Base | null : Base : Base;
|
|
128
|
+
/**
|
|
129
|
+
* Omit array-utility keys that interfere with object/array matching
|
|
130
|
+
* when re-parsing a schema for a single type from a type array.
|
|
131
|
+
*/
|
|
132
|
+
type OmitArrayHelpers<S> = Omit<S, "prefixItems" | "items" | "additionalProperties">;
|
|
133
|
+
/**
|
|
134
|
+
* Parse an array schema: prefixItems -> tuple, items -> T[], or unknown[].
|
|
135
|
+
*
|
|
136
|
+
* `contains` / `minContains` / `maxContains` constrain elements at runtime
|
|
137
|
+
* but don't change the compile-time array element type.
|
|
138
|
+
*/
|
|
139
|
+
type ArraySchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
|
|
140
|
+
prefixItems: infer P;
|
|
141
|
+
} ? PrefixItemsToTuple<P, Defs> : S extends {
|
|
142
|
+
items: infer I;
|
|
143
|
+
} ? FromJSONSchema<I, Defs>[] : unknown[];
|
|
144
|
+
/**
|
|
145
|
+
* Convert a prefixItems array to a TypeScript tuple type.
|
|
146
|
+
*/
|
|
147
|
+
type PrefixItemsToTuple<P, Defs extends Record<string, unknown>> = P extends readonly [infer First, ...infer Rest] ? [FromJSONSchema<First, Defs>, ...PrefixItemsToTuple<Rest, Defs>] : [];
|
|
148
|
+
/**
|
|
149
|
+
* Parse an object schema: properties + required -> specific object,
|
|
150
|
+
* additionalProperties -> Record, or empty object.
|
|
151
|
+
*
|
|
152
|
+
* Handles:
|
|
153
|
+
* - `properties` + `required` -> specific object type with required/optional keys
|
|
154
|
+
* - `additionalProperties` as schema -> Record<string, T>
|
|
155
|
+
* - `patternProperties` -> merged into a loose index signature alongside specific props
|
|
156
|
+
* (TypeScript cannot express regex-keyed properties)
|
|
157
|
+
* - `propertyNames` -> ignored at type level (TS cannot validate key shapes)
|
|
158
|
+
* - `dependentSchemas` / `dependentRequired` -> ignored (runtime-only conditionals)
|
|
159
|
+
* - `unevaluatedProperties` -> ignored (runtime-only)
|
|
160
|
+
*/
|
|
161
|
+
type ObjectSchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
|
|
162
|
+
type: "object";
|
|
163
|
+
properties: infer P;
|
|
164
|
+
} ? 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 {
|
|
165
|
+
additionalProperties: infer V;
|
|
166
|
+
} ? Record<string, FromJSONSchema<V, Defs>> : Record<string, unknown>;
|
|
167
|
+
/**
|
|
168
|
+
* If the schema has `patternProperties`, intersect the base object type
|
|
169
|
+
* with a `Record<string, T>` index signature covering all pattern values.
|
|
170
|
+
* If no `patternProperties`, return the base type unchanged.
|
|
171
|
+
*/
|
|
172
|
+
type MergePatternProps<Base, S, Defs extends Record<string, unknown>> = S extends {
|
|
173
|
+
patternProperties: infer PP;
|
|
174
|
+
} ? PP extends Record<string, unknown> ? Base & Record<string, UnionOfPatternValues<PP, Defs>> : Base : Base;
|
|
175
|
+
/**
|
|
176
|
+
* Extract the union of all pattern property value types.
|
|
177
|
+
*/
|
|
178
|
+
type UnionOfPatternValues<PP extends Record<string, unknown>, Defs extends Record<string, unknown>> = { [K in keyof PP]: FromJSONSchema<PP[K], Defs> }[keyof PP];
|
|
179
|
+
/**
|
|
180
|
+
* Extract the `required` array from a schema as a union of string literals.
|
|
181
|
+
* Handles both readonly `as const` arrays and mutable arrays.
|
|
182
|
+
*/
|
|
183
|
+
type RequiredKeysOf<S> = S extends {
|
|
184
|
+
required: infer R;
|
|
185
|
+
} ? R extends readonly string[] ? R[number] : never : never;
|
|
186
|
+
/**
|
|
187
|
+
* Extract $defs / definitions from a schema for $ref resolution context.
|
|
188
|
+
* Also indexes schemas with `$anchor` or `$dynamicAnchor` by their anchor name,
|
|
189
|
+
* enabling `#SomeName` ref resolution.
|
|
190
|
+
* Merges with the existing Defs context from parent schemas.
|
|
191
|
+
*/
|
|
192
|
+
type ExtractDefs<S, ParentDefs extends Record<string, unknown>> = ExtractRawDefs<S> extends infer RawDefs extends Record<string, unknown> ? RawDefs & ParentDefs & ExtractAnchors<RawDefs> : ParentDefs;
|
|
193
|
+
/** Extract raw $defs / definitions maps. */
|
|
194
|
+
type ExtractRawDefs<S> = S extends {
|
|
195
|
+
$defs: infer D;
|
|
196
|
+
} ? D extends Record<string, unknown> ? D : Record<string, never> : S extends {
|
|
197
|
+
definitions: infer D;
|
|
198
|
+
} ? D extends Record<string, unknown> ? D : Record<string, never> : Record<string, never>;
|
|
199
|
+
/**
|
|
200
|
+
* Build a map of `$anchor` name -> schema from a definitions block.
|
|
201
|
+
* Scans each definition value for `$anchor` or `$dynamicAnchor` and
|
|
202
|
+
* creates entries like `{ Tree: <schema-with-$anchor-Tree> }`.
|
|
203
|
+
*/
|
|
204
|
+
type ExtractAnchors<D extends Record<string, unknown>> = { [K in keyof D as D[K] extends {
|
|
205
|
+
$anchor: infer A extends string;
|
|
206
|
+
} ? A : D[K] extends {
|
|
207
|
+
$dynamicAnchor: infer A extends string;
|
|
208
|
+
} ? A : never]: D[K] };
|
|
209
|
+
/**
|
|
210
|
+
* Convert a union to an intersection.
|
|
211
|
+
* `A | B` -> `A & B`. Used for allOf merging.
|
|
212
|
+
*/
|
|
213
|
+
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
214
|
+
/**
|
|
215
|
+
* Resolves an OpenAPI `ref` string to its JSON Schema, then parses it.
|
|
216
|
+
*
|
|
217
|
+
* Handles:
|
|
218
|
+
* - `#/components/schemas/Name` (OpenAPI 3.x)
|
|
219
|
+
* - `#/definitions/Name` (Swagger 2.0)
|
|
220
|
+
* - `#/paths/...` (path-based refs, navigating the document tree)
|
|
221
|
+
*/
|
|
222
|
+
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;
|
|
223
|
+
/**
|
|
224
|
+
* Resolve a path-based $ref after the `#/paths/` prefix.
|
|
225
|
+
* Splits on `/` and navigates the document tree.
|
|
226
|
+
*
|
|
227
|
+
* Note: JSON Pointer tilde encoding (~1 for /, ~0 for ~) is not decoded
|
|
228
|
+
* at the type level. For `as const` literals, use the literal path
|
|
229
|
+
* character directly (e.g. `#/paths//pets/get/...`).
|
|
230
|
+
*/
|
|
231
|
+
type ResolvePathBasedRef<Spec extends Record<string, unknown>, PathRest extends string> = Spec["paths"] extends Record<string, unknown> ? ResolvePathSegments<Spec["paths"], SplitPath<PathRest>> : unknown;
|
|
232
|
+
/**
|
|
233
|
+
* Split a path string on `/` into a tuple of segments.
|
|
234
|
+
* The first segment is the path key (may be empty for `/pets` -> `""` / `"pets"`).
|
|
235
|
+
*/
|
|
236
|
+
type SplitPath<S extends string> = S extends `${infer Head}/${infer Tail}` ? [Head, ...SplitPath<Tail>] : [S];
|
|
237
|
+
/**
|
|
238
|
+
* Recursively navigate into a document object by path segments.
|
|
239
|
+
*/
|
|
240
|
+
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;
|
|
241
|
+
/** Navigate to a path item in an OpenAPI document. */
|
|
242
|
+
type PathItemOf<Doc, Path extends string> = Doc extends {
|
|
243
|
+
paths: Record<string, unknown>;
|
|
244
|
+
} ? Path extends keyof Doc["paths"] ? Doc["paths"][Path] : unknown : unknown;
|
|
245
|
+
/** Navigate to an operation within a path item. */
|
|
246
|
+
type OperationOf<PathItem, Method extends string> = PathItem extends Record<string, unknown> ? Method extends keyof PathItem ? PathItem[Method] : unknown : unknown;
|
|
247
|
+
/** Extract the schema from request body content (any media type). */
|
|
248
|
+
type RequestBodySchemaOf<Op> = Op extends {
|
|
249
|
+
requestBody: {
|
|
250
|
+
content: Record<string, {
|
|
251
|
+
schema: infer S;
|
|
252
|
+
}>;
|
|
253
|
+
};
|
|
254
|
+
} ? S : Op extends {
|
|
255
|
+
requestBody: {
|
|
256
|
+
content: {
|
|
257
|
+
"application/json": {
|
|
258
|
+
schema: infer S;
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
};
|
|
262
|
+
} ? S : unknown;
|
|
263
|
+
/** Extract the schema from response content (any media type). */
|
|
264
|
+
type ResponseSchemaOf<Op, Status extends string> = Op extends {
|
|
265
|
+
responses: Record<string, unknown>;
|
|
266
|
+
} ? Status extends keyof Op["responses"] ? Op["responses"][Status] extends {
|
|
267
|
+
content: Record<string, {
|
|
268
|
+
schema: infer S;
|
|
269
|
+
}>;
|
|
270
|
+
} ? S : Op["responses"][Status] extends {
|
|
271
|
+
content: {
|
|
272
|
+
"application/json": {
|
|
273
|
+
schema: infer S;
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
} ? S : unknown : unknown : unknown;
|
|
277
|
+
/** Resolve a schema that may be a $ref pointer. */
|
|
278
|
+
type ResolveMaybeRef<Doc, S> = S extends {
|
|
279
|
+
$ref: infer R extends string;
|
|
280
|
+
} ? ResolveOpenAPIRef<Doc & Record<string, unknown>, R> : S extends {
|
|
281
|
+
nullable: true;
|
|
282
|
+
} & Record<string, unknown> ? FromJSONSchema<Omit<S, "nullable">> | null : S extends Record<string, unknown> ? FromJSONSchema<S> : unknown;
|
|
283
|
+
/** Extract parameter names from an operation. */
|
|
284
|
+
type ParameterNamesOf<Doc, Path extends string, Method extends string> = OperationOf<PathItemOf<Doc, Path>, Method> extends {
|
|
285
|
+
parameters: readonly unknown[];
|
|
286
|
+
} ? OperationOf<PathItemOf<Doc, Path>, Method>["parameters"][number] extends {
|
|
287
|
+
name: infer N;
|
|
288
|
+
} ? N extends string ? N : never : never : never;
|
|
289
|
+
/**
|
|
290
|
+
* Infer the TypeScript type of an OpenAPI operation's request body.
|
|
291
|
+
*/
|
|
292
|
+
type OpenAPIRequestBodyType<Doc, Path extends string, Method extends string> = ResolveMaybeRef<Doc, RequestBodySchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>>>;
|
|
293
|
+
/**
|
|
294
|
+
* Infer the TypeScript type of an OpenAPI operation's response.
|
|
295
|
+
*/
|
|
296
|
+
type OpenAPIResponseType<Doc, Path extends string, Method extends string, Status extends string> = ResolveMaybeRef<Doc, ResponseSchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>, Status>>;
|
|
297
|
+
/**
|
|
298
|
+
* Infer the fields prop type for ApiRequestBody.
|
|
299
|
+
* Surfaces `__SchemaInferenceFellBack` when the schema contains
|
|
300
|
+
* recursive $ref chains that exceed type-level depth limits.
|
|
301
|
+
* Falls back to `Record<string, FieldOverride>` for runtime documents.
|
|
302
|
+
*/
|
|
303
|
+
type InferRequestBodyFields<Doc, Path extends string, Method extends string> = unknown extends OpenAPIRequestBodyType<Doc, Path, Method> ? OpenAPIRequestBodyType<Doc, Path, Method> extends __SchemaInferenceFellBack ? __SchemaInferenceFellBack : Record<string, FieldOverride> : FieldOverrides<OpenAPIRequestBodyType<Doc, Path, Method>>;
|
|
304
|
+
/**
|
|
305
|
+
* Infer the fields prop type for ApiResponse.
|
|
306
|
+
* Surfaces `__SchemaInferenceFellBack` when the schema contains
|
|
307
|
+
* recursive $ref chains that exceed type-level depth limits.
|
|
308
|
+
* Falls back to `Record<string, FieldOverride>` for runtime documents.
|
|
309
|
+
*/
|
|
310
|
+
type InferResponseFields<Doc, Path extends string, Method extends string, Status extends string> = unknown extends OpenAPIResponseType<Doc, Path, Method, Status> ? OpenAPIResponseType<Doc, Path, Method, Status> extends __SchemaInferenceFellBack ? __SchemaInferenceFellBack : Record<string, FieldOverride> : FieldOverrides<OpenAPIResponseType<Doc, Path, Method, Status>>;
|
|
311
|
+
/**
|
|
312
|
+
* Infer the overrides prop type for ApiParameters.
|
|
313
|
+
* Falls back to `Record<string, FieldOverride>` for runtime documents.
|
|
314
|
+
*/
|
|
315
|
+
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>>;
|
|
316
|
+
/**
|
|
317
|
+
* Check if T is a "narrow" type (not wide like object, Record, or unknown).
|
|
318
|
+
* Used to determine if we can enumerate keys for path inference.
|
|
319
|
+
*/
|
|
320
|
+
type IsNarrowObject<T> = T extends string | number | boolean | null | undefined | unknown[] ? false : T extends object ? Record<string, never> extends T ? false : true : false;
|
|
321
|
+
/**
|
|
322
|
+
* Extract all valid dot-separated paths from an object type.
|
|
323
|
+
* Produces paths like "name" | "address.city" | "address.postcode".
|
|
324
|
+
* Stops at leaf types (string, number, boolean, null) and arrays.
|
|
325
|
+
* Returns `string` for wide types (object, Record, unknown).
|
|
326
|
+
* Handles optional/nullable fields by unwrapping T | undefined.
|
|
327
|
+
*/
|
|
328
|
+
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;
|
|
329
|
+
/**
|
|
330
|
+
* Extract the type at a given dot-separated path.
|
|
331
|
+
* PathOfType<T> produces valid paths; TypeAtPath resolves the leaf type.
|
|
332
|
+
*/
|
|
333
|
+
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
|
+
//#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 };
|