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.
Files changed (70) hide show
  1. package/dist/core/adapter.d.mts +10 -3
  2. package/dist/core/adapter.mjs +237 -31
  3. package/dist/core/constraints.d.mts +2 -2
  4. package/dist/core/constraints.mjs +0 -2
  5. package/dist/core/diagnostics.d.mts +1 -1
  6. package/dist/core/errors.d.mts +1 -1
  7. package/dist/core/errors.mjs +10 -8
  8. package/dist/core/fieldOrder.d.mts +1 -1
  9. package/dist/core/formats.d.mts +21 -14
  10. package/dist/core/formats.mjs +88 -4
  11. package/dist/core/merge.d.mts +11 -2
  12. package/dist/core/merge.mjs +11 -0
  13. package/dist/core/normalise.d.mts +9 -3
  14. package/dist/core/normalise.mjs +1 -1
  15. package/dist/core/openapi30.d.mts +24 -1
  16. package/dist/core/openapi30.mjs +2 -2
  17. package/dist/core/ref.d.mts +1 -1
  18. package/dist/core/ref.mjs +34 -9
  19. package/dist/core/renderer.d.mts +1 -1
  20. package/dist/core/swagger2.d.mts +1 -1
  21. package/dist/core/swagger2.mjs +1 -1
  22. package/dist/core/typeInference.d.mts +2 -2
  23. package/dist/core/types.d.mts +1 -1
  24. package/dist/core/uri.d.mts +41 -0
  25. package/dist/core/uri.mjs +76 -0
  26. package/dist/core/version.d.mts +2 -2
  27. package/dist/core/version.mjs +25 -1
  28. package/dist/core/walkBuilders.d.mts +13 -5
  29. package/dist/core/walkBuilders.mjs +11 -3
  30. package/dist/core/walker.d.mts +1 -1
  31. package/dist/core/walker.mjs +80 -26
  32. package/dist/{diagnostics-VgEKI_Ct.d.mts → diagnostics-CbBPsxSt.d.mts} +1 -1
  33. package/dist/{errors-CnGjT1cg.d.mts → errors-QEwOtQAA.d.mts} +8 -5
  34. package/dist/html/a11y.d.mts +2 -2
  35. package/dist/html/renderToHtml.d.mts +2 -2
  36. package/dist/html/renderToHtmlStream.d.mts +2 -2
  37. package/dist/html/renderers.d.mts +2 -2
  38. package/dist/html/renderers.mjs +9 -2
  39. package/dist/html/streamRenderers.d.mts +2 -2
  40. package/dist/{normalise-C0ofw3W6.mjs → normalise-DaSrnr8g.mjs} +574 -40
  41. package/dist/openapi/ApiCallbacks.d.mts +1 -1
  42. package/dist/openapi/ApiLinks.d.mts +1 -1
  43. package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
  44. package/dist/openapi/ApiSecurity.d.mts +1 -1
  45. package/dist/openapi/ApiSecurity.mjs +113 -7
  46. package/dist/openapi/bundle.mjs +2 -0
  47. package/dist/openapi/components.d.mts +32 -10
  48. package/dist/openapi/components.mjs +37 -16
  49. package/dist/openapi/parser.d.mts +1 -1
  50. package/dist/openapi/parser.mjs +41 -4
  51. package/dist/openapi/resolve.d.mts +70 -9
  52. package/dist/openapi/resolve.mjs +124 -24
  53. package/dist/react/SchemaComponent.d.mts +21 -9
  54. package/dist/react/SchemaComponent.mjs +32 -4
  55. package/dist/react/SchemaView.d.mts +3 -3
  56. package/dist/react/fieldPath.d.mts +1 -1
  57. package/dist/react/headless.d.mts +1 -1
  58. package/dist/react/headlessRenderers.d.mts +2 -2
  59. package/dist/react/headlessRenderers.mjs +18 -6
  60. package/dist/{ref-Bb43ZURY.d.mts → ref-si8ViYun.d.mts} +7 -2
  61. package/dist/{renderer-BQqiXUYP.d.mts → renderer-DI6ZYf7a.d.mts} +1 -1
  62. package/dist/themes/mantine.d.mts +1 -1
  63. package/dist/themes/mui.d.mts +1 -1
  64. package/dist/themes/radix.d.mts +1 -1
  65. package/dist/themes/shadcn.d.mts +1 -1
  66. package/dist/typeInference-Bxw3NOG1.d.mts +647 -0
  67. package/dist/{types-D_5ST7SS.d.mts → types-BnxPEElk.d.mts} +18 -2
  68. package/dist/{version-XNH7PRGP.d.mts → version-D-u7aMfy.d.mts} +36 -1
  69. package/package.json +1 -1
  70. package/dist/typeInference-5JiqIZ8t.d.mts +0 -388
