schema-components 1.19.0 → 1.21.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/dist/core/adapter.d.mts +10 -3
- package/dist/core/adapter.mjs +237 -31
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/constraints.mjs +0 -2
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +10 -8
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +21 -14
- package/dist/core/formats.mjs +88 -4
- package/dist/core/merge.d.mts +11 -2
- package/dist/core/merge.mjs +11 -0
- package/dist/core/normalise.d.mts +9 -3
- package/dist/core/normalise.mjs +1 -1
- package/dist/core/openapi30.d.mts +24 -1
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/ref.mjs +34 -9
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/typeInference.d.mts +2 -2
- package/dist/core/types.d.mts +1 -1
- package/dist/core/uri.d.mts +41 -0
- package/dist/core/uri.mjs +76 -0
- package/dist/core/version.d.mts +2 -2
- package/dist/core/version.mjs +25 -1
- package/dist/core/walkBuilders.d.mts +13 -5
- package/dist/core/walkBuilders.mjs +11 -3
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +80 -26
- package/dist/{diagnostics-VgEKI_Ct.d.mts → diagnostics-CbBPsxSt.d.mts} +1 -1
- package/dist/{errors-CnGjT1cg.d.mts → errors-QEwOtQAA.d.mts} +8 -5
- package/dist/html/a11y.d.mts +2 -2
- package/dist/html/renderToHtml.d.mts +2 -2
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderers.d.mts +2 -2
- package/dist/html/renderers.mjs +9 -2
- package/dist/html/streamRenderers.d.mts +2 -2
- package/dist/{normalise-C0ofw3W6.mjs → normalise-DaSrnr8g.mjs} +574 -40
- package/dist/openapi/ApiCallbacks.d.mts +1 -1
- package/dist/openapi/ApiLinks.d.mts +1 -1
- package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
- package/dist/openapi/ApiSecurity.d.mts +1 -1
- package/dist/openapi/ApiSecurity.mjs +113 -7
- package/dist/openapi/bundle.mjs +2 -0
- package/dist/openapi/components.d.mts +32 -10
- package/dist/openapi/components.mjs +37 -16
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +41 -4
- package/dist/openapi/resolve.d.mts +70 -9
- package/dist/openapi/resolve.mjs +124 -24
- package/dist/react/SchemaComponent.d.mts +21 -9
- package/dist/react/SchemaComponent.mjs +32 -4
- package/dist/react/SchemaView.d.mts +3 -3
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headlessRenderers.d.mts +2 -2
- package/dist/react/headlessRenderers.mjs +18 -6
- package/dist/{ref-Bb43ZURY.d.mts → ref-si8ViYun.d.mts} +7 -2
- package/dist/{renderer-BQqiXUYP.d.mts → renderer-DI6ZYf7a.d.mts} +1 -1
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/typeInference-Bxw3NOG1.d.mts +647 -0
- package/dist/{types-D_5ST7SS.d.mts → types-BnxPEElk.d.mts} +18 -2
- package/dist/{version-XNH7PRGP.d.mts → version-D-u7aMfy.d.mts} +36 -1
- package/package.json +1 -1
- package/dist/typeInference-5JiqIZ8t.d.mts +0 -388
|
@@ -84,8 +84,6 @@ interface ArrayConstraints {
|
|
|
84
84
|
minItems?: number;
|
|
85
85
|
maxItems?: number;
|
|
86
86
|
uniqueItems?: boolean;
|
|
87
|
-
/** Schema that at least one array item must match. */
|
|
88
|
-
contains?: Record<string, unknown>;
|
|
89
87
|
minContains?: number;
|
|
90
88
|
maxContains?: number;
|
|
91
89
|
/** Constraint schema for unevaluated items. */
|
|
@@ -176,6 +174,12 @@ interface ArrayField extends FieldBase {
|
|
|
176
174
|
constraints: ArrayConstraints;
|
|
177
175
|
/** The element sub-schema. */
|
|
178
176
|
element?: WalkedField;
|
|
177
|
+
/**
|
|
178
|
+
* Walked schema that at least one array item must match
|
|
179
|
+
* (`contains` keyword). Constrains element membership at runtime;
|
|
180
|
+
* paired with `minContains`/`maxContains` for cardinality.
|
|
181
|
+
*/
|
|
182
|
+
contains?: WalkedField;
|
|
179
183
|
/** Walked schema for unevaluated items. */
|
|
180
184
|
unevaluatedItems?: WalkedField;
|
|
181
185
|
}
|
|
@@ -184,6 +188,18 @@ interface TupleField extends FieldBase {
|
|
|
184
188
|
constraints: ArrayConstraints;
|
|
185
189
|
/** Positional element schemas from `prefixItems`. */
|
|
186
190
|
prefixItems: WalkedField[];
|
|
191
|
+
/**
|
|
192
|
+
* Schema for items beyond the `prefixItems` length. In Draft 2020-12,
|
|
193
|
+
* `items` adjacent to `prefixItems` describes the rest element. When
|
|
194
|
+
* absent, additional items are permitted but unconstrained.
|
|
195
|
+
*/
|
|
196
|
+
restItems?: WalkedField;
|
|
197
|
+
/**
|
|
198
|
+
* Walked schema that at least one array item must match
|
|
199
|
+
* (`contains` keyword). Tuples may declare it alongside positional
|
|
200
|
+
* element schemas to require the presence of a specific element.
|
|
201
|
+
*/
|
|
202
|
+
contains?: WalkedField;
|
|
187
203
|
}
|
|
188
204
|
interface RecordField extends FieldBase {
|
|
189
205
|
type: "record";
|
|
@@ -72,5 +72,40 @@ declare function isOpenApi31(version: OpenApiVersionInfo): boolean;
|
|
|
72
72
|
* Check if a document is Swagger 2.0.
|
|
73
73
|
*/
|
|
74
74
|
declare function isSwagger2(version: OpenApiVersionInfo): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Result of inspecting a document for the OpenAPI 3.1 `jsonSchemaDialect`
|
|
77
|
+
* keyword.
|
|
78
|
+
*
|
|
79
|
+
* - `kind: "absent"`: the keyword is not declared. The walker assumes
|
|
80
|
+
* Draft 2020-12, which is the spec-defined default.
|
|
81
|
+
* - `kind: "known"`: the declared dialect URI matches one of the
|
|
82
|
+
* supported drafts. The corresponding `JsonSchemaDraft` is returned so
|
|
83
|
+
* the normaliser can route to the matching per-node transforms.
|
|
84
|
+
* - `kind: "unknown"`: the keyword is present but its URI does not
|
|
85
|
+
* match any supported draft. The caller should emit an
|
|
86
|
+
* `unknown-json-schema-dialect` diagnostic and fall back to
|
|
87
|
+
* Draft 2020-12.
|
|
88
|
+
*/
|
|
89
|
+
type JsonSchemaDialectInfo = {
|
|
90
|
+
kind: "absent";
|
|
91
|
+
} | {
|
|
92
|
+
kind: "known";
|
|
93
|
+
uri: string;
|
|
94
|
+
draft: JsonSchemaDraft;
|
|
95
|
+
} | {
|
|
96
|
+
kind: "unknown";
|
|
97
|
+
uri: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Inspect an OpenAPI 3.1 document for a `jsonSchemaDialect` declaration.
|
|
101
|
+
*
|
|
102
|
+
* Per the OpenAPI 3.1 spec, an OpenAPI document may declare the default
|
|
103
|
+
* JSON Schema dialect for its Schema Objects via the top-level
|
|
104
|
+
* `jsonSchemaDialect` URI. Real-world 3.1 documents overwhelmingly omit
|
|
105
|
+
* the keyword and rely on the spec-defined Draft 2020-12 default — this
|
|
106
|
+
* helper surfaces the declaration so the normaliser can either honour a
|
|
107
|
+
* known dialect or emit a diagnostic for an unknown one.
|
|
108
|
+
*/
|
|
109
|
+
declare function readJsonSchemaDialect(doc: Record<string, unknown>): JsonSchemaDialectInfo;
|
|
75
110
|
//#endregion
|
|
76
|
-
export {
|
|
111
|
+
export { detectJsonSchemaDraft as a, inferJsonSchemaDraftWithReason as c, isSwagger2 as d, matchJsonSchemaDraftUri as f, OpenApiVersionInfo as i, isOpenApi30 as l, JsonSchemaDialectInfo as n, detectOpenApiVersion as o, readJsonSchemaDialect as p, JsonSchemaDraft as r, inferJsonSchemaDraft as s, InferredDraft as t, isOpenApi31 as u };
|
package/package.json
CHANGED
|
@@ -1,388 +0,0 @@
|
|
|
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
|
-
* 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;
|
|
104
|
-
/**
|
|
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
|
-
*
|
|
113
|
-
* Supports:
|
|
114
|
-
* - `#` (root)
|
|
115
|
-
* - `#/$defs/Name` and `#/definitions/Name` (named definitions)
|
|
116
|
-
* - `#SomeName` ($anchor, $dynamicAnchor resolved from definitions)
|
|
117
|
-
*/
|
|
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;
|
|
119
|
-
/**
|
|
120
|
-
* Merge an allOf array into an intersection type.
|
|
121
|
-
*/
|
|
122
|
-
type AllOfToType<A, Defs extends Record<string, unknown>> = A extends readonly unknown[] ? UnionToIntersection<FromJSONSchema<A[number], Defs>> : unknown;
|
|
123
|
-
/**
|
|
124
|
-
* Convert an anyOf/oneOf array into a union type.
|
|
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`.
|
|
142
|
-
*/
|
|
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;
|
|
144
|
-
/**
|
|
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`.
|
|
152
|
-
*/
|
|
153
|
-
type HasNullMember<A> = A extends readonly unknown[] ? null extends A[number] ? false : {
|
|
154
|
-
type: "null";
|
|
155
|
-
} extends A[number] ? true : false : false;
|
|
156
|
-
/**
|
|
157
|
-
* Dispatch on a `type` value -- handles single types, type arrays,
|
|
158
|
-
* and delegates to the appropriate type-specific resolver.
|
|
159
|
-
*/
|
|
160
|
-
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;
|
|
161
|
-
/**
|
|
162
|
-
* Handle `type` as an array (Draft 04-07): `["string", "null"]`.
|
|
163
|
-
* Filters out "null" and makes the result nullable.
|
|
164
|
-
*/
|
|
165
|
-
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;
|
|
166
|
-
/**
|
|
167
|
-
* Make a type nullable if the original schema `type` array includes "null".
|
|
168
|
-
* Detects nullable from the type array directly.
|
|
169
|
-
*/
|
|
170
|
-
type NullableResult<Base, S> = S extends {
|
|
171
|
-
type: readonly (infer T)[];
|
|
172
|
-
} ? "null" extends T ? Base | null : Base : Base;
|
|
173
|
-
/**
|
|
174
|
-
* Omit array-utility keys that interfere with object/array matching
|
|
175
|
-
* when re-parsing a schema for a single type from a type array.
|
|
176
|
-
*/
|
|
177
|
-
type OmitArrayHelpers<S> = Omit<S, "prefixItems" | "items" | "additionalProperties">;
|
|
178
|
-
/**
|
|
179
|
-
* Parse an array schema: prefixItems -> tuple, items -> T[], or unknown[].
|
|
180
|
-
*
|
|
181
|
-
* `contains` / `minContains` / `maxContains` constrain elements at runtime
|
|
182
|
-
* but don't change the compile-time array element type.
|
|
183
|
-
*/
|
|
184
|
-
type ArraySchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
|
|
185
|
-
prefixItems: infer P;
|
|
186
|
-
} ? PrefixItemsToTuple<P, Defs> : S extends {
|
|
187
|
-
items: infer I;
|
|
188
|
-
} ? FromJSONSchema<I, Defs>[] : unknown[];
|
|
189
|
-
/**
|
|
190
|
-
* Convert a prefixItems array to a TypeScript tuple type.
|
|
191
|
-
*/
|
|
192
|
-
type PrefixItemsToTuple<P, Defs extends Record<string, unknown>> = P extends readonly [infer First, ...infer Rest] ? [FromJSONSchema<First, Defs>, ...PrefixItemsToTuple<Rest, Defs>] : [];
|
|
193
|
-
/**
|
|
194
|
-
* Parse an object schema: properties + required -> specific object,
|
|
195
|
-
* additionalProperties -> Record, or empty object.
|
|
196
|
-
*
|
|
197
|
-
* Handles:
|
|
198
|
-
* - `properties` + `required` -> specific object type with required/optional keys
|
|
199
|
-
* - `additionalProperties` as schema -> Record<string, T>
|
|
200
|
-
* - `patternProperties` -> merged into a loose index signature alongside specific props
|
|
201
|
-
* (TypeScript cannot express regex-keyed properties)
|
|
202
|
-
* - `propertyNames` -> ignored at type level (TS cannot validate key shapes)
|
|
203
|
-
* - `dependentSchemas` / `dependentRequired` -> ignored (runtime-only conditionals)
|
|
204
|
-
* - `unevaluatedProperties` -> ignored (runtime-only)
|
|
205
|
-
*/
|
|
206
|
-
type ObjectSchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
|
|
207
|
-
type: "object";
|
|
208
|
-
properties: infer P;
|
|
209
|
-
} ? 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 {
|
|
210
|
-
additionalProperties: infer V;
|
|
211
|
-
} ? Record<string, FromJSONSchema<V, Defs>> : Record<string, unknown>;
|
|
212
|
-
/**
|
|
213
|
-
* If the schema has `patternProperties`, intersect the base object type
|
|
214
|
-
* with a `Record<string, T>` index signature covering all pattern values.
|
|
215
|
-
* If no `patternProperties`, return the base type unchanged.
|
|
216
|
-
*/
|
|
217
|
-
type MergePatternProps<Base, S, Defs extends Record<string, unknown>> = S extends {
|
|
218
|
-
patternProperties: infer PP;
|
|
219
|
-
} ? PP extends Record<string, unknown> ? Base & Record<string, UnionOfPatternValues<PP, Defs>> : Base : Base;
|
|
220
|
-
/**
|
|
221
|
-
* Extract the union of all pattern property value types.
|
|
222
|
-
*/
|
|
223
|
-
type UnionOfPatternValues<PP extends Record<string, unknown>, Defs extends Record<string, unknown>> = { [K in keyof PP]: FromJSONSchema<PP[K], Defs> }[keyof PP];
|
|
224
|
-
/**
|
|
225
|
-
* Extract the `required` array from a schema as a union of string literals.
|
|
226
|
-
* Handles both readonly `as const` arrays and mutable arrays.
|
|
227
|
-
*/
|
|
228
|
-
type RequiredKeysOf<S> = S extends {
|
|
229
|
-
required: infer R;
|
|
230
|
-
} ? R extends readonly string[] ? R[number] : never : never;
|
|
231
|
-
/**
|
|
232
|
-
* Extract $defs / definitions from a schema for $ref resolution context.
|
|
233
|
-
* Also indexes schemas with `$anchor` or `$dynamicAnchor` by their anchor name,
|
|
234
|
-
* enabling `#SomeName` ref resolution.
|
|
235
|
-
* Merges with the existing Defs context from parent schemas.
|
|
236
|
-
*/
|
|
237
|
-
type ExtractDefs<S, ParentDefs extends Record<string, unknown>> = ExtractRawDefs<S> extends infer RawDefs extends Record<string, unknown> ? RawDefs & ParentDefs & ExtractAnchors<RawDefs> : ParentDefs;
|
|
238
|
-
/** Extract raw $defs / definitions maps. */
|
|
239
|
-
type ExtractRawDefs<S> = S extends {
|
|
240
|
-
$defs: infer D;
|
|
241
|
-
} ? D extends Record<string, unknown> ? D : Record<string, never> : S extends {
|
|
242
|
-
definitions: infer D;
|
|
243
|
-
} ? D extends Record<string, unknown> ? D : Record<string, never> : Record<string, never>;
|
|
244
|
-
/**
|
|
245
|
-
* Build a map of `$anchor` name -> schema from a definitions block.
|
|
246
|
-
* Scans each definition value for `$anchor` or `$dynamicAnchor` and
|
|
247
|
-
* creates entries like `{ Tree: <schema-with-$anchor-Tree> }`.
|
|
248
|
-
*/
|
|
249
|
-
type ExtractAnchors<D extends Record<string, unknown>> = { [K in keyof D as D[K] extends {
|
|
250
|
-
$anchor: infer A extends string;
|
|
251
|
-
} ? A : D[K] extends {
|
|
252
|
-
$dynamicAnchor: infer A extends string;
|
|
253
|
-
} ? A : never]: D[K] };
|
|
254
|
-
/**
|
|
255
|
-
* Convert a union to an intersection.
|
|
256
|
-
* `A | B` -> `A & B`. Used for allOf merging.
|
|
257
|
-
*/
|
|
258
|
-
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
259
|
-
/**
|
|
260
|
-
* Resolves an OpenAPI `ref` string to its JSON Schema, then parses it.
|
|
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
|
-
*
|
|
270
|
-
* Handles:
|
|
271
|
-
* - `#/components/schemas/Name` (OpenAPI 3.x)
|
|
272
|
-
* - `#/definitions/Name` (Swagger 2.0)
|
|
273
|
-
* - `#/paths/...` (path-based refs, navigating the document tree)
|
|
274
|
-
*/
|
|
275
|
-
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;
|
|
276
|
-
/**
|
|
277
|
-
* Resolve a path-based $ref after the `#/paths/` prefix.
|
|
278
|
-
* Splits on `/` and navigates the document tree.
|
|
279
|
-
*
|
|
280
|
-
* Note: JSON Pointer tilde encoding (~1 for /, ~0 for ~) is not decoded
|
|
281
|
-
* at the type level. For `as const` literals, use the literal path
|
|
282
|
-
* character directly (e.g. `#/paths//pets/get/...`).
|
|
283
|
-
*/
|
|
284
|
-
type ResolvePathBasedRef<Spec extends Record<string, unknown>, PathRest extends string> = Spec["paths"] extends Record<string, unknown> ? ResolvePathSegments<Spec["paths"], SplitPath<PathRest>> : unknown;
|
|
285
|
-
/**
|
|
286
|
-
* Split a path string on `/` into a tuple of segments.
|
|
287
|
-
* The first segment is the path key (may be empty for `/pets` -> `""` / `"pets"`).
|
|
288
|
-
*/
|
|
289
|
-
type SplitPath<S extends string> = S extends `${infer Head}/${infer Tail}` ? [Head, ...SplitPath<Tail>] : [S];
|
|
290
|
-
/**
|
|
291
|
-
* Recursively navigate into a document object by path segments.
|
|
292
|
-
*/
|
|
293
|
-
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;
|
|
294
|
-
/** Navigate to a path item in an OpenAPI document. */
|
|
295
|
-
type PathItemOf<Doc, Path extends string> = Doc extends {
|
|
296
|
-
paths: Record<string, unknown>;
|
|
297
|
-
} ? Path extends keyof Doc["paths"] ? Doc["paths"][Path] : unknown : unknown;
|
|
298
|
-
/** Navigate to an operation within a path item. */
|
|
299
|
-
type OperationOf<PathItem, Method extends string> = PathItem extends Record<string, unknown> ? Method extends keyof PathItem ? PathItem[Method] : unknown : unknown;
|
|
300
|
-
/** Extract the schema from request body content (any media type). */
|
|
301
|
-
type RequestBodySchemaOf<Op> = Op extends {
|
|
302
|
-
requestBody: {
|
|
303
|
-
content: Record<string, {
|
|
304
|
-
schema: infer S;
|
|
305
|
-
}>;
|
|
306
|
-
};
|
|
307
|
-
} ? S : Op extends {
|
|
308
|
-
requestBody: {
|
|
309
|
-
content: {
|
|
310
|
-
"application/json": {
|
|
311
|
-
schema: infer S;
|
|
312
|
-
};
|
|
313
|
-
};
|
|
314
|
-
};
|
|
315
|
-
} ? S : unknown;
|
|
316
|
-
/** Extract the schema from response content (any media type). */
|
|
317
|
-
type ResponseSchemaOf<Op, Status extends string> = Op extends {
|
|
318
|
-
responses: Record<string, unknown>;
|
|
319
|
-
} ? Status extends keyof Op["responses"] ? Op["responses"][Status] extends {
|
|
320
|
-
content: Record<string, {
|
|
321
|
-
schema: infer S;
|
|
322
|
-
}>;
|
|
323
|
-
} ? S : Op["responses"][Status] extends {
|
|
324
|
-
content: {
|
|
325
|
-
"application/json": {
|
|
326
|
-
schema: infer S;
|
|
327
|
-
};
|
|
328
|
-
};
|
|
329
|
-
} ? S : unknown : unknown : unknown;
|
|
330
|
-
/** Resolve a schema that may be a $ref pointer. */
|
|
331
|
-
type ResolveMaybeRef<Doc, S> = S extends {
|
|
332
|
-
$ref: infer R extends string;
|
|
333
|
-
} ? ResolveOpenAPIRef<Doc & Record<string, unknown>, R> : S extends {
|
|
334
|
-
nullable: true;
|
|
335
|
-
} & Record<string, unknown> ? FromJSONSchema<Omit<S, "nullable">> | null : S extends Record<string, unknown> ? FromJSONSchema<S> : unknown;
|
|
336
|
-
/** Extract parameter names from an operation. */
|
|
337
|
-
type ParameterNamesOf<Doc, Path extends string, Method extends string> = OperationOf<PathItemOf<Doc, Path>, Method> extends {
|
|
338
|
-
parameters: readonly unknown[];
|
|
339
|
-
} ? OperationOf<PathItemOf<Doc, Path>, Method>["parameters"][number] extends {
|
|
340
|
-
name: infer N;
|
|
341
|
-
} ? N extends string ? N : never : never : never;
|
|
342
|
-
/**
|
|
343
|
-
* Infer the TypeScript type of an OpenAPI operation's request body.
|
|
344
|
-
*/
|
|
345
|
-
type OpenAPIRequestBodyType<Doc, Path extends string, Method extends string> = ResolveMaybeRef<Doc, RequestBodySchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>>>;
|
|
346
|
-
/**
|
|
347
|
-
* Infer the TypeScript type of an OpenAPI operation's response.
|
|
348
|
-
*/
|
|
349
|
-
type OpenAPIResponseType<Doc, Path extends string, Method extends string, Status extends string> = ResolveMaybeRef<Doc, ResponseSchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>, Status>>;
|
|
350
|
-
/**
|
|
351
|
-
* Infer the fields prop type for ApiRequestBody.
|
|
352
|
-
* Surfaces `__SchemaInferenceFellBack` when the schema contains
|
|
353
|
-
* recursive $ref chains that exceed type-level depth limits.
|
|
354
|
-
* Falls back to `Record<string, FieldOverride>` for runtime documents.
|
|
355
|
-
*/
|
|
356
|
-
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>>;
|
|
357
|
-
/**
|
|
358
|
-
* Infer the fields prop type for ApiResponse.
|
|
359
|
-
* Surfaces `__SchemaInferenceFellBack` when the schema contains
|
|
360
|
-
* recursive $ref chains that exceed type-level depth limits.
|
|
361
|
-
* Falls back to `Record<string, FieldOverride>` for runtime documents.
|
|
362
|
-
*/
|
|
363
|
-
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>>;
|
|
364
|
-
/**
|
|
365
|
-
* Infer the overrides prop type for ApiParameters.
|
|
366
|
-
* Falls back to `Record<string, FieldOverride>` for runtime documents.
|
|
367
|
-
*/
|
|
368
|
-
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>>;
|
|
369
|
-
/**
|
|
370
|
-
* Check if T is a "narrow" type (not wide like object, Record, or unknown).
|
|
371
|
-
* Used to determine if we can enumerate keys for path inference.
|
|
372
|
-
*/
|
|
373
|
-
type IsNarrowObject<T> = T extends string | number | boolean | null | undefined | unknown[] ? false : T extends object ? Record<string, never> extends T ? false : true : false;
|
|
374
|
-
/**
|
|
375
|
-
* Extract all valid dot-separated paths from an object type.
|
|
376
|
-
* Produces paths like "name" | "address.city" | "address.postcode".
|
|
377
|
-
* Stops at leaf types (string, number, boolean, null) and arrays.
|
|
378
|
-
* Returns `string` for wide types (object, Record, unknown).
|
|
379
|
-
* Handles optional/nullable fields by unwrapping T | undefined.
|
|
380
|
-
*/
|
|
381
|
-
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;
|
|
382
|
-
/**
|
|
383
|
-
* Extract the type at a given dot-separated path.
|
|
384
|
-
* PathOfType<T> produces valid paths; TypeAtPath resolves the leaf type.
|
|
385
|
-
*/
|
|
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;
|
|
387
|
-
//#endregion
|
|
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 };
|