schema-components 1.20.0 → 1.22.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 +1 -1
- package/dist/core/adapter.d.mts +28 -4
- package/dist/core/adapter.mjs +408 -71
- 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 +9 -15
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +22 -1
- package/dist/core/formats.mjs +21 -0
- package/dist/core/limits.d.mts +2 -0
- package/dist/core/limits.mjs +23 -0
- package/dist/core/merge.d.mts +11 -2
- package/dist/core/merge.mjs +11 -0
- package/dist/core/normalise.d.mts +36 -4
- package/dist/core/normalise.mjs +2 -2
- 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 +35 -9
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/renderer.mjs +0 -2
- 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 +2 -2
- package/dist/core/types.mjs +1 -4
- package/dist/core/version.d.mts +1 -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 +110 -26
- package/dist/{diagnostics-CbBPsxSt.d.mts → diagnostics-D0QCYGv0.d.mts} +1 -1
- package/dist/{errors-C2iABcn9.d.mts → errors-DpFwqs5C.d.mts} +7 -11
- package/dist/html/a11y.d.mts +2 -2
- package/dist/html/a11y.mjs +10 -3
- package/dist/html/renderToHtml.d.mts +10 -3
- package/dist/html/renderToHtml.mjs +13 -3
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderers.d.mts +2 -2
- package/dist/html/renderers.mjs +1 -6
- package/dist/html/streamRenderers.d.mts +5 -4
- package/dist/html/streamRenderers.mjs +91 -30
- package/dist/limits-Cw5QZND8.d.mts +29 -0
- package/dist/{normalise-CMMEl4cd.mjs → normalise-DVEJQmF7.mjs} +791 -141
- 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 +127 -7
- package/dist/openapi/components.d.mts +175 -21
- package/dist/openapi/components.mjs +145 -21
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +74 -7
- package/dist/openapi/resolve.d.mts +70 -12
- package/dist/openapi/resolve.mjs +265 -42
- package/dist/react/SchemaComponent.d.mts +100 -35
- package/dist/react/SchemaComponent.mjs +66 -24
- package/dist/react/SchemaView.d.mts +3 -3
- package/dist/react/SchemaView.mjs +2 -2
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headless.mjs +1 -2
- package/dist/react/headlessRenderers.d.mts +3 -4
- package/dist/react/headlessRenderers.mjs +11 -31
- package/dist/{ref-C8JbwfiS.d.mts → ref-D-_JBZkF.d.mts} +7 -2
- package/dist/{renderer-SOIbJBtk.d.mts → renderer-BaRlQIuN.d.mts} +2 -2
- 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-DkcUHfaM.d.mts +982 -0
- package/dist/{types-C9zw9wbX.d.mts → types-BrRMV0en.d.mts} +15 -12
- package/package.json +1 -3
- package/dist/typeInference-CDoD_LZ_.d.mts +0 -533
- /package/dist/{version-D-u7aMfy.d.mts → version-D2jfdX6E.d.mts} +0 -0
|
@@ -59,7 +59,7 @@ type FieldOverride = Partial<SchemaMeta> & {
|
|
|
59
59
|
* All schema types the walker can produce.
|
|
60
60
|
* Used as the discriminant in the WalkedField tagged union.
|
|
61
61
|
*/
|
|
62
|
-
type SchemaType = "string" | "number" | "boolean" | "null" | "enum" | "literal" | "object" | "array" | "tuple" | "record" | "union" | "discriminatedUnion" | "conditional" | "negation" | "
|
|
62
|
+
type SchemaType = "string" | "number" | "boolean" | "null" | "enum" | "literal" | "object" | "array" | "tuple" | "record" | "union" | "discriminatedUnion" | "conditional" | "negation" | "file" | "never" | "unknown";
|
|
63
63
|
/** Constraints that apply to string schemas. */
|
|
64
64
|
interface StringConstraints {
|
|
65
65
|
minLength?: number;
|
|
@@ -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
|
}
|
|
@@ -190,6 +194,12 @@ interface TupleField extends FieldBase {
|
|
|
190
194
|
* absent, additional items are permitted but unconstrained.
|
|
191
195
|
*/
|
|
192
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;
|
|
193
203
|
}
|
|
194
204
|
interface RecordField extends FieldBase {
|
|
195
205
|
type: "record";
|
|
@@ -233,12 +243,6 @@ interface FileField extends FieldBase {
|
|
|
233
243
|
type: "file";
|
|
234
244
|
constraints: FileConstraints;
|
|
235
245
|
}
|
|
236
|
-
interface RecursiveField extends FieldBase {
|
|
237
|
-
type: "recursive";
|
|
238
|
-
constraints: Record<string, never>;
|
|
239
|
-
/** The $ref string that would create the cycle (e.g. "#" or "#Node"). */
|
|
240
|
-
refTarget: string;
|
|
241
|
-
}
|
|
242
246
|
/** Schema position where `false` appears — the field cannot have any value. */
|
|
243
247
|
interface NeverField extends FieldBase {
|
|
244
248
|
type: "never";
|
|
@@ -252,7 +256,7 @@ interface UnknownField extends FieldBase {
|
|
|
252
256
|
* Tagged union of all schema field types produced by the walker.
|
|
253
257
|
* Use `field.type` to narrow to a specific variant.
|
|
254
258
|
*/
|
|
255
|
-
type WalkedField = StringField | NumberField | BooleanField | NullField | EnumField | LiteralField | ObjectField | ArrayField | TupleField | RecordField | UnionField | DiscriminatedUnionField | ConditionalField | NegationField |
|
|
259
|
+
type WalkedField = StringField | NumberField | BooleanField | NullField | EnumField | LiteralField | ObjectField | ArrayField | TupleField | RecordField | UnionField | DiscriminatedUnionField | ConditionalField | NegationField | NeverField | FileField | UnknownField;
|
|
256
260
|
declare function isStringField(field: WalkedField): field is StringField;
|
|
257
261
|
declare function isNumberField(field: WalkedField): field is NumberField;
|
|
258
262
|
declare function isBooleanField(field: WalkedField): field is BooleanField;
|
|
@@ -268,8 +272,7 @@ declare function isDiscriminatedUnionField(field: WalkedField): field is Discrim
|
|
|
268
272
|
declare function isConditionalField(field: WalkedField): field is ConditionalField;
|
|
269
273
|
declare function isNegationField(field: WalkedField): field is NegationField;
|
|
270
274
|
declare function isFileField(field: WalkedField): field is FileField;
|
|
271
|
-
declare function isRecursiveField(field: WalkedField): field is RecursiveField;
|
|
272
275
|
declare function isNeverField(field: WalkedField): field is NeverField;
|
|
273
276
|
declare function isUnknownField(field: WalkedField): field is UnknownField;
|
|
274
277
|
//#endregion
|
|
275
|
-
export {
|
|
278
|
+
export { UnknownField as A, isNeverField as B, RecordField as C, StringField as D, StringConstraints as E, isDiscriminatedUnionField as F, isStringField as G, isNumberField 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, ObjectField as S, SchemaType as T, isObjectField as U, isNullField as V, isRecordField as W, resolveEditability as Y, NeverField as _, DiscriminatedUnionField as a, NumberField 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, NullField as v, SchemaMeta as w, ObjectConstraints as x, NumberConstraints as y, isNegationField as z };
|
package/package.json
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "schema-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "React components that render UI from Zod schemas, JSON Schema, and OpenAPI documents",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.mts",
|
|
8
6
|
"exports": {
|
|
9
7
|
"./styles.css": "./dist/html/styles.css",
|
|
10
8
|
"./core/*": {
|
|
@@ -1,533 +0,0 @@
|
|
|
1
|
-
import { d as FieldOverrides, u as FieldOverride } from "./types-C9zw9wbX.mjs";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
//#region src/core/typeInference.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Zod 4 types that `z.toJSONSchema()` rejects at runtime because they
|
|
7
|
-
* have no JSON Schema representation. The runtime adapter
|
|
8
|
-
* (`packages/core/src/core/adapter.ts` lines 106-116) catches the
|
|
9
|
-
* thrown error and surfaces it as a `SchemaNormalisationError` with
|
|
10
|
-
* kind `zod-type-unrepresentable` — but the failure only happens on
|
|
11
|
-
* first render. Statically rejecting these types at the props boundary
|
|
12
|
-
* gives the same diagnostic at compile time.
|
|
13
|
-
*
|
|
14
|
-
* SOURCE-OF-TRUTH: list mirrors `UNREPRESENTABLE_ZOD_TYPES` in
|
|
15
|
-
* `adapter.ts`. Add or remove entries here whenever the runtime list
|
|
16
|
-
* changes.
|
|
17
|
-
*/
|
|
18
|
-
type UnrepresentableZodType = z.ZodBigInt | z.ZodDate | z.ZodMap | z.ZodSet | z.ZodSymbol | z.ZodFunction | z.ZodUndefined | z.ZodVoid | z.ZodNaN | z.ZodCodec;
|
|
19
|
-
/**
|
|
20
|
-
* Brand returned in place of a rejected Zod input. The descriptive
|
|
21
|
-
* literal is what TypeScript displays when the rejection fires, so
|
|
22
|
-
* developers see why their schema is incompatible.
|
|
23
|
-
*/
|
|
24
|
-
interface UnrepresentableZodSchemaError {
|
|
25
|
-
readonly __schemaComponentsError: "Zod 4 type has no JSON Schema representation. See SchemaNormalisationError code 'zod-type-unrepresentable'.";
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Reject Zod 4 inputs whose runtime conversion is known to throw.
|
|
29
|
-
*
|
|
30
|
-
* - When `T` is one of the {@link UnrepresentableZodType} variants, the
|
|
31
|
-
* resolved type is {@link UnrepresentableZodSchemaError}, which is
|
|
32
|
-
* not assignable from any legitimate Zod / JSON Schema / OpenAPI
|
|
33
|
-
* input — so the prop fails to typecheck.
|
|
34
|
-
* - Anything else (Zod 4 schemas that DO convert, JSON Schema literals,
|
|
35
|
-
* OpenAPI documents, `unknown` for runtime inputs) passes through
|
|
36
|
-
* unchanged.
|
|
37
|
-
*
|
|
38
|
-
* Wrapped in a tuple to suppress distribution over union types.
|
|
39
|
-
*/
|
|
40
|
-
type RejectUnrepresentableZod<T> = [T] extends [UnrepresentableZodType] ? UnrepresentableZodSchemaError : T;
|
|
41
|
-
/**
|
|
42
|
-
* Convert a readonly tuple/array of values to a union type.
|
|
43
|
-
* Handles both `as const` readonly tuples and mutable arrays.
|
|
44
|
-
*/
|
|
45
|
-
type ArrayToUnion<A> = A extends readonly unknown[] ? A[number] : never;
|
|
46
|
-
/**
|
|
47
|
-
* Maps a JSON Schema structure to a TypeScript type.
|
|
48
|
-
* Works with `as const` literals -- provides full autocomplete for `fields`.
|
|
49
|
-
*
|
|
50
|
-
* Supports all JSON Schema draft versions (04-2020-12) and OpenAPI 3.x:
|
|
51
|
-
* - Primitive types: string, number, integer, boolean, null
|
|
52
|
-
* - type as array: `["string", "null"]` -> `string | null` (nullable)
|
|
53
|
-
* - enum -> union of literal types
|
|
54
|
-
* - const -> literal type
|
|
55
|
-
* - object with properties/required -> specific object type
|
|
56
|
-
* - object with additionalProperties -> Record<string, T>
|
|
57
|
-
* - array with items -> T[]
|
|
58
|
-
* - array with prefixItems -> tuple type
|
|
59
|
-
* - allOf -> intersection type
|
|
60
|
-
* - anyOf -> union type
|
|
61
|
-
* - oneOf -> union type
|
|
62
|
-
* - $ref -> resolved via $defs/definitions/$anchor context
|
|
63
|
-
* - $dynamicRef -> resolved via $dynamicAnchor in definitions
|
|
64
|
-
* - $recursiveRef -> unknown (recursive types not expressible in TS)
|
|
65
|
-
* - if/then/else -> base schema (conditionals not expressible in TS)
|
|
66
|
-
* - not -> unknown (negation not expressible in TS)
|
|
67
|
-
* - patternProperties -> merged into loose index signature
|
|
68
|
-
*/
|
|
69
|
-
type FromJSONSchema<S, Defs extends Record<string, unknown> = Record<string, never>> = S extends {
|
|
70
|
-
nullable: true;
|
|
71
|
-
} ?
|
|
72
|
-
/**
|
|
73
|
-
* OpenAPI 3.0 `nullable: true` — surface the keyword wherever it
|
|
74
|
-
* appears (not just inside `ResolveMaybeRef`). The runtime path
|
|
75
|
-
* rewrites this to `anyOf: [T, { type: "null" }]` via
|
|
76
|
-
* `normaliseOpenApi30Node` (`openapi30.ts`). Mirroring at the
|
|
77
|
-
* `FromJSONSchema` level means nested fields inside refs preserve
|
|
78
|
-
* nullability when resolved.
|
|
79
|
-
*/
|
|
80
|
-
FromJSONSchema<Omit<S, "nullable">, Defs> | null : S extends {
|
|
81
|
-
$ref: infer R extends string;
|
|
82
|
-
} ? ResolveSchemaRef<R, Defs> : S extends {
|
|
83
|
-
$recursiveRef: string;
|
|
84
|
-
} ? unknown : S extends {
|
|
85
|
-
$dynamicRef: infer R extends string;
|
|
86
|
-
} ? ResolveSchemaRef<R, Defs> : S extends {
|
|
87
|
-
allOf: infer A;
|
|
88
|
-
} ? AllOfToType<A, Defs> : S extends {
|
|
89
|
-
anyOf: infer A;
|
|
90
|
-
} ? UnionOfMembers<A, Defs> : S extends {
|
|
91
|
-
oneOf: infer A;
|
|
92
|
-
} ? UnionOfMembers<A, Defs> : S extends {
|
|
93
|
-
if: unknown;
|
|
94
|
-
} ? FromJSONSchema<Omit<S, "if" | "then" | "else">, Defs> : S extends {
|
|
95
|
-
not: unknown;
|
|
96
|
-
} ? unknown : S extends {
|
|
97
|
-
const: infer V;
|
|
98
|
-
} ? V : S extends {
|
|
99
|
-
enum: infer E;
|
|
100
|
-
} ? ArrayToUnion<E> : S extends {
|
|
101
|
-
type: infer T;
|
|
102
|
-
} ? TypeToTs<T, S, Defs> : S extends readonly (infer E)[] ? E : unknown;
|
|
103
|
-
/**
|
|
104
|
-
* Marker type emitted when OpenAPI $ref resolution hits the type-level
|
|
105
|
-
* recursion depth limit. Instead of silently falling back to
|
|
106
|
-
* `Record<string, FieldOverride>`, produces this branded type so
|
|
107
|
-
* consumers can detect it via conditional types.
|
|
108
|
-
*
|
|
109
|
-
* Usage:
|
|
110
|
-
* ```ts
|
|
111
|
-
* type Fields = InferRequestBodyFields<Doc, "/users", "post">;
|
|
112
|
-
* type IsFallback = Fields extends __SchemaInferenceFellBack ? true : false;
|
|
113
|
-
* ```
|
|
114
|
-
*/
|
|
115
|
-
interface __SchemaInferenceFellBack {
|
|
116
|
-
readonly __schemaInferenceFallback: unique symbol;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Escape hatch for recursive schemas where type-level inference
|
|
120
|
-
* cannot proceed. Typed as `Record<string, FieldOverride>` but
|
|
121
|
-
* explicitly branded so callers know they are using the unsafe path.
|
|
122
|
-
*
|
|
123
|
-
* JSDoc trade-off note: This bypasses field-level type safety.
|
|
124
|
-
* Prefer restructuring the schema to avoid deep $ref chains
|
|
125
|
-
* when possible.
|
|
126
|
-
*/
|
|
127
|
-
type UnsafeFields = Record<string, FieldOverride> & {
|
|
128
|
-
/** Marks this as the unsafe fallback for recursive schemas. */readonly __unsafe?: true;
|
|
129
|
-
};
|
|
130
|
-
/**
|
|
131
|
-
* Convert a `FromJSONSchema` result to `unknown` when recursion is detected.
|
|
132
|
-
* Returns the original type when the schema is non-recursive.
|
|
133
|
-
*/
|
|
134
|
-
type DetectRecursiveFallback<T> = unknown extends T ? __SchemaInferenceFellBack : T;
|
|
135
|
-
/**
|
|
136
|
-
* Type-level recursion bound for $ref resolution.
|
|
137
|
-
*
|
|
138
|
-
* The TypeScript type system imposes its own recursion limit; without an
|
|
139
|
-
* explicit bound a cyclic schema graph would exhaust it and degrade to
|
|
140
|
-
* `any`/`unknown` silently. Ten levels is the runtime walker's parallel
|
|
141
|
-
* — see `countDistinctRefs` in `ref.ts` (lines 52-55), which derives its
|
|
142
|
-
* bound from the number of distinct `$ref` strings in the document.
|
|
143
|
-
*
|
|
144
|
-
* A fixed bound is used here rather than a derived one because the type
|
|
145
|
-
* system has no way to count distinct strings across a recursive `Defs`
|
|
146
|
-
* map without itself recursing — which is the problem the bound exists
|
|
147
|
-
* to solve. Ten covers every realistic schema graph encountered in
|
|
148
|
-
* practice; deeper graphs surface as `__SchemaInferenceFellBack` so
|
|
149
|
-
* consumers can detect the limit explicitly.
|
|
150
|
-
*/
|
|
151
|
-
type DEFAULT_MAX_DEPTH = 10;
|
|
152
|
-
/**
|
|
153
|
-
* Resolve a $ref against the local definitions context.
|
|
154
|
-
*
|
|
155
|
-
* SOURCE-OF-TRUTH: mirrors runtime `resolveRef` in
|
|
156
|
-
* `packages/core/src/core/ref.ts` (line 90). Any change to the runtime
|
|
157
|
-
* ref-resolution rules (new ref forms, different cycle handling) must be
|
|
158
|
-
* reflected here and pinned in
|
|
159
|
-
* `packages/core/tests/typeInference-walker-parity.test.ts`.
|
|
160
|
-
*
|
|
161
|
-
* Supports:
|
|
162
|
-
* - `#` (root)
|
|
163
|
-
* - `#/$defs/Name` and `#/definitions/Name` (named definitions)
|
|
164
|
-
* - `#/components/schemas/Name` (OpenAPI 3.x component schemas)
|
|
165
|
-
* - `#SomeName` ($anchor, $dynamicAnchor resolved from definitions)
|
|
166
|
-
*
|
|
167
|
-
* `#/components/schemas/` is resolved here for parity with the runtime's
|
|
168
|
-
* `dereference` (`ref.ts` line 217), which walks any `#/...` JSON Pointer
|
|
169
|
-
* uniformly. When the runtime walker encounters an inline `$ref` inside
|
|
170
|
-
* a Zod-converted or hand-written JSON Schema that points into the
|
|
171
|
-
* OpenAPI component tree, this branch produces the corresponding type.
|
|
172
|
-
*/
|
|
173
|
-
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 `#/components/schemas/${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;
|
|
174
|
-
/**
|
|
175
|
-
* Merge an allOf array into an intersection type.
|
|
176
|
-
*/
|
|
177
|
-
type AllOfToType<A, Defs extends Record<string, unknown>> = A extends readonly unknown[] ? UnionToIntersection<FromJSONSchema<A[number], Defs>> : unknown;
|
|
178
|
-
/**
|
|
179
|
-
* Convert an anyOf/oneOf array into a union type.
|
|
180
|
-
*
|
|
181
|
-
* SOURCE-OF-TRUTH: mirrors runtime `walkUnion` (and the
|
|
182
|
-
* `walkDiscriminatedUnion` fast path) in
|
|
183
|
-
* `packages/core/src/core/walker.ts` (lines 723-752), together with
|
|
184
|
-
* `detectDiscriminated` and `normaliseAnyOf` in
|
|
185
|
-
* `packages/core/src/core/merge.ts` (lines 190-260).
|
|
186
|
-
*
|
|
187
|
-
* Deliberate divergence: the walker collapses qualifying `oneOf` members
|
|
188
|
-
* into a `discriminatedUnion` field at runtime. The type-level helper
|
|
189
|
-
* produces a plain TypeScript union because a discriminated union and a
|
|
190
|
-
* plain union over the same members are structurally indistinguishable
|
|
191
|
-
* at the type level. Parity is pinned in
|
|
192
|
-
* `packages/core/tests/typeInference-walker-parity.test.ts`.
|
|
193
|
-
*
|
|
194
|
-
* Filters out `{ type: "null" }` members and instead makes the result
|
|
195
|
-
* nullable when at least one null member is present — mirrors the
|
|
196
|
-
* walker's `normaliseAnyOf`.
|
|
197
|
-
*/
|
|
198
|
-
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;
|
|
199
|
-
/**
|
|
200
|
-
* Check whether an anyOf/oneOf array contains a `{ type: "null" }` member.
|
|
201
|
-
*
|
|
202
|
-
* SOURCE-OF-TRUTH: mirrors runtime `normaliseAnyOf` in
|
|
203
|
-
* `packages/core/src/core/merge.ts` (lines 190-209). Both implementations
|
|
204
|
-
* only recognise schema-shaped null members (`{ type: "null" }`); a bare
|
|
205
|
-
* `null` literal in the array is treated as non-nullable. Parity is
|
|
206
|
-
* pinned in `packages/core/tests/typeInference-walker-parity.test.ts`.
|
|
207
|
-
*/
|
|
208
|
-
type HasNullMember<A> = A extends readonly unknown[] ? null extends A[number] ? false : {
|
|
209
|
-
type: "null";
|
|
210
|
-
} extends A[number] ? true : false : false;
|
|
211
|
-
/**
|
|
212
|
-
* Dispatch on a `type` value -- handles single types, type arrays,
|
|
213
|
-
* and delegates to the appropriate type-specific resolver.
|
|
214
|
-
*/
|
|
215
|
-
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;
|
|
216
|
-
/**
|
|
217
|
-
* Handle `type` as an array (Draft 04-07): `["string", "null"]`.
|
|
218
|
-
* Filters out "null" and makes the result nullable.
|
|
219
|
-
*/
|
|
220
|
-
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;
|
|
221
|
-
/**
|
|
222
|
-
* Make a type nullable if the original schema `type` array includes "null".
|
|
223
|
-
* Detects nullable from the type array directly.
|
|
224
|
-
*/
|
|
225
|
-
type NullableResult<Base, S> = S extends {
|
|
226
|
-
type: readonly (infer T)[];
|
|
227
|
-
} ? "null" extends T ? Base | null : Base : Base;
|
|
228
|
-
/**
|
|
229
|
-
* Omit array-utility keys that interfere with object/array matching
|
|
230
|
-
* when re-parsing a schema for a single type from a type array.
|
|
231
|
-
*/
|
|
232
|
-
type OmitArrayHelpers<S> = Omit<S, "prefixItems" | "items" | "additionalProperties">;
|
|
233
|
-
/**
|
|
234
|
-
* Parse an array schema: prefixItems -> tuple, items -> T[], or unknown[].
|
|
235
|
-
*
|
|
236
|
-
* Draft 04 used tuple-form `items` (an array of schemas) for tuple typing;
|
|
237
|
-
* Draft 2020-12 renamed this to `prefixItems`. The runtime normaliser in
|
|
238
|
-
* `packages/core/src/core/normalise.ts` (lines 526-534) rewrites the legacy
|
|
239
|
-
* form to `prefixItems` before the walker sees it. We mirror that rewrite
|
|
240
|
-
* here so `as const` literals using the legacy form infer the same tuple
|
|
241
|
-
* type at compile time.
|
|
242
|
-
*
|
|
243
|
-
* `contains` / `minContains` / `maxContains` constrain elements at runtime
|
|
244
|
-
* but don't change the compile-time array element type.
|
|
245
|
-
*/
|
|
246
|
-
type ArraySchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
|
|
247
|
-
prefixItems: infer P;
|
|
248
|
-
} ? PrefixItemsToTuple<P, Defs> : S extends {
|
|
249
|
-
items: infer I extends readonly unknown[];
|
|
250
|
-
} ? PrefixItemsToTuple<I, Defs> : S extends {
|
|
251
|
-
items: infer I;
|
|
252
|
-
} ? FromJSONSchema<I, Defs>[] : unknown[];
|
|
253
|
-
/**
|
|
254
|
-
* Convert a prefixItems array to a TypeScript tuple type.
|
|
255
|
-
*/
|
|
256
|
-
type PrefixItemsToTuple<P, Defs extends Record<string, unknown>> = P extends readonly [infer First, ...infer Rest] ? [FromJSONSchema<First, Defs>, ...PrefixItemsToTuple<Rest, Defs>] : [];
|
|
257
|
-
/**
|
|
258
|
-
* Parse an object schema: properties + required -> specific object,
|
|
259
|
-
* additionalProperties -> Record, or empty object.
|
|
260
|
-
*
|
|
261
|
-
* Handles:
|
|
262
|
-
* - `properties` + `required` -> specific object type with required/optional keys
|
|
263
|
-
* - `additionalProperties` as schema -> Record<string, T>
|
|
264
|
-
* - `patternProperties` -> merged into a loose index signature alongside specific props
|
|
265
|
-
* (TypeScript cannot express regex-keyed properties)
|
|
266
|
-
* - `propertyNames` -> ignored at type level (TS cannot validate key shapes)
|
|
267
|
-
* - `dependentSchemas` / `dependentRequired` -> ignored (runtime-only conditionals)
|
|
268
|
-
* - `unevaluatedProperties` -> ignored (runtime-only)
|
|
269
|
-
*/
|
|
270
|
-
type ObjectSchemaToTs<S, Defs extends Record<string, unknown>> = S extends {
|
|
271
|
-
type: "object";
|
|
272
|
-
properties: infer P;
|
|
273
|
-
} ? 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 {
|
|
274
|
-
additionalProperties: infer V;
|
|
275
|
-
} ? Record<string, FromJSONSchema<V, Defs>> : Record<string, unknown>;
|
|
276
|
-
/**
|
|
277
|
-
* If the schema has `patternProperties`, intersect the base object type
|
|
278
|
-
* with a `Record<string, T>` index signature covering all pattern values.
|
|
279
|
-
* If no `patternProperties`, return the base type unchanged.
|
|
280
|
-
*/
|
|
281
|
-
type MergePatternProps<Base, S, Defs extends Record<string, unknown>> = S extends {
|
|
282
|
-
patternProperties: infer PP;
|
|
283
|
-
} ? PP extends Record<string, unknown> ? Base & Record<string, UnionOfPatternValues<PP, Defs>> : Base : Base;
|
|
284
|
-
/**
|
|
285
|
-
* Extract the union of all pattern property value types.
|
|
286
|
-
*/
|
|
287
|
-
type UnionOfPatternValues<PP extends Record<string, unknown>, Defs extends Record<string, unknown>> = { [K in keyof PP]: FromJSONSchema<PP[K], Defs> }[keyof PP];
|
|
288
|
-
/**
|
|
289
|
-
* Extract the `required` array from a schema as a union of string literals.
|
|
290
|
-
* Handles both readonly `as const` arrays and mutable arrays.
|
|
291
|
-
*/
|
|
292
|
-
type RequiredKeysOf<S> = S extends {
|
|
293
|
-
required: infer R;
|
|
294
|
-
} ? R extends readonly string[] ? R[number] : never : never;
|
|
295
|
-
/**
|
|
296
|
-
* Extract $defs / definitions from a schema for $ref resolution context.
|
|
297
|
-
* Also indexes schemas with `$anchor` or `$dynamicAnchor` by their anchor name,
|
|
298
|
-
* enabling `#SomeName` ref resolution.
|
|
299
|
-
* Merges with the existing Defs context from parent schemas.
|
|
300
|
-
*/
|
|
301
|
-
type ExtractDefs<S, ParentDefs extends Record<string, unknown>> = ExtractRawDefs<S> extends infer RawDefs extends Record<string, unknown> ? RawDefs & ParentDefs & ExtractAnchors<RawDefs> : ParentDefs;
|
|
302
|
-
/** Extract raw $defs / definitions maps. */
|
|
303
|
-
type ExtractRawDefs<S> = S extends {
|
|
304
|
-
$defs: infer D;
|
|
305
|
-
} ? D extends Record<string, unknown> ? D : Record<string, never> : S extends {
|
|
306
|
-
definitions: infer D;
|
|
307
|
-
} ? D extends Record<string, unknown> ? D : Record<string, never> : Record<string, never>;
|
|
308
|
-
/**
|
|
309
|
-
* Build a map of `$anchor` name -> schema from a definitions block.
|
|
310
|
-
* Scans each definition value for `$anchor`, `$dynamicAnchor`, or the
|
|
311
|
-
* Draft 2019-09 `$recursiveAnchor` keyword and creates entries like
|
|
312
|
-
* `{ Tree: <schema-with-$anchor-Tree> }`.
|
|
313
|
-
*
|
|
314
|
-
* SOURCE-OF-TRUTH: mirrors `normaliseDraft201909NodeWithContext` in
|
|
315
|
-
* `packages/core/src/core/normalise.ts` (lines 638-650), which rewrites
|
|
316
|
-
* `$recursiveAnchor: true` to `$anchor: "__recursive__"` and a string
|
|
317
|
-
* `$recursiveAnchor: "name"` to `$anchor: "name"`. The corresponding
|
|
318
|
-
* `$recursiveRef: "#"` therefore resolves through the same `Defs` map
|
|
319
|
-
* as a modern `$ref: "#__recursive__"`.
|
|
320
|
-
*/
|
|
321
|
-
type ExtractAnchors<D extends Record<string, unknown>> = { [K in keyof D as D[K] extends {
|
|
322
|
-
$anchor: infer A extends string;
|
|
323
|
-
} ? A : D[K] extends {
|
|
324
|
-
$dynamicAnchor: infer A extends string;
|
|
325
|
-
} ? A : D[K] extends {
|
|
326
|
-
$recursiveAnchor: infer A extends string;
|
|
327
|
-
} ? A : D[K] extends {
|
|
328
|
-
$recursiveAnchor: true;
|
|
329
|
-
} ? "__recursive__" : never]: D[K] };
|
|
330
|
-
/**
|
|
331
|
-
* Convert a union to an intersection.
|
|
332
|
-
* `A | B` -> `A & B`. Used for allOf merging.
|
|
333
|
-
*/
|
|
334
|
-
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
335
|
-
/**
|
|
336
|
-
* Resolves an OpenAPI `ref` string to its JSON Schema, then parses it.
|
|
337
|
-
*
|
|
338
|
-
* SOURCE-OF-TRUTH: mirrors runtime `resolveRef` in
|
|
339
|
-
* `packages/core/src/core/ref.ts` (line 90), which is invoked by the
|
|
340
|
-
* walker entry point in `packages/core/src/core/walker.ts` (lines
|
|
341
|
-
* 144-154) for OpenAPI documents. Any change to the runtime ref-resolution
|
|
342
|
-
* rules (new ref forms, different cycle handling, JSON Pointer decoding)
|
|
343
|
-
* must be reflected here and pinned in
|
|
344
|
-
* `packages/core/tests/typeInference-walker-parity.test.ts`.
|
|
345
|
-
*
|
|
346
|
-
* Handles:
|
|
347
|
-
* - `#/components/schemas/Name` (OpenAPI 3.x)
|
|
348
|
-
* - `#/definitions/Name` (Swagger 2.0)
|
|
349
|
-
* - `#/paths/...` (path-based refs, navigating the document tree)
|
|
350
|
-
*/
|
|
351
|
-
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;
|
|
352
|
-
/**
|
|
353
|
-
* Resolve a path-based $ref after the `#/paths/` prefix.
|
|
354
|
-
* Splits on `/` and navigates the document tree, decoding JSON Pointer
|
|
355
|
-
* tilde escapes (`~1` -> `/`, `~0` -> `~`) on every segment.
|
|
356
|
-
*
|
|
357
|
-
* SOURCE-OF-TRUTH: mirrors runtime `dereference` in
|
|
358
|
-
* `packages/core/src/core/ref.ts` (line 226), which applies the same
|
|
359
|
-
* `~1` -> `/`, `~0` -> `~` substitutions per RFC 6901 §4. The runtime
|
|
360
|
-
* uses ordered string replacement; the type-level mirror does the same
|
|
361
|
-
* via {@link DecodeJsonPointerSegment}.
|
|
362
|
-
*/
|
|
363
|
-
type ResolvePathBasedRef<Spec extends Record<string, unknown>, PathRest extends string> = Spec["paths"] extends Record<string, unknown> ? ResolvePathSegments<Spec["paths"], SplitPath<PathRest>> : unknown;
|
|
364
|
-
/**
|
|
365
|
-
* Replace every occurrence of `From` with `To` inside `S`.
|
|
366
|
-
*
|
|
367
|
-
* Pure type-level alternative to `String.prototype.replaceAll` used for
|
|
368
|
-
* JSON Pointer escape decoding. Terminates when no further match is
|
|
369
|
-
* found in the tail.
|
|
370
|
-
*/
|
|
371
|
-
type ReplaceAll<S extends string, From extends string, To extends string> = S extends `${infer Head}${From}${infer Tail}` ? `${Head}${To}${ReplaceAll<Tail, From, To>}` : S;
|
|
372
|
-
/**
|
|
373
|
-
* Decode a single JSON Pointer reference token per RFC 6901 §4:
|
|
374
|
-
* apply `~1` -> `/` first, then `~0` -> `~`. The order matters — an
|
|
375
|
-
* encoded `~` containing a literal `1` (e.g. `~01`) must remain `~1`
|
|
376
|
-
* after decoding, which only works when `~1` is processed first.
|
|
377
|
-
*/
|
|
378
|
-
type DecodeJsonPointerSegment<S extends string> = ReplaceAll<ReplaceAll<S, "~1", "/">, "~0", "~">;
|
|
379
|
-
/**
|
|
380
|
-
* Split a path string on `/` into a tuple of segments.
|
|
381
|
-
* The first segment is the path key (may be empty for `/pets` -> `""` / `"pets"`).
|
|
382
|
-
*/
|
|
383
|
-
type SplitPath<S extends string> = S extends `${infer Head}/${infer Tail}` ? [Head, ...SplitPath<Tail>] : [S];
|
|
384
|
-
/**
|
|
385
|
-
* Recursively navigate into a document object by path segments. Each
|
|
386
|
-
* segment is JSON-Pointer-decoded before indexing so encoded forms such
|
|
387
|
-
* as `~1pets` correctly resolve to the `"/pets"` key.
|
|
388
|
-
*/
|
|
389
|
-
type ResolvePathSegments<Doc, Segs extends string[]> = Segs extends [infer Head extends string, ...infer Rest extends string[]] ? Doc extends Record<string, unknown> ? DecodeJsonPointerSegment<Head> extends infer Decoded extends string ? Rest extends [] ? Doc[Decoded] : ResolvePathSegments<Doc[Decoded], Rest> : unknown : unknown : unknown;
|
|
390
|
-
/** Navigate to a path item in an OpenAPI document. */
|
|
391
|
-
type PathItemOf<Doc, Path extends string> = Doc extends {
|
|
392
|
-
paths: Record<string, unknown>;
|
|
393
|
-
} ? Path extends keyof Doc["paths"] ? Doc["paths"][Path] : unknown : unknown;
|
|
394
|
-
/** Navigate to an operation within a path item. */
|
|
395
|
-
type OperationOf<PathItem, Method extends string> = PathItem extends Record<string, unknown> ? Method extends keyof PathItem ? PathItem[Method] : unknown : unknown;
|
|
396
|
-
/**
|
|
397
|
-
* Extract the schema from request body content (any media type).
|
|
398
|
-
*
|
|
399
|
-
* `Record<string, { schema: infer S }>` already subsumes the previous
|
|
400
|
-
* `application/json`-specific branch — if the JSON content matches the
|
|
401
|
-
* specific shape it also matches the general index-signature pattern.
|
|
402
|
-
* The narrower branch was therefore unreachable and has been removed.
|
|
403
|
-
*/
|
|
404
|
-
type RequestBodySchemaOf<Op> = Op extends {
|
|
405
|
-
requestBody: {
|
|
406
|
-
content: Record<string, {
|
|
407
|
-
schema: infer S;
|
|
408
|
-
}>;
|
|
409
|
-
};
|
|
410
|
-
} ? S : unknown;
|
|
411
|
-
/**
|
|
412
|
-
* Extract the schema from response content (any media type).
|
|
413
|
-
*
|
|
414
|
-
* Same rationale as `RequestBodySchemaOf`: the index-signature branch
|
|
415
|
-
* subsumes the `application/json` branch, which was unreachable.
|
|
416
|
-
*/
|
|
417
|
-
type ResponseSchemaOf<Op, Status extends string> = Op extends {
|
|
418
|
-
responses: Record<string, unknown>;
|
|
419
|
-
} ? Status extends keyof Op["responses"] ? Op["responses"][Status] extends {
|
|
420
|
-
content: Record<string, {
|
|
421
|
-
schema: infer S;
|
|
422
|
-
}>;
|
|
423
|
-
} ? S : unknown : unknown : unknown;
|
|
424
|
-
/**
|
|
425
|
-
* Resolve a schema that may be a `$ref` pointer.
|
|
426
|
-
*
|
|
427
|
-
* The `nullable: true` handling lives inside `FromJSONSchema` so it
|
|
428
|
-
* applies uniformly to direct schemas, refs, and nested fields. This
|
|
429
|
-
* helper only dispatches between ref-resolution and plain inference.
|
|
430
|
-
*/
|
|
431
|
-
type ResolveMaybeRef<Doc, S> = S extends {
|
|
432
|
-
$ref: infer R extends string;
|
|
433
|
-
} ? ResolveOpenAPIRef<Doc & Record<string, unknown>, R> : S extends Record<string, unknown> ? FromJSONSchema<S> : unknown;
|
|
434
|
-
/** Extract parameter names from an operation. */
|
|
435
|
-
type ParameterNamesOf<Doc, Path extends string, Method extends string> = OperationOf<PathItemOf<Doc, Path>, Method> extends {
|
|
436
|
-
parameters: readonly unknown[];
|
|
437
|
-
} ? OperationOf<PathItemOf<Doc, Path>, Method>["parameters"][number] extends {
|
|
438
|
-
name: infer N;
|
|
439
|
-
} ? N extends string ? N : never : never : never;
|
|
440
|
-
/**
|
|
441
|
-
* Detect whether a document is Swagger 2.0 (OpenAPI 2.0).
|
|
442
|
-
*
|
|
443
|
-
* SOURCE-OF-TRUTH: mirrors runtime `isSwagger2` in
|
|
444
|
-
* `packages/core/src/core/version.ts`, which checks for `swagger: "2.0"`.
|
|
445
|
-
* The runtime path also recognises top-level `definitions` / parameters in
|
|
446
|
-
* the body location, but `swagger: "2.0"` is the canonical marker.
|
|
447
|
-
*
|
|
448
|
-
* Type-level Swagger 2.0 documents cannot be fully normalised at compile
|
|
449
|
-
* time — the rewrite reorders the document tree (definitions →
|
|
450
|
-
* components/schemas, body parameters → requestBody, etc.) in ways
|
|
451
|
-
* TypeScript's mapped-type machinery cannot express. Detecting the
|
|
452
|
-
* version is tractable, so we surface `__SchemaInferenceFellBack`
|
|
453
|
-
* deliberately rather than silently producing `unknown`.
|
|
454
|
-
*/
|
|
455
|
-
type IsSwagger2Doc<Doc> = Doc extends {
|
|
456
|
-
swagger: "2.0";
|
|
457
|
-
} ? true : false;
|
|
458
|
-
/**
|
|
459
|
-
* Infer the TypeScript type of an OpenAPI operation's request body.
|
|
460
|
-
*
|
|
461
|
-
* Swagger 2.0 documents are not normalised at the type level. When the
|
|
462
|
-
* input is Swagger 2.0, this returns `__SchemaInferenceFellBack` so
|
|
463
|
-
* callers can detect the fallback explicitly via a conditional type.
|
|
464
|
-
*/
|
|
465
|
-
type OpenAPIRequestBodyType<Doc, Path extends string, Method extends string> = IsSwagger2Doc<Doc> extends true ? __SchemaInferenceFellBack : ResolveMaybeRef<Doc, RequestBodySchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>>>;
|
|
466
|
-
/**
|
|
467
|
-
* Infer the TypeScript type of an OpenAPI operation's response.
|
|
468
|
-
*
|
|
469
|
-
* Swagger 2.0 documents are not normalised at the type level. When the
|
|
470
|
-
* input is Swagger 2.0, this returns `__SchemaInferenceFellBack` so
|
|
471
|
-
* callers can detect the fallback explicitly via a conditional type.
|
|
472
|
-
*/
|
|
473
|
-
type OpenAPIResponseType<Doc, Path extends string, Method extends string, Status extends string> = IsSwagger2Doc<Doc> extends true ? __SchemaInferenceFellBack : ResolveMaybeRef<Doc, ResponseSchemaOf<OperationOf<PathItemOf<Doc, Path>, Method>, Status>>;
|
|
474
|
-
/**
|
|
475
|
-
* Convert a resolved request/response type into the corresponding
|
|
476
|
-
* `fields` prop type used by ApiRequestBody / ApiResponse:
|
|
477
|
-
*
|
|
478
|
-
* - `__SchemaInferenceFellBack` (Swagger 2.0, depth-exceeded refs) is
|
|
479
|
-
* preserved verbatim so callers can detect the brand.
|
|
480
|
-
* - `unknown` (no schema found at the supplied path/status) falls back
|
|
481
|
-
* to the loose `Record<string, FieldOverride>` shape so runtime
|
|
482
|
-
* documents still typecheck.
|
|
483
|
-
* - Any other concrete type is mapped through `FieldOverrides`.
|
|
484
|
-
*
|
|
485
|
-
* The brand check intentionally precedes the `unknown` check. The brand
|
|
486
|
-
* is a structural object type and is therefore NOT assignable to
|
|
487
|
-
* `unknown extends T` — checking that first would always short-circuit
|
|
488
|
-
* to the loose `Record` fallback and the brand would never surface.
|
|
489
|
-
*/
|
|
490
|
-
type FieldsFromInferred<T> = [T] extends [__SchemaInferenceFellBack] ? __SchemaInferenceFellBack : unknown extends T ? Record<string, FieldOverride> : FieldOverrides<T>;
|
|
491
|
-
/**
|
|
492
|
-
* Infer the fields prop type for ApiRequestBody.
|
|
493
|
-
*
|
|
494
|
-
* Surfaces `__SchemaInferenceFellBack` for Swagger 2.0 documents and
|
|
495
|
-
* for schemas whose $ref chains exceed type-level depth limits. Falls
|
|
496
|
-
* back to `Record<string, FieldOverride>` for runtime documents whose
|
|
497
|
-
* shape cannot be inferred at compile time.
|
|
498
|
-
*/
|
|
499
|
-
type InferRequestBodyFields<Doc, Path extends string, Method extends string> = FieldsFromInferred<OpenAPIRequestBodyType<Doc, Path, Method>>;
|
|
500
|
-
/**
|
|
501
|
-
* Infer the fields prop type for ApiResponse.
|
|
502
|
-
*
|
|
503
|
-
* Surfaces `__SchemaInferenceFellBack` for Swagger 2.0 documents and
|
|
504
|
-
* for schemas whose $ref chains exceed type-level depth limits. Falls
|
|
505
|
-
* back to `Record<string, FieldOverride>` for runtime documents whose
|
|
506
|
-
* shape cannot be inferred at compile time.
|
|
507
|
-
*/
|
|
508
|
-
type InferResponseFields<Doc, Path extends string, Method extends string, Status extends string> = FieldsFromInferred<OpenAPIResponseType<Doc, Path, Method, Status>>;
|
|
509
|
-
/**
|
|
510
|
-
* Infer the overrides prop type for ApiParameters.
|
|
511
|
-
* Falls back to `Record<string, FieldOverride>` for runtime documents.
|
|
512
|
-
*/
|
|
513
|
-
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>>;
|
|
514
|
-
/**
|
|
515
|
-
* Check if T is a "narrow" type (not wide like object, Record, or unknown).
|
|
516
|
-
* Used to determine if we can enumerate keys for path inference.
|
|
517
|
-
*/
|
|
518
|
-
type IsNarrowObject<T> = T extends string | number | boolean | null | undefined | unknown[] ? false : T extends object ? Record<string, never> extends T ? false : true : false;
|
|
519
|
-
/**
|
|
520
|
-
* Extract all valid dot-separated paths from an object type.
|
|
521
|
-
* Produces paths like "name" | "address.city" | "address.postcode".
|
|
522
|
-
* Stops at leaf types (string, number, boolean, null) and arrays.
|
|
523
|
-
* Returns `string` for wide types (object, Record, unknown).
|
|
524
|
-
* Handles optional/nullable fields by unwrapping T | undefined.
|
|
525
|
-
*/
|
|
526
|
-
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;
|
|
527
|
-
/**
|
|
528
|
-
* Extract the type at a given dot-separated path.
|
|
529
|
-
* PathOfType<T> produces valid paths; TypeAtPath resolves the leaf type.
|
|
530
|
-
*/
|
|
531
|
-
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;
|
|
532
|
-
//#endregion
|
|
533
|
-
export { InferResponseFields as a, PathOfType as c, TypeAtPath as d, UnrepresentableZodSchemaError as f, __SchemaInferenceFellBack as h, InferRequestBodyFields as i, RejectUnrepresentableZod as l, UnsafeFields as m, FromJSONSchema as n, OpenAPIRequestBodyType as o, UnrepresentableZodType as p, InferParameterOverrides as r, OpenAPIResponseType as s, DEFAULT_MAX_DEPTH as t, ResolveOpenAPIRef as u };
|
|
File without changes
|