@@ -1,4 +1,4 @@
1
- import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
1
+ import { T as SchemaMeta } from "../types-BnxPEElk.mjs";
2
2
  import { CallbackInfo } from "./parser.mjs";
3
3
  import { ReactNode } from "react";
4
4
 
@@ -1,4 +1,4 @@
1
- import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
1
+ import { T as SchemaMeta } from "../types-BnxPEElk.mjs";
2
2
  import { LinkInfo } from "./parser.mjs";
3
3
  import { ReactNode } from "react";
4
4
 
@@ -1,4 +1,4 @@
1
- import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
1
+ import { T as SchemaMeta } from "../types-BnxPEElk.mjs";
2
2
  import { HeaderInfo } from "./parser.mjs";
3
3
  import { ReactNode } from "react";
4
4
 
@@ -1,4 +1,4 @@
1
- import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
1
+ import { T as SchemaMeta } from "../types-BnxPEElk.mjs";
2
2
  import { SecurityRequirement, SecurityScheme } from "./parser.mjs";
3
3
  import { ReactNode } from "react";
4
4
 
@@ -1,5 +1,46 @@
1
+ import { isObject } from "../core/guards.mjs";
1
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
3
  //#region src/openapi/ApiSecurity.tsx
4
+ /**
5
+ * The four OAuth 2 flow keys defined by OpenAPI 3.x. Listed in the
6
+ * canonical specification order so renders are deterministic.
7
+ */
8
+ const OAUTH_FLOW_KEYS = [
9
+ "implicit",
10
+ "password",
11
+ "clientCredentials",
12
+ "authorizationCode"
13
+ ];
14
+ function readString(source, key) {
15
+ const value = source[key];
16
+ return typeof value === "string" ? value : void 0;
17
+ }
18
+ function readScopes(source) {
19
+ const scopes = source.scopes;
20
+ const result = /* @__PURE__ */ new Map();
21
+ if (!isObject(scopes)) return result;
22
+ for (const [name, description] of Object.entries(scopes)) {
23
+ if (typeof description !== "string") continue;
24
+ result.set(name, description);
25
+ }
26
+ return result;
27
+ }
28
+ function extractFlows(flows) {
29
+ if (flows === void 0) return [];
30
+ const result = [];
31
+ for (const name of OAUTH_FLOW_KEYS) {
32
+ const flow = flows[name];
33
+ if (!isObject(flow)) continue;
34
+ result.push({
35
+ name,
36
+ authorizationUrl: readString(flow, "authorizationUrl"),
37
+ tokenUrl: readString(flow, "tokenUrl"),
38
+ refreshUrl: readString(flow, "refreshUrl"),
39
+ scopes: readScopes(flow)
40
+ });
41
+ }
42
+ return result;
43
+ }
3
44
  function ApiSecurity({ requirements, schemes }) {
4
45
  if (requirements.length === 0) return null;
5
46
  return /* @__PURE__ */ jsxs("section", {
@@ -13,13 +54,7 @@ function ApiSecurity({ requirements, schemes }) {
13
54
  "data-security-name": true,
14
55
  children: req.name
15
56
  }),
16
- scheme !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [scheme.type !== void 0 && /* @__PURE__ */ jsx("span", {
17
- "data-security-type": true,
18
- children: scheme.type
19
- }), scheme.description && /* @__PURE__ */ jsx("span", {
20
- "data-security-description": true,
21
- children: scheme.description
22
- })] }),
57
+ scheme !== void 0 && /* @__PURE__ */ jsx(SchemeDetails, { scheme }),
23
58
  req.scopes.length > 0 && /* @__PURE__ */ jsx("span", {
24
59
  "data-security-scopes": true,
25
60
  children: req.scopes.join(", ")
@@ -29,5 +64,76 @@ function ApiSecurity({ requirements, schemes }) {
29
64
  })]
