schema-components 1.21.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.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/dist/core/adapter.d.mts +20 -3
  3. package/dist/core/adapter.mjs +209 -28
  4. package/dist/core/constraints.d.mts +2 -2
  5. package/dist/core/diagnostics.d.mts +1 -1
  6. package/dist/core/errors.d.mts +1 -1
  7. package/dist/core/fieldOrder.d.mts +1 -1
  8. package/dist/core/formats.d.mts +22 -1
  9. package/dist/core/formats.mjs +21 -0
  10. package/dist/core/limits.d.mts +2 -0
  11. package/dist/core/limits.mjs +23 -0
  12. package/dist/core/merge.d.mts +1 -1
  13. package/dist/core/normalise.d.mts +29 -3
  14. package/dist/core/normalise.mjs +2 -2
  15. package/dist/core/openapi30.mjs +1 -1
  16. package/dist/core/ref.d.mts +1 -1
  17. package/dist/core/ref.mjs +1 -0
  18. package/dist/core/renderer.d.mts +1 -1
  19. package/dist/core/renderer.mjs +0 -2
  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 +2 -2
  24. package/dist/core/types.mjs +1 -4
  25. package/dist/core/version.d.mts +1 -1
  26. package/dist/core/walkBuilders.d.mts +3 -3
  27. package/dist/core/walker.d.mts +1 -1
  28. package/dist/core/walker.mjs +79 -2
  29. package/dist/{diagnostics-CbBPsxSt.d.mts → diagnostics-D0QCYGv0.d.mts} +1 -1
  30. package/dist/{errors-QEwOtQAA.d.mts → errors-DpFwqs5C.d.mts} +1 -1
  31. package/dist/html/a11y.d.mts +2 -2
  32. package/dist/html/a11y.mjs +10 -3
  33. package/dist/html/renderToHtml.d.mts +10 -3
  34. package/dist/html/renderToHtml.mjs +13 -3
  35. package/dist/html/renderToHtmlStream.d.mts +2 -2
  36. package/dist/html/renderers.d.mts +2 -2
  37. package/dist/html/renderers.mjs +0 -5
  38. package/dist/html/streamRenderers.d.mts +5 -4
  39. package/dist/html/streamRenderers.mjs +91 -30
  40. package/dist/limits-Cw5QZND8.d.mts +29 -0
  41. package/dist/{normalise-DaSrnr8g.mjs → normalise-DVEJQmF7.mjs} +468 -115
  42. package/dist/openapi/ApiCallbacks.d.mts +1 -1
  43. package/dist/openapi/ApiLinks.d.mts +1 -1
  44. package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
  45. package/dist/openapi/ApiSecurity.d.mts +1 -1
  46. package/dist/openapi/ApiSecurity.mjs +16 -2
  47. package/dist/openapi/components.d.mts +150 -18
  48. package/dist/openapi/components.mjs +129 -15
  49. package/dist/openapi/parser.d.mts +1 -1
  50. package/dist/openapi/parser.mjs +35 -3
  51. package/dist/openapi/resolve.d.mts +12 -5
  52. package/dist/openapi/resolve.mjs +183 -23
  53. package/dist/react/SchemaComponent.d.mts +100 -35
  54. package/dist/react/SchemaComponent.mjs +59 -45
  55. package/dist/react/SchemaView.d.mts +3 -3
  56. package/dist/react/SchemaView.mjs +2 -2
  57. package/dist/react/fieldPath.d.mts +1 -1
  58. package/dist/react/headless.d.mts +1 -1
  59. package/dist/react/headless.mjs +1 -2
  60. package/dist/react/headlessRenderers.d.mts +3 -4
  61. package/dist/react/headlessRenderers.mjs +10 -30
  62. package/dist/{ref-si8ViYun.d.mts → ref-D-_JBZkF.d.mts} +1 -1
  63. package/dist/{renderer-DI6ZYf7a.d.mts → renderer-BaRlQIuN.d.mts} +2 -2
  64. package/dist/themes/mantine.d.mts +1 -1
  65. package/dist/themes/mui.d.mts +1 -1
  66. package/dist/themes/radix.d.mts +1 -1
  67. package/dist/themes/shadcn.d.mts +1 -1
  68. package/dist/typeInference-DkcUHfaM.d.mts +982 -0
  69. package/dist/{types-BnxPEElk.d.mts → types-BrRMV0en.d.mts} +3 -10
  70. package/package.json +1 -3
  71. package/dist/typeInference-Bxw3NOG1.d.mts +0 -647
  72. /package/dist/{version-D-u7aMfy.d.mts → version-D2jfdX6E.d.mts} +0 -0
@@ -1,4 +1,4 @@
1
- import { T as SchemaMeta } from "../types-BnxPEElk.mjs";
1
+ import { w as SchemaMeta } from "../types-BrRMV0en.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-BnxPEElk.mjs";
1
+ import { w as SchemaMeta } from "../types-BrRMV0en.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-BnxPEElk.mjs";
1
+ import { w as SchemaMeta } from "../types-BrRMV0en.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-BnxPEElk.mjs";
1
+ import { w as SchemaMeta } from "../types-BrRMV0en.mjs";
2
2
  import { SecurityRequirement, SecurityScheme } from "./parser.mjs";
