schema-components 1.20.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 +9 -2
- package/dist/core/adapter.mjs +220 -64
- package/dist/core/constraints.d.mts +1 -1
- package/dist/core/constraints.mjs +0 -2
- 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/merge.d.mts +10 -1
- package/dist/core/merge.mjs +11 -0
- package/dist/core/normalise.d.mts +7 -1
- 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.mjs +1 -1
- package/dist/core/typeInference.d.mts +1 -1
- package/dist/core/types.d.mts +1 -1
- package/dist/core/walkBuilders.d.mts +12 -4
- package/dist/core/walkBuilders.mjs +11 -3
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +32 -25
- package/dist/{errors-C2iABcn9.d.mts → errors-QEwOtQAA.d.mts} +7 -11
- 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 +1 -1
- package/dist/html/streamRenderers.d.mts +2 -2
- package/dist/{normalise-CMMEl4cd.mjs → normalise-DaSrnr8g.mjs} +325 -28
- 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/components.d.mts +32 -10
- package/dist/openapi/components.mjs +22 -12
- package/dist/openapi/parser.d.mts +1 -1
- package/dist/openapi/parser.mjs +39 -4
- package/dist/openapi/resolve.d.mts +60 -9
- package/dist/openapi/resolve.mjs +86 -23
- package/dist/react/SchemaComponent.d.mts +4 -4
- package/dist/react/SchemaComponent.mjs +32 -4
- package/dist/react/SchemaView.d.mts +2 -2
- 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 +1 -1
- package/dist/{ref-C8JbwfiS.d.mts → ref-si8ViYun.d.mts} +6 -1
- package/dist/{renderer-SOIbJBtk.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-CDoD_LZ_.d.mts → typeInference-Bxw3NOG1.d.mts} +162 -48
- package/dist/{types-C9zw9wbX.d.mts → types-BnxPEElk.d.mts} +12 -2
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ import { ApiResponseHeaders } from "./ApiResponseHeaders.mjs";
|
|
|
6
6
|
import { ApiSecurity } from "./ApiSecurity.mjs";
|
|
7
7
|
import { getLinks, getSecurityRequirements, getSecuritySchemes, listCallbacks } from "./parser.mjs";
|
|
8
8
|
import { joinPath, renderField, sanitisePrefix } from "../react/SchemaComponent.mjs";
|
|
9
|
-
import { getParsed,
|
|
9
|
+
import { getParsed, resolveOperationFromParsed, resolveParametersFromParsed, resolveRequestBodyFromParsed, resolveResponseFromParsed, toDoc } from "./resolve.mjs";
|
|
10
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
import { useId } from "react";
|
|
12
12
|
//#region src/openapi/components.tsx
|
|
@@ -23,6 +23,13 @@ import { useId } from "react";
|
|
|
23
23
|
* rendered via the walker + headless resolver directly, bypassing
|
|
24
24
|
* SchemaComponent to avoid deferred-conditional-type compatibility issues.
|
|
25
25
|
*/
|
|
26
|
+
function buildDiagnostics(onDiagnostic, strict) {
|
|
27
|
+
if (onDiagnostic === void 0 && strict !== true) return void 0;
|
|
28
|
+
const opts = {};
|
|
29
|
+
if (onDiagnostic !== void 0) opts.diagnostics = onDiagnostic;
|
|
30
|
+
if (strict === true) opts.strict = true;
|
|
31
|
+
return opts;
|
|
32
|
+
}
|
|
26
33
|
function noop() {}
|
|
27
34
|
function renderSchema(schema, rootDocument, options) {
|
|
28
35
|
if (!isObject(schema)) throw new Error("renderSchema received a non-object schema from the resolver.");
|
|
@@ -42,10 +49,10 @@ function renderSchema(schema, rootDocument, options) {
|
|
|
42
49
|
};
|
|
43
50
|
return renderField(tree, options.value, options.onChange ?? noop, void 0, makeRenderChild(options.rootPath), options.rootPath, options.widgets);
|
|
44
51
|
}
|
|
45
|
-
function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBodyChange, responseValue, meta, requestBodyFields, widgets }) {
|
|
52
|
+
function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBodyChange, responseValue, meta, requestBodyFields, widgets, onDiagnostic, strict }) {
|
|
46
53
|
const rootDoc = toDoc(doc);
|
|
47
|
-
const
|
|
48
|
-
const
|
|
54
|
+
const parsed = getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict));
|
|
55
|
+
const resolved = resolveOperationFromParsed(parsed, path, method);
|
|
49
56
|
const securityReqs = getSecurityRequirements(parsed, path, method);
|
|
50
57
|
const securitySchemes = getSecuritySchemes(parsed);
|
|
51
58
|
const callbacks = listCallbacks(parsed, path, method);
|
|
@@ -99,6 +106,7 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
|
|
|
99
106
|
children: [/* @__PURE__ */ jsx("h4", { children: "Responses" }), resolved.responses.map((response) => /* @__PURE__ */ jsx(ResponseCard, {
|
|
100
107
|
response,
|
|
101
108
|
rootDoc,
|
|
109
|
+
parsed,
|
|
102
110
|
value: responseValue,
|
|
103
111
|
meta,
|
|
104
112
|
widgets,
|
|
@@ -110,9 +118,9 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
|
|
|
110
118
|
]
|
|
111
119
|
});
|
|
112
120
|
}
|
|
113
|
-
function ApiParameters({ schema: doc, path, method, meta, overrides, widgets }) {
|
|
121
|
+
function ApiParameters({ schema: doc, path, method, meta, overrides, widgets, onDiagnostic, strict }) {
|
|
114
122
|
const rootDoc = toDoc(doc);
|
|
115
|
-
const params =
|
|
123
|
+
const params = resolveParametersFromParsed(getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict)), path, method);
|
|
116
124
|
const instancePrefix = sanitisePrefix(useId());
|
|
117
125
|
if (params.length === 0) return null;
|
|
118
126
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -127,9 +135,9 @@ function ApiParameters({ schema: doc, path, method, meta, overrides, widgets })
|
|
|
127
135
|
})]
|
|
128
136
|
});
|
|
129
137
|
}
|
|
130
|
-
function ApiRequestBody({ schema: doc, path, method, value, onChange, meta, fields, widgets }) {
|
|
138
|
+
function ApiRequestBody({ schema: doc, path, method, value, onChange, meta, fields, widgets, onDiagnostic, strict }) {
|
|
131
139
|
const rootDoc = toDoc(doc);
|
|
132
|
-
const requestBody =
|
|
140
|
+
const requestBody = resolveRequestBodyFromParsed(getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict)), path, method);
|
|
133
141
|
const instancePrefix = sanitisePrefix(useId());
|
|
134
142
|
if (requestBody?.schema === void 0) return null;
|
|
135
143
|
return /* @__PURE__ */ jsxs("section", {
|
|
@@ -155,9 +163,10 @@ function ApiRequestBody({ schema: doc, path, method, value, onChange, meta, fiel
|
|
|
155
163
|
]
|
|
156
164
|
});
|
|
157
165
|
}
|
|
158
|
-
function ApiResponse({ schema: doc, path, method, status, value, meta, fields, widgets }) {
|
|
166
|
+
function ApiResponse({ schema: doc, path, method, status, value, meta, fields, widgets, onDiagnostic, strict }) {
|
|
159
167
|
const rootDoc = toDoc(doc);
|
|
160
|
-
const
|
|
168
|
+
const parsed = getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict));
|
|
169
|
+
const response = resolveResponseFromParsed(parsed, path, method, status);
|
|
161
170
|
const instancePrefix = sanitisePrefix(useId());
|
|
162
171
|
if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
|
|
163
172
|
"data-status": status,
|
|
@@ -170,6 +179,7 @@ function ApiResponse({ schema: doc, path, method, status, value, meta, fields, w
|
|
|
170
179
|
return /* @__PURE__ */ jsx(ResponseCard, {
|
|
171
180
|
response,
|
|
172
181
|
rootDoc,
|
|
182
|
+
parsed,
|
|
173
183
|
value,
|
|
174
184
|
fields,
|
|
175
185
|
meta,
|
|
@@ -227,7 +237,7 @@ function ParameterList({ parameters, rootDoc, overrides, meta, widgets, idPrefix
|
|
|
227
237
|
]
|
|
228
238
|
}, param.name)) });
|
|
229
239
|
}
|
|
230
|
-
function ResponseCard({ response, rootDoc, value, fields, meta, widgets, path, method, idPrefix }) {
|
|
240
|
+
function ResponseCard({ response, rootDoc, parsed, value, fields, meta, widgets, path, method, idPrefix }) {
|
|
231
241
|
if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
|
|
232
242
|
"data-status": response.statusCode,
|
|
233
243
|
children: [
|
|
@@ -237,7 +247,7 @@ function ResponseCard({ response, rootDoc, value, fields, meta, widgets, path, m
|
|
|
237
247
|
]
|
|
238
248
|
});
|
|
239
249
|
let links = [];
|
|
240
|
-
if (path !== void 0 && method !== void 0) links = getLinks(
|
|
250
|
+
if (path !== void 0 && method !== void 0) links = getLinks(parsed, path, method, response.statusCode);
|
|
241
251
|
return /* @__PURE__ */ jsxs("div", {
|
|
242
252
|
"data-status": response.statusCode,
|
|
243
253
|
children: [
|
package/dist/openapi/parser.mjs
CHANGED
|
@@ -120,8 +120,10 @@ function resolveParam(doc, param) {
|
|
|
120
120
|
return param;
|
|
121
121
|
}
|
|
122
122
|
function getRequestBody(parsed, path, method) {
|
|
123
|
-
const
|
|
124
|
-
if (!isObject(
|
|
123
|
+
const requestBodyRaw = getProperty(getProperty(lookupPathItem(parsed, path), method), "requestBody");
|
|
124
|
+
if (!isObject(requestBodyRaw)) return void 0;
|
|
125
|
+
const requestBody = resolveWrapperRef(parsed.doc, requestBodyRaw);
|
|
126
|
+
if (requestBody === void 0) return void 0;
|
|
125
127
|
const content = getProperty(requestBody, "content");
|
|
126
128
|
if (!isObject(content)) return {
|
|
127
129
|
required: getProperty(requestBody, "required") === true,
|
|
@@ -142,8 +144,10 @@ function getResponses(parsed, path, method) {
|
|
|
142
144
|
const responses = getProperty(getProperty(lookupPathItem(parsed, path), method), "responses");
|
|
143
145
|
if (!isObject(responses)) return [];
|
|
144
146
|
const result = [];
|
|
145
|
-
for (const [statusCode,
|
|
146
|
-
if (!isObject(
|
|
147
|
+
for (const [statusCode, responseRaw] of Object.entries(responses)) {
|
|
148
|
+
if (!isObject(responseRaw)) continue;
|
|
149
|
+
const response = resolveWrapperRef(parsed.doc, responseRaw);
|
|
150
|
+
if (response === void 0) continue;
|
|
147
151
|
const content = getProperty(response, "content");
|
|
148
152
|
const contentTypes = isObject(content) ? Object.keys(content) : [];
|
|
149
153
|
const schema = isObject(content) ? extractSchemaFromContent(content) : void 0;
|
|
@@ -158,15 +162,46 @@ function getResponses(parsed, path, method) {
|
|
|
158
162
|
}
|
|
159
163
|
return result;
|
|
160
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Resolve a single-hop `$ref` on a wrapper object — Response Object,
|
|
167
|
+
* Request Body Object, etc. — against the document root. Returns the
|
|
168
|
+
* referenced node when the wrapper is a `$ref`, the wrapper itself when
|
|
169
|
+
* it has no `$ref`, or `undefined` when the `$ref` is malformed or
|
|
170
|
+
* cannot be resolved (so the caller skips the entry rather than reading
|
|
171
|
+
* stale fields from the bare `{ $ref }` envelope).
|
|
172
|
+
*/
|
|
173
|
+
function resolveWrapperRef(doc, wrapper) {
|
|
174
|
+
const ref = getString(wrapper, "$ref");
|
|
175
|
+
if (ref === void 0) return wrapper;
|
|
176
|
+
return resolveRefInDoc(doc, ref);
|
|
177
|
+
}
|
|
161
178
|
function extractSchemaFromContent(content) {
|
|
162
179
|
const jsonSchema = getProperty(getProperty(content, "application/json"), "schema");
|
|
163
180
|
if (isObject(jsonSchema)) return jsonSchema;
|
|
181
|
+
for (const [mediaType, mediaObj] of Object.entries(content)) {
|
|
182
|
+
if (!isJsonSuffixMediaType(mediaType)) continue;
|
|
183
|
+
if (!isObject(mediaObj)) continue;
|
|
184
|
+
const schema = getProperty(mediaObj, "schema");
|
|
185
|
+
if (isObject(schema)) return schema;
|
|
186
|
+
}
|
|
164
187
|
for (const mediaType of Object.values(content)) {
|
|
165
188
|
if (!isObject(mediaType)) continue;
|
|
166
189
|
const schema = getProperty(mediaType, "schema");
|
|
167
190
|
if (isObject(schema)) return schema;
|
|
168
191
|
}
|
|
169
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Detect RFC 6839 structured-syntax-suffix media types that encode JSON.
|
|
195
|
+
* Matches `application/<anything>+json`, optionally with parameters
|
|
196
|
+
* (`; charset=utf-8`). Excludes the literal `application/json`, which
|
|
197
|
+
* the caller checks separately to preserve preference order.
|
|
198
|
+
*/
|
|
199
|
+
function isJsonSuffixMediaType(mediaType) {
|
|
200
|
+
const lower = mediaType.toLowerCase();
|
|
201
|
+
if (lower === "application/json") return false;
|
|
202
|
+
const baseType = lower.split(";", 1)[0]?.trim() ?? "";
|
|
203
|
+
return baseType.startsWith("application/") && baseType.endsWith("+json");
|
|
204
|
+
}
|
|
170
205
|
function resolveRefInDoc(doc, ref) {
|
|
171
206
|
if (!ref.startsWith("#/")) return void 0;
|
|
172
207
|
const parts = ref.slice(2).split("/");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { i as DiagnosticsOptions } from "../diagnostics-CbBPsxSt.mjs";
|
|
1
2
|
import { OpenApiDocument, OperationInfo, ParameterInfo, ResponseInfo, getRequestBody } from "./parser.mjs";
|
|
2
3
|
|
|
3
4
|
//#region src/openapi/resolve.d.ts
|
|
@@ -14,10 +15,19 @@ import { OpenApiDocument, OperationInfo, ParameterInfo, ResponseInfo, getRequest
|
|
|
14
15
|
* same form `<SchemaComponent>` does, keeping the OpenAPI components on
|
|
15
16
|
* the same pipeline as the top-level adapter.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
18
|
+
* When `diagnostics` is supplied, normalisation events
|
|
19
|
+
* (`duplicate-body-parameter`, `dropped-swagger-feature`,
|
|
20
|
+
* `unknown-json-schema-dialect`, `divisible-by-conflict`,
|
|
21
|
+
* `relative-ref-resolved`, etc.) are forwarded to the sink. Passing
|
|
22
|
+
* diagnostics also bypasses the cache so each call observes the
|
|
23
|
+
* normalisation pipeline running against the supplied sink — caching
|
|
24
|
+
* would silently swallow every emission after the first.
|
|
25
|
+
*
|
|
26
|
+
* The cache is keyed by the caller-supplied document so subsequent
|
|
27
|
+
* cache-eligible calls with the same input bypass both normalisation
|
|
28
|
+
* and parsing.
|
|
19
29
|
*/
|
|
20
|
-
declare function getParsed(doc: Record<string, unknown
|
|
30
|
+
declare function getParsed(doc: Record<string, unknown>, diagnostics?: DiagnosticsOptions): OpenApiDocument;
|
|
21
31
|
/**
|
|
22
32
|
* Coerce an unknown value to a record, returning an empty record
|
|
23
33
|
* for non-objects.
|
|
@@ -39,26 +49,67 @@ interface ResolvedOperation {
|
|
|
39
49
|
requestBody: ReturnType<typeof getRequestBody>;
|
|
40
50
|
responses: ResponseInfo[];
|
|
41
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve an operation against an already-parsed document. Throws if
|
|
54
|
+
* the operation is not found.
|
|
55
|
+
*
|
|
56
|
+
* Used by callers that have already obtained a parsed document via
|
|
57
|
+
* {@link getParsed} — most importantly the React components, which
|
|
58
|
+
* supply `diagnostics` to `getParsed` and must avoid re-running the
|
|
59
|
+
* normalisation pipeline (every re-run would emit each diagnostic
|
|
60
|
+
* again into the sink).
|
|
61
|
+
*/
|
|
62
|
+
declare function resolveOperationFromParsed(parsed: OpenApiDocument, path: string, method: string): ResolvedOperation;
|
|
42
63
|
/**
|
|
43
64
|
* Resolve an operation from an OpenAPI document by path and method.
|
|
44
65
|
* Throws if the operation is not found.
|
|
66
|
+
*
|
|
67
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
68
|
+
* events surface to the caller's sink.
|
|
69
|
+
*/
|
|
70
|
+
declare function resolveOperation(doc: Record<string, unknown>, path: string, method: string, diagnostics?: DiagnosticsOptions): ResolvedOperation;
|
|
71
|
+
/**
|
|
72
|
+
* Resolve parameters against an already-parsed document. See
|
|
73
|
+
* {@link resolveOperationFromParsed} for the rationale.
|
|
45
74
|
*/
|
|
46
|
-
declare function
|
|
75
|
+
declare function resolveParametersFromParsed(parsed: OpenApiDocument, path: string, method: string): ParameterInfo[];
|
|
47
76
|
/**
|
|
48
77
|
* Resolve parameters for an operation. Returns empty array if none.
|
|
78
|
+
*
|
|
79
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
80
|
+
* events surface to the caller's sink.
|
|
49
81
|
*/
|
|
50
|
-
declare function resolveParameters(doc: Record<string, unknown>, path: string, method: string): ParameterInfo[];
|
|
82
|
+
declare function resolveParameters(doc: Record<string, unknown>, path: string, method: string, diagnostics?: DiagnosticsOptions): ParameterInfo[];
|
|
83
|
+
/**
|
|
84
|
+
* Resolve a request body against an already-parsed document. See
|
|
85
|
+
* {@link resolveOperationFromParsed} for the rationale.
|
|
86
|
+
*/
|
|
87
|
+
declare function resolveRequestBodyFromParsed(parsed: OpenApiDocument, path: string, method: string): ReturnType<typeof getRequestBody>;
|
|
51
88
|
/**
|
|
52
89
|
* Resolve request body for an operation. Returns undefined if none.
|
|
90
|
+
*
|
|
91
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
92
|
+
* events surface to the caller's sink.
|
|
53
93
|
*/
|
|
54
|
-
declare function resolveRequestBody(doc: Record<string, unknown>, path: string, method: string): ReturnType<typeof getRequestBody>;
|
|
94
|
+
declare function resolveRequestBody(doc: Record<string, unknown>, path: string, method: string, diagnostics?: DiagnosticsOptions): ReturnType<typeof getRequestBody>;
|
|
95
|
+
/**
|
|
96
|
+
* Resolve a specific response against an already-parsed document. See
|
|
97
|
+
* {@link resolveOperationFromParsed} for the rationale.
|
|
98
|
+
*/
|
|
99
|
+
declare function resolveResponseFromParsed(parsed: OpenApiDocument, path: string, method: string, statusCode: string): ResponseInfo;
|
|
55
100
|
/**
|
|
56
101
|
* Resolve a specific response by status code. Throws if not found.
|
|
102
|
+
*
|
|
103
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
104
|
+
* events surface to the caller's sink.
|
|
57
105
|
*/
|
|
58
|
-
declare function resolveResponse(doc: Record<string, unknown>, path: string, method: string, statusCode: string): ResponseInfo;
|
|
106
|
+
declare function resolveResponse(doc: Record<string, unknown>, path: string, method: string, statusCode: string, diagnostics?: DiagnosticsOptions): ResponseInfo;
|
|
59
107
|
/**
|
|
60
108
|
* Resolve all responses for an operation.
|
|
109
|
+
*
|
|
110
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
111
|
+
* events surface to the caller's sink.
|
|
61
112
|
*/
|
|
62
|
-
declare function resolveResponses(doc: Record<string, unknown>, path: string, method: string): ResponseInfo[];
|
|
113
|
+
declare function resolveResponses(doc: Record<string, unknown>, path: string, method: string, diagnostics?: DiagnosticsOptions): ResponseInfo[];
|
|
63
114
|
//#endregion
|
|
64
|
-
export { PathItemInfo, ResolvedOperation, getParsed, resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, resolveResponses, toDoc };
|
|
115
|
+
export { PathItemInfo, ResolvedOperation, getParsed, resolveOperation, resolveOperationFromParsed, resolveParameters, resolveParametersFromParsed, resolveRequestBody, resolveRequestBodyFromParsed, resolveResponse, resolveResponseFromParsed, resolveResponses, toDoc };
|
package/dist/openapi/resolve.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getProperty, isObject } from "../core/guards.mjs";
|
|
2
|
+
import { isPrototypePollutingKey } from "../core/uri.mjs";
|
|
2
3
|
import { detectOpenApiVersion } from "../core/version.mjs";
|
|
3
|
-
import { a as normaliseOpenApiSchemas } from "../normalise-
|
|
4
|
+
import { a as normaliseOpenApiSchemas } from "../normalise-DaSrnr8g.mjs";
|
|
4
5
|
import { getParameters, getRequestBody, getResponses, listOperations, parseOpenApiDocument } from "./parser.mjs";
|
|
5
6
|
//#region src/openapi/resolve.ts
|
|
6
7
|
/**
|
|
@@ -24,17 +25,30 @@ const docCache = /* @__PURE__ */ new WeakMap();
|
|
|
24
25
|
* same form `<SchemaComponent>` does, keeping the OpenAPI components on
|
|
25
26
|
* the same pipeline as the top-level adapter.
|
|
26
27
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
28
|
+
* When `diagnostics` is supplied, normalisation events
|
|
29
|
+
* (`duplicate-body-parameter`, `dropped-swagger-feature`,
|
|
30
|
+
* `unknown-json-schema-dialect`, `divisible-by-conflict`,
|
|
31
|
+
* `relative-ref-resolved`, etc.) are forwarded to the sink. Passing
|
|
32
|
+
* diagnostics also bypasses the cache so each call observes the
|
|
33
|
+
* normalisation pipeline running against the supplied sink — caching
|
|
34
|
+
* would silently swallow every emission after the first.
|
|
35
|
+
*
|
|
36
|
+
* The cache is keyed by the caller-supplied document so subsequent
|
|
37
|
+
* cache-eligible calls with the same input bypass both normalisation
|
|
38
|
+
* and parsing.
|
|
29
39
|
*/
|
|
30
|
-
function getParsed(doc) {
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
function getParsed(doc, diagnostics) {
|
|
41
|
+
if (diagnostics === void 0) {
|
|
42
|
+
const cached = docCache.get(doc);
|
|
43
|
+
if (cached !== void 0) return cached;
|
|
44
|
+
}
|
|
33
45
|
const version = detectOpenApiVersion(doc);
|
|
34
|
-
const normalisedDoc = version !== void 0 ? normaliseOpenApiSchemas(doc, version) : doc;
|
|
46
|
+
const normalisedDoc = version !== void 0 ? normaliseOpenApiSchemas(doc, version, diagnostics) : doc;
|
|
35
47
|
const parsed = parseOpenApiDocument(normalisedDoc);
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
if (diagnostics === void 0) {
|
|
49
|
+
docCache.set(doc, parsed);
|
|
50
|
+
if (normalisedDoc !== doc) docCache.set(normalisedDoc, parsed);
|
|
51
|
+
}
|
|
38
52
|
return parsed;
|
|
39
53
|
}
|
|
40
54
|
/**
|
|
@@ -66,6 +80,7 @@ function resolvePathItemNode(parsed, pathItem) {
|
|
|
66
80
|
for (const part of parts) {
|
|
67
81
|
if (!isObject(current)) return void 0;
|
|
68
82
|
const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
83
|
+
if (isPrototypePollutingKey(decoded)) return void 0;
|
|
69
84
|
current = current[decoded];
|
|
70
85
|
}
|
|
71
86
|
return isObject(current) ? current : pathItem;
|
|
@@ -79,11 +94,16 @@ function extractPathItemInfo(pathItem) {
|
|
|
79
94
|
};
|
|
80
95
|
}
|
|
81
96
|
/**
|
|
82
|
-
* Resolve an operation
|
|
83
|
-
*
|
|
97
|
+
* Resolve an operation against an already-parsed document. Throws if
|
|
98
|
+
* the operation is not found.
|
|
99
|
+
*
|
|
100
|
+
* Used by callers that have already obtained a parsed document via
|
|
101
|
+
* {@link getParsed} — most importantly the React components, which
|
|
102
|
+
* supply `diagnostics` to `getParsed` and must avoid re-running the
|
|
103
|
+
* normalisation pipeline (every re-run would emit each diagnostic
|
|
104
|
+
* again into the sink).
|
|
84
105
|
*/
|
|
85
|
-
function
|
|
86
|
-
const parsed = getParsed(doc);
|
|
106
|
+
function resolveOperationFromParsed(parsed, path, method) {
|
|
87
107
|
const operation = listOperations(parsed).find((op) => op.path === path && op.method === method);
|
|
88
108
|
if (operation === void 0) throw new Error(`Operation not found: ${method.toUpperCase()} ${path}`);
|
|
89
109
|
const pathItemNode = lookupPathItemNode(parsed, path);
|
|
@@ -97,30 +117,73 @@ function resolveOperation(doc, path, method) {
|
|
|
97
117
|
};
|
|
98
118
|
}
|
|
99
119
|
/**
|
|
120
|
+
* Resolve an operation from an OpenAPI document by path and method.
|
|
121
|
+
* Throws if the operation is not found.
|
|
122
|
+
*
|
|
123
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
124
|
+
* events surface to the caller's sink.
|
|
125
|
+
*/
|
|
126
|
+
function resolveOperation(doc, path, method, diagnostics) {
|
|
127
|
+
return resolveOperationFromParsed(getParsed(doc, diagnostics), path, method);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Resolve parameters against an already-parsed document. See
|
|
131
|
+
* {@link resolveOperationFromParsed} for the rationale.
|
|
132
|
+
*/
|
|
133
|
+
function resolveParametersFromParsed(parsed, path, method) {
|
|
134
|
+
return getParameters(parsed, path, method);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
100
137
|
* Resolve parameters for an operation. Returns empty array if none.
|
|
138
|
+
*
|
|
139
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
140
|
+
* events surface to the caller's sink.
|
|
101
141
|
*/
|
|
102
|
-
function resolveParameters(doc, path, method) {
|
|
103
|
-
return
|
|
142
|
+
function resolveParameters(doc, path, method, diagnostics) {
|
|
143
|
+
return resolveParametersFromParsed(getParsed(doc, diagnostics), path, method);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve a request body against an already-parsed document. See
|
|
147
|
+
* {@link resolveOperationFromParsed} for the rationale.
|
|
148
|
+
*/
|
|
149
|
+
function resolveRequestBodyFromParsed(parsed, path, method) {
|
|
150
|
+
return getRequestBody(parsed, path, method);
|
|
104
151
|
}
|
|
105
152
|
/**
|
|
106
153
|
* Resolve request body for an operation. Returns undefined if none.
|
|
154
|
+
*
|
|
155
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
156
|
+
* events surface to the caller's sink.
|
|
107
157
|
*/
|
|
108
|
-
function resolveRequestBody(doc, path, method) {
|
|
109
|
-
return
|
|
158
|
+
function resolveRequestBody(doc, path, method, diagnostics) {
|
|
159
|
+
return resolveRequestBodyFromParsed(getParsed(doc, diagnostics), path, method);
|
|
110
160
|
}
|
|
111
161
|
/**
|
|
112
|
-
* Resolve a specific response
|
|
162
|
+
* Resolve a specific response against an already-parsed document. See
|
|
163
|
+
* {@link resolveOperationFromParsed} for the rationale.
|
|
113
164
|
*/
|
|
114
|
-
function
|
|
115
|
-
const response = getResponses(
|
|
165
|
+
function resolveResponseFromParsed(parsed, path, method, statusCode) {
|
|
166
|
+
const response = getResponses(parsed, path, method).find((r) => r.statusCode === statusCode);
|
|
116
167
|
if (response === void 0) throw new Error(`Response not found: ${statusCode}`);
|
|
117
168
|
return response;
|
|
118
169
|
}
|
|
119
170
|
/**
|
|
171
|
+
* Resolve a specific response by status code. Throws if not found.
|
|
172
|
+
*
|
|
173
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
174
|
+
* events surface to the caller's sink.
|
|
175
|
+
*/
|
|
176
|
+
function resolveResponse(doc, path, method, statusCode, diagnostics) {
|
|
177
|
+
return resolveResponseFromParsed(getParsed(doc, diagnostics), path, method, statusCode);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
120
180
|
* Resolve all responses for an operation.
|
|
181
|
+
*
|
|
182
|
+
* `diagnostics` is forwarded to {@link getParsed} so normalisation
|
|
183
|
+
* events surface to the caller's sink.
|
|
121
184
|
*/
|
|
122
|
-
function resolveResponses(doc, path, method) {
|
|
123
|
-
return getResponses(getParsed(doc), path, method);
|
|
185
|
+
function resolveResponses(doc, path, method, diagnostics) {
|
|
186
|
+
return getResponses(getParsed(doc, diagnostics), path, method);
|
|
124
187
|
}
|
|
125
188
|
//#endregion
|
|
126
|
-
export { getParsed, resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, resolveResponses, toDoc };
|
|
189
|
+
export { getParsed, resolveOperation, resolveOperationFromParsed, resolveParameters, resolveParametersFromParsed, resolveRequestBody, resolveRequestBodyFromParsed, resolveResponse, resolveResponseFromParsed, resolveResponses, toDoc };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { M as WalkedField, T as SchemaMeta, d as FieldOverrides, u as FieldOverride } from "../types-
|
|
1
|
+
import { M as WalkedField, T as SchemaMeta, d as FieldOverrides, u as FieldOverride } from "../types-BnxPEElk.mjs";
|
|
2
2
|
import { t as Diagnostic } from "../diagnostics-CbBPsxSt.mjs";
|
|
3
|
-
import { t as SchemaError } from "../errors-
|
|
4
|
-
import { l as RenderProps, r as ComponentResolver } from "../renderer-
|
|
5
|
-
import { c as PathOfType, l as RejectUnrepresentableZod, n as FromJSONSchema, u as ResolveOpenAPIRef } from "../typeInference-
|
|
3
|
+
import { t as SchemaError } from "../errors-QEwOtQAA.mjs";
|
|
4
|
+
import { l as RenderProps, r as ComponentResolver } from "../renderer-DI6ZYf7a.mjs";
|
|
5
|
+
import { c as PathOfType, l as RejectUnrepresentableZod, n as FromJSONSchema, u as ResolveOpenAPIRef } from "../typeInference-Bxw3NOG1.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
8
8
|
import { ReactNode } from "react";
|
|
@@ -87,7 +87,7 @@ function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange,
|
|
|
87
87
|
}
|
|
88
88
|
const handleChange = useCallback((nextValue) => {
|
|
89
89
|
if (validate) {
|
|
90
|
-
const error = runValidation(zodSchema, jsonSchema, nextValue);
|
|
90
|
+
const error = runValidation(zodSchema, jsonSchema, nextValue, onDiagnostic);
|
|
91
91
|
if (error !== void 0) {
|
|
92
92
|
onValidationError?.(error);
|
|
93
93
|
dispatchFieldErrors(fields, error);
|
|
@@ -100,7 +100,8 @@ function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange,
|
|
|
100
100
|
jsonSchema,
|
|
101
101
|
onChange,
|
|
102
102
|
onValidationError,
|
|
103
|
-
fields
|
|
103
|
+
fields,
|
|
104
|
+
onDiagnostic
|
|
104
105
|
]);
|
|
105
106
|
const walkOptions = {
|
|
106
107
|
componentMeta: mergedMeta,
|
|
@@ -145,7 +146,7 @@ function sanitisePrefix(value) {
|
|
|
145
146
|
if (sanitised.length === 0) throw new Error(`Cannot derive a DOM-safe id prefix from "${value}". Pass an explicit idPrefix prop.`);
|
|
146
147
|
return sanitised;
|
|
147
148
|
}
|
|
148
|
-
function runValidation(zodSchema, jsonSchema, value) {
|
|
149
|
+
function runValidation(zodSchema, jsonSchema, value, onDiagnostic) {
|
|
149
150
|
if (zodSchema !== void 0 && isObject(zodSchema)) {
|
|
150
151
|
const safeParseFn = zodSchema.safeParse;
|
|
151
152
|
if (isCallable(safeParseFn)) {
|
|
@@ -154,7 +155,13 @@ function runValidation(zodSchema, jsonSchema, value) {
|
|
|
154
155
|
return;
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
|
-
|
|
158
|
+
let parsed;
|
|
159
|
+
try {
|
|
160
|
+
parsed = z.fromJSONSchema(jsonSchema);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
emitFromJsonSchemaDiagnostic(err, onDiagnostic);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
158
165
|
if (isObject(parsed)) {
|
|
159
166
|
const safeParseFn = parsed.safeParse;
|
|
160
167
|
if (isCallable(safeParseFn)) {
|
|
@@ -163,6 +170,27 @@ function runValidation(zodSchema, jsonSchema, value) {
|
|
|
163
170
|
}
|
|
164
171
|
}
|
|
165
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Emit a diagnostic when `z.fromJSONSchema` refuses to round-trip the
|
|
175
|
+
* already-normalised JSON Schema. The diagnostic reuses the existing
|
|
176
|
+
* `unsupported-type` code because the failure mode is the same — a
|
|
177
|
+
* keyword/structure Zod cannot represent — and the consumer should be
|
|
178
|
+
* able to opt in to noticing it via the existing diagnostics channel.
|
|
179
|
+
*
|
|
180
|
+
* Best-effort: when no `onDiagnostic` sink is configured we still swallow
|
|
181
|
+
* the throw (the alternative would crash the React render for a
|
|
182
|
+
* non-essential validation step), matching the silent-fallback contract
|
|
183
|
+
* the rest of the diagnostics system uses.
|
|
184
|
+
*/
|
|
185
|
+
function emitFromJsonSchemaDiagnostic(err, onDiagnostic) {
|
|
186
|
+
if (onDiagnostic === void 0) return;
|
|
187
|
+
onDiagnostic({
|
|
188
|
+
code: "unsupported-type",
|
|
189
|
+
message: `Skipping fallback validation: z.fromJSONSchema could not round-trip the normalised JSON Schema. Original message: ${err instanceof Error ? err.message : "z.fromJSONSchema threw a non-Error value"}`,
|
|
190
|
+
pointer: "",
|
|
191
|
+
detail: { source: "z.fromJSONSchema" }
|
|
192
|
+
});
|
|
193
|
+
}
|
|
166
194
|
/** Maximum rendering depth before treating a field as recursive. */
|
|
167
195
|
const MAX_RENDER_DEPTH = 10;
|
|
168
196
|
function renderField(tree, value, onChange, userResolver, renderChild, path, instanceWidgets, contextWidgets, depth = 0) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { T as SchemaMeta } from "../types-
|
|
1
|
+
import { T as SchemaMeta } from "../types-BnxPEElk.mjs";
|
|
2
2
|
import { t as Diagnostic } from "../diagnostics-CbBPsxSt.mjs";
|
|
3
|
-
import { r as ComponentResolver } from "../renderer-
|
|
3
|
+
import { r as ComponentResolver } from "../renderer-DI6ZYf7a.mjs";
|
|
4
4
|
import { WidgetMap } from "./SchemaComponent.mjs";
|
|
5
5
|
import { ReactNode } from "react";
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as WalkedField } from "../types-
|
|
2
|
-
import { l as RenderProps } from "../renderer-
|
|
1
|
+
import { M as WalkedField } from "../types-BnxPEElk.mjs";
|
|
2
|
+
import { l as RenderProps } from "../renderer-DI6ZYf7a.mjs";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/react/headlessRenderers.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
-
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
3
2
|
import { isSafeHyperlink, isSafeMailtoAddress } from "../core/uri.mjs";
|
|
3
|
+
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { isValidElement, useCallback, useEffect, useRef } from "react";
|
|
6
6
|
//#region src/react/headlessRenderers.tsx
|
|
@@ -38,7 +38,12 @@ declare function dereference(ref: string, root: Record<string, unknown>): Record
|
|
|
38
38
|
/**
|
|
39
39
|
* Recursively scan a schema document for a `$anchor` matching the given name.
|
|
40
40
|
* Returns the schema object containing the anchor, or undefined.
|
|
41
|
+
*
|
|
42
|
+
* The optional `visited` set guards against shared object references and
|
|
43
|
+
* cycles introduced by the OpenAPI bundler's `structuredClone`-based
|
|
44
|
+
* inlining of external refs. Without it a recursive document would stack
|
|
45
|
+
* overflow before reaching the matching anchor.
|
|
41
46
|
*/
|
|
42
|
-
declare function findAnchor(node: unknown, anchorName: string): Record<string, unknown> | undefined;
|
|
47
|
+
declare function findAnchor(node: unknown, anchorName: string, visited?: WeakSet<object>): Record<string, unknown> | undefined;
|
|
43
48
|
//#endregion
|
|
44
49
|
export { findAnchor as a, dereference as i, RefOptions as n, resolveRef as o, countDistinctRefs as r, ExternalResolver as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
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-
|
|
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-BnxPEElk.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/renderer.d.ts
|
|
4
4
|
/**
|
package/dist/themes/mui.d.mts
CHANGED
package/dist/themes/radix.d.mts
CHANGED
package/dist/themes/shadcn.d.mts
CHANGED