30
65
  });
31
66
  }
67
+ function SchemeDetails({ scheme }) {
68
+ const flows = extractFlows(scheme.flows);
69
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
70
+ scheme.type !== void 0 && /* @__PURE__ */ jsx("span", {
71
+ "data-security-type": true,
72
+ children: scheme.type
73
+ }),
74
+ scheme.description !== void 0 && /* @__PURE__ */ jsx("span", {
75
+ "data-security-description": true,
76
+ children: scheme.description
77
+ }),
78
+ scheme.scheme !== void 0 && /* @__PURE__ */ jsx("span", {
79
+ "data-security-http-scheme": true,
80
+ children: scheme.scheme
81
+ }),
82
+ scheme.bearerFormat !== void 0 && /* @__PURE__ */ jsx("span", {
83
+ "data-security-bearer-format": true,
84
+ children: scheme.bearerFormat
85
+ }),
86
+ scheme.name !== void 0 && /* @__PURE__ */ jsx("span", {
87
+ "data-security-apikey-name": true,
88
+ children: scheme.name
89
+ }),
90
+ scheme.location !== void 0 && /* @__PURE__ */ jsx("span", {
91
+ "data-security-apikey-in": true,
92
+ children: scheme.location
93
+ }),
94
+ scheme.openIdConnectUrl !== void 0 && /* @__PURE__ */ jsx("a", {
95
+ "data-security-openid-url": true,
96
+ href: scheme.openIdConnectUrl,
97
+ children: scheme.openIdConnectUrl
98
+ }),
99
+ flows.length > 0 && /* @__PURE__ */ jsx("section", {
100
+ "data-security-flows": true,
101
+ children: flows.map((flow) => /* @__PURE__ */ jsx(FlowDetails, { flow }, flow.name))
102
+ })
103
+ ] });
104
+ }
105
+ function FlowDetails({ flow }) {
106
+ return /* @__PURE__ */ jsxs("div", {
107
+ "data-security-flow": flow.name,
108
+ children: [
109
+ /* @__PURE__ */ jsx("span", {
110
+ "data-security-flow-name": true,
111
+ children: flow.name
112
+ }),
113
+ flow.authorizationUrl !== void 0 && /* @__PURE__ */ jsx("a", {
114
+ "data-security-flow-authorization-url": true,
115
+ href: flow.authorizationUrl,
116
+ children: flow.authorizationUrl
117
+ }),
118
+ flow.tokenUrl !== void 0 && /* @__PURE__ */ jsx("a", {
119
+ "data-security-flow-token-url": true,
120
+ href: flow.tokenUrl,
121
+ children: flow.tokenUrl
122
+ }),
123
+ flow.refreshUrl !== void 0 && /* @__PURE__ */ jsx("a", {
124
+ "data-security-flow-refresh-url": true,
125
+ href: flow.refreshUrl,
126
+ children: flow.refreshUrl
127
+ }),
128
+ flow.scopes.size > 0 && /* @__PURE__ */ jsx("dl", {
129
+ "data-security-flow-scopes": true,
130
+ children: [...flow.scopes.entries()].map(([name, description]) => /* @__PURE__ */ jsxs("div", {
131
+ "data-security-flow-scope": name,
132
+ children: [/* @__PURE__ */ jsx("dt", { children: name }), /* @__PURE__ */ jsx("dd", { children: description })]
133
+ }, name))
134
+ })
135
+ ]
136
+ });
137
+ }
32
138
  //#endregion