3
3
  import { ReactNode } from "react";
4
4
 
@@ -11,6 +11,18 @@ const OAUTH_FLOW_KEYS = [
11
11
  "clientCredentials",
12
12
  "authorizationCode"
13
13
  ];
14
+ /**
15
+ * Known Security Scheme `type` values per the OpenAPI 3.0/3.1 spec.
16
+ * Used to flag unknown values in the rendered output so authors can
17
+ * spot typos like `mutalTLS` without consulting the diagnostic sink.
18
+ */
19
+ const KNOWN_SECURITY_SCHEME_TYPES = new Set([
20
+ "apiKey",
21
+ "http",
22
+ "oauth2",
23
+ "openIdConnect",
24
+ "mutualTLS"
25
+ ]);
14
26
  function readString(source, key) {
15
27
  const value = source[key];
16
28
  return typeof value === "string" ? value : void 0;
@@ -66,10 +78,12 @@ function ApiSecurity({ requirements, schemes }) {
66
78
  }
67
79
  function SchemeDetails({ scheme }) {
68
80
  const flows = extractFlows(scheme.flows);
81
+ const isKnownType = scheme.type !== void 0 && KNOWN_SECURITY_SCHEME_TYPES.has(scheme.type);
69
82
  return /* @__PURE__ */ jsxs(Fragment, { children: [
70
- scheme.type !== void 0 && /* @__PURE__ */ jsx("span", {
83
+ scheme.type !== void 0 && /* @__PURE__ */ jsxs("span", {
71
84
  "data-security-type": true,
72
- children: scheme.type
85
+ "data-security-type-unknown": isKnownType ? void 0 : "true",
86
+ children: [scheme.type, !isKnownType && " (unknown type)"]
73
87
  }),
74
88
  scheme.description !== void 0 && /* @__PURE__ */ jsx("span", {
75
89
  "data-security-description": true,
@@ -1,10 +1,85 @@
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";
1
+ import { u as FieldOverride, w as SchemaMeta } from "../types-BrRMV0en.mjs";
2
+ import { r as DiagnosticSink } from "../diagnostics-D0QCYGv0.mjs";
3
+ import { a as InferParameterOverrides, g as UnsafeFields, o as InferRequestBodyFields, s as InferResponseFields } from "../typeInference-DkcUHfaM.mjs";
4
4
  import { WidgetMap } from "../react/SchemaComponent.mjs";
5
5
  import { ReactNode } from "react";
6
6
 
7
7
  //#region src/openapi/components.d.ts
8
+ /**
9
+ * The canonical set of HTTP method strings recognised by OpenAPI 3.x.
10
+ * Used to constrain `Method` generics so autocomplete on typed
11
+ * documents only suggests methods the path item actually declares,
12
+ * not arbitrary string keys.
13
+ */
14
+ type HttpMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace";
15
+ /**
16
+ * Extract the literal path keys from a document type, or the broad
17
+ * `string` fallback when the document is untyped at compile time.
18
+ *
19
+ * The `string extends keyof D["paths"]` guard distinguishes a typed
20
+ * `as const` document (whose `paths` map has literal keys) from a
21
+ * runtime `Record<string, unknown>` document (whose `keyof` collapses
22
+ * to `string`). For the runtime case we surface `string` so callers
23
+ * pass arbitrary path values without losing the existing freedom.
24
+ */
25
+ type PathKeysOf<D> = D extends {
26
+ paths: infer P;
27
+ } ? P extends Record<string, unknown> ? string extends keyof P ? string : Extract<keyof P, string> : string : string;
28
+ /**
29
+ * Extract the methods declared on a specific path item, restricted to
30
+ * the OpenAPI-recognised method set so non-method extension keys
31
+ * (e.g. `summary`, `description`, `parameters`) do not pollute the
32
+ * autocomplete.
33
+ *
34
+ * Runtime documents (typed `Record<string, unknown>`) widen back to
35
+ * `string` so callers retain the freedom to pass arbitrary method
36
+ * strings without surfacing an `HttpMethod` constraint at runtime
37
+ * call sites.
38
+ */
39
+ type MethodKeysOf<D, P extends string> = IsRuntimeDoc<D> extends true ? string : D extends {
40
+ paths: infer Paths;
41
+ } ? Paths extends Record<string, unknown> ? P extends keyof Paths ? Extract<keyof Paths[P], HttpMethod> : HttpMethod : HttpMethod : HttpMethod;
42
+ /**
43
+ * True for the runtime-document sentinel — a `Record<string, unknown>`
44
+ * (or wider) where `keyof` collapses to `string`. Used to drop
45
+ * narrow-constraint defaults so runtime callers retain the prior
46
+ * freedom to pass arbitrary path/method/status values.
47
+ */
48
+ type IsRuntimeDoc<D> = D extends Record<string, unknown> ? string extends keyof D ? true : false : false;
49
+ /**
50
+ * Extract the status-code keys declared by an operation's `responses`
51
+ * map. Includes class wildcards (`2XX`, etc.) and the `default`
52
+ * sentinel; runtime documents widen to `string`.
53
+ */
54
+ type StatusKeysOf<D, P extends string, M extends string> = D extends {
55
+ paths: infer Paths;
56
+ } ? Paths extends Record<string, unknown> ? P extends keyof Paths ? Paths[P] extends Record<string, unknown> ? M extends keyof Paths[P] ? Paths[P][M] extends {
57
+ responses: infer R;
58
+ } ? R extends Record<string, unknown> ? string extends keyof R ? string : Extract<keyof R, string> : string : string : string : string : string : string : string;
59
+ /**
60
+ * Extract the content-type keys declared on a request body's
61
+ * `content` map for the given path and method. Runtime documents
62
+ * widen to `string`.
63
+ */
64
+ type RequestContentTypesOf<D, P extends string, M extends string> = D extends {
65
+ paths: infer Paths;
66
+ } ? Paths extends Record<string, unknown> ? P extends keyof Paths ? Paths[P] extends Record<string, unknown> ? M extends keyof Paths[P] ? Paths[P][M] extends {
67
+ requestBody: {
68
+ content: infer C;
69
+ };
70
+ } ? C extends Record<string, unknown> ? string extends keyof C ? string : Extract<keyof C, string> : string : string : string : string : string : string : string;
71
+ /**
72
+ * Extract the content-type keys declared on a response entry's
73
+ * `content` map for the given path, method, and status. Runtime
74
+ * documents widen to `string`.
75
+ */
76
+ type ResponseContentTypesOf<D, P extends string, M extends string, S extends string> = D extends {
77
+ paths: infer Paths;
78
+ } ? Paths extends Record<string, unknown> ? P extends keyof Paths ? Paths[P] extends Record<string, unknown> ? M extends keyof Paths[P] ? Paths[P][M] extends {
79
+ responses: infer R;
80
+ } ? R extends Record<string, unknown> ? S extends keyof R ? R[S] extends {
81
+ content: infer C;
82
+ } ? C extends Record<string, unknown> ? string extends keyof C ? string : Extract<keyof C, string> : string : string : string : string : string : string : string : string : string : string;
8
83
  /**
9
84
  * Diagnostics props accepted by every top-level OpenAPI component.
10
85
  *
@@ -18,7 +93,7 @@ interface ApiDiagnosticsProps {
18
93
  onDiagnostic?: DiagnosticSink;
19
94
  strict?: boolean;
20
95
  }
21
- interface ApiOperationProps<Doc = unknown, Path extends string = string, Method extends string = string> extends ApiDiagnosticsProps {
96
+ interface ApiOperationProps<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>> extends ApiDiagnosticsProps {
22
97
  schema: Doc;
23
98
  path: Path;
24
99
  method: Method;
@@ -26,7 +101,7 @@ interface ApiOperationProps<Doc = unknown, Path extends string = string, Method
26
101
  onRequestBodyChange?: (value: unknown) => void;
27
102
  responseValue?: unknown;
28
103
  meta?: SchemaMeta;
29
- requestBodyFields?: Doc extends Record<string, unknown> ? InferRequestBodyFields<Doc, Path, Method> : Record<string, FieldOverride>;
104
+ requestBodyFields?: Doc extends Record<string, unknown> ? InferRequestBodyFields<Doc, Path & string, Method & string> : Record<string, FieldOverride>;
30
105
  /** Escape hatch for recursive schemas where type-level inference fails.
31
106
  * Typed as Record<string, FieldOverride> — use when the schema contains
32
107
  * deeply nested $ref chains.
@@ -35,7 +110,7 @@ interface ApiOperationProps<Doc = unknown, Path extends string = string, Method
35
110
  /** Instance-scoped widgets. */
36
111
  widgets?: WidgetMap;
37
112
  }
38
- declare function ApiOperation<Doc = unknown, Path extends string = string, Method extends string = string>({
113
+ declare function ApiOperation<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>>({
39
114
  schema: doc,
40
115
  path,
41
116
  method,
@@ -48,16 +123,16 @@ declare function ApiOperation<Doc = unknown, Path extends string = string, Metho
48
123
  onDiagnostic,
49
124
  strict
50
125
  }: ApiOperationProps<Doc, Path, Method>): ReactNode;
51
- interface ApiParametersProps<Doc = unknown, Path extends string = string, Method extends string = string> extends ApiDiagnosticsProps {
126
+ interface ApiParametersProps<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>> extends ApiDiagnosticsProps {
52
127
  schema: Doc;
53
128
  path: Path;
54
129
  method: Method;
55
130
  meta?: SchemaMeta;
56
- overrides?: Doc extends Record<string, unknown> ? InferParameterOverrides<Doc, Path, Method> : Record<string, FieldOverride>;
131
+ overrides?: Doc extends Record<string, unknown> ? InferParameterOverrides<Doc, Path & string, Method & string> : Record<string, FieldOverride>;
57
132
  /** Instance-scoped widgets. */
58
133
  widgets?: WidgetMap;
59
134
  }
60
- declare function ApiParameters<Doc = unknown, Path extends string = string, Method extends string = string>({
135
+ declare function ApiParameters<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>>({
61
136
  schema: doc,
62
137
  path,
63
138
  method,
@@ -67,18 +142,25 @@ declare function ApiParameters<Doc = unknown, Path extends string = string, Meth
67
142
  onDiagnostic,
68
143
  strict
69
144
  }: ApiParametersProps<Doc, Path, Method>): ReactNode;
70
- interface ApiRequestBodyProps<Doc = unknown, Path extends string = string, Method extends string = string> extends ApiDiagnosticsProps {
145
+ interface ApiRequestBodyProps<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>, ContentType extends RequestContentTypesOf<Doc, Path, Method> = RequestContentTypesOf<Doc, Path, Method>> extends ApiDiagnosticsProps {
71
146
  schema: Doc;
72
147
  path: Path;
73
148
  method: Method;
149
+ /**
150
+ * Media type whose schema should be rendered for the request body.
151
+ * Defaults to the union of declared content types so callers can
152
+ * omit it; supply explicitly to narrow `fields` inference to a
153
+ * specific media type via {@link InferRequestBodyFields}.
154
+ */
155
+ contentType?: ContentType;
74
156
  value?: unknown;
75
157
  onChange?: (value: unknown) => void;
76
158
  meta?: SchemaMeta;
77
- fields?: Doc extends Record<string, unknown> ? InferRequestBodyFields<Doc, Path, Method> : Record<string, FieldOverride>;
159
+ fields?: Doc extends Record<string, unknown> ? InferRequestBodyFields<Doc, Path & string, Method & string, ContentType & string> : Record<string, FieldOverride>;
78
160
  /** Instance-scoped widgets. */
79
161
  widgets?: WidgetMap;
80
162
  }
81
- declare function ApiRequestBody<Doc = unknown, Path extends string = string, Method extends string = string>({
163
+ declare function ApiRequestBody<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>, ContentType extends RequestContentTypesOf<Doc, Path, Method> = RequestContentTypesOf<Doc, Path, Method>>({
82
164
  schema: doc,
83
165
  path,
84
166
  method,
@@ -89,19 +171,26 @@ declare function ApiRequestBody<Doc = unknown, Path extends string = string, Met
89
171
  widgets,
90
172
  onDiagnostic,
91
173
  strict
92
- }: ApiRequestBodyProps<Doc, Path, Method>): ReactNode;
93
- interface ApiResponseProps<Doc = unknown, Path extends string = string, Method extends string = string, Status extends string = string> extends ApiDiagnosticsProps {
174
+ }: ApiRequestBodyProps<Doc, Path, Method, ContentType>): ReactNode;
175
+ interface ApiResponseProps<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>, Status extends StatusKeysOf<Doc, Path, Method> = StatusKeysOf<Doc, Path, Method>, ContentType extends ResponseContentTypesOf<Doc, Path, Method, Status> = ResponseContentTypesOf<Doc, Path, Method, Status>> extends ApiDiagnosticsProps {
94
176
  schema: Doc;
95
177
  path: Path;
96
178
  method: Method;
97
179
  status: Status;
180
+ /**
181
+ * Media type whose schema should be rendered. Defaults to the
182
+ * union of declared content types so callers can omit it;
183
+ * supply explicitly to narrow `fields` inference via
184
+ * {@link InferResponseFields}.
185
+ */
186
+ contentType?: ContentType;
98
187
  value?: unknown;
99
188
  meta?: SchemaMeta;
100
- fields?: Doc extends Record<string, unknown> ? InferResponseFields<Doc, Path, Method, Status> : Record<string, FieldOverride>;
189
+ fields?: Doc extends Record<string, unknown> ? InferResponseFields<Doc, Path & string, Method & string, Status & string, ContentType & string> : Record<string, FieldOverride>;
101
190
  /** Instance-scoped widgets. */
102
191
  widgets?: WidgetMap;
103
192
  }
104
- declare function ApiResponse<Doc = unknown, Path extends string = string, Method extends string = string, Status extends string = string>({
193
+ declare function ApiResponse<Doc = unknown, Path extends PathKeysOf<Doc> = PathKeysOf<Doc>, Method extends MethodKeysOf<Doc, Path> = MethodKeysOf<Doc, Path>, Status extends StatusKeysOf<Doc, Path, Method> = StatusKeysOf<Doc, Path, Method>, ContentType extends ResponseContentTypesOf<Doc, Path, Method, Status> = ResponseContentTypesOf<Doc, Path, Method, Status>>({
105
194
  schema: doc,
106
195
  path,
107
196
  method,
@@ -112,6 +201,49 @@ declare function ApiResponse<Doc = unknown, Path extends string = string, Method
112
201
  widgets,
113
202
  onDiagnostic,
114
203
  strict
115
- }: ApiResponseProps<Doc, Path, Method, Status>): ReactNode;
204
+ }: ApiResponseProps<Doc, Path, Method, Status, ContentType>): ReactNode;
205
+ /**
206
+ * Render a single OpenAPI 3.1 webhook by name. A webhook is a Path Item
207
+ * Object under the document's top-level `webhooks` map; once resolved,
208
+ * its operations are structurally identical to operations under `paths`.
209
+ *
210
+ * Internally, this delegates to `ApiOperation` for each method present
211
+ * on the webhook's Path Item Object. The parser's `lookupPathItem`
212
+ * resolves webhook names through the same code path as paths, so
213
+ * `ApiOperation` works for both with no special-casing in the renderer.
214
+ */
215
+ interface ApiWebhookProps extends ApiDiagnosticsProps {
216
+ schema: unknown;
217
+ /** Webhook name (key under the document's `webhooks` map). */
218
+ name: string;
219
+ /** Instance-scoped widgets, forwarded to each rendered operation. */
220
+ widgets?: WidgetMap;
221
+ meta?: SchemaMeta;
222
+ }
223
+ declare function ApiWebhook({
224
+ schema: doc,
225
+ name,
226
+ widgets,
227
+ meta,
228
+ onDiagnostic,
229
+ strict
230
+ }: ApiWebhookProps): ReactNode;
231
+ /**
232
+ * Render every OpenAPI 3.1 webhook declared on the document, one
233
+ * `<ApiWebhook>` per entry. Returns `null` when the document has no
234
+ * `webhooks` map or it is empty.
235
+ */
236
+ interface ApiWebhooksProps extends ApiDiagnosticsProps {
237
+ schema: unknown;
238
+ widgets?: WidgetMap;
239
+ meta?: SchemaMeta;
240
+ }
241
+ declare function ApiWebhooks({
242
+ schema: doc,
243
+ widgets,
244
+ meta,
245
+ onDiagnostic,
246
+ strict
247
+ }: ApiWebhooksProps): ReactNode;
116
248
  //#endregion
117
- export { ApiOperation, ApiOperationProps, ApiParameters, ApiParametersProps, ApiRequestBody, ApiRequestBodyProps, ApiResponse, ApiResponseProps };
249
+ export { ApiOperation, ApiOperationProps, ApiParameters, ApiParametersProps, ApiRequestBody, ApiRequestBodyProps, ApiResponse, ApiResponseProps, ApiWebhook, ApiWebhookProps, ApiWebhooks, ApiWebhooksProps };
@@ -1,10 +1,11 @@
1
1
  import { isObject, toRecordOrUndefined } from "../core/guards.mjs";
2
+ import { emitDiagnostic } from "../core/diagnostics.mjs";
2
3
  import { walk } from "../core/walker.mjs";
3
4
  import { ApiCallbacks } from "./ApiCallbacks.mjs";
4
5
  import { ApiLinks } from "./ApiLinks.mjs";
5
6
  import { ApiResponseHeaders } from "./ApiResponseHeaders.mjs";
6
7
  import { ApiSecurity } from "./ApiSecurity.mjs";
7
- import { getLinks, getSecurityRequirements, getSecuritySchemes, listCallbacks } from "./parser.mjs";
8
+ import { getExternalDocs, getLinks, getSecurityRequirements, getSecuritySchemes, getXmlInfo, listCallbacks, listWebhooks } from "./parser.mjs";
8
9
  import { joinPath, renderField, sanitisePrefix } from "../react/SchemaComponent.mjs";
9
10
  import { getParsed, resolveOperationFromParsed, resolveParametersFromParsed, resolveRequestBodyFromParsed, resolveResponseFromParsed, toDoc } from "./resolve.mjs";
10
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -30,6 +31,25 @@ function buildDiagnostics(onDiagnostic, strict) {
30
31
  if (strict === true) opts.strict = true;
31
32
  return opts;
32
33
  }
34
+ /**
35
+ * Coerce an `unknown` `schema` prop to a document record. Returns
36
+ * `undefined` when the prop is not a plain object, surfacing a
37
+ * `doc-not-object` diagnostic so silent "empty document" misbehaviour
38
+ * (the historic `toDoc` `{}` fallback) is impossible.
39
+ *
40
+ * Components MUST short-circuit when this returns `undefined` rather
41
+ * than rendering empty operation lists.
42
+ */
43
+ function resolveRootDoc(doc, diagnostics) {
44
+ const resolved = toDoc(doc);
45
+ if (resolved === void 0) emitDiagnostic(diagnostics, {
46
+ code: "doc-not-object",
47
+ message: "OpenAPI document prop is not a plain object; nothing to render",
48
+ pointer: "",
49
+ detail: { received: typeof doc }
50
+ });
51
+ return resolved;
52
+ }
33
53
  function noop() {}
34
54
  function renderSchema(schema, rootDocument, options) {
35
55
  if (!isObject(schema)) throw new Error("renderSchema received a non-object schema from the resolver.");
@@ -49,14 +69,55 @@ function renderSchema(schema, rootDocument, options) {
49
69
  };
50
70
  return renderField(tree, options.value, options.onChange ?? noop, void 0, makeRenderChild(options.rootPath), options.rootPath, options.widgets);
51
71
  }
72
+ /**
73
+ * Render a Schema Object or Operation Object's `externalDocs` as a
74
+ * simple anchor with optional descriptive text. Returns `null` when no
75
+ * externalDocs are attached so callers can drop it into JSX without an
76
+ * extra guard.
77
+ */
78
+ function ExternalDocsLink({ externalDocs }) {
79
+ if (externalDocs === void 0) return null;
80
+ return /* @__PURE__ */ jsx("p", {
81
+ "data-external-docs": true,
82
+ children: /* @__PURE__ */ jsx("a", {
83
+ href: externalDocs.url,
84
+ children: externalDocs.description ?? externalDocs.url
85
+ })
86
+ });
87
+ }
88
+ /**
89
+ * Render a Schema Object's `xml` metadata as a footnote. The library
90
+ * does not render XML payloads natively, but the metadata still
91
+ * carries author intent (namespaces, element names, wrapping rules).
92
+ * Surface it so consumers can audit the dropped feature without
93
+ * losing the underlying information.
94
+ */
95
+ function SchemaXmlFootnote({ xml }) {
96
+ if (xml === void 0) return null;
97
+ return /* @__PURE__ */ jsx("aside", {
98
+ "data-schema-xml": true,
99
+ children: /* @__PURE__ */ jsxs("small", { children: [
100
+ "XML representation",
101
+ xml.name !== void 0 && ` — name: ${xml.name}`,
102
+ xml.namespace !== void 0 && ` — namespace: ${xml.namespace}`,
103
+ xml.prefix !== void 0 && ` — prefix: ${xml.prefix}`,
104
+ xml.attribute && " — attribute",
105
+ xml.wrapped && " — wrapped"
106
+ ] })
107
+ });
108
+ }
52
109
  function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBodyChange, responseValue, meta, requestBodyFields, widgets, onDiagnostic, strict }) {
53
- const rootDoc = toDoc(doc);
54
- const parsed = getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict));
55
- const resolved = resolveOperationFromParsed(parsed, path, method);
110
+ const diagnostics = buildDiagnostics(onDiagnostic, strict);
111
+ const instancePrefix = sanitisePrefix(useId());
112
+ const rootDoc = resolveRootDoc(doc, diagnostics);
113
+ if (rootDoc === void 0) return null;
114
+ const parsed = getParsed(rootDoc, diagnostics);
115
+ const resolved = resolveOperationFromParsed(parsed, path, method, diagnostics);
56
116
  const securityReqs = getSecurityRequirements(parsed, path, method);
57
117
  const securitySchemes = getSecuritySchemes(parsed);
58
118
  const callbacks = listCallbacks(parsed, path, method);
59
- const instancePrefix = sanitisePrefix(useId());
119
+ const operationExternalDocs = getExternalDocs(resolved.operation.operation);
120
+ const requestBodyXml = resolved.requestBody?.schema !== void 0 ? getXmlInfo(resolved.requestBody.schema) : void 0;
60
121
  return /* @__PURE__ */ jsxs("section", {
61
122
  "data-operation": `${method.toUpperCase()} ${path}`,
62
123
  children: [
@@ -64,6 +125,7 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
64
125
  operation: resolved.operation,
65
126
  pathItem: resolved.pathItem
66
127
  }),
128
+ /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: operationExternalDocs }),
67
129
  /* @__PURE__ */ jsx(ApiSecurity, {
68
130
  requirements: securityReqs,
69
131
  schemes: securitySchemes
@@ -98,7 +160,8 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
98
160
  meta,
99
161
  widgets,
100
162
  rootPath: joinPath(instancePrefix, "requestBody")
101
- })
163
+ }),
164
+ /* @__PURE__ */ jsx(SchemaXmlFootnote, { xml: requestBodyXml })
102
165
  ]
103
166
  }),
104
167
  resolved.responses.length > 0 && /* @__PURE__ */ jsxs("section", {
@@ -119,9 +182,11 @@ function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBo
119
182
  });
120
183
  }
121
184
  function ApiParameters({ schema: doc, path, method, meta, overrides, widgets, onDiagnostic, strict }) {
122
- const rootDoc = toDoc(doc);
123
- const params = resolveParametersFromParsed(getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict)), path, method);
185
+ const diagnostics = buildDiagnostics(onDiagnostic, strict);
124
186
  const instancePrefix = sanitisePrefix(useId());
187
+ const rootDoc = resolveRootDoc(doc, diagnostics);
188
+ if (rootDoc === void 0) return null;
189
+ const params = resolveParametersFromParsed(getParsed(rootDoc, diagnostics), path, method);
125
190
  if (params.length === 0) return null;
126
191
  return /* @__PURE__ */ jsxs("section", {
127
192
  "data-parameters": true,
@@ -136,10 +201,13 @@ function ApiParameters({ schema: doc, path, method, meta, overrides, widgets, on
136
201
  });
137
202
  }
138
203
  function ApiRequestBody({ schema: doc, path, method, value, onChange, meta, fields, widgets, onDiagnostic, strict }) {
139
- const rootDoc = toDoc(doc);
140
- const requestBody = resolveRequestBodyFromParsed(getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict)), path, method);
204
+ const diagnostics = buildDiagnostics(onDiagnostic, strict);
141
205
  const instancePrefix = sanitisePrefix(useId());
206
+ const rootDoc = resolveRootDoc(doc, diagnostics);
207
+ if (rootDoc === void 0) return null;
208
+ const requestBody = resolveRequestBodyFromParsed(getParsed(rootDoc, diagnostics), path, method);
142
209
  if (requestBody?.schema === void 0) return null;
210
+ const requestBodyXml = getXmlInfo(requestBody.schema);
143
211
  return /* @__PURE__ */ jsxs("section", {
144
212
  "data-request-body": true,
145
213
  children: [
@@ -159,15 +227,18 @@ function ApiRequestBody({ schema: doc, path, method, value, onChange, meta, fiel
159
227
  meta,
160
228
  widgets,
161
229
  rootPath: instancePrefix
162
- })
230
+ }),
231
+ /* @__PURE__ */ jsx(SchemaXmlFootnote, { xml: requestBodyXml })
163
232
  ]
164
233
  });
165
234
  }
166
235
  function ApiResponse({ schema: doc, path, method, status, value, meta, fields, widgets, onDiagnostic, strict }) {
167
- const rootDoc = toDoc(doc);
168
- const parsed = getParsed(rootDoc, buildDiagnostics(onDiagnostic, strict));
169
- const response = resolveResponseFromParsed(parsed, path, method, status);
236
+ const diagnostics = buildDiagnostics(onDiagnostic, strict);
170
237
  const instancePrefix = sanitisePrefix(useId());
238
+ const rootDoc = resolveRootDoc(doc, diagnostics);
239
+ if (rootDoc === void 0) return null;
240
+ const parsed = getParsed(rootDoc, diagnostics);
241
+ const response = resolveResponseFromParsed(parsed, path, method, status);
171
242
  if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
172
243
  "data-status": status,
173
244
  children: [
@@ -189,6 +260,49 @@ function ApiResponse({ schema: doc, path, method, status, value, meta, fields, w
189
260
  idPrefix: instancePrefix
190
261
  });
191
262
  }
263
+ function ApiWebhook({ schema: doc, name, widgets, meta, onDiagnostic, strict }) {
264
+ const diagnostics = buildDiagnostics(onDiagnostic, strict);
265
+ const instancePrefix = sanitisePrefix(useId());
266
+ const rootDoc = resolveRootDoc(doc, diagnostics);
267
+ if (rootDoc === void 0) return null;
268
+ const webhook = listWebhooks(getParsed(rootDoc, diagnostics)).find((w) => w.name === name);
269
+ if (webhook === void 0) return null;
270
+ return /* @__PURE__ */ jsxs("section", {
271
+ "data-webhook": name,
272
+ "data-instance": instancePrefix,
273
+ children: [/* @__PURE__ */ jsxs("h3", { children: ["Webhook: ", name] }), webhook.operations.map((op) => {
274
+ const opProps = {
275
+ schema: rootDoc,
276
+ path: name,
277
+ method: op.method
278
+ };
279
+ if (widgets !== void 0) opProps.widgets = widgets;
280
+ if (meta !== void 0) opProps.meta = meta;
281
+ return /* @__PURE__ */ jsx(ApiOperation, { ...opProps }, `${name}-${op.method}`);
282
+ })]
283
+ });
284
+ }
285
+ function ApiWebhooks({ schema: doc, widgets, meta, onDiagnostic, strict }) {
286
+ const diagnostics = buildDiagnostics(onDiagnostic, strict);
287
+ const instancePrefix = sanitisePrefix(useId());
288
+ const rootDoc = resolveRootDoc(doc, diagnostics);
289
+ if (rootDoc === void 0) return null;
290
+ const webhooks = listWebhooks(getParsed(rootDoc, diagnostics));
291
+ if (webhooks.length === 0) return null;
292
+ return /* @__PURE__ */ jsxs("section", {
293
+ "data-webhooks": true,
294
+ "data-instance": instancePrefix,
295
+ children: [/* @__PURE__ */ jsx("h2", { children: "Webhooks" }), webhooks.map((webhook) => {
296
+ const props = {
297
+ schema: rootDoc,
298
+ name: webhook.name
299
+ };
300
+ if (widgets !== void 0) props.widgets = widgets;
301
+ if (meta !== void 0) props.meta = meta;
302
+ return /* @__PURE__ */ jsx(ApiWebhook, { ...props }, webhook.name);
303
+ })]
304
+ });
305
+ }
192
306
  function OperationHeader({ operation, pathItem }) {
193
307
  return /* @__PURE__ */ jsxs("header", { children: [
194
308
  (pathItem.summary !== void 0 || pathItem.description !== void 0) && /* @__PURE__ */ jsxs("div", {
@@ -293,4 +407,4 @@ function extractRootMetaFromSchema(jsonSchema) {
293
407
  return Object.keys(meta).length > 0 ? meta : void 0;
294
408
  }
295
409
  //#endregion
296
- export { ApiOperation, ApiParameters, ApiRequestBody, ApiResponse };
410
+ export { ApiOperation, ApiParameters, ApiRequestBody, ApiResponse, ApiWebhook, ApiWebhooks };
@@ -1,4 +1,4 @@
1
- import { m as JsonObject } from "../types-BnxPEElk.mjs";
1
+ import { m as JsonObject } from "../types-BrRMV0en.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 "../core/limits.mjs";
2
3
  import { isPrototypePollutingKey } from "../core/uri.mjs";
3
4
  //#region src/openapi/parser.ts
4
5
  function getString(value, key) {
@@ -44,11 +45,27 @@ const METHODS = [
44
45
  * (OpenAPI 3.1) if present. Returns `undefined` when the value is not a
45
46
  * path item, the ref is malformed, or the target does not resolve.
46
47
  */
48
+ /**
49
+ * Follow Path Item Object `$ref` chains (up to MAX_PATH_ITEM_REF_HOPS).
50
+ * Returns the resolved Path Item, or `undefined` when the chain cycles,
51
+ * exceeds the cap, or any intermediate ref fails to resolve. The
52
+ * detailed diagnostics for cycle and depth-cap are emitted by the
53
+ * mirroring resolver in `resolve.ts` — this parser-side resolver simply
54
+ * stops walking.
55
+ */
47
56
  function resolvePathItem(parsed, pathItem) {
48
57
  if (!isObject(pathItem)) return void 0;
49
- const ref = getString(pathItem, "$ref");
50
- if (ref === void 0) return pathItem;
51
- return resolveRefInDoc(parsed.doc, ref) ?? void 0;
58
+ const visited = /* @__PURE__ */ new Set();
59
+ let current = pathItem;
60
+ for (let hop = 0; hop < 8; hop++) {
61
+ const ref = getString(current, "$ref");
62
+ if (ref === void 0) return current;
63
+ if (visited.has(ref)) return void 0;
64
+ visited.add(ref);
65
+ const target = resolveRefInDoc(parsed.doc, ref);
66
+ if (target === void 0) return void 0;
67
+ current = target;
68
+ }
52
69
  }
53
70
  function lookupPathItem(parsed, path) {
54
71
  const resolved = resolvePathItem(parsed, getProperty(getProperty(parsed.doc, "paths"), path));
@@ -202,6 +219,21 @@ function isJsonSuffixMediaType(mediaType) {
202
219
  const baseType = lower.split(";", 1)[0]?.trim() ?? "";
203
220
  return baseType.startsWith("application/") && baseType.endsWith("+json");
204
221
  }
222
+ /**
223
+ * Resolve an in-document `$ref` against the supplied doc root.
224
+ *
225
+ * Limitation — cross-Schema-Object relative refs: refs that do NOT
226
+ * start with `#/` are not resolved here. The `normaliseOpenApiSchemas`
227
+ * pipeline (see `resolveRelativeRefs` in `core/normalise.ts`) rewrites
228
+ * relative refs WITHIN a Schema Object using that schema's `$id` base
229
+ * URI, but it does not currently model `$id` scopes that span Schema
230
+ * Object boundaries (e.g. a sibling component schema with its own
231
+ * `$id` that another schema's relative ref targets). Such refs survive
232
+ * normalisation unchanged and fall through this function returning
233
+ * `undefined`. `resolve.ts:detectUnsupportedCrossSchemaRefs` walks the
234
+ * normalised doc and emits `cross-schema-relative-ref-unsupported` per
235
+ * offending ref so consumers notice the silent failure.
236
+ */
205
237
  function resolveRefInDoc(doc, ref) {
206
238
  if (!ref.startsWith("#/")) return void 0;
207
239
  const parts = ref.slice(2).split("/");
@@ -1,4 +1,4 @@
1
- import { i as DiagnosticsOptions } from "../diagnostics-CbBPsxSt.mjs";
1
+ import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.mjs";
2
2
  import { OpenApiDocument, OperationInfo, ParameterInfo, ResponseInfo, getRequestBody } from "./parser.mjs";
3
3
 
4
4
  //#region src/openapi/resolve.d.ts
@@ -29,10 +29,17 @@ import { OpenApiDocument, OperationInfo, ParameterInfo, ResponseInfo, getRequest
29
29
  */
30
30
  declare function getParsed(doc: Record<string, unknown>, diagnostics?: DiagnosticsOptions): OpenApiDocument;
31
31
  /**
32
- * Coerce an unknown value to a record, returning an empty record
33
- * for non-objects.
32
+ * Coerce an unknown value to a record, returning `undefined` when the
33
+ * value is not a plain object. Callers MUST handle the `undefined` case
34
+ * explicitly — typically by rendering a "doc not an object" diagnostic
35
+ * and short-circuiting, never by silently substituting `{}`.
36
+ *
37
+ * A previous implementation fell back to `{}` for non-objects, which
38
+ * masked configuration mistakes (passing a string, `null`, an array, or
39
+ * `undefined` as the OpenAPI document) as an empty document with no
40
+ * operations.
34
41
  */
35
- declare function toDoc(value: unknown): Record<string, unknown>;
42
+ declare function toDoc(value: unknown): Record<string, unknown> | undefined;
36
43
  /**
37
44
  * Path-Item-level metadata. OpenAPI 3.1 added `summary` and `description`
38
45
  * to Path Item Objects alongside the existing operation-level fields.
@@ -59,7 +66,7 @@ interface ResolvedOperation {
59
66
  * normalisation pipeline (every re-run would emit each diagnostic
60
67
  * again into the sink).
61
68
  */
62
- declare function resolveOperationFromParsed(parsed: OpenApiDocument, path: string, method: string): ResolvedOperation;
69
+ declare function resolveOperationFromParsed(parsed: OpenApiDocument, path: string, method: string, diagnostics?: DiagnosticsOptions): ResolvedOperation;
63
70
  /**
64
71
  * Resolve an operation from an OpenAPI document by path and method.
65
72
  * Throws if the operation is not found.