33
139
  export { ApiSecurity };
@@ -1,4 +1,5 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
+ import { isPrototypePollutingKey } from "../core/uri.mjs";
2
3
  //#region src/openapi/bundle.ts
3
4
  /**
4
5
  * OpenAPI document bundler — inlines external $ref files.
@@ -104,6 +105,7 @@ function resolveFragment(doc, fragment) {
104
105
  for (const part of parts) {
105
106
  if (!isObject(current)) return void 0;
106
107
  const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
108
+ if (isPrototypePollutingKey(decoded)) return void 0;
107
109
  current = current[decoded];
108
110
  }
109
111
  return isObject(current) ? current : void 0;
@@ -1,10 +1,24 @@
1
- import { T as SchemaMeta, u as FieldOverride } from "../types-D_5ST7SS.mjs";
2
- import { a as InferResponseFields, d as UnsafeFields, i as InferRequestBodyFields, r as InferParameterOverrides } from "../typeInference-5JiqIZ8t.mjs";
1
+ import { T as SchemaMeta, u as FieldOverride } from "../types-BnxPEElk.mjs";
2
+ import { r as DiagnosticSink } from "../diagnostics-CbBPsxSt.mjs";
3
+ import { a as InferResponseFields, i as InferRequestBodyFields, m as UnsafeFields, r as InferParameterOverrides } from "../typeInference-Bxw3NOG1.mjs";
3
4
  import { WidgetMap } from "../react/SchemaComponent.mjs";
4
5
  import { ReactNode } from "react";
5
6
 
6
7
  //#region src/openapi/components.d.ts
7
- interface ApiOperationProps<Doc = unknown, Path extends string = string, Method extends string = string> {
8
+ /**
9
+ * Diagnostics props accepted by every top-level OpenAPI component.
10
+ *
11
+ * `onDiagnostic` is the sink invoked for each event surfaced by the
12
+ * normalisation pipeline (duplicate body parameter, dropped Swagger
13
+ * feature, divisible-by conflict, unknown JSON Schema dialect,
14
+ * relative-ref resolved, etc.). `strict` converts every emitted
15
+ * diagnostic into a thrown `SchemaNormalisationError`.
16
+ */
17
+ interface ApiDiagnosticsProps {
18
+ onDiagnostic?: DiagnosticSink;
19
+ strict?: boolean;
20
+ }
21
+ interface ApiOperationProps<Doc = unknown, Path extends string = string, Method extends string = string> extends ApiDiagnosticsProps {
8
22
  schema: Doc;
9
23
  path: Path;
10
24
  method: Method;
@@ -30,9 +44,11 @@ declare function ApiOperation<Doc = unknown, Path extends string = string, Metho
30
44
  responseValue,
31
45
  meta,
32
46
  requestBodyFields,
33
- widgets
47
+ widgets,
48
+ onDiagnostic,
49
+ strict
34
50
  }: ApiOperationProps<Doc, Path, Method>): ReactNode;
35
- interface ApiParametersProps<Doc = unknown, Path extends string = string, Method extends string = string> {
51
+ interface ApiParametersProps<Doc = unknown, Path extends string = string, Method extends string = string> extends ApiDiagnosticsProps {
36
52
  schema: Doc;
37
53
  path: Path;
38
54
  method: Method;
@@ -47,9 +63,11 @@ declare function ApiParameters<Doc = unknown, Path extends string = string, Meth
47
63
  method,
48
64
  meta,
49
65
  overrides,
50
- widgets
66
+ widgets,
67
+ onDiagnostic,
68
+ strict
51
69
  }: ApiParametersProps<Doc, Path, Method>): ReactNode;
52
- interface ApiRequestBodyProps<Doc = unknown, Path extends string = string, Method extends string = string> {
70
+ interface ApiRequestBodyProps<Doc = unknown, Path extends string = string, Method extends string = string> extends ApiDiagnosticsProps {
53
71
  schema: Doc;
54
72
  path: Path;
55
73
  method: Method;
@@ -68,9 +86,11 @@ declare function ApiRequestBody<Doc = unknown, Path extends string = string, Met
68
86
  onChange,
69
87
  meta,
70
88
  fields,
71
- widgets
89
+ widgets,
90
+ onDiagnostic,
91
+ strict
72
92
  }: ApiRequestBodyProps<Doc, Path, Method>): ReactNode;
73
- interface ApiResponseProps<Doc = unknown, Path extends string = string, Method extends string = string, Status extends string = string> {
93
+ interface ApiResponseProps<Doc = unknown, Path extends string = string, Method extends string = string, Status extends string = string> extends ApiDiagnosticsProps {
74
94
  schema: Doc;
75
95
  path: Path;
76
96
  method: Method;
@@ -89,7 +109,9 @@ declare function ApiResponse<Doc = unknown, Path extends string = string, Method
89
109
  value,
90
110
  meta,
91
111
  fields,
92
- widgets
112
+ widgets,
113
+ onDiagnostic,
114
+ strict
93
115
  }: ApiResponseProps<Doc, Path, Method, Status>): ReactNode;
94
116
  //#endregion
95
117
  export { ApiOperation, ApiOperationProps, ApiParameters, ApiParametersProps, ApiRequestBody, ApiRequestBodyProps, ApiResponse, ApiResponseProps };
@@ -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, resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, toDoc } from "./resolve.mjs";
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 resolved = resolveOperation(rootDoc, path, method);
48
- const parsed = getParsed(rootDoc);
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);
@@ -53,7 +60,10 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
53
60
  return /* @__PURE__ */ jsxs("section", {
54
61
  "data-operation": `${method.toUpperCase()} ${path}`,
55
62
  children: [
56
- /* @__PURE__ */ jsx(OperationHeader, { operation: resolved.operation }),
63
+ /* @__PURE__ */ jsx(OperationHeader, {
64
+ operation: resolved.operation,
65
+ pathItem: resolved.pathItem
66
+ }),
57
67
  /* @__PURE__ */ jsx(ApiSecurity, {
58
68
  requirements: securityReqs,
59
69
  schemes: securitySchemes
@@ -96,6 +106,7 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
96
106
  children: [/* @__PURE__ */ jsx("h4", { children: "Responses" }), resolved.responses.map((response) => /* @__PURE__ */ jsx(ResponseCard, {
97
107
  response,
98
108
  rootDoc,
109
+ parsed,
99
110
  value: responseValue,
100
111
  meta,
101
112
  widgets,
@@ -107,9 +118,9 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
107
118
  ]
108
119
  });
109
120
  }
110
- function ApiParameters({ schema: doc, path, method, meta, overrides, widgets }) {
121
+ function ApiParameters({ schema: doc, path, method, meta, overrides, widgets, onDiagnostic, strict }) {
111
122
  const rootDoc = toDoc(doc);
112
- const params = resolveParameters(rootDoc, path, method);
123
+ const params = resolveParametersFromParsed(getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict)), path, method);
113
124
  const instancePrefix = sanitisePrefix(useId());
114
125
  if (params.length === 0) return null;
115
126
  return /* @__PURE__ */ jsxs("section", {
@@ -124,9 +135,9 @@ function ApiParameters({ schema: doc, path, method, meta, overrides, widgets })
124
135
  })]
125
136
  });
126
137
  }
127
- 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 }) {
128
139
  const rootDoc = toDoc(doc);
129
- const requestBody = resolveRequestBody(rootDoc, path, method);
140
+ const requestBody = resolveRequestBodyFromParsed(getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict)), path, method);
130
141
  const instancePrefix = sanitisePrefix(useId());
131
142
  if (requestBody?.schema === void 0) return null;
132
143
  return /* @__PURE__ */ jsxs("section", {
@@ -152,9 +163,10 @@ function ApiRequestBody({ schema: doc, path, method, value, onChange, meta, fiel
152
163
  ]
153
164
  });
154
165
  }
155
- 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 }) {
156
167
  const rootDoc = toDoc(doc);
157
- const response = resolveResponse(rootDoc, path, method, status);
168
+ const parsed = getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict));
169
+ const response = resolveResponseFromParsed(parsed, path, method, status);
158
170
  const instancePrefix = sanitisePrefix(useId());
159
171
  if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
160
172
  "data-status": status,
@@ -167,6 +179,7 @@ function ApiResponse({ schema: doc, path, method, status, value, meta, fields, w
167
179
  return /* @__PURE__ */ jsx(ResponseCard, {
168
180
  response,
169
181
  rootDoc,
182
+ parsed,
170
183
  value,
171
184
  fields,
172
185
  meta,
@@ -176,8 +189,18 @@ function ApiResponse({ schema: doc, path, method, status, value, meta, fields, w
176
189
  idPrefix: instancePrefix
177
190
  });
178
191
  }
179
- function OperationHeader({ operation }) {
192
+ function OperationHeader({ operation, pathItem }) {
180
193
  return /* @__PURE__ */ jsxs("header", { children: [
194
+ (pathItem.summary !== void 0 || pathItem.description !== void 0) && /* @__PURE__ */ jsxs("div", {
195
+ "data-path-info": true,
196
+ children: [pathItem.summary !== void 0 && /* @__PURE__ */ jsx("p", {
197
+ "data-path-summary": true,
198
+ children: pathItem.summary
199
+ }), pathItem.description !== void 0 && /* @__PURE__ */ jsx("p", {
200
+ "data-path-description": true,
201
+ children: pathItem.description
202
+ })]
203
+ }),
181
204
  /* @__PURE__ */ jsxs("h3", { children: [
182
205
  operation.method.toUpperCase(),
183
206
  " ",
@@ -214,7 +237,7 @@ function ParameterList({ parameters, rootDoc, overrides, meta, widgets, idPrefix
214
237
  ]
215
238
  }, param.name)) });
216
239
  }
217
- function ResponseCard({ response, rootDoc, value, fields, meta, widgets, path, method, idPrefix }) {
240
+ function ResponseCard({ response, rootDoc, parsed, value, fields, meta, widgets, path, method, idPrefix }) {
218
241
  if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
219
242
  "data-status": response.statusCode,
220
243
  children: [
@@ -224,9 +247,7 @@ function ResponseCard({ response, rootDoc, value, fields, meta, widgets, path, m
224
247
  ]
225
248
  });
226
249
  let links = [];
227
- if (path !== void 0 && method !== void 0) try {
228
- links = getLinks(getParsed(rootDoc), path, method, response.statusCode);
229
- } catch {}
250
+ if (path !== void 0 && method !== void 0) links = getLinks(parsed, path, method, response.statusCode);
230
251
  return /* @__PURE__ */ jsxs("div", {
231
252
  "data-status": response.statusCode,
232
253
  children: [
@@ -1,4 +1,4 @@
1
- import { m as JsonObject } from "../types-D_5ST7SS.mjs";
1
+ import { m as JsonObject } from "../types-BnxPEElk.mjs";
2
2
 
3
3
  //#region src/openapi/parser.d.ts
4
4
  interface OpenApiDocument {
@@ -1,4 +1,5 @@
1
1
  import { getProperty, isObject } from "../core/guards.mjs";
2
+ import { isPrototypePollutingKey } from "../core/uri.mjs";
2
3
  //#region src/openapi/parser.ts
3
4
  function getString(value, key) {
4
5
  const result = isObject(value) ? value[key] : void 0;
@@ -119,8 +120,10 @@ function resolveParam(doc, param) {
119
120
  return param;
120
121
  }
121
122
  function getRequestBody(parsed, path, method) {
122
- const requestBody = getProperty(getProperty(lookupPathItem(parsed, path), method), "requestBody");
123
- if (!isObject(requestBody)) return void 0;
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;
124
127
  const content = getProperty(requestBody, "content");
125
128
  if (!isObject(content)) return {
126
129
  required: getProperty(requestBody, "required") === true,
@@ -141,8 +144,10 @@ function getResponses(parsed, path, method) {
141
144
  const responses = getProperty(getProperty(lookupPathItem(parsed, path), method), "responses");
142
145
  if (!isObject(responses)) return [];
143
146
  const result = [];
144
- for (const [statusCode, response] of Object.entries(responses)) {
145
- if (!isObject(response)) continue;
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;
146
151
  const content = getProperty(response, "content");
147
152
  const contentTypes = isObject(content) ? Object.keys(content) : [];
148
153
  const schema = isObject(content) ? extractSchemaFromContent(content) : void 0;
@@ -157,15 +162,46 @@ function getResponses(parsed, path, method) {
157
162
  }
158
163
  return result;
159
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
+ }
160
178
  function extractSchemaFromContent(content) {
161
179
  const jsonSchema = getProperty(getProperty(content, "application/json"), "schema");
162
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
+ }
163
187
  for (const mediaType of Object.values(content)) {
164
188
  if (!isObject(mediaType)) continue;
165
189
  const schema = getProperty(mediaType, "schema");
166
190
  if (isObject(schema)) return schema;
167
191
  }
168
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
+ }
169
205
  function resolveRefInDoc(doc, ref) {
170
206
  if (!ref.startsWith("#/")) return void 0;
171
207
  const parts = ref.slice(2).split("/");
@@ -173,6 +209,7 @@ function resolveRefInDoc(doc, ref) {
173
209
  for (const part of parts) {
174
210
  if (!isObject(current)) return void 0;
175
211
  const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
212
+ if (isPrototypePollutingKey(decoded)) return void 0;
176
213
  current = current[decoded];
177
214
  }
178
215
  return isObject(current) ? current : void 0;
@@ -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,41 +15,101 @@ 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
- * The cache is keyed by the caller-supplied document so subsequent calls
18
- * with the same input bypass both normalisation and parsing.
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>): OpenApiDocument;
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.
24
34
  */
25
35
  declare function toDoc(value: unknown): Record<string, unknown>;
36
+ /**
37
+ * Path-Item-level metadata. OpenAPI 3.1 added `summary` and `description`
38
+ * to Path Item Objects alongside the existing operation-level fields.
39
+ * Both are plain strings (no Markdown rendering at this layer).
40
+ */
41
+ interface PathItemInfo {
42
+ summary: string | undefined;
43
+ description: string | undefined;
44
+ }
26
45
  interface ResolvedOperation {
27
46
  operation: OperationInfo;
47
+ pathItem: PathItemInfo;
28
48
  parameters: ParameterInfo[];
29
49
  requestBody: ReturnType<typeof getRequestBody>;
30
50
  responses: ResponseInfo[];
31
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;
32
63
  /**
33
64
  * Resolve an operation from an OpenAPI document by path and method.
34
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.
35
74
  */
36
- declare function resolveOperation(doc: Record<string, unknown>, path: string, method: string): ResolvedOperation;
75
+ declare function resolveParametersFromParsed(parsed: OpenApiDocument, path: string, method: string): ParameterInfo[];
37
76
  /**
38
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.
39
81
  */
40
- 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>;
41
88
  /**
42
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.
43
93
  */
44
- 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;
45
100
  /**
46
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.
47
105
  */
48
- 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;
49
107
  /**
50
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.
51
112
  */
52
- 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[];
53
114
  //#endregion
54
- export { ResolvedOperation, getParsed, resolveOperation, resolveParameters, resolveRequestBody, resolveResponse, resolveResponses, toDoc };
115
+ export { PathItemInfo, ResolvedOperation, getParsed, resolveOperation, resolveOperationFromParsed, resolveParameters, resolveParametersFromParsed, resolveRequestBody, resolveRequestBodyFromParsed, resolveResponse, resolveResponseFromParsed, resolveResponses, toDoc };