@gitbook/react-openapi 1.4.2 → 1.5.1

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 (225) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/index.d.ts +663 -10
  3. package/dist/index.js +3873 -8
  4. package/package.json +11 -7
  5. package/dist/InteractiveSection.d.ts +0 -33
  6. package/dist/InteractiveSection.jsx +0 -61
  7. package/dist/Markdown.d.ts +0 -4
  8. package/dist/Markdown.jsx +0 -5
  9. package/dist/OpenAPICodeSample.d.ts +0 -19
  10. package/dist/OpenAPICodeSample.jsx +0 -230
  11. package/dist/OpenAPICodeSampleInteractive.d.ts +0 -14
  12. package/dist/OpenAPICodeSampleInteractive.jsx +0 -73
  13. package/dist/OpenAPICodeSampleSelector.d.ts +0 -14
  14. package/dist/OpenAPICodeSampleSelector.jsx +0 -44
  15. package/dist/OpenAPICopyButton.d.ts +0 -13
  16. package/dist/OpenAPICopyButton.jsx +0 -35
  17. package/dist/OpenAPIDisclosure.d.ts +0 -11
  18. package/dist/OpenAPIDisclosure.jsx +0 -30
  19. package/dist/OpenAPIDisclosureGroup.d.ts +0 -23
  20. package/dist/OpenAPIDisclosureGroup.jsx +0 -83
  21. package/dist/OpenAPIExample.d.ts +0 -16
  22. package/dist/OpenAPIExample.jsx +0 -36
  23. package/dist/OpenAPIMediaType.d.ts +0 -21
  24. package/dist/OpenAPIMediaType.jsx +0 -61
  25. package/dist/OpenAPIOperation.d.ts +0 -10
  26. package/dist/OpenAPIOperation.jsx +0 -25
  27. package/dist/OpenAPIOperationContext.d.ts +0 -16
  28. package/dist/OpenAPIOperationContext.jsx +0 -26
  29. package/dist/OpenAPIOperationDescription.d.ts +0 -9
  30. package/dist/OpenAPIOperationDescription.jsx +0 -22
  31. package/dist/OpenAPIOperationStability.d.ts +0 -9
  32. package/dist/OpenAPIOperationStability.jsx +0 -27
  33. package/dist/OpenAPIPath.d.ts +0 -18
  34. package/dist/OpenAPIPath.jsx +0 -55
  35. package/dist/OpenAPIPrefillContextProvider.d.ts +0 -22
  36. package/dist/OpenAPIPrefillContextProvider.jsx +0 -19
  37. package/dist/OpenAPIRequestBody.d.ts +0 -11
  38. package/dist/OpenAPIRequestBody.jsx +0 -28
  39. package/dist/OpenAPIRequestBodyHeaderType.d.ts +0 -8
  40. package/dist/OpenAPIRequestBodyHeaderType.jsx +0 -25
  41. package/dist/OpenAPIResponse.d.ts +0 -10
  42. package/dist/OpenAPIResponse.jsx +0 -57
  43. package/dist/OpenAPIResponseExample.d.ts +0 -9
  44. package/dist/OpenAPIResponseExample.jsx +0 -105
  45. package/dist/OpenAPIResponseExampleContent.d.ts +0 -22
  46. package/dist/OpenAPIResponseExampleContent.jsx +0 -60
  47. package/dist/OpenAPIResponses.d.ts +0 -9
  48. package/dist/OpenAPIResponses.jsx +0 -77
  49. package/dist/OpenAPISchema.d.ts +0 -27
  50. package/dist/OpenAPISchema.jsx +0 -400
  51. package/dist/OpenAPISchemaName.d.ts +0 -16
  52. package/dist/OpenAPISchemaName.jsx +0 -43
  53. package/dist/OpenAPISchemaServer.d.ts +0 -12
  54. package/dist/OpenAPISchemaServer.jsx +0 -8
  55. package/dist/OpenAPISecurities.d.ts +0 -9
  56. package/dist/OpenAPISecurities.jsx +0 -114
  57. package/dist/OpenAPISelect.d.ts +0 -22
  58. package/dist/OpenAPISelect.jsx +0 -44
  59. package/dist/OpenAPISpec.d.ts +0 -6
  60. package/dist/OpenAPISpec.jsx +0 -80
  61. package/dist/OpenAPITabs.d.ts +0 -26
  62. package/dist/OpenAPITabs.jsx +0 -109
  63. package/dist/OpenAPIWebhook.d.ts +0 -10
  64. package/dist/OpenAPIWebhook.jsx +0 -23
  65. package/dist/OpenAPIWebhookExample.d.ts +0 -6
  66. package/dist/OpenAPIWebhookExample.jsx +0 -41
  67. package/dist/ScalarApiButton.d.ts +0 -14
  68. package/dist/ScalarApiButton.jsx +0 -81
  69. package/dist/StaticSection.d.ts +0 -13
  70. package/dist/StaticSection.jsx +0 -32
  71. package/dist/code-samples.d.ts +0 -17
  72. package/dist/code-samples.js +0 -427
  73. package/dist/common/OpenAPIColumnSpec.d.ts +0 -6
  74. package/dist/common/OpenAPIColumnSpec.jsx +0 -20
  75. package/dist/common/OpenAPIOperationDescription.d.ts +0 -6
  76. package/dist/common/OpenAPIOperationDescription.jsx +0 -19
  77. package/dist/common/OpenAPIStability.d.ts +0 -4
  78. package/dist/common/OpenAPIStability.jsx +0 -15
  79. package/dist/common/OpenAPISummary.d.ts +0 -6
  80. package/dist/common/OpenAPISummary.jsx +0 -30
  81. package/dist/contentTypeChecks.d.ts +0 -10
  82. package/dist/contentTypeChecks.js +0 -30
  83. package/dist/context.d.ts +0 -75
  84. package/dist/context.js +0 -43
  85. package/dist/decycle.d.ts +0 -2
  86. package/dist/decycle.js +0 -70
  87. package/dist/dereference.d.ts +0 -5
  88. package/dist/dereference.js +0 -68
  89. package/dist/generateSchemaExample.d.ts +0 -45
  90. package/dist/generateSchemaExample.js +0 -342
  91. package/dist/getDisclosureLabel.d.ts +0 -7
  92. package/dist/getDisclosureLabel.js +0 -18
  93. package/dist/getOrCreateStoreByKey.d.ts +0 -10
  94. package/dist/getOrCreateStoreByKey.js +0 -19
  95. package/dist/json2xml.d.ts +0 -4
  96. package/dist/json2xml.js +0 -7
  97. package/dist/resolveOpenAPIOperation.d.ts +0 -11
  98. package/dist/resolveOpenAPIOperation.js +0 -173
  99. package/dist/resolveOpenAPIWebhook.d.ts +0 -11
  100. package/dist/resolveOpenAPIWebhook.js +0 -127
  101. package/dist/schemas/OpenAPISchemaItem.d.ts +0 -7
  102. package/dist/schemas/OpenAPISchemaItem.jsx +0 -16
  103. package/dist/schemas/OpenAPISchemas.d.ts +0 -14
  104. package/dist/schemas/OpenAPISchemas.jsx +0 -59
  105. package/dist/schemas/index.d.ts +0 -2
  106. package/dist/schemas/index.js +0 -2
  107. package/dist/schemas/resolveOpenAPISchemas.d.ts +0 -10
  108. package/dist/schemas/resolveOpenAPISchemas.js +0 -61
  109. package/dist/stringifyOpenAPI.d.ts +0 -4
  110. package/dist/stringifyOpenAPI.js +0 -15
  111. package/dist/translate.d.ts +0 -10
  112. package/dist/translate.jsx +0 -75
  113. package/dist/translations/de.d.ts +0 -43
  114. package/dist/translations/de.js +0 -43
  115. package/dist/translations/en.d.ts +0 -43
  116. package/dist/translations/en.js +0 -43
  117. package/dist/translations/es.d.ts +0 -43
  118. package/dist/translations/es.js +0 -43
  119. package/dist/translations/fr.d.ts +0 -43
  120. package/dist/translations/fr.js +0 -43
  121. package/dist/translations/index.d.ts +0 -395
  122. package/dist/translations/index.js +0 -27
  123. package/dist/translations/ja.d.ts +0 -43
  124. package/dist/translations/ja.js +0 -43
  125. package/dist/translations/nl.d.ts +0 -43
  126. package/dist/translations/nl.js +0 -43
  127. package/dist/translations/no.d.ts +0 -43
  128. package/dist/translations/no.js +0 -43
  129. package/dist/translations/pt-br.d.ts +0 -43
  130. package/dist/translations/pt-br.js +0 -43
  131. package/dist/translations/types.d.ts +0 -5
  132. package/dist/translations/types.js +0 -1
  133. package/dist/translations/zh.d.ts +0 -43
  134. package/dist/translations/zh.js +0 -43
  135. package/dist/tsconfig.build.tsbuildinfo +0 -1
  136. package/dist/types.d.ts +0 -31
  137. package/dist/types.js +0 -1
  138. package/dist/util/example.d.ts +0 -35
  139. package/dist/util/example.jsx +0 -103
  140. package/dist/util/server.d.ts +0 -9
  141. package/dist/util/server.js +0 -44
  142. package/dist/util/tryit-prefill.d.ts +0 -20
  143. package/dist/util/tryit-prefill.js +0 -129
  144. package/dist/utils.d.ts +0 -50
  145. package/dist/utils.js +0 -224
  146. package/src/InteractiveSection.tsx +0 -147
  147. package/src/Markdown.tsx +0 -12
  148. package/src/OpenAPICodeSample.tsx +0 -330
  149. package/src/OpenAPICodeSampleInteractive.tsx +0 -136
  150. package/src/OpenAPICodeSampleSelector.tsx +0 -94
  151. package/src/OpenAPICopyButton.tsx +0 -72
  152. package/src/OpenAPIDisclosure.tsx +0 -46
  153. package/src/OpenAPIDisclosureGroup.tsx +0 -158
  154. package/src/OpenAPIExample.tsx +0 -55
  155. package/src/OpenAPIMediaType.tsx +0 -139
  156. package/src/OpenAPIOperation.tsx +0 -35
  157. package/src/OpenAPIOperationContext.tsx +0 -45
  158. package/src/OpenAPIOperationDescription.tsx +0 -34
  159. package/src/OpenAPIOperationStability.tsx +0 -39
  160. package/src/OpenAPIPath.tsx +0 -90
  161. package/src/OpenAPIPrefillContextProvider.tsx +0 -40
  162. package/src/OpenAPIRequestBody.tsx +0 -54
  163. package/src/OpenAPIRequestBodyHeaderType.tsx +0 -36
  164. package/src/OpenAPIResponse.tsx +0 -82
  165. package/src/OpenAPIResponseExample.tsx +0 -151
  166. package/src/OpenAPIResponseExampleContent.tsx +0 -125
  167. package/src/OpenAPIResponses.tsx +0 -125
  168. package/src/OpenAPISchema.test.ts +0 -172
  169. package/src/OpenAPISchema.tsx +0 -654
  170. package/src/OpenAPISchemaName.tsx +0 -80
  171. package/src/OpenAPISchemaServer.tsx +0 -34
  172. package/src/OpenAPISecurities.tsx +0 -231
  173. package/src/OpenAPISelect.tsx +0 -96
  174. package/src/OpenAPISpec.tsx +0 -138
  175. package/src/OpenAPITabs.tsx +0 -147
  176. package/src/OpenAPIWebhook.tsx +0 -33
  177. package/src/OpenAPIWebhookExample.tsx +0 -60
  178. package/src/ScalarApiButton.tsx +0 -132
  179. package/src/StaticSection.tsx +0 -91
  180. package/src/__snapshots__/json2xml.test.ts.snap +0 -18
  181. package/src/code-samples.test.ts +0 -714
  182. package/src/code-samples.ts +0 -448
  183. package/src/common/OpenAPIColumnSpec.tsx +0 -31
  184. package/src/common/OpenAPIOperationDescription.tsx +0 -31
  185. package/src/common/OpenAPIStability.tsx +0 -23
  186. package/src/common/OpenAPISummary.tsx +0 -45
  187. package/src/contentTypeChecks.ts +0 -39
  188. package/src/context.ts +0 -99
  189. package/src/decycle.ts +0 -68
  190. package/src/dereference.ts +0 -29
  191. package/src/generateSchemaExample.test.ts +0 -1040
  192. package/src/generateSchemaExample.ts +0 -530
  193. package/src/getDisclosureLabel.ts +0 -25
  194. package/src/getOrCreateStoreByKey.ts +0 -33
  195. package/src/index.ts +0 -10
  196. package/src/json2xml.test.ts +0 -46
  197. package/src/json2xml.ts +0 -8
  198. package/src/resolveOpenAPIOperation.test.ts +0 -177
  199. package/src/resolveOpenAPIOperation.ts +0 -151
  200. package/src/resolveOpenAPIWebhook.ts +0 -99
  201. package/src/schemas/OpenAPISchemaItem.tsx +0 -34
  202. package/src/schemas/OpenAPISchemas.tsx +0 -98
  203. package/src/schemas/index.ts +0 -2
  204. package/src/schemas/resolveOpenAPISchemas.test.ts +0 -174
  205. package/src/schemas/resolveOpenAPISchemas.ts +0 -28
  206. package/src/stringifyOpenAPI.ts +0 -25
  207. package/src/translate.tsx +0 -80
  208. package/src/translations/de.ts +0 -43
  209. package/src/translations/en.ts +0 -43
  210. package/src/translations/es.ts +0 -43
  211. package/src/translations/fr.ts +0 -43
  212. package/src/translations/index.ts +0 -33
  213. package/src/translations/ja.ts +0 -43
  214. package/src/translations/nl.ts +0 -43
  215. package/src/translations/no.ts +0 -43
  216. package/src/translations/pt-br.ts +0 -43
  217. package/src/translations/types.ts +0 -7
  218. package/src/translations/zh.ts +0 -43
  219. package/src/types.ts +0 -46
  220. package/src/util/example.tsx +0 -129
  221. package/src/util/server.test.ts +0 -58
  222. package/src/util/server.ts +0 -47
  223. package/src/util/tryit-prefill.test.ts +0 -311
  224. package/src/util/tryit-prefill.ts +0 -160
  225. package/src/utils.ts +0 -255
package/dist/index.js CHANGED
@@ -1,8 +1,3873 @@
1
- export * from './schemas';
2
- export * from './OpenAPIOperation';
3
- export * from './OpenAPIWebhook';
4
- export * from './OpenAPIOperationContext';
5
- export * from './OpenAPIPrefillContextProvider';
6
- export * from './resolveOpenAPIOperation';
7
- export * from './resolveOpenAPIWebhook';
8
- export { checkIsValidLocale } from './translations';
1
+ import { createRequire } from "node:module";
2
+ import clsx from "clsx";
3
+ import yaml from "js-yaml";
4
+ import { jsXml } from "json-xml-parse";
5
+ import * as React$1 from "react";
6
+ import React, { Fragment, Suspense, createContext, forwardRef, useCallback, useContext, useEffect, useId, useImperativeHandle, useMemo, useRef, useState } from "react";
7
+ import { Button, Disclosure, DisclosurePanel, ListBox, ListBoxItem, Popover, Select, SelectValue, Tooltip, TooltipTrigger } from "react-aria-components";
8
+ import { dereference, filterSelectedOpenAPISchemas } from "@gitbook/openapi-parser";
9
+ import { createStore, useStore } from "zustand";
10
+ import { ApiClientModalProvider, useApiClientModal } from "@scalar/api-client-react";
11
+ import { useEventCallback } from "usehooks-ts";
12
+ import { ExpressionRuntime, parseTemplate } from "@gitbook/expr";
13
+ import { mergeProps, useButton, useDisclosure, useFocusRing, useId as useId$1 } from "react-aria";
14
+ import "flatted";
15
+
16
+ //#region rolldown:runtime
17
+ var __create = Object.create;
18
+ var __defProp = Object.defineProperty;
19
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
20
+ var __getOwnPropNames = Object.getOwnPropertyNames;
21
+ var __getProtoOf = Object.getPrototypeOf;
22
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
23
+ var __commonJS = (cb, mod) => function() {
24
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
25
+ };
26
+ var __copyProps = (to, from, except, desc) => {
27
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
28
+ key = keys[i];
29
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
30
+ get: ((k) => from[k]).bind(null, key),
31
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
32
+ });
33
+ }
34
+ return to;
35
+ };
36
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
37
+ value: mod,
38
+ enumerable: true
39
+ }) : target, mod));
40
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
41
+
42
+ //#endregion
43
+ //#region src/json2xml.ts
44
+ /**
45
+ * This function converts an object to XML.
46
+ */
47
+ function json2xml(data) {
48
+ return jsXml.toXmlString(data, { beautify: true });
49
+ }
50
+
51
+ //#endregion
52
+ //#region src/stringifyOpenAPI.ts
53
+ /**
54
+ * Stringify an OpenAPI object. Same API as JSON.stringify.
55
+ */
56
+ function stringifyOpenAPI(value, replacer, space) {
57
+ return JSON.stringify(value, (key, value$1) => {
58
+ if (key.startsWith("x-gitbook-")) return;
59
+ if (replacer) return replacer(key, value$1);
60
+ return value$1;
61
+ }, space);
62
+ }
63
+
64
+ //#endregion
65
+ //#region src/translate.tsx
66
+ /**
67
+ * Translate a string.
68
+ */
69
+ function t(translation, id, ...args) {
70
+ const string = translation[id];
71
+ if (!string) throw new Error(`Translation not found for "${id}"`);
72
+ const parts = [];
73
+ let currentStringToReplace = string;
74
+ args.forEach((arg, i) => {
75
+ if (typeof arg === "string") currentStringToReplace = currentStringToReplace.replace(`\${${i + 1}}`, arg);
76
+ else {
77
+ const [partToPush, partToReplace] = currentStringToReplace.split(`\${${i + 1}}`);
78
+ if (partToPush === void 0 || partToReplace === void 0) throw new Error(`Invalid translation "${id}"`);
79
+ parts.push(<React.Fragment key={`string-${i}`}>{partToPush}</React.Fragment>);
80
+ parts.push(<React.Fragment key={`arg-${i}`}>{arg}</React.Fragment>);
81
+ currentStringToReplace = partToReplace;
82
+ }
83
+ });
84
+ if (!parts.length) return currentStringToReplace;
85
+ return <>
86
+ {parts}
87
+ {currentStringToReplace}
88
+ </>;
89
+ }
90
+ /**
91
+ * Version of `t` that returns a string.
92
+ */
93
+ function tString(translation, id, ...args) {
94
+ return reactToString(t(translation, id, ...args));
95
+ }
96
+ function reactToString(el) {
97
+ if (typeof el === "string" || typeof el === "number" || typeof el === "boolean") return `${el}`;
98
+ if (el === null || el === void 0) return "";
99
+ if (Array.isArray(el)) return el.map(reactToString).join("");
100
+ if (typeof el === "object" && "props" in el) return el.props.children.map(reactToString).join("");
101
+ throw new Error(`Unsupported type ${typeof el}`);
102
+ }
103
+
104
+ //#endregion
105
+ //#region src/OpenAPIExample.tsx
106
+ /**
107
+ * Display an example.
108
+ */
109
+ function OpenAPIExample(props) {
110
+ const { example, context, syntax } = props;
111
+ const code = stringifyExample({
112
+ example,
113
+ syntax
114
+ });
115
+ if (code === null) return <OpenAPIEmptyExample context={context} />;
116
+ return context.renderCodeBlock({
117
+ code,
118
+ syntax
119
+ });
120
+ }
121
+ function stringifyExample(args) {
122
+ const { example, syntax } = args;
123
+ if (!example.value) return null;
124
+ if (typeof example.value === "string") return example.value;
125
+ if (syntax === "xml") return json2xml(example.value);
126
+ if (syntax === "yaml") return yaml.dump(example.value).replace(/'/g, "").replace(/\\n/g, "\n");
127
+ return stringifyOpenAPI(example.value, null, 2);
128
+ }
129
+ /**
130
+ * Empty response example.
131
+ */
132
+ function OpenAPIEmptyExample(props) {
133
+ const { context } = props;
134
+ return <pre className="openapi-example-empty">
135
+ <p>{t(context.translation, "no_content")}</p>
136
+ </pre>;
137
+ }
138
+
139
+ //#endregion
140
+ //#region src/Markdown.tsx
141
+ function Markdown(props) {
142
+ const { source, className } = props;
143
+ return <div className={clsx("openapi-markdown", className)} dangerouslySetInnerHTML={{ __html: source }} />;
144
+ }
145
+
146
+ //#endregion
147
+ //#region src/OpenAPICopyButton.tsx
148
+ function OpenAPICopyButton(props) {
149
+ const { value, label, children, onPress, className, context, withTooltip = true } = props;
150
+ const [copied, setCopied] = useState(false);
151
+ const [isOpen, setIsOpen] = useState(false);
152
+ const handleCopy = () => {
153
+ if (!value) return;
154
+ navigator.clipboard.writeText(value).then(() => {
155
+ setIsOpen(true);
156
+ setCopied(true);
157
+ setTimeout(() => {
158
+ setCopied(false);
159
+ setIsOpen(false);
160
+ }, 2e3);
161
+ });
162
+ };
163
+ return <TooltipTrigger isOpen={isOpen} onOpenChange={setIsOpen} isDisabled={!withTooltip} closeDelay={200} delay={200}>
164
+ <Button type="button" preventFocusOnPress onPress={(e) => {
165
+ handleCopy();
166
+ onPress?.(e);
167
+ }} className={`openapi-copy-button ${className}`} {...props}>
168
+ {children}
169
+ </Button>
170
+
171
+ <Tooltip isOpen={isOpen} onOpenChange={setIsOpen} placement="top" offset={4} className="openapi-tooltip">
172
+ {copied ? t(context.translation, "copied") : label || t(context.translation, "copy_to_clipboard")}
173
+ </Tooltip>
174
+ </TooltipTrigger>;
175
+ }
176
+
177
+ //#endregion
178
+ //#region src/OpenAPIDisclosure.tsx
179
+ /**
180
+ * Display an interactive OpenAPI disclosure.
181
+ */
182
+ function OpenAPIDisclosure(props) {
183
+ const { icon, header, label, children, className } = props;
184
+ const [isExpanded, setIsExpanded] = useState(false);
185
+ return <Disclosure className={clsx("openapi-disclosure", className)} isExpanded={isExpanded} onExpandedChange={setIsExpanded}>
186
+ <Button slot="trigger" className="openapi-disclosure-trigger" style={({ isFocusVisible }) => ({ outline: isFocusVisible ? "2px solid rgb(var(--primary-color-500) / 0.4)" : "none" })}>
187
+ {header}
188
+ <div className="openapi-disclosure-trigger-label">
189
+ <span>{typeof label === "function" ? label(isExpanded) : label}</span>
190
+ {icon}
191
+ </div>
192
+ </Button>
193
+ <DisclosurePanel className="openapi-disclosure-panel">
194
+ {isExpanded ? children : null}
195
+ </DisclosurePanel>
196
+ </Disclosure>;
197
+ }
198
+
199
+ //#endregion
200
+ //#region src/OpenAPISchemaName.tsx
201
+ /**
202
+ * Display the schema name row.
203
+ * It includes the property name, type, required and deprecated status.
204
+ */
205
+ function OpenAPISchemaName(props) {
206
+ const { schema, type, propertyName, required, isDiscriminatorProperty, context } = props;
207
+ const additionalItems = schema && getAdditionalItems(schema, context);
208
+ return <span className="openapi-schema-name">
209
+ {propertyName ? <span data-deprecated={schema?.deprecated} className="openapi-schema-propertyname">
210
+ {propertyName}
211
+ </span> : null}
212
+ {isDiscriminatorProperty ? <span className="openapi-schema-discriminator">
213
+ {t(context.translation, "discriminator")}
214
+ </span> : null}
215
+ {type || additionalItems ? <span>
216
+ {schema?.const ? <span className="openapi-schema-type">const: {schema?.const}</span> : type ? <span className="openapi-schema-type">{type}</span> : null}
217
+ {additionalItems ? <span className="openapi-schema-type">{additionalItems}</span> : null}
218
+ </span> : null}
219
+ {schema?.readOnly ? <span className="openapi-schema-readonly">
220
+ {t(context.translation, "read_only")}
221
+ </span> : null}
222
+ {schema?.writeOnly ? <span className="openapi-schema-writeonly">
223
+ {t(context.translation, "write_only")}
224
+ </span> : null}
225
+ {required === null ? null : required ? <span className="openapi-schema-required">
226
+ {t(context.translation, "required")}
227
+ </span> : <span className="openapi-schema-optional">
228
+ {t(context.translation, "optional")}
229
+ </span>}
230
+ {schema?.deprecated ? <span className="openapi-deprecated">{t(context.translation, "deprecated")}</span> : null}
231
+ </span>;
232
+ }
233
+ function getAdditionalItems(schema, context) {
234
+ let additionalItems = "";
235
+ if (schema.minimum || schema.minLength || schema.minItems) additionalItems += ` · ${tString(context.translation, "min").toLowerCase()}: ${schema.minimum || schema.minLength || schema.minItems}`;
236
+ if (schema.maximum || schema.maxLength || schema.maxItems) additionalItems += ` · ${tString(context.translation, "max").toLowerCase()}: ${schema.maximum || schema.maxLength || schema.maxItems}`;
237
+ if (schema.nullable) additionalItems = ` | ${tString(context.translation, "nullable").toLowerCase()}`;
238
+ return additionalItems;
239
+ }
240
+
241
+ //#endregion
242
+ //#region src/decycle.ts
243
+ const isObject = (value) => typeof value === "object" && value != null && !(value instanceof Boolean) && !(value instanceof Date) && !(value instanceof Number) && !(value instanceof RegExp) && !(value instanceof String);
244
+ const toPointer = (parts) => `#${parts.map((part) => String(part).replace(/~/g, "~0").replace(/\//g, "~1")).join("/")}`;
245
+ const decycle = () => {
246
+ const paths = /* @__PURE__ */ new WeakMap();
247
+ return function replacer(key, value) {
248
+ if (key !== "$reference" && isObject(value)) {
249
+ if (paths.has(value)) return { $reference: toPointer(paths.get(value)) };
250
+ paths.set(value, [...paths.get(this) ?? [], key]);
251
+ }
252
+ return value;
253
+ };
254
+ };
255
+ function retrocycle() {
256
+ const parents = /* @__PURE__ */ new WeakMap();
257
+ const keys = /* @__PURE__ */ new WeakMap();
258
+ const refs = /* @__PURE__ */ new Set();
259
+ function dereference$1(ref) {
260
+ const parts = ref.$reference.slice(1).split("/");
261
+ let key;
262
+ let value = this;
263
+ for (let i = 0; i < parts.length; i++) {
264
+ key = parts[i]?.replace(/~1/g, "/").replace(/~0/g, "~");
265
+ value = value[key];
266
+ }
267
+ const parent = parents.get(ref);
268
+ parent[keys.get(ref)] = value;
269
+ }
270
+ return function reviver(key, value) {
271
+ if (key === "$reference") refs.add(this);
272
+ else if (isObject(value)) if (key === "" && Object.keys(this).length === 1) refs.forEach(dereference$1, this);
273
+ else {
274
+ parents.set(value, this);
275
+ keys.set(value, key);
276
+ }
277
+ return value;
278
+ };
279
+ }
280
+
281
+ //#endregion
282
+ //#region src/getDisclosureLabel.ts
283
+ function getDisclosureLabel(props) {
284
+ const { schema, isExpanded, context } = props;
285
+ let label;
286
+ if (schema.type === "array" && !!schema.items) if (schema.items.oneOf) label = tString(context.translation, "available_items").toLowerCase();
287
+ else label = tString(context.translation, "properties").toLowerCase();
288
+ else label = tString(context.translation, "properties").toLowerCase();
289
+ return tString(context.translation, isExpanded ? "hide" : "show", label);
290
+ }
291
+
292
+ //#endregion
293
+ //#region src/utils.ts
294
+ function checkIsReference(input) {
295
+ return typeof input === "object" && !!input && "$ref" in input;
296
+ }
297
+ function createStateKey(key, scope) {
298
+ return scope ? `${scope}_${key}` : key;
299
+ }
300
+ /**
301
+ * Check if an object has a description. Either at the root level or in items.
302
+ */
303
+ function hasDescription(object) {
304
+ return "description" in object || "x-gitbook-description-html" in object;
305
+ }
306
+ /**
307
+ * Resolve the description of an object.
308
+ */
309
+ function resolveDescription(object) {
310
+ if (hasDescription(object)) return "x-gitbook-description-html" in object && typeof object["x-gitbook-description-html"] === "string" ? object["x-gitbook-description-html"].trim() : typeof object.description === "string" ? object.description.trim() : void 0;
311
+ if ("items" in object && typeof object.items === "object" && hasDescription(object.items)) return resolveDescription(object.items);
312
+ }
313
+ /**
314
+ * Extract descriptions from an object.
315
+ */
316
+ function extractDescriptions(object) {
317
+ return {
318
+ description: object.description,
319
+ "x-gitbook-description-html": "x-gitbook-description-html" in object ? object["x-gitbook-description-html"] : void 0
320
+ };
321
+ }
322
+ /**
323
+ * Resolve the first example from an object.
324
+ */
325
+ function resolveFirstExample(object) {
326
+ if ("examples" in object && typeof object.examples === "object" && object.examples) {
327
+ const firstKey = Object.keys(object.examples)[0];
328
+ if (firstKey && object.examples[firstKey]) return formatExample(object.examples[firstKey]);
329
+ }
330
+ if (shouldDisplayExample(object)) return formatExample(object.example);
331
+ if (object.items && typeof object.items === "object") return formatExample(object.items.example);
332
+ }
333
+ /**
334
+ * Resolve the schema of a parameter.
335
+ * Extract the description, example and deprecated from parameter.
336
+ */
337
+ function resolveParameterSchema(parameter) {
338
+ const schema = checkIsReference(parameter.schema) ? void 0 : parameter.schema;
339
+ return {
340
+ ...extractDescriptions(parameter),
341
+ example: resolveFirstExample(parameter),
342
+ deprecated: parameter.deprecated,
343
+ ...schema
344
+ };
345
+ }
346
+ /**
347
+ * Transform a parameter object to a property object.
348
+ */
349
+ function parameterToProperty(parameter) {
350
+ if (checkIsReference(parameter)) return {
351
+ propertyName: parameter.$ref ?? "Unknown ref",
352
+ schema: {},
353
+ required: void 0
354
+ };
355
+ return {
356
+ propertyName: parameter.name,
357
+ schema: resolveParameterSchema(parameter),
358
+ required: parameter.required
359
+ };
360
+ }
361
+ /**
362
+ * Format the example of a schema.
363
+ */
364
+ function formatExample(example) {
365
+ if (typeof example === "string") return example.replace(/\n/g, " ").replace(/\s+/g, " ").replace(/([\{\}:,])\s+/g, "$1 ").replace(/\s+([\{\}:,])/g, " $1").trim();
366
+ return stringifyOpenAPI(example);
367
+ }
368
+ /**
369
+ * Check if an example should be displayed.
370
+ */
371
+ function shouldDisplayExample(schema) {
372
+ return typeof schema.example === "string" && !!schema.example || typeof schema.example === "number" || typeof schema.example === "boolean" || Array.isArray(schema.example) && schema.example.length > 0 || typeof schema.example === "object" && schema.example !== null && Object.keys(schema.example).length > 0;
373
+ }
374
+ /**
375
+ * Get the class name for a status code.
376
+ * 1xx: informational
377
+ * 2xx: success
378
+ * 3xx: redirect
379
+ * 4xx, 5xx: error
380
+ */
381
+ function getStatusCodeClassName(statusCode) {
382
+ switch (getStatusCodeCategory(statusCode)) {
383
+ case 1: return "informational";
384
+ case 2: return "success";
385
+ case 3: return "redirect";
386
+ case 4:
387
+ case 5: return "error";
388
+ default: return "unknown";
389
+ }
390
+ }
391
+ /**
392
+ * Get a default label for a status code.
393
+ * This is used when there is no label provided in the OpenAPI spec.
394
+ * 1xx: Information
395
+ * 2xx: Success
396
+ * 3xx: Redirect
397
+ * 4xx, 5xx: Error
398
+ */
399
+ function getStatusCodeDefaultLabel(statusCode, context) {
400
+ switch (getStatusCodeCategory(statusCode)) {
401
+ case 1: return tString(context.translation, "information");
402
+ case 2: return tString(context.translation, "success");
403
+ case 3: return tString(context.translation, "redirect");
404
+ case 4:
405
+ case 5: return tString(context.translation, "error");
406
+ default: return "";
407
+ }
408
+ }
409
+ function getStatusCodeCategory(statusCode) {
410
+ const code = typeof statusCode === "string" ? Number.parseInt(statusCode, 10) : statusCode;
411
+ if (Number.isNaN(code) || code < 100 || code >= 600) return "unknown";
412
+ return Math.floor(code / 100);
413
+ }
414
+ function getSchemaTitle(schema) {
415
+ let type = "any";
416
+ if (schema.enum || schema["x-enumDescriptions"] || schema["x-gitbook-enum"]) type = `${schema.type} · enum`;
417
+ else if (schema.type === "array" && !!schema.items) type = `${getSchemaTitle(schema.items)}[]`;
418
+ else if (Array.isArray(schema.type)) type = schema.type.join(" | ");
419
+ else if (schema.type || schema.properties) {
420
+ type = schema.type ?? "object";
421
+ if (schema.format) type += ` · ${schema.format}`;
422
+ if (type === "object" && schema.title) type += ` · ${schema.title.replaceAll(" ", "")}`;
423
+ }
424
+ if ("anyOf" in schema) type = "any of";
425
+ else if ("oneOf" in schema) type = "one of";
426
+ else if ("allOf" in schema) type = "all of";
427
+ else if ("not" in schema) type = "not";
428
+ return type;
429
+ }
430
+ /**
431
+ * Extract security information for an operation based on its security requirements and the spec security schemes.
432
+ */
433
+ function extractOperationSecurityInfo(args) {
434
+ const { securityRequirement, securities } = args;
435
+ const securitiesMap = new Map(securities);
436
+ if (!securityRequirement || securityRequirement.length === 0) return securities.map(([key, security]) => ({
437
+ key,
438
+ label: key,
439
+ schemes: [security]
440
+ }));
441
+ return securityRequirement.map((requirement, idx) => {
442
+ const schemeKeys = Object.keys(requirement);
443
+ return {
444
+ key: `security-${idx}`,
445
+ label: schemeKeys.join(" & "),
446
+ schemes: schemeKeys.map((schemeKey) => securitiesMap.get(schemeKey)).filter((s) => s !== void 0)
447
+ };
448
+ });
449
+ }
450
+
451
+ //#endregion
452
+ //#region src/OpenAPISchema.tsx
453
+ /**
454
+ * Render a property of an OpenAPI schema.
455
+ */
456
+ function OpenAPISchemaProperty(props) {
457
+ const { circularRefs: parentCircularRefs, context, className, property,...rest } = props;
458
+ const { schema } = property;
459
+ const id = useId();
460
+ const circularRefId = parentCircularRefs.get(schema);
461
+ if (circularRefId) return <OpenAPISchemaCircularRef id={circularRefId} schema={schema} />;
462
+ const circularRefs = new Map(parentCircularRefs);
463
+ circularRefs.set(schema, id);
464
+ const properties = getSchemaProperties(schema);
465
+ const alternatives = getSchemaAlternatives(schema, new Set(circularRefs.keys()));
466
+ const header = <OpenAPISchemaPresentation context={context} property={property} />;
467
+ const content = (() => {
468
+ if (alternatives?.schemas) {
469
+ const { schemas, discriminator } = alternatives;
470
+ return <div className="openapi-schema-alternatives">
471
+ {schemas.map((alternativeSchema, index) => <div key={index} className="openapi-schema-alternative">
472
+ <OpenAPISchemaAlternative schema={alternativeSchema} discriminator={discriminator} circularRefs={circularRefs} context={context} />
473
+ {index < schemas.length - 1 ? <OpenAPISchemaAlternativeSeparator schema={schema} context={context} /> : null}
474
+ </div>)}
475
+ </div>;
476
+ }
477
+ if (properties?.length) return <OpenAPISchemaProperties$1 properties={properties} circularRefs={circularRefs} context={context} />;
478
+ return null;
479
+ })();
480
+ if (properties?.length) return <OpenAPIDisclosure icon={context.icons.plus} className={clsx("openapi-schema", className)} header={header} label={(isExpanded) => getDisclosureLabel({
481
+ schema,
482
+ isExpanded,
483
+ context
484
+ })} {...rest}>
485
+ {content}
486
+ </OpenAPIDisclosure>;
487
+ return <div id={id} {...rest} className={clsx("openapi-schema", className)}>
488
+ {header}
489
+ {content}
490
+ </div>;
491
+ }
492
+ /**
493
+ * Render a set of properties of an OpenAPI schema.
494
+ */
495
+ function OpenAPISchemaProperties$1(props) {
496
+ const { id, properties, circularRefs = /* @__PURE__ */ new Map(), context } = props;
497
+ return <div id={id} className="openapi-schema-properties">
498
+ {properties.map((property, index) => {
499
+ return <OpenAPISchemaProperty key={index} circularRefs={circularRefs} property={property} context={context} style={{ animationDelay: `${index * .02}s` }} />;
500
+ })}
501
+ </div>;
502
+ }
503
+ function OpenAPISchemaPropertiesFromServer(props) {
504
+ return <OpenAPISchemaProperties$1 id={props.id} properties={JSON.parse(props.properties, retrocycle())} context={props.context} />;
505
+ }
506
+ /**
507
+ * Render a root schema (such as the request body or response body).
508
+ */
509
+ function OpenAPIRootSchema$1(props) {
510
+ const { schema, context, circularRefs: parentCircularRefs = /* @__PURE__ */ new Map() } = props;
511
+ const id = useId();
512
+ const properties = getSchemaProperties(schema);
513
+ const description = resolveDescription(schema);
514
+ if (properties?.length) {
515
+ const circularRefs = new Map(parentCircularRefs);
516
+ circularRefs.set(schema, id);
517
+ return <>
518
+ {description ? <Markdown source={description} className="openapi-schema-root-description" /> : null}
519
+ <OpenAPISchemaProperties$1 properties={properties} circularRefs={circularRefs} context={context} />
520
+ </>;
521
+ }
522
+ return <OpenAPISchemaProperty className="openapi-schema-root" property={{ schema }} context={context} circularRefs={parentCircularRefs} />;
523
+ }
524
+ function OpenAPIRootSchemaFromServer(props) {
525
+ return <OpenAPIRootSchema$1 schema={JSON.parse(props.schema, retrocycle())} context={props.context} />;
526
+ }
527
+ /**
528
+ * Render a tab for an alternative schema.
529
+ * It renders directly the properties if relevant;
530
+ * for primitives, it renders the schema itself.
531
+ */
532
+ function OpenAPISchemaAlternative(props) {
533
+ const { schema, discriminator, circularRefs, context } = props;
534
+ const properties = getSchemaProperties(schema, discriminator);
535
+ return properties?.length ? <OpenAPIDisclosure icon={context.icons.plus} header={<OpenAPISchemaPresentation property={{ schema }} context={context} />} label={(isExpanded) => getDisclosureLabel({
536
+ schema,
537
+ isExpanded,
538
+ context
539
+ })}>
540
+ <OpenAPISchemaProperties$1 properties={properties} circularRefs={circularRefs} context={context} />
541
+ </OpenAPIDisclosure> : <OpenAPISchemaProperty property={{ schema }} circularRefs={circularRefs} context={context} />;
542
+ }
543
+ function OpenAPISchemaAlternativeSeparator(props) {
544
+ const { schema, context } = props;
545
+ const anyOf = schema.anyOf || schema.items?.anyOf;
546
+ const oneOf = schema.oneOf || schema.items?.oneOf;
547
+ const allOf = schema.allOf || schema.items?.allOf;
548
+ if (!anyOf && !oneOf && !allOf) return null;
549
+ return <span className="openapi-schema-alternative-separator">
550
+ {(anyOf || oneOf) && tString(context.translation, "or")}
551
+ {allOf && tString(context.translation, "and")}
552
+ </span>;
553
+ }
554
+ /**
555
+ * Render a circular reference to a schema.
556
+ */
557
+ function OpenAPISchemaCircularRef(props) {
558
+ const { id, schema } = props;
559
+ return <div className="openapi-schema-circular">
560
+ Circular reference to <a href={`#${id}`}>{getSchemaTitle(schema)}</a>{" "}
561
+ <span className="openapi-schema-circular-glyph">↩</span>
562
+ </div>;
563
+ }
564
+ /**
565
+ * Render the enum value for a schema.
566
+ */
567
+ function OpenAPISchemaEnum(props) {
568
+ const { schema, context } = props;
569
+ const enumValues = (() => {
570
+ if (schema["x-gitbook-enum"]) return Object.entries(schema["x-gitbook-enum"]).map(([name, { description }]) => {
571
+ return {
572
+ value: name,
573
+ description
574
+ };
575
+ });
576
+ if (schema["x-enumDescriptions"]) return Object.entries(schema["x-enumDescriptions"]).map(([value, description]) => {
577
+ return {
578
+ value,
579
+ description
580
+ };
581
+ });
582
+ return schema.enum?.map((value) => {
583
+ return {
584
+ value,
585
+ description: void 0
586
+ };
587
+ });
588
+ })();
589
+ if (!enumValues?.length) return null;
590
+ return <span className="openapi-schema-enum">
591
+ {tString(context.translation, "possible_values")}:{" "}
592
+ {enumValues.map((item, index) => <span key={index} className="openapi-schema-enum-value">
593
+ <OpenAPICopyButton value={item.value} label={item.description} withTooltip={!!item.description} context={context}>
594
+ <code>{`${item.value}`}</code>
595
+ </OpenAPICopyButton>
596
+ </span>)}
597
+ </span>;
598
+ }
599
+ /**
600
+ * Render the top row of a schema. e.g: name, type, and required status.
601
+ */
602
+ function OpenAPISchemaPresentation(props) {
603
+ const { property: { schema, propertyName, required, isDiscriminatorProperty }, context } = props;
604
+ const description = resolveDescription(schema);
605
+ const example = resolveFirstExample(schema);
606
+ return <div className="openapi-schema-presentation">
607
+ <OpenAPISchemaName schema={schema} type={getSchemaTitle(schema)} propertyName={propertyName} isDiscriminatorProperty={isDiscriminatorProperty} required={required} context={context} />
608
+ {typeof schema["x-deprecated-sunset"] === "string" ? <div className="openapi-deprecated-sunset openapi-schema-description openapi-markdown">
609
+ Sunset date:{" "}
610
+ <span className="openapi-deprecated-sunset-date">
611
+ {schema["x-deprecated-sunset"]}
612
+ </span>
613
+ </div> : null}
614
+ {description ? <Markdown source={description} className="openapi-schema-description" /> : null}
615
+ {schema.default !== void 0 ? <span className="openapi-schema-default">
616
+ Default:{" "}
617
+ <code>
618
+ {typeof schema.default === "string" && schema.default ? schema.default : stringifyOpenAPI(schema.default)}
619
+ </code>
620
+ </span> : null}
621
+ {typeof example === "string" ? <span className="openapi-schema-example">
622
+ Example: <code>{example}</code>
623
+ </span> : null}
624
+ {schema.pattern ? <span className="openapi-schema-pattern">
625
+ Pattern: <code>{schema.pattern}</code>
626
+ </span> : null}
627
+ <OpenAPISchemaEnum schema={schema} context={context} />
628
+ </div>;
629
+ }
630
+ /**
631
+ * Get the sub-properties of a schema.
632
+ */
633
+ function getSchemaProperties(schema, discriminator) {
634
+ if (schema.type === "array" && schema.items && !checkIsReference(schema.items)) {
635
+ const items = schema.items;
636
+ const itemProperties = getSchemaProperties(items);
637
+ if (itemProperties) return itemProperties.map((prop) => ({
638
+ ...prop,
639
+ isDiscriminatorProperty: discriminator?.propertyName === prop.propertyName
640
+ }));
641
+ if ((items.type === "string" || items.type === "number" || items.type === "boolean" || items.type === "integer") && !items.enum) return null;
642
+ return [{
643
+ propertyName: "items",
644
+ schema: items
645
+ }];
646
+ }
647
+ if (schema.type === "object" || schema.properties) {
648
+ const result = [];
649
+ if (schema.properties) Object.entries(schema.properties).forEach(([propertyName, propertySchema]) => {
650
+ if (checkIsReference(propertySchema)) return;
651
+ result.push({
652
+ propertyName,
653
+ required: Array.isArray(schema.required) ? schema.required.includes(propertyName) : void 0,
654
+ isDiscriminatorProperty: discriminator?.propertyName === propertyName,
655
+ schema: propertySchema
656
+ });
657
+ });
658
+ if (schema.additionalProperties && !checkIsReference(schema.additionalProperties)) result.push({
659
+ propertyName: "Other properties",
660
+ schema: schema.additionalProperties === true ? {} : schema.additionalProperties
661
+ });
662
+ return result;
663
+ }
664
+ return null;
665
+ }
666
+ /**
667
+ * Get the alternatives to display for a schema.
668
+ */
669
+ function getSchemaAlternatives(schema, ancestors = /* @__PURE__ */ new Set()) {
670
+ if (schema.items && ("oneOf" in schema.items || "allOf" in schema.items || "anyOf" in schema.items)) return getSchemaAlternatives(schema.items, ancestors);
671
+ const alternatives = (() => {
672
+ if (schema.anyOf) return [
673
+ "anyOf",
674
+ schema.anyOf,
675
+ schema.discriminator
676
+ ];
677
+ if (schema.oneOf) return [
678
+ "oneOf",
679
+ schema.oneOf,
680
+ schema.discriminator
681
+ ];
682
+ if (schema.allOf) return [
683
+ "allOf",
684
+ schema.allOf,
685
+ schema.discriminator
686
+ ];
687
+ return null;
688
+ })();
689
+ if (!alternatives) return null;
690
+ const [type, schemas, discriminator] = alternatives;
691
+ return {
692
+ type,
693
+ schemas: mergeAlternatives(type, flattenAlternatives(type, schemas, new Set(ancestors).add(schema))) ?? [],
694
+ discriminator
695
+ };
696
+ }
697
+ const safeExtensions = [
698
+ "description",
699
+ "title",
700
+ "example",
701
+ "examples",
702
+ "default",
703
+ "readOnly",
704
+ "writeOnly",
705
+ "deprecated"
706
+ ];
707
+ /**
708
+ * Determine if a schema is safe to merge based on its properties
709
+ */
710
+ function isSafeToMerge(schema) {
711
+ const keys = Object.keys(schema);
712
+ const coreProperties = [
713
+ "type",
714
+ "properties",
715
+ "required",
716
+ "nullable"
717
+ ];
718
+ const coreKeys = keys.filter((key) => coreProperties.includes(key));
719
+ const unknownKeys = keys.filter((key) => !coreProperties.includes(key) && !safeExtensions.includes(key) && !key.startsWith("x-"));
720
+ return coreKeys.length > 0 && unknownKeys.length === 0;
721
+ }
722
+ /**
723
+ * Merge alternatives of the same type into a single schema.
724
+ * - Merge string enums
725
+ * - Safely merge object schemas with compatible properties
726
+ */
727
+ function mergeAlternatives(alternativeType, schemasOrRefs) {
728
+ switch (alternativeType) {
729
+ case "oneOf": return schemasOrRefs.reduce((acc, schemaOrRef) => {
730
+ const latest = acc.at(-1);
731
+ if (latest && latest.type === "string" && latest.enum && schemaOrRef.type === "string" && schemaOrRef.enum) {
732
+ latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
733
+ latest.nullable = latest.nullable || schemaOrRef.nullable;
734
+ return acc;
735
+ }
736
+ acc.push(schemaOrRef);
737
+ return acc;
738
+ }, []);
739
+ case "allOf": return schemasOrRefs.reduce((acc, schemaOrRef) => {
740
+ const latest = acc.at(-1);
741
+ if (latest && latest.type === "string" && latest.enum && schemaOrRef.type === "string" && schemaOrRef.enum) {
742
+ if (Object.keys(schemaOrRef).every((key) => [
743
+ "type",
744
+ "enum",
745
+ "nullable"
746
+ ].includes(key))) {
747
+ latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
748
+ latest.nullable = latest.nullable || schemaOrRef.nullable;
749
+ return acc;
750
+ }
751
+ }
752
+ if (latest && latest.type === "object" && schemaOrRef.type === "object") {
753
+ const keys = Object.keys(schemaOrRef);
754
+ if (isSafeToMerge(schemaOrRef)) {
755
+ const safeKeys = keys.filter((key) => safeExtensions.includes(key));
756
+ const vendorKeys = keys.filter((key) => key.startsWith("x-"));
757
+ latest.properties = {
758
+ ...latest.properties || {},
759
+ ...schemaOrRef.properties || {}
760
+ };
761
+ latest.required = Array.from(new Set([...latest.required && Array.isArray(latest.required) ? latest.required : [], ...schemaOrRef.required && Array.isArray(schemaOrRef.required) ? schemaOrRef.required : []]));
762
+ latest.nullable = latest.nullable || schemaOrRef.nullable;
763
+ [...vendorKeys, ...safeKeys].forEach((key) => {
764
+ if (typeof latest[key] === "object" && typeof schemaOrRef[key] === "object") latest[key] = {
765
+ ...latest[key],
766
+ ...schemaOrRef[key]
767
+ };
768
+ else latest[key] = schemaOrRef[key];
769
+ });
770
+ return acc;
771
+ }
772
+ }
773
+ acc.push(schemaOrRef);
774
+ return acc;
775
+ }, []);
776
+ default: return schemasOrRefs;
777
+ }
778
+ }
779
+ function flattenAlternatives(alternativeType, schemasOrRefs, ancestors) {
780
+ const latestAncestor = Array.from(ancestors).pop();
781
+ return schemasOrRefs.reduce((acc, schemaOrRef) => {
782
+ if (checkIsReference(schemaOrRef)) return acc;
783
+ if (schemaOrRef[alternativeType] && !ancestors.has(schemaOrRef)) {
784
+ const alternatives = getSchemaAlternatives(schemaOrRef, ancestors);
785
+ if (alternatives?.schemas) acc.push(...alternatives.schemas.map((schema$1) => ({
786
+ ...schema$1,
787
+ required: mergeRequiredFields(schema$1, latestAncestor)
788
+ })));
789
+ return acc;
790
+ }
791
+ const schema = {
792
+ ...schemaOrRef,
793
+ required: mergeRequiredFields(schemaOrRef, latestAncestor)
794
+ };
795
+ acc.push(schema);
796
+ return acc;
797
+ }, []);
798
+ }
799
+ /**
800
+ * Merge the required fields of a schema with the required fields of its latest ancestor.
801
+ */
802
+ function mergeRequiredFields(schemaOrRef, latestAncestor) {
803
+ if (!schemaOrRef.required && !latestAncestor?.required) return;
804
+ if (checkIsReference(schemaOrRef)) return latestAncestor?.required;
805
+ return Array.from(new Set([...latestAncestor?.required || [], ...schemaOrRef.required || []]));
806
+ }
807
+
808
+ //#endregion
809
+ //#region src/OpenAPISchemaServer.tsx
810
+ function OpenAPISchemaProperties(props) {
811
+ return <OpenAPISchemaPropertiesFromServer id={props.id} properties={JSON.stringify(props.properties, decycle())} context={props.context} />;
812
+ }
813
+ function OpenAPIRootSchema(props) {
814
+ return <OpenAPIRootSchemaFromServer schema={JSON.stringify(props.schema, decycle())} context={props.context} />;
815
+ }
816
+
817
+ //#endregion
818
+ //#region src/StaticSection.tsx
819
+ function Section(props) {
820
+ return <div {...props} className={clsx("openapi-section", props.className)} />;
821
+ }
822
+ function SectionHeader(props) {
823
+ return <div {...props} className={clsx("openapi-section-header", props.className ? `${props.className}-header` : void 0)} />;
824
+ }
825
+ function SectionHeaderContent(props) {
826
+ return <div {...props} className={clsx("openapi-section-header-content", props.className && `${props.className}-header-content`)} />;
827
+ }
828
+ const SectionBody = forwardRef(function SectionBody$1(props, ref) {
829
+ return <div ref={ref} {...props} className={clsx("openapi-section-body", props.className && `${props.className}-body`)} />;
830
+ });
831
+ function SectionFooter(props) {
832
+ return <div {...props} className={clsx("openapi-section-footer", props.className && `${props.className}-footer`)} />;
833
+ }
834
+ function SectionFooterContent(props) {
835
+ return <div {...props} className={clsx("openapi-section-footer-content", props.className && `${props.className}-footer-content`)} />;
836
+ }
837
+ function StaticSection(props) {
838
+ const { className, header, children, footer } = props;
839
+ return <Section className={className}>
840
+ {header ? <SectionHeader className={className}>
841
+ <SectionHeaderContent className={className}>{header}</SectionHeaderContent>
842
+ </SectionHeader> : null}
843
+ <SectionBody className={className}>{children}</SectionBody>
844
+ {footer ? <SectionFooter className={className}>
845
+ <SectionFooterContent className={className}>{footer}</SectionFooterContent>
846
+ </SectionFooter> : null}
847
+ </Section>;
848
+ }
849
+
850
+ //#endregion
851
+ //#region src/translations/de.ts
852
+ const de = {
853
+ required: "Erforderlich",
854
+ deprecated: "Veraltet",
855
+ deprecated_and_sunset_on: "Diese Operation ist veraltet und wird am ${1} eingestellt.",
856
+ stability_experimental: "Experimentell",
857
+ stability_alpha: "Alpha",
858
+ stability_beta: "Beta",
859
+ discriminator: "Diskriminator",
860
+ copy_to_clipboard: "In die Zwischenablage kopieren",
861
+ copied: "Kopiert",
862
+ no_content: "Kein Inhalt",
863
+ unresolved_reference: "Nicht aufgelöste Referenz",
864
+ circular_reference: "Zirkuläre Referenz",
865
+ read_only: "Nur lesen",
866
+ write_only: "Nur schreiben",
867
+ optional: "Optional",
868
+ min: "Min",
869
+ max: "Max",
870
+ nullable: "Nullfähig",
871
+ body: "Rumpf",
872
+ payload: "Nutzlast",
873
+ headers: "Header",
874
+ header: "Header",
875
+ authorizations: "Autorisierungen",
876
+ responses: "Antworten",
877
+ response: "Antwort",
878
+ path_parameters: "Pfadparameter",
879
+ query_parameters: "Abfrageparameter",
880
+ header_parameters: "Header-Parameter",
881
+ attributes: "Attribute",
882
+ test_it: "Teste es",
883
+ information: "Information",
884
+ success: "Erfolg",
885
+ redirect: "Umleitung",
886
+ error: "Fehler",
887
+ show: "Zeige ${1}",
888
+ hide: "Verstecke ${1}",
889
+ available_items: "Verfügbare Elemente",
890
+ required_scopes: "Erforderliche Scopes",
891
+ properties: "Eigenschaften",
892
+ or: "oder",
893
+ and: "und",
894
+ possible_values: "Mögliche Werte"
895
+ };
896
+
897
+ //#endregion
898
+ //#region src/translations/en.ts
899
+ const en = {
900
+ required: "Required",
901
+ deprecated: "Deprecated",
902
+ deprecated_and_sunset_on: "This operation is deprecated and will be sunset on ${1}.",
903
+ stability_experimental: "Experimental",
904
+ stability_alpha: "Alpha",
905
+ stability_beta: "Beta",
906
+ discriminator: "Discriminator",
907
+ copy_to_clipboard: "Copy to clipboard",
908
+ copied: "Copied",
909
+ no_content: "No content",
910
+ unresolved_reference: "Unresolved reference",
911
+ circular_reference: "Circular reference",
912
+ read_only: "Read-only",
913
+ write_only: "Write-only",
914
+ optional: "Optional",
915
+ min: "Min",
916
+ max: "Max",
917
+ nullable: "Nullable",
918
+ body: "Body",
919
+ payload: "Payload",
920
+ headers: "Headers",
921
+ header: "Header",
922
+ authorizations: "Authorizations",
923
+ responses: "Responses",
924
+ response: "Response",
925
+ path_parameters: "Path parameters",
926
+ query_parameters: "Query parameters",
927
+ header_parameters: "Header parameters",
928
+ attributes: "Attributes",
929
+ test_it: "Test it",
930
+ information: "Information",
931
+ success: "Success",
932
+ redirect: "Redirect",
933
+ error: "Error",
934
+ show: "Show ${1}",
935
+ hide: "Hide ${1}",
936
+ available_items: "Available items",
937
+ required_scopes: "Required scopes",
938
+ possible_values: "Possible values",
939
+ properties: "Properties",
940
+ or: "or",
941
+ and: "and"
942
+ };
943
+
944
+ //#endregion
945
+ //#region src/translations/es.ts
946
+ const es = {
947
+ required: "Requerido",
948
+ deprecated: "Obsoleto",
949
+ deprecated_and_sunset_on: "Esta operación está obsoleta y se retirará el ${1}.",
950
+ stability_experimental: "Experimental",
951
+ stability_alpha: "Alfa",
952
+ stability_beta: "Beta",
953
+ discriminator: "Discriminador",
954
+ copy_to_clipboard: "Copiar al portapapeles",
955
+ copied: "Copiado",
956
+ no_content: "Sin contenido",
957
+ unresolved_reference: "Referencia no resuelta",
958
+ circular_reference: "Referencia circular",
959
+ read_only: "Solo lectura",
960
+ write_only: "Solo escritura",
961
+ optional: "Opcional",
962
+ min: "Mín",
963
+ max: "Máx",
964
+ nullable: "Nulo",
965
+ body: "Cuerpo",
966
+ payload: "Caga útil",
967
+ headers: "Headers",
968
+ header: "Header",
969
+ authorizations: "Autorizaciones",
970
+ responses: "Respuestas",
971
+ response: "Respuesta",
972
+ path_parameters: "Parámetros de ruta",
973
+ query_parameters: "Parámetros de consulta",
974
+ header_parameters: "Parámetros de encabezado",
975
+ attributes: "Atributos",
976
+ test_it: "Pruébalo",
977
+ information: "Información",
978
+ success: "Éxito",
979
+ redirect: "Redirección",
980
+ error: "Error",
981
+ show: "Mostrar ${1}",
982
+ hide: "Ocultar ${1}",
983
+ available_items: "Elementos disponibles",
984
+ required_scopes: "Scopes requeridos",
985
+ properties: "Propiedades",
986
+ or: "o",
987
+ and: "y",
988
+ possible_values: "Valores posibles"
989
+ };
990
+
991
+ //#endregion
992
+ //#region src/translations/fr.ts
993
+ const fr = {
994
+ required: "Requis",
995
+ deprecated: "Obsolète",
996
+ deprecated_and_sunset_on: "Cette opération est obsolète et sera supprimée le ${1}.",
997
+ stability_experimental: "Expérimental",
998
+ stability_alpha: "Alpha",
999
+ stability_beta: "Bêta",
1000
+ discriminator: "Discriminateur",
1001
+ copy_to_clipboard: "Copier dans le presse-papiers",
1002
+ copied: "Copié",
1003
+ no_content: "Aucun contenu",
1004
+ unresolved_reference: "Référence non résolue",
1005
+ circular_reference: "Référence circulaire",
1006
+ read_only: "Lecture seule",
1007
+ write_only: "Écriture seule",
1008
+ optional: "Optionnel",
1009
+ min: "Min",
1010
+ max: "Max",
1011
+ nullable: "Nullable",
1012
+ body: "Corps",
1013
+ payload: "Charge utile",
1014
+ headers: "Headers",
1015
+ header: "Header",
1016
+ authorizations: "Autorisations",
1017
+ responses: "Réponses",
1018
+ response: "Réponse",
1019
+ path_parameters: "Paramètres de chemin",
1020
+ query_parameters: "Paramètres de requête",
1021
+ header_parameters: "Paramètres d'en-tête",
1022
+ attributes: "Attributs",
1023
+ test_it: "Tester",
1024
+ information: "Information",
1025
+ success: "Succès",
1026
+ redirect: "Redirection",
1027
+ error: "Erreur",
1028
+ show: "Afficher ${1}",
1029
+ hide: "Masquer ${1}",
1030
+ available_items: "Éléments disponibles",
1031
+ required_scopes: "Scopes requis",
1032
+ properties: "Propriétés",
1033
+ or: "ou",
1034
+ and: "et",
1035
+ possible_values: "Valeurs possibles"
1036
+ };
1037
+
1038
+ //#endregion
1039
+ //#region src/translations/ja.ts
1040
+ const ja = {
1041
+ required: "必須",
1042
+ deprecated: "非推奨",
1043
+ deprecated_and_sunset_on: "この操作は非推奨であり、${1}に廃止されます。",
1044
+ stability_experimental: "実験的",
1045
+ stability_alpha: "アルファ",
1046
+ stability_beta: "ベータ",
1047
+ discriminator: "識別子",
1048
+ copy_to_clipboard: "クリップボードにコピー",
1049
+ copied: "コピー済み",
1050
+ no_content: "コンテンツなし",
1051
+ unresolved_reference: "未解決の参照",
1052
+ circular_reference: "循環参照",
1053
+ read_only: "読み取り専用",
1054
+ write_only: "書き込み専用",
1055
+ optional: "オプション",
1056
+ min: "最小",
1057
+ max: "最大",
1058
+ nullable: "ヌル許容",
1059
+ body: "本文",
1060
+ payload: "ペイロード",
1061
+ headers: "ヘッダー",
1062
+ header: "ヘッダー",
1063
+ authorizations: "認可",
1064
+ responses: "レスポンス",
1065
+ response: "レスポンス",
1066
+ path_parameters: "パスパラメータ",
1067
+ query_parameters: "クエリパラメータ",
1068
+ header_parameters: "ヘッダーパラメータ",
1069
+ attributes: "属性",
1070
+ test_it: "テストする",
1071
+ information: "情報",
1072
+ success: "成功",
1073
+ redirect: "リダイレクト",
1074
+ error: "エラー",
1075
+ show: "${1}を表示",
1076
+ hide: "${1}を非表示",
1077
+ available_items: "利用可能なアイテム",
1078
+ required_scopes: "必須スコープ",
1079
+ properties: "プロパティ",
1080
+ or: "または",
1081
+ and: "かつ",
1082
+ possible_values: "可能な値"
1083
+ };
1084
+
1085
+ //#endregion
1086
+ //#region src/translations/nl.ts
1087
+ const nl = {
1088
+ required: "Vereist",
1089
+ deprecated: "Verouderd",
1090
+ deprecated_and_sunset_on: "Deze bewerking is verouderd en wordt op ${1} beëindigd.",
1091
+ stability_experimental: "Experimenteel",
1092
+ stability_alpha: "Alfa",
1093
+ stability_beta: "Bèta",
1094
+ discriminator: "Discriminator",
1095
+ copy_to_clipboard: "Kopiëren naar klembord",
1096
+ copied: "Gekopieerd",
1097
+ no_content: "Geen inhoud",
1098
+ unresolved_reference: "Onopgeloste verwijzing",
1099
+ circular_reference: "Circulaire verwijzing",
1100
+ read_only: "Alleen lezen",
1101
+ write_only: "Alleen schrijven",
1102
+ optional: "Optioneel",
1103
+ min: "Min",
1104
+ max: "Max",
1105
+ nullable: "Null toegestaan",
1106
+ body: "Body",
1107
+ payload: "Payload",
1108
+ headers: "Headers",
1109
+ header: "Header",
1110
+ authorizations: "Autorisaties",
1111
+ responses: "Reacties",
1112
+ response: "Reactie",
1113
+ path_parameters: "Padparameters",
1114
+ query_parameters: "Queryparameters",
1115
+ header_parameters: "Headerparameters",
1116
+ attributes: "Attributen",
1117
+ test_it: "Test het",
1118
+ information: "Informatie",
1119
+ success: "Succes",
1120
+ redirect: "Omleiding",
1121
+ error: "Fout",
1122
+ show: "Toon ${1}",
1123
+ hide: "Verberg ${1}",
1124
+ available_items: "Beschikbare items",
1125
+ required_scopes: "Vereiste scopes",
1126
+ properties: "Eigenschappen",
1127
+ or: "of",
1128
+ and: "en",
1129
+ possible_values: "Mogelijke waarden"
1130
+ };
1131
+
1132
+ //#endregion
1133
+ //#region src/translations/no.ts
1134
+ const no = {
1135
+ required: "Påkrevd",
1136
+ deprecated: "Foreldet",
1137
+ deprecated_and_sunset_on: "Denne operasjonen er foreldet og vil bli avviklet den ${1}.",
1138
+ stability_experimental: "Eksperimentell",
1139
+ stability_alpha: "Alfa",
1140
+ stability_beta: "Beta",
1141
+ discriminator: "Diskriminator",
1142
+ copy_to_clipboard: "Kopier til utklippstavle",
1143
+ copied: "Kopiert",
1144
+ no_content: "Ingen innhold",
1145
+ unresolved_reference: "Uavklart referanse",
1146
+ circular_reference: "Sirkulær referanse",
1147
+ read_only: "Skrivebeskyttet",
1148
+ write_only: "Kun skriving",
1149
+ optional: "Valgfri",
1150
+ min: "Min",
1151
+ max: "Maks",
1152
+ nullable: "Kan være null",
1153
+ body: "Brødtekst",
1154
+ payload: "Nyttelast",
1155
+ headers: "Headers",
1156
+ header: "Header",
1157
+ authorizations: "Autorisasjoner",
1158
+ responses: "Responser",
1159
+ response: "Respons",
1160
+ path_parameters: "Sti-parametere",
1161
+ query_parameters: "Forespørselsparametere",
1162
+ header_parameters: "Header-parametere",
1163
+ attributes: "Attributter",
1164
+ test_it: "Test det",
1165
+ information: "Informasjon",
1166
+ success: "Suksess",
1167
+ redirect: "Viderekobling",
1168
+ error: "Feil",
1169
+ show: "Vis ${1}",
1170
+ hide: "Skjul ${1}",
1171
+ available_items: "Tilgjengelige elementer",
1172
+ required_scopes: "Påkrevde scopes",
1173
+ properties: "Egenskaper",
1174
+ or: "eller",
1175
+ and: "og",
1176
+ possible_values: "Mulige verdier"
1177
+ };
1178
+
1179
+ //#endregion
1180
+ //#region src/translations/pt-br.ts
1181
+ const pt_br = {
1182
+ required: "Obrigatório",
1183
+ deprecated: "Obsoleto",
1184
+ deprecated_and_sunset_on: "Esta operação está obsoleta e será descontinuada em ${1}.",
1185
+ stability_experimental: "Experimental",
1186
+ stability_alpha: "Alfa",
1187
+ stability_beta: "Beta",
1188
+ discriminator: "Discriminador",
1189
+ copy_to_clipboard: "Copiar para a área de transferência",
1190
+ copied: "Copiado",
1191
+ no_content: "Sem conteúdo",
1192
+ unresolved_reference: "Referência não resolvida",
1193
+ circular_reference: "Referência circular",
1194
+ read_only: "Somente leitura",
1195
+ write_only: "Somente escrita",
1196
+ optional: "Opcional",
1197
+ min: "Mín",
1198
+ max: "Máx",
1199
+ nullable: "Nulo",
1200
+ body: "Corpo",
1201
+ payload: "Carga útil",
1202
+ headers: "Headers",
1203
+ header: "Header",
1204
+ authorizations: "Autorizações",
1205
+ responses: "Respostas",
1206
+ response: "Resposta",
1207
+ path_parameters: "Parâmetros de rota",
1208
+ query_parameters: "Parâmetros de consulta",
1209
+ header_parameters: "Parâmetros de cabeçalho",
1210
+ attributes: "Atributos",
1211
+ test_it: "Testar",
1212
+ information: "Informação",
1213
+ success: "Sucesso",
1214
+ redirect: "Redirecionamento",
1215
+ error: "Erro",
1216
+ show: "Mostrar ${1}",
1217
+ hide: "Ocultar ${1}",
1218
+ available_items: "Itens disponíveis",
1219
+ required_scopes: "Scopes obrigatórios",
1220
+ properties: "Propriedades",
1221
+ or: "ou",
1222
+ and: "e",
1223
+ possible_values: "Valores possíveis"
1224
+ };
1225
+
1226
+ //#endregion
1227
+ //#region src/translations/zh.ts
1228
+ const zh = {
1229
+ required: "必填",
1230
+ deprecated: "已弃用",
1231
+ deprecated_and_sunset_on: "此操作已弃用,将于 ${1} 停止使用。",
1232
+ stability_experimental: "实验性",
1233
+ stability_alpha: "Alpha",
1234
+ stability_beta: "Beta",
1235
+ discriminator: "判别器",
1236
+ copy_to_clipboard: "复制到剪贴板",
1237
+ copied: "已复制",
1238
+ no_content: "无内容",
1239
+ unresolved_reference: "未解析的引用",
1240
+ circular_reference: "循环引用",
1241
+ read_only: "只读",
1242
+ write_only: "只写",
1243
+ optional: "可选",
1244
+ min: "最小值",
1245
+ max: "最大值",
1246
+ nullable: "可为 null",
1247
+ body: "请求体",
1248
+ payload: "有效载荷",
1249
+ headers: "头字段",
1250
+ header: "头部",
1251
+ authorizations: "授权",
1252
+ responses: "响应",
1253
+ response: "响应",
1254
+ path_parameters: "路径参数",
1255
+ query_parameters: "查询参数",
1256
+ header_parameters: "头参数",
1257
+ attributes: "属性",
1258
+ test_it: "测试一下",
1259
+ information: "信息",
1260
+ success: "成功",
1261
+ redirect: "重定向",
1262
+ error: "错误",
1263
+ show: "显示${1}",
1264
+ hide: "隐藏${1}",
1265
+ available_items: "可用项",
1266
+ required_scopes: "必需范围",
1267
+ properties: "属性",
1268
+ or: "或",
1269
+ and: "和",
1270
+ possible_values: "可能的值"
1271
+ };
1272
+
1273
+ //#endregion
1274
+ //#region src/translations/index.ts
1275
+ const translations = {
1276
+ en,
1277
+ de,
1278
+ es,
1279
+ fr,
1280
+ ja,
1281
+ nl,
1282
+ no,
1283
+ "pt-br": pt_br,
1284
+ zh
1285
+ };
1286
+ /**
1287
+ * Check if the locale is valid.
1288
+ */
1289
+ function checkIsValidLocale(locale) {
1290
+ return Object.prototype.hasOwnProperty.call(translations, locale);
1291
+ }
1292
+
1293
+ //#endregion
1294
+ //#region src/context.ts
1295
+ /**
1296
+ * Resolve OpenAPI context from the input.
1297
+ */
1298
+ function resolveOpenAPIContext(context) {
1299
+ const { locale,...rest } = context;
1300
+ return {
1301
+ ...rest,
1302
+ translation: translations[locale ?? "en"]
1303
+ };
1304
+ }
1305
+ /**
1306
+ * Get the client context from the OpenAPI context.
1307
+ */
1308
+ function getOpenAPIClientContext(context) {
1309
+ return {
1310
+ translation: context.translation,
1311
+ icons: context.icons,
1312
+ defaultInteractiveOpened: context.defaultInteractiveOpened,
1313
+ blockKey: context.blockKey,
1314
+ id: context.id,
1315
+ $$isClientContext$$: true
1316
+ };
1317
+ }
1318
+
1319
+ //#endregion
1320
+ //#region src/generateSchemaExample.ts
1321
+ /**
1322
+ * Generate a JSON example from a schema
1323
+ */
1324
+ function generateSchemaExample(schema, options) {
1325
+ return getExampleFromSchema$1(schema, {
1326
+ emptyString: "text",
1327
+ ...options
1328
+ });
1329
+ }
1330
+ /**
1331
+ * Generate an example for a media type.
1332
+ */
1333
+ function generateMediaTypeExamples(mediaType, options) {
1334
+ if (mediaType.example) return [{
1335
+ summary: "default",
1336
+ value: mediaType.example
1337
+ }];
1338
+ if (mediaType.examples) {
1339
+ const { examples } = mediaType;
1340
+ const keys = Object.keys(examples);
1341
+ if (keys.length > 0) return keys.reduce((result, key) => {
1342
+ const example = examples[key];
1343
+ if (!example || checkIsReference(example)) return result;
1344
+ result.push({
1345
+ summary: example.summary || key,
1346
+ value: example.value,
1347
+ description: example.description,
1348
+ externalValue: example.externalValue
1349
+ });
1350
+ return result;
1351
+ }, []);
1352
+ }
1353
+ if (mediaType.schema) return [{
1354
+ summary: "default",
1355
+ value: generateSchemaExample(mediaType.schema, options)
1356
+ }];
1357
+ return [];
1358
+ }
1359
+ /** Hard limit for rendering circular references */
1360
+ const MAX_LEVELS_DEEP = 5;
1361
+ const genericExampleValues = {
1362
+ "date-time": (/* @__PURE__ */ new Date()).toISOString(),
1363
+ date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? "1970-01-01",
1364
+ email: "name@gmail.com",
1365
+ hostname: "example.com",
1366
+ ipv4: "0.0.0.0",
1367
+ ipv6: "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
1368
+ uri: "https://example.com",
1369
+ uuid: "123e4567-e89b-12d3-a456-426614174000",
1370
+ binary: "binary",
1371
+ byte: "Ynl0ZXM=",
1372
+ password: "password",
1373
+ "idn-email": "jane.doe@example.com",
1374
+ "idn-hostname": "example.com",
1375
+ "iri-reference": "/entitiy/1",
1376
+ iri: "https://example.com/entity/123",
1377
+ "json-pointer": "/nested/objects",
1378
+ regex: "/[a-z]/",
1379
+ "relative-json-pointer": "1/nested/objects",
1380
+ time: (/* @__PURE__ */ new Date()).toISOString().split("T")[1]?.split(".")[0] ?? "00:00:00Z",
1381
+ "uri-reference": "../folder",
1382
+ "uri-template": "https://example.com/{id}",
1383
+ "object-id": "6592008029c8c3e4dc76256c"
1384
+ };
1385
+ /**
1386
+ * We can use the `format` to generate some random values.
1387
+ */
1388
+ function guessFromFormat(schema, fallback = "") {
1389
+ return genericExampleValues[schema.format] ?? fallback;
1390
+ }
1391
+ /**
1392
+ * This function takes an OpenAPI schema and generates an example from it
1393
+ * Forked from : https://github.com/scalar/scalar/blob/main/packages/oas-utils/src/spec-getters/getExampleFromSchema.ts
1394
+ */
1395
+ const getExampleFromSchema$1 = (schema, options, level = 0, parentSchema, name, resultCache = /* @__PURE__ */ new WeakMap()) => {
1396
+ function cache(schema$1, result) {
1397
+ if (typeof result !== "object" || result === null) return result;
1398
+ resultCache.set(schema$1, result);
1399
+ return result;
1400
+ }
1401
+ if (resultCache.has(schema)) return resultCache.get(schema);
1402
+ if (level === MAX_LEVELS_DEEP + 1) try {
1403
+ JSON.stringify(schema);
1404
+ } catch {
1405
+ return "[Circular Reference]";
1406
+ }
1407
+ const makeUpRandomData = !!options?.emptyString;
1408
+ if (schema.deprecated || schema.type === "array" && schema.items?.deprecated) return;
1409
+ if (options?.mode === "write" && schema.readOnly || options?.mode === "read" && schema.writeOnly) return;
1410
+ if (schema["x-variable"]) {
1411
+ const value = options?.variables?.[schema["x-variable"]];
1412
+ if (value !== void 0) {
1413
+ if (schema.type === "number" || schema.type === "integer") return Number.parseInt(value, 10);
1414
+ return cache(schema, value);
1415
+ }
1416
+ }
1417
+ if (Array.isArray(schema.examples) && schema.examples.length > 0) return cache(schema, schema.examples[0]);
1418
+ if (schema.example !== void 0) return cache(schema, schema.example);
1419
+ if (schema.default !== void 0 && [
1420
+ "string",
1421
+ "number",
1422
+ "boolean"
1423
+ ].includes(typeof schema.default)) return cache(schema, schema.default);
1424
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) return cache(schema, schema.enum[0]);
1425
+ if (!(schema.type === "object" || schema.type === "array" || !!schema.allOf?.at?.(0) || !!schema.anyOf?.at?.(0) || !!schema.oneOf?.at?.(0)) && options?.omitEmptyAndOptionalProperties === true) {
1426
+ if (!(schema.required === true || parentSchema?.required === true || parentSchema?.required?.includes(name ?? schema.name))) return;
1427
+ }
1428
+ if (schema.type === "object" || schema.properties !== void 0) {
1429
+ const response = {};
1430
+ if (schema.properties !== void 0) {
1431
+ for (const propertyName in schema.properties) if (Object.prototype.hasOwnProperty.call(schema.properties, propertyName)) {
1432
+ const property = schema.properties[propertyName];
1433
+ const propertyXmlTagName = options?.xml ? property.xml?.name : void 0;
1434
+ response[propertyXmlTagName ?? propertyName] = getExampleFromSchema$1(property, options, level + 1, schema, propertyName, resultCache);
1435
+ if (typeof response[propertyXmlTagName ?? propertyName] === "undefined") delete response[propertyXmlTagName ?? propertyName];
1436
+ }
1437
+ }
1438
+ if (schema.patternProperties !== void 0) {
1439
+ for (const pattern in schema.patternProperties) if (Object.prototype.hasOwnProperty.call(schema.patternProperties, pattern)) {
1440
+ const property = schema.patternProperties[pattern];
1441
+ const exampleKey = pattern;
1442
+ response[exampleKey] = getExampleFromSchema$1(property, options, level + 1, schema, exampleKey, resultCache);
1443
+ }
1444
+ }
1445
+ if (schema.additionalProperties !== void 0) {
1446
+ if (schema.additionalProperties === true || typeof schema.additionalProperties === "object" && !Object.keys(schema.additionalProperties).length) response.ANY_ADDITIONAL_PROPERTY = "anything";
1447
+ else if (schema.additionalProperties !== false) response.ANY_ADDITIONAL_PROPERTY = getExampleFromSchema$1(schema.additionalProperties, options, level + 1, void 0, void 0, resultCache);
1448
+ }
1449
+ if (schema.anyOf !== void 0) Object.assign(response, getExampleFromSchema$1(schema.anyOf[0], options, level + 1, void 0, void 0, resultCache));
1450
+ else if (schema.oneOf !== void 0) Object.assign(response, getExampleFromSchema$1(schema.oneOf[0], options, level + 1, void 0, void 0, resultCache));
1451
+ else if (schema.allOf !== void 0) Object.assign(response, ...schema.allOf.map((item) => getExampleFromSchema$1(item, options, level + 1, schema, void 0, resultCache)).filter((item) => item !== void 0));
1452
+ return cache(schema, response);
1453
+ }
1454
+ if (schema.type === "array" || schema.items !== void 0) {
1455
+ const itemsXmlTagName = schema?.items?.xml?.name;
1456
+ const wrapItems = !!(options?.xml && schema.xml?.wrapped && itemsXmlTagName);
1457
+ if (schema.example !== void 0) return cache(schema, wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example);
1458
+ if (schema.items) {
1459
+ if (schema.items.allOf) {
1460
+ if (schema.items.allOf[0].type === "object") {
1461
+ const mergedExample = getExampleFromSchema$1({
1462
+ type: "object",
1463
+ allOf: schema.items.allOf
1464
+ }, options, level + 1, schema, void 0, resultCache);
1465
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: mergedExample }] : [mergedExample]);
1466
+ }
1467
+ const examples = schema.items.allOf.map((item) => getExampleFromSchema$1(item, options, level + 1, schema, void 0, resultCache)).filter((item) => item !== void 0);
1468
+ return cache(schema, wrapItems ? examples.map((example) => ({ [itemsXmlTagName]: example })) : examples);
1469
+ }
1470
+ for (const rule of ["anyOf", "oneOf"]) {
1471
+ if (!schema.items[rule]) continue;
1472
+ const exampleFromRule = schema.items[rule].slice(0, 1).map((item) => getExampleFromSchema$1(item, options, level + 1, schema, void 0, resultCache)).filter((item) => item !== void 0);
1473
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: exampleFromRule }] : exampleFromRule);
1474
+ }
1475
+ }
1476
+ if (schema.items?.type) {
1477
+ const exampleFromSchema = getExampleFromSchema$1(schema.items, options, level + 1, void 0, void 0, resultCache);
1478
+ return wrapItems ? [{ [itemsXmlTagName]: exampleFromSchema }] : [exampleFromSchema];
1479
+ }
1480
+ return [];
1481
+ }
1482
+ const exampleValues = {
1483
+ string: makeUpRandomData ? guessFromFormat(schema, options?.emptyString) : "",
1484
+ boolean: true,
1485
+ integer: schema.min ?? 1,
1486
+ number: schema.min ?? 1,
1487
+ array: []
1488
+ };
1489
+ if (schema.type !== void 0 && exampleValues[schema.type] !== void 0) return cache(schema, exampleValues[schema.type]);
1490
+ const discriminateSchema = schema.oneOf || schema.anyOf;
1491
+ if (Array.isArray(discriminateSchema) && discriminateSchema.length > 0) {
1492
+ const firstOneOfItem = discriminateSchema[0];
1493
+ return getExampleFromSchema$1(firstOneOfItem, options, level + 1, void 0, void 0, resultCache);
1494
+ }
1495
+ if (Array.isArray(schema.allOf)) {
1496
+ let example = null;
1497
+ schema.allOf.forEach((allOfItem) => {
1498
+ const newExample = getExampleFromSchema$1(allOfItem, options, level + 1, void 0, void 0, resultCache);
1499
+ example = typeof newExample === "object" && typeof example === "object" ? {
1500
+ ...example ?? {},
1501
+ ...newExample
1502
+ } : Array.isArray(newExample) && Array.isArray(example) ? [...example ?? {}, ...newExample] : newExample;
1503
+ });
1504
+ return cache(schema, example);
1505
+ }
1506
+ if (Array.isArray(schema.type)) {
1507
+ if (schema.type.includes("null")) return null;
1508
+ const exampleValue = exampleValues[schema.type[0]];
1509
+ if (exampleValue !== void 0) return cache(schema, exampleValue);
1510
+ }
1511
+ return null;
1512
+ };
1513
+
1514
+ //#endregion
1515
+ //#region src/util/example.tsx
1516
+ /**
1517
+ * Generate an example from a reference object.
1518
+ */
1519
+ function getExampleFromReference(ref, context) {
1520
+ return {
1521
+ summary: tString(context.translation, "unresolved_reference"),
1522
+ value: { $ref: ref.$ref }
1523
+ };
1524
+ }
1525
+ /**
1526
+ * Get examples from a media type object.
1527
+ */
1528
+ function getExamplesFromMediaTypeObject(args) {
1529
+ const { mediaTypeObject, mediaType, context } = args;
1530
+ if (mediaTypeObject.examples) return Object.entries(mediaTypeObject.examples).map(([key, example]) => {
1531
+ return {
1532
+ key,
1533
+ example: checkIsReference(example) ? getExampleFromReference(example, context) : example
1534
+ };
1535
+ });
1536
+ if (mediaTypeObject.example) return [{
1537
+ key: "default",
1538
+ example: { value: mediaTypeObject.example }
1539
+ }];
1540
+ if (mediaTypeObject.schema) {
1541
+ if (mediaType === "application/xml") return [{
1542
+ key: "default",
1543
+ example: { value: { [mediaTypeObject.schema.xml?.name ?? "object"]: generateSchemaExample(mediaTypeObject.schema, {
1544
+ xml: mediaType === "application/xml",
1545
+ mode: "read"
1546
+ }) } }
1547
+ }];
1548
+ return [{
1549
+ key: "default",
1550
+ example: { value: generateSchemaExample(mediaTypeObject.schema, { mode: "read" }) }
1551
+ }];
1552
+ }
1553
+ return [];
1554
+ }
1555
+ /**
1556
+ * Get example from a schema object.
1557
+ */
1558
+ function getExampleFromSchema(args) {
1559
+ const { schema } = args;
1560
+ if (schema.example) return { value: schema.example };
1561
+ return { value: generateSchemaExample(schema, { mode: "read" }) };
1562
+ }
1563
+ /**
1564
+ * Get the examples from a media type object.
1565
+ */
1566
+ function getExamples(props) {
1567
+ const { mediaTypeObject, mediaType, context } = props;
1568
+ const examples = getExamplesFromMediaTypeObject({
1569
+ mediaTypeObject,
1570
+ mediaType,
1571
+ context
1572
+ });
1573
+ const syntax = getSyntaxFromMediaType(mediaType);
1574
+ return examples.map((example) => {
1575
+ return {
1576
+ key: example.key,
1577
+ label: example.example.summary || example.key,
1578
+ body: <OpenAPIExample example={example.example} context={props.context} syntax={syntax} />
1579
+ };
1580
+ });
1581
+ }
1582
+ /**
1583
+ * Get the syntax from a media type.
1584
+ */
1585
+ function getSyntaxFromMediaType(mediaType) {
1586
+ if (mediaType.includes("json")) return "json";
1587
+ if (mediaType.includes("yaml")) return "yaml";
1588
+ if (mediaType === "application/xml") return "xml";
1589
+ return "text";
1590
+ }
1591
+
1592
+ //#endregion
1593
+ //#region src/schemas/OpenAPISchemaItem.tsx
1594
+ function OpenAPISchemaItem(props) {
1595
+ const { schema, context, name } = props;
1596
+ return <OpenAPIDisclosure className="openapi-schemas-disclosure" key={name} icon={context.icons.plus} header={name} label={(isExpanded) => getDisclosureLabel({
1597
+ schema,
1598
+ isExpanded,
1599
+ context
1600
+ })}>
1601
+ <Section className="openapi-section-schemas">
1602
+ <SectionBody>
1603
+ <OpenAPIRootSchema schema={schema} context={context} />
1604
+ </SectionBody>
1605
+ </Section>
1606
+ </OpenAPIDisclosure>;
1607
+ }
1608
+
1609
+ //#endregion
1610
+ //#region src/schemas/OpenAPISchemas.tsx
1611
+ /**
1612
+ * OpenAPI Schemas component.
1613
+ */
1614
+ function OpenAPISchemas(props) {
1615
+ const { schemas, context: contextInput, grouped, className } = props;
1616
+ const firstSchema = schemas[0];
1617
+ if (!firstSchema) return null;
1618
+ const context = resolveOpenAPIContext(contextInput);
1619
+ const clientContext = getOpenAPIClientContext(context);
1620
+ if (schemas.length === 1 && !grouped) {
1621
+ const title = `The ${firstSchema.name} object`;
1622
+ return <div className={clsx("openapi-schemas", className)}>
1623
+ <div className="openapi-summary" id={context.id}>
1624
+ {context.renderHeading({
1625
+ title,
1626
+ deprecated: Boolean(firstSchema.schema.deprecated),
1627
+ stability: firstSchema.schema["x-stability"]
1628
+ })}
1629
+ </div>
1630
+ <div className="openapi-columns">
1631
+ <div className="openapi-column-spec">
1632
+ <StaticSection className="openapi-parameters" header={t(context.translation, "attributes")}>
1633
+ <OpenAPIRootSchema schema={firstSchema.schema} context={clientContext} />
1634
+ </StaticSection>
1635
+ </div>
1636
+ <div className="openapi-column-preview">
1637
+ <div className="openapi-column-preview-body">
1638
+ <div className="openapi-panel">
1639
+ <h4 className="openapi-panel-heading">{title}</h4>
1640
+ <div className="openapi-panel-body">
1641
+ <OpenAPIExample example={getExampleFromSchema({ schema: firstSchema.schema })} context={context} syntax="json" />
1642
+ </div>
1643
+ </div>
1644
+ </div>
1645
+ </div>
1646
+ </div>
1647
+ </div>;
1648
+ }
1649
+ return <div className={clsx("openapi-schemas", className)}>
1650
+ {schemas.map(({ name, schema }) => {
1651
+ return <OpenAPISchemaItem key={name} name={name} context={clientContext} schema={schema} />;
1652
+ })}
1653
+ </div>;
1654
+ }
1655
+
1656
+ //#endregion
1657
+ //#region src/dereference.ts
1658
+ const dereferenceCache = /* @__PURE__ */ new WeakMap();
1659
+ /**
1660
+ * Memoized version of `dereferenceSchema`.
1661
+ */
1662
+ function dereferenceFilesystem(filesystem) {
1663
+ if (dereferenceCache.has(filesystem)) return dereferenceCache.get(filesystem);
1664
+ const promise = baseDereferenceFilesystem(filesystem);
1665
+ dereferenceCache.set(filesystem, promise);
1666
+ return promise;
1667
+ }
1668
+ /**
1669
+ * Dereference an OpenAPI schema.
1670
+ */
1671
+ async function baseDereferenceFilesystem(filesystem) {
1672
+ const result = await dereference(filesystem);
1673
+ if (!result.schema) throw new Error("Failed to dereference OpenAPI document");
1674
+ return result.schema;
1675
+ }
1676
+
1677
+ //#endregion
1678
+ //#region src/schemas/resolveOpenAPISchemas.ts
1679
+ /**
1680
+ * Resolve an OpenAPI schemas from a file and compile it to a more usable format.
1681
+ * Schemas are extracted from the OpenAPI components.schemas
1682
+ */
1683
+ async function resolveOpenAPISchemas(filesystem, options) {
1684
+ const { schemas: selectedSchemas } = options;
1685
+ const schemas = filterSelectedOpenAPISchemas(await dereferenceFilesystem(filesystem), selectedSchemas);
1686
+ if (schemas.length === 0) return null;
1687
+ return { schemas };
1688
+ }
1689
+
1690
+ //#endregion
1691
+ //#region src/getOrCreateStoreByKey.ts
1692
+ const createStateStore = (initial) => {
1693
+ return createStore()((set) => ({
1694
+ key: initial ?? null,
1695
+ setKey: (key) => {
1696
+ set(() => ({ key }));
1697
+ }
1698
+ }));
1699
+ };
1700
+ const defaultStores = /* @__PURE__ */ new Map();
1701
+ const createStateStoreFactory = (stores) => {
1702
+ return (storeKey, initialKey) => {
1703
+ if (!stores.has(storeKey)) stores.set(storeKey, createStateStore(initialKey));
1704
+ return stores.get(storeKey);
1705
+ };
1706
+ };
1707
+ const getOrCreateStoreByKey = createStateStoreFactory(defaultStores);
1708
+
1709
+ //#endregion
1710
+ //#region src/OpenAPISelect.tsx
1711
+ function useSelectState(stateKey = "select-state", initialKey = "default") {
1712
+ const store = useStore(getOrCreateStoreByKey(stateKey, initialKey));
1713
+ return {
1714
+ key: store.key,
1715
+ setKey: useCallback((key) => store.setKey(key), [store.setKey])
1716
+ };
1717
+ }
1718
+ function OpenAPISelect(props) {
1719
+ const { icon = "▼", items, children, className, placement, stateKey, selectedKey, onSelectionChange } = props;
1720
+ const state = useSelectState(stateKey, items[0]?.key);
1721
+ const selected = items.find((item) => item.key === state.key) || items[0];
1722
+ return <Select aria-label="OpenAPI Select" {...props} selectedKey={selectedKey || selected?.key} onSelectionChange={(key) => {
1723
+ onSelectionChange?.(key);
1724
+ state.setKey(key);
1725
+ }} className={clsx("openapi-select", className)}>
1726
+ <Button>
1727
+ <SelectValue />
1728
+ {icon}
1729
+ </Button>
1730
+ <Popover placement={placement} className="openapi-select-popover">
1731
+ <ListBox className="openapi-select-listbox" items={items}>
1732
+ {children}
1733
+ </ListBox>
1734
+ </Popover>
1735
+ </Select>;
1736
+ }
1737
+ function OpenAPISelectItem(props) {
1738
+ return <ListBoxItem {...props} className={({ isFocused, isSelected }) => clsx("openapi-select-item", {
1739
+ "openapi-select-item-focused": isFocused,
1740
+ "openapi-select-item-selected": isSelected
1741
+ })} />;
1742
+ }
1743
+
1744
+ //#endregion
1745
+ //#region src/OpenAPICodeSampleInteractive.tsx
1746
+ function OpenAPIMediaTypeExamplesSelector(props) {
1747
+ const { method, path, renderers, selectIcon, blockKey } = props;
1748
+ if (!renderers[0]) throw new Error("No renderers provided");
1749
+ const stateKey = createStateKey("request-body-media-type", blockKey);
1750
+ const state = useSelectState(stateKey, renderers[0].mediaType);
1751
+ const selected = renderers.find((r) => r.mediaType === state.key) || renderers[0];
1752
+ return <div className="openapi-codesample-selectors">
1753
+ <MediaTypeSelector selectIcon={selectIcon} stateKey={stateKey} renderers={renderers} />
1754
+ <ExamplesSelector selectIcon={selectIcon} method={method} path={path} renderer={selected} />
1755
+ </div>;
1756
+ }
1757
+ function MediaTypeSelector(props) {
1758
+ const { renderers, stateKey, selectIcon } = props;
1759
+ if (renderers.length < 2) return null;
1760
+ const items = renderers.map((renderer) => ({
1761
+ key: renderer.mediaType,
1762
+ label: renderer.mediaType
1763
+ }));
1764
+ return <OpenAPISelect className={clsx("openapi-select")} items={renderers.map((renderer) => ({
1765
+ key: renderer.mediaType,
1766
+ label: renderer.mediaType
1767
+ }))} icon={selectIcon} stateKey={stateKey} placement="bottom start">
1768
+ {items.map((item) => <OpenAPISelectItem key={item.key} id={item.key} value={item}>
1769
+ {item.label}
1770
+ </OpenAPISelectItem>)}
1771
+ </OpenAPISelect>;
1772
+ }
1773
+ function ExamplesSelector(props) {
1774
+ const { method, path, renderer, selectIcon } = props;
1775
+ if (renderer.examples.length < 2) return null;
1776
+ const items = renderer.examples.map((example, index) => ({
1777
+ key: index,
1778
+ label: example.example.summary || `Example ${index + 1}`
1779
+ }));
1780
+ return <OpenAPISelect items={items} icon={selectIcon} stateKey={`media-type-sample-${renderer.mediaType}-${method}-${path}`} placement="bottom start">
1781
+ {items.map((item) => <OpenAPISelectItem key={item.key} id={item.key} value={item}>
1782
+ {item.label}
1783
+ </OpenAPISelectItem>)}
1784
+ </OpenAPISelect>;
1785
+ }
1786
+ function OpenAPIMediaTypeExamplesBody(props) {
1787
+ const { renderers, method, path, blockKey } = props;
1788
+ if (!renderers[0]) throw new Error("No renderers provided");
1789
+ const mediaTypeState = useSelectState(createStateKey("request-body-media-type", blockKey), renderers[0].mediaType);
1790
+ const selected = renderers.find((r) => r.mediaType === mediaTypeState.key) ?? renderers[0];
1791
+ if (selected.examples.length === 0) return selected.element;
1792
+ return <ExamplesBody method={method} path={path} renderer={selected} />;
1793
+ }
1794
+ function ExamplesBody(props) {
1795
+ const { method, path, renderer } = props;
1796
+ const exampleState = useSelectState(`media-type-sample-${renderer.mediaType}-${method}-${path}`, renderer.mediaType);
1797
+ const example = renderer.examples[Number(exampleState.key)] ?? renderer.examples[0];
1798
+ if (!example) throw new Error(`No example found for key ${exampleState.key}`);
1799
+ return example.element;
1800
+ }
1801
+
1802
+ //#endregion
1803
+ //#region src/util/server.ts
1804
+ /**
1805
+ * Get the default URL for the server.
1806
+ */
1807
+ function getDefaultServerURL(servers) {
1808
+ const server = servers[0];
1809
+ if (!server) return "";
1810
+ return interpolateServerURL(server);
1811
+ }
1812
+ /**
1813
+ * Interpolate the server URL with the default values of the variables.
1814
+ */
1815
+ function interpolateServerURL(server) {
1816
+ return parseServerURL(server?.url ?? "").map((part) => {
1817
+ if (part.kind === "text") return part.text;
1818
+ return server.variables?.[part.name]?.default ?? `{${part.name}}`;
1819
+ }).join("");
1820
+ }
1821
+ function parseServerURL(url) {
1822
+ const parts = url.split(/{([^}]+)}/g);
1823
+ const result = [];
1824
+ for (let i = 0; i < parts.length; i++) {
1825
+ const part = parts[i];
1826
+ if (!part) continue;
1827
+ if (i % 2 === 0) result.push({
1828
+ kind: "text",
1829
+ text: part
1830
+ });
1831
+ else result.push({
1832
+ kind: "variable",
1833
+ name: part
1834
+ });
1835
+ }
1836
+ return result;
1837
+ }
1838
+
1839
+ //#endregion
1840
+ //#region src/OpenAPIPath.tsx
1841
+ /**
1842
+ * Display the path of an operation.
1843
+ */
1844
+ function OpenAPIPath(props) {
1845
+ const { data, context, withServer = true, canCopy = true } = props;
1846
+ const { method, path, operation } = data;
1847
+ const server = getDefaultServerURL(data.servers);
1848
+ const formattedPath = formatPath(path);
1849
+ const element = (() => {
1850
+ return <>
1851
+ {withServer ? <span className="openapi-path-server">{server}</span> : null}
1852
+ {formattedPath}
1853
+ </>;
1854
+ })();
1855
+ return <div className="openapi-path">
1856
+ <div className={`openapi-method openapi-method-${method}`}>{method}</div>
1857
+
1858
+ <OpenAPICopyButton value={`${withServer ? server : ""}${path}`} className="openapi-path-title" data-deprecated={operation.deprecated} isDisabled={!canCopy} context={getOpenAPIClientContext(context)}>
1859
+ {element}
1860
+ </OpenAPICopyButton>
1861
+ </div>;
1862
+ }
1863
+ /**
1864
+ * Format the path by wrapping placeholders in <span> tags.
1865
+ */
1866
+ function formatPath(path) {
1867
+ const regex = /\{\s*(\w+)\s*\}|:\w+/g;
1868
+ const parts = [];
1869
+ let lastIndex = 0;
1870
+ path.replace(regex, (match, _, offset) => {
1871
+ if (offset > lastIndex) parts.push(path.slice(lastIndex, offset));
1872
+ parts.push(<span key={`offset-${offset}`} className="openapi-path-variable">
1873
+ {match}
1874
+ </span>);
1875
+ lastIndex = offset + match.length;
1876
+ return match;
1877
+ });
1878
+ if (lastIndex < path.length) parts.push(path.slice(lastIndex));
1879
+ return parts.map((part, index) => {
1880
+ if (typeof part === "string") return <span key={`part-${index}`}>{part}</span>;
1881
+ return part;
1882
+ });
1883
+ }
1884
+
1885
+ //#endregion
1886
+ //#region src/OpenAPICodeSampleSelector.tsx
1887
+ function useCodeSampleState(initialKey = "default") {
1888
+ const store = useStore(getOrCreateStoreByKey("codesample", initialKey));
1889
+ return {
1890
+ key: store.key,
1891
+ setKey: useCallback((key) => store.setKey(key), [store.setKey])
1892
+ };
1893
+ }
1894
+ function OpenAPICodeSampleHeader(props) {
1895
+ const { data, items, selectIcon, context } = props;
1896
+ return <>
1897
+ <OpenAPIPath context={context} canCopy={false} withServer={false} data={data} />
1898
+ {items.length > 1 ? <OpenAPISelect icon={selectIcon} items={items} stateKey="codesample" placement="bottom end">
1899
+ {items.map((item) => <OpenAPISelectItem key={item.key} id={item.key} value={item}>
1900
+ {item.label}
1901
+ </OpenAPISelectItem>)}
1902
+ </OpenAPISelect> : items[0] ? <span className="openapi-codesample-label">{items[0].label}</span> : null}
1903
+ </>;
1904
+ }
1905
+ function OpenAPICodeSampleBody(props) {
1906
+ const { items, data, selectIcon, context } = props;
1907
+ if (!items[0]) throw new Error("No items provided");
1908
+ const state = useCodeSampleState(items[0]?.key);
1909
+ const selected = items.find((item) => item.key === state.key) || items[0];
1910
+ if (!selected) return null;
1911
+ return <StaticSection header={<OpenAPICodeSampleHeader context={context} selectIcon={selectIcon} data={data} items={items} />} className="openapi-codesample">
1912
+ <div id={selected.key} className="openapi-codesample-panel">
1913
+ {selected.body ? selected.body : null}
1914
+ {selected.footer ? selected.footer : null}
1915
+ </div>
1916
+ </StaticSection>;
1917
+ }
1918
+
1919
+ //#endregion
1920
+ //#region ../../node_modules/react-dom/cjs/react-dom.production.js
1921
+ var require_react_dom_production = /* @__PURE__ */ __commonJS({ "../../node_modules/react-dom/cjs/react-dom.production.js": ((exports) => {
1922
+ var React$2 = __require("react");
1923
+ function formatProdErrorMessage(code) {
1924
+ var url = "https://react.dev/errors/" + code;
1925
+ if (1 < arguments.length) {
1926
+ url += "?args[]=" + encodeURIComponent(arguments[1]);
1927
+ for (var i = 2; i < arguments.length; i++) url += "&args[]=" + encodeURIComponent(arguments[i]);
1928
+ }
1929
+ return "Minified React error #" + code + "; visit " + url + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";
1930
+ }
1931
+ function noop() {}
1932
+ var Internals = {
1933
+ d: {
1934
+ f: noop,
1935
+ r: function() {
1936
+ throw Error(formatProdErrorMessage(522));
1937
+ },
1938
+ D: noop,
1939
+ C: noop,
1940
+ L: noop,
1941
+ m: noop,
1942
+ X: noop,
1943
+ S: noop,
1944
+ M: noop
1945
+ },
1946
+ p: 0,
1947
+ findDOMNode: null
1948
+ }, REACT_PORTAL_TYPE = Symbol.for("react.portal");
1949
+ function createPortal$1(children, containerInfo, implementation) {
1950
+ var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
1951
+ return {
1952
+ $$typeof: REACT_PORTAL_TYPE,
1953
+ key: null == key ? null : "" + key,
1954
+ children,
1955
+ containerInfo,
1956
+ implementation
1957
+ };
1958
+ }
1959
+ var ReactSharedInternals = React$2.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
1960
+ exports.createPortal = function(children, container) {
1961
+ var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
1962
+ if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType) throw Error(formatProdErrorMessage(299));
1963
+ return createPortal$1(children, container, null, key);
1964
+ };
1965
+ }) });
1966
+
1967
+ //#endregion
1968
+ //#region ../../node_modules/react-dom/cjs/react-dom.development.js
1969
+ var require_react_dom_development = /* @__PURE__ */ __commonJS({ "../../node_modules/react-dom/cjs/react-dom.development.js": ((exports) => {
1970
+ "production" !== process.env.NODE_ENV && (function() {
1971
+ function noop$1() {}
1972
+ function testStringCoercion(value) {
1973
+ return "" + value;
1974
+ }
1975
+ function createPortal$1$1(children, containerInfo, implementation) {
1976
+ var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
1977
+ try {
1978
+ testStringCoercion(key);
1979
+ var JSCompiler_inline_result = !1;
1980
+ } catch (e) {
1981
+ JSCompiler_inline_result = !0;
1982
+ }
1983
+ JSCompiler_inline_result && (console.error("The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", "function" === typeof Symbol && Symbol.toStringTag && key[Symbol.toStringTag] || key.constructor.name || "Object"), testStringCoercion(key));
1984
+ return {
1985
+ $$typeof: REACT_PORTAL_TYPE$1,
1986
+ key: null == key ? null : "" + key,
1987
+ children,
1988
+ containerInfo,
1989
+ implementation
1990
+ };
1991
+ }
1992
+ function getCrossOriginStringAs(as, input) {
1993
+ if ("font" === as) return "";
1994
+ if ("string" === typeof input) return "use-credentials" === input ? input : "";
1995
+ }
1996
+ function getValueDescriptorExpectingObjectForWarning(thing) {
1997
+ return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : "something with type \"" + typeof thing + "\"";
1998
+ }
1999
+ function getValueDescriptorExpectingEnumForWarning(thing) {
2000
+ return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : "string" === typeof thing ? JSON.stringify(thing) : "number" === typeof thing ? "`" + thing + "`" : "something with type \"" + typeof thing + "\"";
2001
+ }
2002
+ function resolveDispatcher() {
2003
+ var dispatcher = ReactSharedInternals$1.H;
2004
+ null === dispatcher && console.error("Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.");
2005
+ return dispatcher;
2006
+ }
2007
+ "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
2008
+ var React$3 = __require("react"), Internals$1 = {
2009
+ d: {
2010
+ f: noop$1,
2011
+ r: function() {
2012
+ throw Error("Invalid form element. requestFormReset must be passed a form that was rendered by React.");
2013
+ },
2014
+ D: noop$1,
2015
+ C: noop$1,
2016
+ L: noop$1,
2017
+ m: noop$1,
2018
+ X: noop$1,
2019
+ S: noop$1,
2020
+ M: noop$1
2021
+ },
2022
+ p: 0,
2023
+ findDOMNode: null
2024
+ }, REACT_PORTAL_TYPE$1 = Symbol.for("react.portal"), ReactSharedInternals$1 = React$3.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
2025
+ "function" === typeof Map && null != Map.prototype && "function" === typeof Map.prototype.forEach && "function" === typeof Set && null != Set.prototype && "function" === typeof Set.prototype.clear && "function" === typeof Set.prototype.forEach || console.error("React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills");
2026
+ exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals$1;
2027
+ exports.createPortal = function(children, container) {
2028
+ var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
2029
+ if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType) throw Error("Target container is not a DOM element.");
2030
+ return createPortal$1$1(children, container, null, key);
2031
+ };
2032
+ exports.flushSync = function(fn) {
2033
+ var previousTransition = ReactSharedInternals$1.T, previousUpdatePriority = Internals$1.p;
2034
+ try {
2035
+ if (ReactSharedInternals$1.T = null, Internals$1.p = 2, fn) return fn();
2036
+ } finally {
2037
+ ReactSharedInternals$1.T = previousTransition, Internals$1.p = previousUpdatePriority, Internals$1.d.f() && console.error("flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task.");
2038
+ }
2039
+ };
2040
+ exports.preconnect = function(href, options) {
2041
+ "string" === typeof href && href ? null != options && "object" !== typeof options ? console.error("ReactDOM.preconnect(): Expected the `options` argument (second) to be an object but encountered %s instead. The only supported option at this time is `crossOrigin` which accepts a string.", getValueDescriptorExpectingEnumForWarning(options)) : null != options && "string" !== typeof options.crossOrigin && console.error("ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered %s instead. Try removing this option or passing a string value instead.", getValueDescriptorExpectingObjectForWarning(options.crossOrigin)) : console.error("ReactDOM.preconnect(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.", getValueDescriptorExpectingObjectForWarning(href));
2042
+ "string" === typeof href && (options ? (options = options.crossOrigin, options = "string" === typeof options ? "use-credentials" === options ? options : "" : void 0) : options = null, Internals$1.d.C(href, options));
2043
+ };
2044
+ exports.prefetchDNS = function(href) {
2045
+ if ("string" !== typeof href || !href) console.error("ReactDOM.prefetchDNS(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.", getValueDescriptorExpectingObjectForWarning(href));
2046
+ else if (1 < arguments.length) {
2047
+ var options = arguments[1];
2048
+ "object" === typeof options && options.hasOwnProperty("crossOrigin") ? console.error("ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.", getValueDescriptorExpectingEnumForWarning(options)) : console.error("ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.", getValueDescriptorExpectingEnumForWarning(options));
2049
+ }
2050
+ "string" === typeof href && Internals$1.d.D(href);
2051
+ };
2052
+ exports.preinit = function(href, options) {
2053
+ "string" === typeof href && href ? null == options || "object" !== typeof options ? console.error("ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.", getValueDescriptorExpectingEnumForWarning(options)) : "style" !== options.as && "script" !== options.as && console.error("ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are \"style\" and \"script\".", getValueDescriptorExpectingEnumForWarning(options.as)) : console.error("ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.", getValueDescriptorExpectingObjectForWarning(href));
2054
+ if ("string" === typeof href && options && "string" === typeof options.as) {
2055
+ var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = "string" === typeof options.integrity ? options.integrity : void 0, fetchPriority = "string" === typeof options.fetchPriority ? options.fetchPriority : void 0;
2056
+ "style" === as ? Internals$1.d.S(href, "string" === typeof options.precedence ? options.precedence : void 0, {
2057
+ crossOrigin,
2058
+ integrity,
2059
+ fetchPriority
2060
+ }) : "script" === as && Internals$1.d.X(href, {
2061
+ crossOrigin,
2062
+ integrity,
2063
+ fetchPriority,
2064
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
2065
+ });
2066
+ }
2067
+ };
2068
+ exports.preinitModule = function(href, options) {
2069
+ var encountered = "";
2070
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
2071
+ void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "script" !== options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingEnumForWarning(options.as) + ".");
2072
+ if (encountered) console.error("ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s", encountered);
2073
+ else switch (encountered = options && "string" === typeof options.as ? options.as : "script", encountered) {
2074
+ case "script": break;
2075
+ default: encountered = getValueDescriptorExpectingEnumForWarning(encountered), console.error("ReactDOM.preinitModule(): Currently the only supported \"as\" type for this function is \"script\" but received \"%s\" instead. This warning was generated for `href` \"%s\". In the future other module types will be supported, aligning with the import-attributes proposal. Learn more here: (https://github.com/tc39/proposal-import-attributes)", encountered, href);
2076
+ }
2077
+ if ("string" === typeof href) if ("object" === typeof options && null !== options) {
2078
+ if (null == options.as || "script" === options.as) encountered = getCrossOriginStringAs(options.as, options.crossOrigin), Internals$1.d.M(href, {
2079
+ crossOrigin: encountered,
2080
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
2081
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
2082
+ });
2083
+ } else options ?? Internals$1.d.M(href);
2084
+ };
2085
+ exports.preload = function(href, options) {
2086
+ var encountered = "";
2087
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
2088
+ null == options || "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : "string" === typeof options.as && options.as || (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
2089
+ encountered && console.error("ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an `options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag.%s", encountered);
2090
+ if ("string" === typeof href && "object" === typeof options && null !== options && "string" === typeof options.as) {
2091
+ encountered = options.as;
2092
+ var crossOrigin = getCrossOriginStringAs(encountered, options.crossOrigin);
2093
+ Internals$1.d.L(href, encountered, {
2094
+ crossOrigin,
2095
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
2096
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0,
2097
+ type: "string" === typeof options.type ? options.type : void 0,
2098
+ fetchPriority: "string" === typeof options.fetchPriority ? options.fetchPriority : void 0,
2099
+ referrerPolicy: "string" === typeof options.referrerPolicy ? options.referrerPolicy : void 0,
2100
+ imageSrcSet: "string" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,
2101
+ imageSizes: "string" === typeof options.imageSizes ? options.imageSizes : void 0,
2102
+ media: "string" === typeof options.media ? options.media : void 0
2103
+ });
2104
+ }
2105
+ };
2106
+ exports.preloadModule = function(href, options) {
2107
+ var encountered = "";
2108
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
2109
+ void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "string" !== typeof options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
2110
+ encountered && console.error("ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag.%s", encountered);
2111
+ "string" === typeof href && (options ? (encountered = getCrossOriginStringAs(options.as, options.crossOrigin), Internals$1.d.m(href, {
2112
+ as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
2113
+ crossOrigin: encountered,
2114
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0
2115
+ })) : Internals$1.d.m(href));
2116
+ };
2117
+ exports.requestFormReset = function(form) {
2118
+ Internals$1.d.r(form);
2119
+ };
2120
+ exports.unstable_batchedUpdates = function(fn, a) {
2121
+ return fn(a);
2122
+ };
2123
+ exports.useFormState = function(action, initialState, permalink) {
2124
+ return resolveDispatcher().useFormState(action, initialState, permalink);
2125
+ };
2126
+ exports.useFormStatus = function() {
2127
+ return resolveDispatcher().useHostTransitionStatus();
2128
+ };
2129
+ exports.version = "19.1.0";
2130
+ "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
2131
+ })();
2132
+ }) });
2133
+
2134
+ //#endregion
2135
+ //#region ../../node_modules/react-dom/index.js
2136
+ var require_react_dom = /* @__PURE__ */ __commonJS({ "../../node_modules/react-dom/index.js": ((exports, module) => {
2137
+ function checkDCE() {
2138
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined" || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== "function") return;
2139
+ if (process.env.NODE_ENV !== "production") throw new Error("^_^");
2140
+ try {
2141
+ __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);
2142
+ } catch (err) {
2143
+ console.error(err);
2144
+ }
2145
+ }
2146
+ if (process.env.NODE_ENV === "production") {
2147
+ checkDCE();
2148
+ module.exports = require_react_dom_production();
2149
+ } else module.exports = require_react_dom_development();
2150
+ }) });
2151
+
2152
+ //#endregion
2153
+ //#region src/OpenAPIOperationContext.tsx
2154
+ var import_react_dom = /* @__PURE__ */ __toESM(require_react_dom());
2155
+ const OpenAPIOperationContext = createContext({ onOpenClient: () => {} });
2156
+ /**
2157
+ * Provider for the OpenAPIOperationContext.
2158
+ */
2159
+ function OpenAPIOperationContextProvider(props) {
2160
+ const { children } = props;
2161
+ const onOpenClient = useEventCallback((pointer) => {
2162
+ props.onOpenClient?.(pointer);
2163
+ });
2164
+ const value = useMemo(() => ({ onOpenClient }), [onOpenClient]);
2165
+ return <OpenAPIOperationContext.Provider value={value}>
2166
+ {children}
2167
+ </OpenAPIOperationContext.Provider>;
2168
+ }
2169
+ /**
2170
+ * Hook to access the OpenAPIOperationContext.
2171
+ */
2172
+ function useOpenAPIOperationContext() {
2173
+ return useContext(OpenAPIOperationContext);
2174
+ }
2175
+
2176
+ //#endregion
2177
+ //#region src/OpenAPIPrefillContextProvider.tsx
2178
+ const OpenAPIPrefillContext = React$1.createContext(null);
2179
+ /**
2180
+ * Provide context to help prefill dynamic info like visitor data in OpenAPI blocks.
2181
+ */
2182
+ function OpenAPIPrefillContextProvider(props) {
2183
+ const { getPrefillInputContextData, children } = props;
2184
+ return <OpenAPIPrefillContext.Provider value={getPrefillInputContextData}>
2185
+ {children}
2186
+ </OpenAPIPrefillContext.Provider>;
2187
+ }
2188
+ /**
2189
+ * Hook to access the prefill context function.
2190
+ */
2191
+ function useOpenAPIPrefillContext() {
2192
+ return React$1.useContext(OpenAPIPrefillContext) ?? (() => null);
2193
+ }
2194
+
2195
+ //#endregion
2196
+ //#region src/util/tryit-prefill.ts
2197
+ const PREFILL_CUSTOM_PROPERTY = "x-gitbook-prefill";
2198
+ /**
2199
+ * Resolve the Scalar API client prefill configuration for a given OpenAPI operation.
2200
+ */
2201
+ function resolveTryItPrefillForOperation(args) {
2202
+ const { operation: { securities, servers }, prefillInputContext } = args;
2203
+ if (!prefillInputContext) return {};
2204
+ const runtime = new ExpressionRuntime();
2205
+ const resolveTryItPrefillExpression = (expr) => {
2206
+ if (!parseTemplate(expr).length) return;
2207
+ return runtime.evaluateTemplate(expr, prefillInputContext);
2208
+ };
2209
+ const prefillAuth = securities ? resolveTryItPrefillAuthForOperationSecurities({
2210
+ securities,
2211
+ resolveTryItPrefillExpression
2212
+ }) : void 0;
2213
+ const prefillServers = servers ? resolveTryItPrefillServersForOperationServers({
2214
+ servers,
2215
+ resolveTryItPrefillExpression
2216
+ }) : [];
2217
+ return {
2218
+ ...prefillAuth ? { authentication: prefillAuth } : {},
2219
+ ...prefillServers ? { servers: prefillServers } : {}
2220
+ };
2221
+ }
2222
+ /**
2223
+ * Resolve prefill authentication configuration for the security schemes defined for an operation.
2224
+ */
2225
+ function resolveTryItPrefillAuthForOperationSecurities(args) {
2226
+ const { securities, resolveTryItPrefillExpression } = args;
2227
+ const prefillAuthConfig = {};
2228
+ for (const [schemeName, security] of Object.values(securities)) {
2229
+ const tryitPrefillAuthValue = security[PREFILL_CUSTOM_PROPERTY] ? resolveTryItPrefillExpression(security[PREFILL_CUSTOM_PROPERTY]) : void 0;
2230
+ if (!tryitPrefillAuthValue) continue;
2231
+ switch (security.type) {
2232
+ case "http":
2233
+ if (security.scheme?.includes("bearer")) prefillAuthConfig[schemeName] = { token: tryitPrefillAuthValue };
2234
+ else if (security.scheme?.includes("basic") && tryitPrefillAuthValue.includes(":")) {
2235
+ const [username, password] = tryitPrefillAuthValue.split(":", 2);
2236
+ prefillAuthConfig[schemeName] = {
2237
+ username,
2238
+ password
2239
+ };
2240
+ }
2241
+ break;
2242
+ case "apiKey":
2243
+ prefillAuthConfig[schemeName] = {
2244
+ name: security.name,
2245
+ in: security.in,
2246
+ value: tryitPrefillAuthValue
2247
+ };
2248
+ break;
2249
+ case "oauth2":
2250
+ case "openIdConnect": break;
2251
+ }
2252
+ }
2253
+ return Object.keys(prefillAuthConfig).length > 0 ? { securitySchemes: prefillAuthConfig } : void 0;
2254
+ }
2255
+ /**
2256
+ * Resolve prefill server configuration for the servers defined for an operation.
2257
+ */
2258
+ function resolveTryItPrefillServersForOperationServers(args) {
2259
+ const { servers, resolveTryItPrefillExpression } = args;
2260
+ const resolvedServers = [];
2261
+ for (const server of servers) {
2262
+ const tryItPrefillServerUrlExpr = server[PREFILL_CUSTOM_PROPERTY];
2263
+ const tryItPrefillServerUrlValue = tryItPrefillServerUrlExpr ? resolveTryItPrefillExpression(tryItPrefillServerUrlExpr) : void 0;
2264
+ const variables = server.variables ? { ...server.variables } : {};
2265
+ if (server.variables) for (const [varName, variable] of Object.entries(server.variables)) {
2266
+ const { [PREFILL_CUSTOM_PROPERTY]: tryItPrefillVarExpr,...variableProps } = variable;
2267
+ const tryItPrefillVarValue = tryItPrefillVarExpr ? resolveTryItPrefillExpression(tryItPrefillVarExpr) : void 0;
2268
+ variables[varName] = {
2269
+ ...variableProps,
2270
+ ...tryItPrefillVarValue ? { default: String(tryItPrefillVarValue) } : {}
2271
+ };
2272
+ }
2273
+ const hasServerVariables = Object.keys(variables).length > 0;
2274
+ if (server.url && (tryItPrefillServerUrlValue || hasServerVariables)) {
2275
+ const resolvedServer = {
2276
+ url: tryItPrefillServerUrlValue ?? server.url,
2277
+ ...server.description ? { description: server.description } : {},
2278
+ ...hasServerVariables ? { variables } : {}
2279
+ };
2280
+ resolvedServers.push(resolvedServer);
2281
+ }
2282
+ }
2283
+ return resolvedServers.length > 0 ? resolvedServers : void 0;
2284
+ }
2285
+ /**
2286
+ * Return a X-GITBOOK-PREFILL placeholder based on the prefill custom property in the provided security scheme.
2287
+ */
2288
+ function resolvePrefillCodePlaceholderFromSecurityScheme(args) {
2289
+ const { security, defaultPlaceholderValue } = args;
2290
+ const prefillExprParts = extractPrefillExpressionPartsFromSecurityScheme(security);
2291
+ if (prefillExprParts.length === 0) return defaultPlaceholderValue ?? "";
2292
+ return toPrefillCodePlaceholder(templatePartsToExpression(prefillExprParts), defaultPlaceholderValue);
2293
+ }
2294
+ function extractPrefillExpressionPartsFromSecurityScheme(security) {
2295
+ const expression = security[PREFILL_CUSTOM_PROPERTY];
2296
+ if (!expression || expression.length === 0) return [];
2297
+ return parseTemplate(expression);
2298
+ }
2299
+ /**
2300
+ * Return a server URL with X-GITBOOK-PREFILL placeholders based on the prefill custom properties in the provided security scheme.
2301
+ */
2302
+ function resolveURLWithPrefillCodePlaceholdersFromServer(server, defaultServerUrl) {
2303
+ const serverVariables = server.variables ?? {};
2304
+ const variableExprs = {};
2305
+ let hasVariablePrefill = false;
2306
+ for (const [name, variable] of Object.entries(serverVariables ?? {})) if (variable[PREFILL_CUSTOM_PROPERTY]) {
2307
+ hasVariablePrefill = true;
2308
+ variableExprs[name] = `(${templatePartsToExpression(parseTemplate(variable[PREFILL_CUSTOM_PROPERTY]))} ?? '${variable.default ?? ""}')`;
2309
+ } else variableExprs[name] = String(variable.default) ?? "";
2310
+ let interpolatedUrl = server.url ?? "";
2311
+ interpolatedUrl = interpolatedUrl.replace(/{([^}]+)}/g, (_, varName) => {
2312
+ const expr = variableExprs[varName];
2313
+ if (serverVariables[varName]?.[PREFILL_CUSTOM_PROPERTY]) return `\${${expr ?? `'${varName}'`}}`;
2314
+ return expr ?? `{${varName}}`;
2315
+ });
2316
+ const interpolatedUrlTemplate = hasVariablePrefill ? `\`${interpolatedUrl}\`` : interpolatedUrl;
2317
+ const urlLevelExpr = server[PREFILL_CUSTOM_PROPERTY];
2318
+ if (urlLevelExpr) return toPrefillCodePlaceholder(`${templatePartsToExpression(parseTemplate(urlLevelExpr))} ?? ${hasVariablePrefill ? interpolatedUrlTemplate : `'${interpolatedUrlTemplate}'`}`, defaultServerUrl);
2319
+ if (hasVariablePrefill) return toPrefillCodePlaceholder(interpolatedUrlTemplate, defaultServerUrl);
2320
+ return interpolatedUrl;
2321
+ }
2322
+ function templatePartsToExpression(parts) {
2323
+ return parts.map((part) => {
2324
+ switch (part.type) {
2325
+ case "text": return `"${part.value}"`;
2326
+ case "expression": return part.value;
2327
+ default: return "";
2328
+ }
2329
+ }).join(" + ");
2330
+ }
2331
+ function toPrefillCodePlaceholder(expression, defaultValue) {
2332
+ return `$$__X-GITBOOK-PREFILL[(${expression})${defaultValue ? ` ?? '${defaultValue}'` : ""}]__$$`;
2333
+ }
2334
+
2335
+ //#endregion
2336
+ //#region src/ScalarApiButton.tsx
2337
+ /**
2338
+ * Button which launches the Scalar API Client
2339
+ */
2340
+ function ScalarApiButton(props) {
2341
+ const { method, path, securities, servers, specUrl, context } = props;
2342
+ const [isOpen, setIsOpen] = useState(false);
2343
+ const controllerRef = useRef(null);
2344
+ return <div className="scalar scalar-activate">
2345
+ <button className="scalar-activate-button button" onClick={() => {
2346
+ controllerRef.current?.openClient?.();
2347
+ setIsOpen(true);
2348
+ }}>
2349
+ {t(context.translation, "test_it")}
2350
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 12" fill="currentColor">
2351
+ <path stroke="currentColor" strokeWidth="1.5" d="M1 10.05V1.43c0-.2.2-.31.37-.22l7.26 4.08c.17.1.17.33.01.43l-7.26 4.54a.25.25 0 0 1-.38-.21Z" />
2352
+ </svg>
2353
+ </button>
2354
+
2355
+ {isOpen && (0, import_react_dom.createPortal)(<Suspense fallback={null}>
2356
+ <ScalarModal controllerRef={controllerRef} method={method} path={path} securities={securities} servers={servers} specUrl={specUrl} />
2357
+ </Suspense>, document.body)}
2358
+ </div>;
2359
+ }
2360
+ function ScalarModal(props) {
2361
+ const { method, path, securities, servers, specUrl, controllerRef } = props;
2362
+ const prefillInputContext = useOpenAPIPrefillContext()();
2363
+ const prefillConfig = resolveTryItPrefillForOperation({
2364
+ operation: {
2365
+ securities,
2366
+ servers
2367
+ },
2368
+ prefillInputContext
2369
+ });
2370
+ return <ApiClientModalProvider configuration={{
2371
+ url: specUrl,
2372
+ ...prefillConfig
2373
+ }} initialRequest={{
2374
+ method,
2375
+ path
2376
+ }}>
2377
+ <ScalarModalController method={method} path={path} controllerRef={controllerRef} />
2378
+ </ApiClientModalProvider>;
2379
+ }
2380
+ function ScalarModalController(props) {
2381
+ const { method, path, controllerRef } = props;
2382
+ const openScalarClient = useApiClientModal()?.open;
2383
+ const { onOpenClient: trackClientOpening } = useOpenAPIOperationContext();
2384
+ const openClient = useMemo(() => {
2385
+ if (openScalarClient) return () => {
2386
+ openScalarClient({
2387
+ method,
2388
+ path,
2389
+ _source: "gitbook"
2390
+ });
2391
+ trackClientOpening({
2392
+ method,
2393
+ path
2394
+ });
2395
+ };
2396
+ return null;
2397
+ }, [
2398
+ openScalarClient,
2399
+ method,
2400
+ path,
2401
+ trackClientOpening
2402
+ ]);
2403
+ useImperativeHandle(controllerRef, () => ({ openClient: openClient ? () => openClient() : void 0 }), [openClient]);
2404
+ useEffect(() => {
2405
+ openClient?.();
2406
+ }, [openClient]);
2407
+ return null;
2408
+ }
2409
+
2410
+ //#endregion
2411
+ //#region src/contentTypeChecks.ts
2412
+ function isJSON(contentType) {
2413
+ return contentType?.toLowerCase().includes("application/json") || false;
2414
+ }
2415
+ function isXML(contentType) {
2416
+ return contentType?.toLowerCase().includes("application/xml") || false;
2417
+ }
2418
+ function isYAML(contentType) {
2419
+ return contentType?.toLowerCase().includes("application/yaml") || false;
2420
+ }
2421
+ function isGraphQL(contentType) {
2422
+ return contentType?.toLowerCase().includes("application/graphql") || false;
2423
+ }
2424
+ function isCSV(contentType) {
2425
+ return contentType?.toLowerCase().includes("text/csv") || false;
2426
+ }
2427
+ function isPDF(contentType) {
2428
+ return contentType?.toLowerCase().includes("application/pdf") || false;
2429
+ }
2430
+ function isText(contentType) {
2431
+ return contentType?.toLowerCase().includes("text/plain") || false;
2432
+ }
2433
+ function isFormUrlEncoded(contentType) {
2434
+ return contentType?.toLowerCase().includes("application/x-www-form-urlencoded") || false;
2435
+ }
2436
+ function isFormData(contentType) {
2437
+ return !!contentType && contentType.toLowerCase().includes("multipart/form-data");
2438
+ }
2439
+ function isPlainObject(value) {
2440
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2441
+ }
2442
+
2443
+ //#endregion
2444
+ //#region src/code-samples.ts
2445
+ const codeSampleGenerators = [
2446
+ {
2447
+ id: "http",
2448
+ label: "HTTP",
2449
+ syntax: "http",
2450
+ generate: ({ method, url: { origin, path }, headers = {}, body }) => {
2451
+ if (body) {
2452
+ const bodyContent = body ? stringifyOpenAPI(body) : "";
2453
+ const encoder = new TextEncoder();
2454
+ const bodyString$1 = BodyGenerators.getHTTPBody(body, headers);
2455
+ if (bodyString$1) body = bodyString$1;
2456
+ headers = {
2457
+ ...headers,
2458
+ "Content-Length": encoder.encode(bodyContent).length.toString()
2459
+ };
2460
+ }
2461
+ if (!headers.hasOwnProperty("Accept")) headers.Accept = "*/*";
2462
+ const headerString = headers ? `${Object.entries(headers).map(([key, value]) => key.toLowerCase() !== "host" ? `${key}: ${value}` : "").join("\n")}\n` : "";
2463
+ const bodyString = body ? `\n${body}` : "";
2464
+ return `${method.toUpperCase()} ${decodeURI(path)} HTTP/1.1
2465
+ Host: ${origin.replaceAll(/https*:\/\//g, "")}
2466
+ ${headerString}${bodyString}`;
2467
+ }
2468
+ },
2469
+ {
2470
+ id: "curl",
2471
+ label: "cURL",
2472
+ syntax: "bash",
2473
+ generate: ({ method, url: { origin, path }, headers, body }) => {
2474
+ const separator = " \\\n";
2475
+ const lines = ["curl -L"];
2476
+ if (method.toUpperCase() !== "GET") lines.push(`--request ${method.toUpperCase()}`);
2477
+ lines.push(`--url '${origin}${path}'`);
2478
+ if (body) {
2479
+ const bodyContent = BodyGenerators.getCurlBody(body, headers);
2480
+ if (bodyContent) {
2481
+ body = bodyContent.body;
2482
+ headers = bodyContent.headers;
2483
+ }
2484
+ }
2485
+ if (headers && Object.keys(headers).length > 0) Object.entries(headers).forEach(([key, value]) => {
2486
+ lines.push(`--header '${key}: ${value}'`);
2487
+ });
2488
+ if (body) if (Array.isArray(body)) lines.push(...body);
2489
+ else lines.push(body);
2490
+ return lines.map((line, index) => index > 0 ? indent(line, 2) : line).join(separator);
2491
+ }
2492
+ },
2493
+ {
2494
+ id: "javascript",
2495
+ label: "JavaScript",
2496
+ syntax: "javascript",
2497
+ generate: ({ method, url: { origin, path }, headers, body }) => {
2498
+ let code = "";
2499
+ if (body) {
2500
+ const lines = BodyGenerators.getJavaScriptBody(body, headers);
2501
+ if (lines) {
2502
+ code += lines.code;
2503
+ body = lines.body;
2504
+ headers = lines.headers;
2505
+ }
2506
+ }
2507
+ code += `const response = await fetch('${origin}${path}', {
2508
+ method: '${method.toUpperCase()}',\n`;
2509
+ if (headers && Object.keys(headers).length > 0) code += indent(`headers: ${stringifyOpenAPI(headers, null, 2)},\n`, 4);
2510
+ if (body) code += indent(`body: ${body}\n`, 4);
2511
+ code += "});\n\n";
2512
+ code += "const data = await response.json();";
2513
+ return code;
2514
+ }
2515
+ },
2516
+ {
2517
+ id: "python",
2518
+ label: "Python",
2519
+ syntax: "python",
2520
+ generate: ({ method, url: { origin, path }, headers, body }) => {
2521
+ const contentType = headers?.["Content-Type"];
2522
+ let code = `${isJSON(contentType) ? "import json\n" : ""}import requests\n\n`;
2523
+ if (body) {
2524
+ const lines = BodyGenerators.getPythonBody(body, headers);
2525
+ if (lines) {
2526
+ code += lines.code;
2527
+ body = lines.body;
2528
+ headers = lines.headers;
2529
+ }
2530
+ }
2531
+ code += `response = requests.${method.toLowerCase()}(\n`;
2532
+ code += indent(`"${origin}${path}",\n`, 4);
2533
+ if (headers && Object.keys(headers).length > 0) code += indent(`headers=${stringifyOpenAPI(headers)},\n`, 4);
2534
+ if (body) if (body === "files") code += indent(`files=${body}\n`, 4);
2535
+ else if (isJSON(contentType)) code += indent(`data=json.dumps(${body})\n`, 4);
2536
+ else code += indent(`data=${body}\n`, 4);
2537
+ code += ")\n\n";
2538
+ code += "data = response.json()";
2539
+ return code;
2540
+ }
2541
+ }
2542
+ ];
2543
+ function indent(code, spaces) {
2544
+ const indent$1 = " ".repeat(spaces);
2545
+ return code.split("\n").map((line) => line ? indent$1 + line : "").join("\n");
2546
+ }
2547
+ function parseHostAndPath(url) {
2548
+ try {
2549
+ const urlObj = new URL(url);
2550
+ const path = urlObj.pathname || "/";
2551
+ return {
2552
+ host: urlObj.host,
2553
+ path
2554
+ };
2555
+ } catch (_e) {
2556
+ const splitted = url.split("//");
2557
+ const parts = (splitted[1] ? splitted[1] : url).split("/");
2558
+ return {
2559
+ host: parts.shift(),
2560
+ path: `/${parts.join("/")}`
2561
+ };
2562
+ }
2563
+ }
2564
+ const BodyGenerators = {
2565
+ getCurlBody(body, headers) {
2566
+ if (!body || !headers) return void 0;
2567
+ const headersCopy = { ...headers };
2568
+ const contentType = headersCopy["Content-Type"] || "";
2569
+ if (isFormData(contentType)) body = isPlainObject(body) ? Object.entries(body).map(([key, value]) => `--form '${key}=${String(value)}'`) : `--form 'file=@${body}'`;
2570
+ else if (isFormUrlEncoded(contentType)) body = isPlainObject(body) ? `--data '${Object.entries(body).map(([key, value]) => `${key}=${String(value)}`).join("&")}'` : String(body);
2571
+ else if (isText(contentType)) body = `--data '${String(body).replace(/"/g, "")}'`;
2572
+ else if (isXML(contentType)) body = `--data-binary $'${convertBodyToXML(body)}'`;
2573
+ else if (isCSV(contentType)) body = `--data-binary $'${stringifyOpenAPI(body).replace(/"/g, "").replace(/\\n/g, "\n")}'`;
2574
+ else if (isGraphQL(contentType)) {
2575
+ body = `--data '${stringifyOpenAPI(body)}'`;
2576
+ headersCopy["Content-Type"] = "application/json";
2577
+ } else if (isPDF(contentType)) body = `--data-binary '@${String(body)}'`;
2578
+ else if (isYAML(contentType)) body = `--data-binary $'${yaml.dump(body).replace(/'/g, "").replace(/\\n/g, "\n")}'`;
2579
+ else body = `--data '${stringifyOpenAPI(body, null, 2).replace(/\\n/g, "\n")}'`;
2580
+ return {
2581
+ body,
2582
+ headers: headersCopy
2583
+ };
2584
+ },
2585
+ getJavaScriptBody: (body, headers) => {
2586
+ if (!body || !headers) return;
2587
+ let code = "";
2588
+ const headersCopy = { ...headers };
2589
+ const contentType = headersCopy["Content-Type"] || "";
2590
+ if (isFormData(contentType)) {
2591
+ code += "const formData = new FormData();\n\n";
2592
+ if (isPlainObject(body)) Object.entries(body).forEach(([key, value]) => {
2593
+ code += `formData.append("${key}", "${String(value)}");\n`;
2594
+ });
2595
+ else if (typeof body === "string") code += `formData.append("file", "${body}");\n`;
2596
+ code += "\n";
2597
+ body = "formData";
2598
+ } else if (isFormUrlEncoded(contentType)) {
2599
+ code += "const params = new URLSearchParams();\n\n";
2600
+ if (isPlainObject(body)) Object.entries(body).forEach(([key, value]) => {
2601
+ code += `params.append("${key}", "${String(value)}");\n`;
2602
+ });
2603
+ code += "\n";
2604
+ body = "params.toString()";
2605
+ } else if (isGraphQL(contentType)) if (isPlainObject(body)) {
2606
+ Object.entries(body).forEach(([key, value]) => {
2607
+ code += `const ${key} = \`\n${indent(String(value), 4)}\`;\n\n`;
2608
+ });
2609
+ body = `JSON.stringify({ ${Object.keys(body).join(", ")} })`;
2610
+ headersCopy["Content-Type"] = "application/json";
2611
+ } else {
2612
+ code += `const query = \`\n${indent(String(body), 4)}\`;\n\n`;
2613
+ body = "JSON.stringify(query)";
2614
+ }
2615
+ else if (isCSV(contentType)) {
2616
+ code += "const csv = `\n";
2617
+ code += indent(String(body), 4);
2618
+ code += "`;\n\n";
2619
+ body = "csv";
2620
+ } else if (isPDF(contentType)) {
2621
+ code += "const formData = new FormData();\n\n";
2622
+ code += `formData.append("file", "${body}");\n\n`;
2623
+ body = "formData";
2624
+ } else if (isXML(contentType)) {
2625
+ code += "const xml = `\n";
2626
+ code += indent(convertBodyToXML(body), 4);
2627
+ code += "`;\n\n";
2628
+ body = "xml";
2629
+ } else if (isYAML(contentType)) {
2630
+ code += `const yamlBody = \`\n${indent(yaml.dump(body), 4)}\`;\n\n`;
2631
+ body = "yamlBody";
2632
+ } else if (isText(contentType)) body = stringifyOpenAPI(body, null, 2);
2633
+ else body = `JSON.stringify(${stringifyOpenAPI(body, null, 2)})`;
2634
+ return {
2635
+ body,
2636
+ code,
2637
+ headers: headersCopy
2638
+ };
2639
+ },
2640
+ getPythonBody: (body, headers) => {
2641
+ if (!body || !headers) return;
2642
+ let code = "";
2643
+ const contentType = headers["Content-Type"] || "";
2644
+ if (isFormData(contentType)) {
2645
+ code += "files = {\n";
2646
+ if (isPlainObject(body)) Object.entries(body).forEach(([key, value]) => {
2647
+ code += `${indent(`"${key}": "${String(value)}",`, 4)}\n`;
2648
+ });
2649
+ code += "}\n\n";
2650
+ body = "files";
2651
+ } else if (isPDF(contentType)) {
2652
+ code += "files = {\n";
2653
+ code += `${indent(`"file": "${body}",`, 4)}\n`;
2654
+ code += "}\n\n";
2655
+ body = "files";
2656
+ } else if (isXML(contentType)) body = JSON.stringify(convertBodyToXML(body));
2657
+ else if (isYAML(contentType)) {
2658
+ code += `yamlBody = \"\"\"\n${indent(yaml.dump(body), 4)}\"\"\"\n\n`;
2659
+ body = "yamlBody";
2660
+ } else body = stringifyOpenAPI(body, (_key, value) => {
2661
+ switch (value) {
2662
+ case true: return "$$__TRUE__$$";
2663
+ case false: return "$$__FALSE__$$";
2664
+ case null: return "$$__NULL__$$";
2665
+ default: return value;
2666
+ }
2667
+ }, 2).replaceAll("\"$$__TRUE__$$\"", "True").replaceAll("\"$$__FALSE__$$\"", "False").replaceAll("\"$$__NULL__$$\"", "None");
2668
+ return {
2669
+ body,
2670
+ code,
2671
+ headers
2672
+ };
2673
+ },
2674
+ getHTTPBody: (body, headers) => {
2675
+ if (!body || !headers) return void 0;
2676
+ const contentType = headers["Content-Type"] || "";
2677
+ const typeHandlers = {
2678
+ pdf: () => `${stringifyOpenAPI(body, null, 2)}`,
2679
+ formUrlEncoded: () => {
2680
+ return `"${(isPlainObject(body) ? Object.entries(body).map(([key, value]) => `${key}=${stringifyOpenAPI(value)}`).join("&") : stringifyOpenAPI(body)).replace(/"/g, "'")}"`;
2681
+ },
2682
+ text: () => `"${String(body)}"`,
2683
+ xml: () => {
2684
+ return `"${convertBodyToXML(body)}"`;
2685
+ },
2686
+ yaml: () => `"${yaml.dump(body).replace(/"/g, "\\\"")}"`,
2687
+ csv: () => `"${stringifyOpenAPI(body).replace(/"/g, "")}"`,
2688
+ default: () => `${stringifyOpenAPI(body, null, 2)}`
2689
+ };
2690
+ if (isPDF(contentType)) return typeHandlers.pdf();
2691
+ if (isFormUrlEncoded(contentType)) return typeHandlers.formUrlEncoded();
2692
+ if (isText(contentType)) return typeHandlers.text();
2693
+ if (isXML(contentType)) return typeHandlers.xml();
2694
+ if (isYAML(contentType)) return typeHandlers.yaml();
2695
+ if (isCSV(contentType)) return typeHandlers.csv();
2696
+ return typeHandlers.default();
2697
+ }
2698
+ };
2699
+ /**
2700
+ * Converts a body to XML format
2701
+ */
2702
+ function convertBodyToXML(body) {
2703
+ if (typeof body === "string" && body.trim().startsWith("<")) return body;
2704
+ if (typeof body !== "object" || body === null) try {
2705
+ body = JSON.parse(body);
2706
+ } catch {
2707
+ return body;
2708
+ }
2709
+ return json2xml(body).replace(/"/g, "").replace(/\\n/g, "\n").replace(/\\t/g, " ");
2710
+ }
2711
+
2712
+ //#endregion
2713
+ //#region src/OpenAPICodeSample.tsx
2714
+ const CUSTOM_CODE_SAMPLES_KEYS = [
2715
+ "x-custom-examples",
2716
+ "x-code-samples",
2717
+ "x-codeSamples"
2718
+ ];
2719
+ /**
2720
+ * Display code samples to execute the operation.
2721
+ * It supports the Redocly custom syntax as well (https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples/)
2722
+ */
2723
+ function OpenAPICodeSample(props) {
2724
+ const { data, context } = props;
2725
+ if (data.operation["x-codeSamples"] === false) return null;
2726
+ const customCodeSamples = getCustomCodeSamples(props);
2727
+ if (data["x-codeSamples"] === false && !customCodeSamples) return null;
2728
+ const samples = customCodeSamples ?? generateCodeSamples(props);
2729
+ if (samples.length === 0) return null;
2730
+ return <OpenAPICodeSampleBody context={getOpenAPIClientContext(context)} data={data} items={samples} selectIcon={context.icons.chevronDown} />;
2731
+ }
2732
+ /**
2733
+ * Generate code samples for the operation.
2734
+ */
2735
+ function generateCodeSamples(props) {
2736
+ const { data, context } = props;
2737
+ const searchParams = new URLSearchParams();
2738
+ const headersObject = {};
2739
+ (Array.isArray(data.operation.parameters) ? data.operation.parameters : []).forEach((param) => {
2740
+ if (!param) return;
2741
+ if (param.in === "header" && param.required) {
2742
+ const example = param.schema ? generateSchemaExample(param.schema, { mode: "write" }) : void 0;
2743
+ if (example !== void 0 && param.name) headersObject[param.name] = typeof example !== "string" ? stringifyOpenAPI(example) : example;
2744
+ } else if (param.in === "query" && param.required) {
2745
+ const example = param.schema ? generateSchemaExample(param.schema, { mode: "write" }) : void 0;
2746
+ if (example !== void 0 && param.name) searchParams.append(param.name, String(Array.isArray(example) ? example[0] : example));
2747
+ }
2748
+ });
2749
+ const requestBody = !checkIsReference(data.operation.requestBody) ? data.operation.requestBody : void 0;
2750
+ const defaultServerUrl = getDefaultServerURL(data.servers);
2751
+ let serverUrlPath = defaultServerUrl ? parseHostAndPath(defaultServerUrl).path : "";
2752
+ serverUrlPath = serverUrlPath === "/" ? "" : serverUrlPath;
2753
+ const serverUrlOrigin = (data.servers[0] ? resolveURLWithPrefillCodePlaceholdersFromServer(data.servers[0], defaultServerUrl) : defaultServerUrl).replaceAll(serverUrlPath, "");
2754
+ const path = serverUrlPath + data.path + (searchParams.size ? `?${searchParams.toString()}` : "");
2755
+ const genericHeaders = {
2756
+ ...getSecurityHeaders({
2757
+ securityRequirement: data.operation.security,
2758
+ securities: data.securities
2759
+ }),
2760
+ ...headersObject
2761
+ };
2762
+ const mediaTypeRendererFactories = Object.entries(requestBody?.content ?? {}).map(([mediaType, mediaTypeObject]) => {
2763
+ return (generator) => {
2764
+ const mediaTypeHeaders = {
2765
+ ...genericHeaders,
2766
+ "Content-Type": mediaType
2767
+ };
2768
+ return {
2769
+ mediaType,
2770
+ element: context.renderCodeBlock({
2771
+ code: generator.generate({
2772
+ url: {
2773
+ origin: serverUrlOrigin,
2774
+ path
2775
+ },
2776
+ method: data.method,
2777
+ body: void 0,
2778
+ headers: mediaTypeHeaders
2779
+ }),
2780
+ syntax: generator.syntax
2781
+ }),
2782
+ examples: generateMediaTypeExamples(mediaTypeObject, { mode: "write" }).map((example) => ({
2783
+ example,
2784
+ element: context.renderCodeBlock({
2785
+ code: generator.generate({
2786
+ url: {
2787
+ origin: serverUrlOrigin,
2788
+ path
2789
+ },
2790
+ method: data.method,
2791
+ body: example.value,
2792
+ headers: mediaTypeHeaders
2793
+ }),
2794
+ syntax: generator.syntax
2795
+ })
2796
+ }))
2797
+ };
2798
+ };
2799
+ });
2800
+ return codeSampleGenerators.map((generator) => {
2801
+ if (mediaTypeRendererFactories.length > 0) {
2802
+ const renderers = mediaTypeRendererFactories.map((generate) => generate(generator));
2803
+ return {
2804
+ key: `default-${generator.id}`,
2805
+ label: generator.label,
2806
+ body: <OpenAPIMediaTypeExamplesBody method={data.method} path={data.path} renderers={renderers} blockKey={context.blockKey} />,
2807
+ footer: <OpenAPICodeSampleFooter renderers={renderers} data={data} context={context} />
2808
+ };
2809
+ }
2810
+ return {
2811
+ key: `default-${generator.id}`,
2812
+ label: generator.label,
2813
+ body: context.renderCodeBlock({
2814
+ code: generator.generate({
2815
+ url: {
2816
+ origin: serverUrlOrigin,
2817
+ path
2818
+ },
2819
+ method: data.method,
2820
+ body: void 0,
2821
+ headers: genericHeaders
2822
+ }),
2823
+ syntax: generator.syntax
2824
+ }),
2825
+ footer: <OpenAPICodeSampleFooter data={data} renderers={[]} context={context} />
2826
+ };
2827
+ });
2828
+ }
2829
+ function OpenAPICodeSampleFooter(props) {
2830
+ const { data, context, renderers } = props;
2831
+ const { method, path, securities, servers } = data;
2832
+ const { specUrl } = context;
2833
+ const hideTryItPanel = data["x-hideTryItPanel"] || data.operation["x-hideTryItPanel"];
2834
+ const hasMultipleMediaTypes = renderers.length > 1 || renderers.some((renderer) => renderer.examples.length > 0);
2835
+ if (hideTryItPanel && !hasMultipleMediaTypes) return null;
2836
+ if (!validateHttpMethod(method)) return null;
2837
+ return <div className="openapi-codesample-footer">
2838
+ {hasMultipleMediaTypes ? <OpenAPIMediaTypeExamplesSelector method={data.method} path={data.path} renderers={renderers} selectIcon={context.icons.chevronDown} blockKey={context.blockKey} /> : <span />}
2839
+ {!hideTryItPanel && <ScalarApiButton context={getOpenAPIClientContext(context)} method={method} path={path} securities={securities} servers={servers} specUrl={specUrl} />}
2840
+ </div>;
2841
+ }
2842
+ /**
2843
+ * Get custom code samples for the operation.
2844
+ */
2845
+ function getCustomCodeSamples(props) {
2846
+ const { data, context } = props;
2847
+ let customCodeSamples = null;
2848
+ CUSTOM_CODE_SAMPLES_KEYS.forEach((key) => {
2849
+ const customSamples = data.operation[key];
2850
+ if (customSamples && Array.isArray(customSamples)) customCodeSamples = customSamples.filter((sample) => {
2851
+ return typeof sample.source === "string" && typeof sample.lang === "string";
2852
+ }).map((sample, index) => ({
2853
+ key: `custom-sample-${sample.lang}-${index}`,
2854
+ label: sample.label || sample.lang,
2855
+ body: context.renderCodeBlock({
2856
+ code: sample.source,
2857
+ syntax: sample.lang
2858
+ }),
2859
+ footer: <OpenAPICodeSampleFooter renderers={[]} data={data} context={context} />
2860
+ }));
2861
+ });
2862
+ return customCodeSamples;
2863
+ }
2864
+ function getSecurityHeaders(args) {
2865
+ const { securityRequirement, securities } = args;
2866
+ const operationSecurityInfo = extractOperationSecurityInfo({
2867
+ securityRequirement,
2868
+ securities
2869
+ });
2870
+ if (operationSecurityInfo.length === 0) return {};
2871
+ const selectedSecurity = operationSecurityInfo.at(0);
2872
+ if (!selectedSecurity) return {};
2873
+ const headers = {};
2874
+ for (const security of selectedSecurity.schemes) switch (security.type) {
2875
+ case "http": {
2876
+ let scheme = security.scheme;
2877
+ const format = resolvePrefillCodePlaceholderFromSecurityScheme({
2878
+ security,
2879
+ defaultPlaceholderValue: scheme?.includes("basic") ? "username:password" : "YOUR_SECRET_TOKEN"
2880
+ });
2881
+ if (scheme?.includes("bearer")) scheme = "Bearer";
2882
+ else if (scheme?.includes("basic")) scheme = "Basic";
2883
+ else if (scheme?.includes("token")) scheme = "Token";
2884
+ headers.Authorization = `${scheme} ${format}`;
2885
+ break;
2886
+ }
2887
+ case "apiKey": {
2888
+ if (security.in !== "header") break;
2889
+ const name = security.name ?? "Authorization";
2890
+ headers[name] = resolvePrefillCodePlaceholderFromSecurityScheme({
2891
+ security,
2892
+ defaultPlaceholderValue: "YOUR_API_KEY"
2893
+ });
2894
+ break;
2895
+ }
2896
+ case "oauth2":
2897
+ headers.Authorization = `Bearer ${resolvePrefillCodePlaceholderFromSecurityScheme({
2898
+ security,
2899
+ defaultPlaceholderValue: "YOUR_OAUTH2_TOKEN"
2900
+ })}`;
2901
+ break;
2902
+ default: break;
2903
+ }
2904
+ return headers;
2905
+ }
2906
+ function validateHttpMethod(method) {
2907
+ return [
2908
+ "get",
2909
+ "post",
2910
+ "put",
2911
+ "delete",
2912
+ "patch",
2913
+ "head",
2914
+ "options",
2915
+ "trace"
2916
+ ].includes(method);
2917
+ }
2918
+
2919
+ //#endregion
2920
+ //#region src/OpenAPIMediaType.tsx
2921
+ /**
2922
+ * Get the state of the response examples select.
2923
+ */
2924
+ function useMediaTypesState(stateKey, initialKey = "default") {
2925
+ return useSelectState(stateKey, initialKey);
2926
+ }
2927
+ function useMediaTypeExamplesState(stateKey, initialKey = "default") {
2928
+ return useSelectState(stateKey, initialKey);
2929
+ }
2930
+ function OpenAPIMediaTypeContent(props) {
2931
+ const { stateKey, items, selectIcon, context } = props;
2932
+ const state = useMediaTypesState(stateKey, items[0]?.key);
2933
+ const examples = items.find((item) => item.key === state.key)?.examples ?? [];
2934
+ if (!items.length && !examples.length) return null;
2935
+ return <StaticSection footer={items.length > 1 || examples.length > 1 ? <OpenAPIMediaTypeFooter items={items} examples={examples} selectIcon={selectIcon} stateKey={stateKey} /> : null} className="openapi-response-media-types-examples">
2936
+ <OpenAPIMediaTypeBody context={context} stateKey={stateKey} items={items} examples={examples} />
2937
+ </StaticSection>;
2938
+ }
2939
+ function OpenAPIMediaTypeFooter(props) {
2940
+ const { items, examples, stateKey, selectIcon } = props;
2941
+ return <>
2942
+ {items.length > 1 && <OpenAPISelect icon={selectIcon} items={items} stateKey={stateKey} placement="bottom start">
2943
+ {items.map((item) => <OpenAPISelectItem key={item.key} id={item.key} value={item}>
2944
+ <span>{item.label}</span>
2945
+ </OpenAPISelectItem>)}
2946
+ </OpenAPISelect>}
2947
+
2948
+ {examples && examples.length > 1 ? <OpenAPISelect icon={selectIcon} items={examples} stateKey={`${stateKey}-examples`} placement="bottom start">
2949
+ {examples.map((example) => <OpenAPISelectItem key={example.key} id={example.key} value={example}>
2950
+ <span>{example.label}</span>
2951
+ </OpenAPISelectItem>)}
2952
+ </OpenAPISelect> : null}
2953
+ </>;
2954
+ }
2955
+ function OpenAPIMediaTypeBody(props) {
2956
+ const { stateKey, items, examples, context } = props;
2957
+ const state = useMediaTypesState(stateKey, items[0]?.key);
2958
+ const selectedItem = items.find((item) => item.key === state.key) ?? items[0];
2959
+ const exampleState = useMediaTypeExamplesState(`${stateKey}-examples`, selectedItem?.examples?.[0]?.key);
2960
+ if (!selectedItem) return null;
2961
+ if (examples) {
2962
+ const selectedExample = examples.find((example) => example.key === exampleState.key) ?? examples[0];
2963
+ if (!selectedExample) return <OpenAPIEmptyExample context={context} />;
2964
+ return selectedExample.body;
2965
+ }
2966
+ return selectedItem.body;
2967
+ }
2968
+
2969
+ //#endregion
2970
+ //#region src/OpenAPIResponseExampleContent.tsx
2971
+ /**
2972
+ * Get the state of the response examples select.
2973
+ */
2974
+ function useResponseExamplesState(blockKey, initialKey = "default") {
2975
+ return useSelectState(getResponseExampleStateKey(blockKey), initialKey);
2976
+ }
2977
+ function OpenAPIResponseExampleContent(props) {
2978
+ const { blockKey, items, selectIcon } = props;
2979
+ return <StaticSection header={<OpenAPIResponseExampleHeader selectIcon={selectIcon} blockKey={blockKey} items={items} />} className="openapi-response-examples">
2980
+ <OpenAPIResponseExampleBody blockKey={blockKey} items={items} />
2981
+ </StaticSection>;
2982
+ }
2983
+ function OpenAPIResponseExampleHeader(props) {
2984
+ const { items, blockKey, selectIcon } = props;
2985
+ if (items.length === 1) {
2986
+ const item = items[0];
2987
+ if (!item) return null;
2988
+ return <span className="openapi-response-examples-statuscode-title">
2989
+ <OpenAPIResponseExampleItem item={item} />
2990
+ </span>;
2991
+ }
2992
+ return <OpenAPISelect items={items} icon={selectIcon} stateKey={getResponseExampleStateKey(blockKey)} placement="bottom start">
2993
+ {items.map((item) => <OpenAPISelectItem key={item.key} id={item.key} value={item}>
2994
+ <OpenAPIResponseExampleItem item={item} />
2995
+ </OpenAPISelectItem>)}
2996
+ </OpenAPISelect>;
2997
+ }
2998
+ function OpenAPIResponseExampleItem(props) {
2999
+ const { item } = props;
3000
+ return <>
3001
+ <span className={clsx("openapi-statuscode", `openapi-statuscode-${getStatusCodeClassName(item.statusCode)}`, "openapi-response-examples-statuscode")}>
3002
+ {item.statusCode}
3003
+ </span>
3004
+ <span className="openapi-response-examples-statuscode-label">{item.label}</span>
3005
+ </>;
3006
+ }
3007
+ function OpenAPIResponseExampleBody(props) {
3008
+ const { blockKey, items } = props;
3009
+ const state = useResponseExamplesState(blockKey, items[0]?.key);
3010
+ const selectedItem = items.find((item) => item.key === state.key) ?? items[0];
3011
+ if (!selectedItem) return null;
3012
+ return <div className="openapi-response-examples-panel">{selectedItem.body}</div>;
3013
+ }
3014
+ /**
3015
+ * Return the state key for the response examples.
3016
+ */
3017
+ function getResponseExampleStateKey(blockKey) {
3018
+ return createStateKey("openapi-responses", blockKey);
3019
+ }
3020
+
3021
+ //#endregion
3022
+ //#region src/OpenAPIResponseExample.tsx
3023
+ /**
3024
+ * Display an example of the response content.
3025
+ */
3026
+ function OpenAPIResponseExample(props) {
3027
+ const { data, context } = props;
3028
+ if (!data.operation.responses) return null;
3029
+ const responses = Object.entries(data.operation.responses);
3030
+ responses.sort(([a], [b]) => {
3031
+ if (a === "default") return 1;
3032
+ if (b === "default") return -1;
3033
+ if (a === "200") return -1;
3034
+ if (b === "200") return 1;
3035
+ return Number(a) - Number(b);
3036
+ });
3037
+ const tabs = responses.filter(([_, responseObject]) => responseObject && typeof responseObject === "object" && !responseObject["x-hideSample"]).map(([key, responseObject]) => {
3038
+ const description = resolveDescription(responseObject);
3039
+ const label = description ? <Markdown key={`response-description-${key}`} source={description} /> : getStatusCodeDefaultLabel(key, context);
3040
+ if (checkIsReference(responseObject)) return {
3041
+ key,
3042
+ label,
3043
+ statusCode: key,
3044
+ body: <OpenAPIExample example={getExampleFromReference(responseObject, context)} context={context} syntax="json" />
3045
+ };
3046
+ if (!responseObject.content || Object.keys(responseObject.content).length === 0) return {
3047
+ key,
3048
+ label,
3049
+ statusCode: key,
3050
+ body: <OpenAPIEmptyExample context={context} />
3051
+ };
3052
+ return {
3053
+ key,
3054
+ label,
3055
+ statusCode: key,
3056
+ body: <OpenAPIResponse$1 context={context} content={responseObject.content} />
3057
+ };
3058
+ });
3059
+ if (tabs.length === 0) return null;
3060
+ return <OpenAPIResponseExampleContent selectIcon={context.icons.chevronDown} blockKey={context.blockKey} items={tabs} />;
3061
+ }
3062
+ function OpenAPIResponse$1(props) {
3063
+ const { context, content } = props;
3064
+ const entries = Object.entries(content);
3065
+ if (!entries[0]) throw new Error("One media type is required");
3066
+ const tabs = entries.map((entry) => {
3067
+ const [mediaType, mediaTypeObject] = entry;
3068
+ if (!mediaTypeObject) return {
3069
+ key: mediaType,
3070
+ label: mediaType,
3071
+ body: <OpenAPIEmptyExample context={context} />
3072
+ };
3073
+ return {
3074
+ key: mediaType,
3075
+ label: mediaType,
3076
+ body: <></>,
3077
+ examples: getExamples({
3078
+ mediaTypeObject,
3079
+ mediaType,
3080
+ context
3081
+ })
3082
+ };
3083
+ });
3084
+ return <OpenAPIMediaTypeContent selectIcon={context.icons.chevronDown} stateKey={createStateKey("response-media-types", context.blockKey)} items={tabs} context={getOpenAPIClientContext(context)} />;
3085
+ }
3086
+
3087
+ //#endregion
3088
+ //#region ../../node_modules/@react-stately/utils/dist/useControlledState.mjs
3089
+ function $458b0a5536c1a7cf$export$40bfa8c7b0832715(value, defaultValue, onChange) {
3090
+ let [stateValue, setStateValue] = useState(value || defaultValue);
3091
+ let isControlledRef = useRef(value !== void 0);
3092
+ let isControlled = value !== void 0;
3093
+ useEffect(() => {
3094
+ let wasControlled = isControlledRef.current;
3095
+ if (wasControlled !== isControlled) console.warn(`WARN: A component changed from ${wasControlled ? "controlled" : "uncontrolled"} to ${isControlled ? "controlled" : "uncontrolled"}.`);
3096
+ isControlledRef.current = isControlled;
3097
+ }, [isControlled]);
3098
+ let currentValue = isControlled ? value : stateValue;
3099
+ let setValue = useCallback((value$1, ...args) => {
3100
+ let onChangeCaller = (value$2, ...onChangeArgs) => {
3101
+ if (onChange) {
3102
+ if (!Object.is(currentValue, value$2)) onChange(value$2, ...onChangeArgs);
3103
+ }
3104
+ if (!isControlled) currentValue = value$2;
3105
+ };
3106
+ if (typeof value$1 === "function") {
3107
+ console.warn("We can not support a function callback. See Github Issues for details https://github.com/adobe/react-spectrum/issues/2320");
3108
+ let updateFunction = (oldValue, ...functionArgs) => {
3109
+ let interceptedValue = value$1(isControlled ? currentValue : oldValue, ...functionArgs);
3110
+ onChangeCaller(interceptedValue, ...args);
3111
+ if (!isControlled) return interceptedValue;
3112
+ return oldValue;
3113
+ };
3114
+ setStateValue(updateFunction);
3115
+ } else {
3116
+ if (!isControlled) setStateValue(value$1);
3117
+ onChangeCaller(value$1, ...args);
3118
+ }
3119
+ }, [
3120
+ isControlled,
3121
+ currentValue,
3122
+ onChange
3123
+ ]);
3124
+ return [currentValue, setValue];
3125
+ }
3126
+
3127
+ //#endregion
3128
+ //#region ../../node_modules/@react-stately/disclosure/dist/useDisclosureState.mjs
3129
+ function $bf996d45f4a36925$export$3fcbf6e4407997e0(props) {
3130
+ let [isExpanded, setExpanded] = $458b0a5536c1a7cf$export$40bfa8c7b0832715(props.isExpanded, props.defaultExpanded || false, props.onExpandedChange);
3131
+ return {
3132
+ isExpanded,
3133
+ setExpanded,
3134
+ expand: useCallback(() => {
3135
+ setExpanded(true);
3136
+ }, [setExpanded]),
3137
+ collapse: useCallback(() => {
3138
+ setExpanded(false);
3139
+ }, [setExpanded]),
3140
+ toggle: useCallback(() => {
3141
+ setExpanded(!isExpanded);
3142
+ }, [setExpanded, isExpanded])
3143
+ };
3144
+ }
3145
+
3146
+ //#endregion
3147
+ //#region ../../node_modules/@react-stately/disclosure/dist/useDisclosureGroupState.mjs
3148
+ function $9385b3affbdec831$export$f36461af0ef4707d(props) {
3149
+ let { allowsMultipleExpanded = false, isDisabled = false } = props;
3150
+ let [expandedKeys, setExpandedKeys] = $458b0a5536c1a7cf$export$40bfa8c7b0832715(useMemo(() => props.expandedKeys ? new Set(props.expandedKeys) : void 0, [props.expandedKeys]), useMemo(() => props.defaultExpandedKeys ? new Set(props.defaultExpandedKeys) : /* @__PURE__ */ new Set(), [props.defaultExpandedKeys]), props.onExpandedChange);
3151
+ useEffect(() => {
3152
+ if (!allowsMultipleExpanded && expandedKeys.size > 1) setExpandedKeys(new Set([expandedKeys.values().next().value]));
3153
+ });
3154
+ return {
3155
+ allowsMultipleExpanded,
3156
+ isDisabled,
3157
+ expandedKeys,
3158
+ setExpandedKeys,
3159
+ toggleKey(key) {
3160
+ let keys;
3161
+ if (allowsMultipleExpanded) {
3162
+ keys = new Set(expandedKeys);
3163
+ if (keys.has(key)) keys.delete(key);
3164
+ else keys.add(key);
3165
+ } else keys = new Set(expandedKeys.has(key) ? [] : [key]);
3166
+ setExpandedKeys(keys);
3167
+ }
3168
+ };
3169
+ }
3170
+
3171
+ //#endregion
3172
+ //#region src/InteractiveSection.tsx
3173
+ /**
3174
+ * To optimize rendering, most of the components are server-components,
3175
+ * and the interactiveness is mainly handled by a few key components like this one.
3176
+ */
3177
+ function InteractiveSection(props) {
3178
+ const { id, className, toggeable = false, defaultOpened = true, tabs = [], defaultTab = tabs[0]?.key, header, overlay, toggleIcon = "▶", selectIcon, stateKey = "interactive-section" } = props;
3179
+ const state = $bf996d45f4a36925$export$3fcbf6e4407997e0({ defaultExpanded: defaultOpened });
3180
+ const panelRef = useRef(null);
3181
+ const triggerRef = useRef(null);
3182
+ const { buttonProps: triggerProps, panelProps } = useDisclosure({}, state, panelRef);
3183
+ const { buttonProps } = useButton(triggerProps, triggerRef);
3184
+ const { isFocusVisible, focusProps } = useFocusRing();
3185
+ const store = useSelectState(stateKey, defaultTab);
3186
+ const selectedTab = tabs.find((tab) => tab.key === store.key) ?? tabs[0];
3187
+ return <Section id={id} className={clsx("openapi-section", toggeable ? "openapi-section-toggeable" : null, className, toggeable ? `${className}-${state.isExpanded ? "opened" : "closed"}` : null)}>
3188
+ {header ? <SectionHeader onClick={() => {
3189
+ if (toggeable) state.toggle();
3190
+ }} className={className}>
3191
+ <SectionHeaderContent className={className}>
3192
+ {selectedTab?.body && toggeable ? <button {...mergeProps(buttonProps, focusProps)} ref={triggerRef} className={clsx("openapi-section-toggle", `${className}-toggle`)} style={{ outline: isFocusVisible ? "2px solid rgb(var(--primary-color-500) / 0.4)" : "none" }}>
3193
+ {toggleIcon}
3194
+ </button> : null}
3195
+ {header}
3196
+ </SectionHeaderContent>
3197
+ {}
3198
+ <div className={clsx("openapi-section-header-controls", `${className}-header-controls`)} onClick={(event) => {
3199
+ event.stopPropagation();
3200
+ }}>
3201
+ {tabs.length > 0 ? <OpenAPISelect stateKey={stateKey} items={tabs} onSelectionChange={() => {
3202
+ state.expand();
3203
+ }} icon={selectIcon} placement="bottom end">
3204
+ {tabs.map((tab) => <OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
3205
+ {tab.label}
3206
+ </OpenAPISelectItem>)}
3207
+ </OpenAPISelect> : null}
3208
+ </div>
3209
+ </SectionHeader> : null}
3210
+ {(!toggeable || state.isExpanded) && selectedTab?.body ? <SectionBody ref={panelRef} {...panelProps} className={className}>
3211
+ {selectedTab?.body}
3212
+ </SectionBody> : null}
3213
+ {overlay ? <div className={clsx("openapi-section-overlay", `${className}-overlay`)}>
3214
+ {overlay}
3215
+ </div> : null}
3216
+ </Section>;
3217
+ }
3218
+
3219
+ //#endregion
3220
+ //#region src/OpenAPIRequestBodyHeaderType.tsx
3221
+ /**
3222
+ * Display the type of a request body. It only displays the type if the selected content is an array.
3223
+ */
3224
+ function OpenAPIRequestBodyHeaderType(props) {
3225
+ const { requestBody, stateKey } = props;
3226
+ const content = requestBody.content ?? {};
3227
+ const state = useSelectState(stateKey, Object.keys(content)[0]);
3228
+ const selectedContentMediaType = Object.entries(content).find(([contentType]) => contentType === state.key)?.[1];
3229
+ if (!selectedContentMediaType || !selectedContentMediaType.schema?.type || selectedContentMediaType.schema.type !== "array") return null;
3230
+ return <span className="openapi-requestbody-header-type">
3231
+ {`${getSchemaTitle(selectedContentMediaType.schema)}`}
3232
+ </span>;
3233
+ }
3234
+
3235
+ //#endregion
3236
+ //#region src/OpenAPIRequestBody.tsx
3237
+ /**
3238
+ * Display an interactive request body.
3239
+ */
3240
+ function OpenAPIRequestBody(props) {
3241
+ const { requestBody, context, data } = props;
3242
+ if (checkIsReference(requestBody)) return null;
3243
+ const stateKey = createStateKey("request-body-media-type", context.blockKey);
3244
+ return <InteractiveSection header={<>
3245
+ <span>{t(context.translation, "name" in data ? "payload" : "body")}</span>
3246
+ <OpenAPIRequestBodyHeaderType requestBody={requestBody} stateKey={stateKey} />
3247
+ </>} className="openapi-requestbody" stateKey={stateKey} selectIcon={context.icons.chevronDown} tabs={Object.entries(requestBody.content ?? {}).map(([contentType, mediaTypeObject]) => {
3248
+ return {
3249
+ key: contentType,
3250
+ label: contentType,
3251
+ body: <OpenAPIRootSchema schema={mediaTypeObject.schema ?? {}} context={context} key={contentType} />
3252
+ };
3253
+ })} />;
3254
+ }
3255
+
3256
+ //#endregion
3257
+ //#region src/OpenAPIDisclosureGroup.tsx
3258
+ const DisclosureGroupStateContext = createContext(null);
3259
+ /**
3260
+ * Display an interactive OpenAPI disclosure group.
3261
+ */
3262
+ function OpenAPIDisclosureGroup(props) {
3263
+ const { icon, groups, selectStateKey, selectIcon } = props;
3264
+ const state = $9385b3affbdec831$export$f36461af0ef4707d(props);
3265
+ return <DisclosureGroupStateContext.Provider value={state}>
3266
+ {groups.map((group) => <DisclosureItem selectStateKey={selectStateKey} selectIcon={selectIcon} icon={icon} key={group.key} group={group} />)}
3267
+ </DisclosureGroupStateContext.Provider>;
3268
+ }
3269
+ function DisclosureItem(props) {
3270
+ const { icon, group, selectStateKey, selectIcon } = props;
3271
+ const defaultId = useId$1();
3272
+ const id = group.key || defaultId;
3273
+ const groupState = useContext(DisclosureGroupStateContext);
3274
+ const isExpanded = groupState?.expandedKeys.has(id) || false;
3275
+ const state = $bf996d45f4a36925$export$3fcbf6e4407997e0({
3276
+ isExpanded,
3277
+ onExpandedChange() {
3278
+ if (groupState) groupState.toggleKey(id);
3279
+ }
3280
+ });
3281
+ const panelRef = useRef(null);
3282
+ const triggerRef = useRef(null);
3283
+ const isDisabled = groupState?.isDisabled || !group.tabs?.length || false;
3284
+ const { buttonProps: triggerProps, panelProps } = useDisclosure({
3285
+ ...props,
3286
+ isExpanded,
3287
+ isDisabled
3288
+ }, state, panelRef);
3289
+ const { buttonProps } = useButton(triggerProps, triggerRef);
3290
+ const { isFocusVisible, focusProps } = useFocusRing();
3291
+ const store = useSelectState(selectStateKey, group.tabs?.[0]?.key || "");
3292
+ const selectedTab = group.tabs?.find((tab) => tab.key === store.key) || group.tabs?.[0];
3293
+ return <div className="openapi-disclosure-group" aria-expanded={state.isExpanded}>
3294
+ <div slot="trigger" ref={triggerRef} {...mergeProps(buttonProps, focusProps)} aria-disabled={isDisabled} style={{ outline: isFocusVisible ? "2px solid rgb(var(--primary-color-500)/0.4)" : "none" }} className="openapi-disclosure-group-trigger">
3295
+ <div className="openapi-disclosure-group-icon">
3296
+ {icon || <svg viewBox="0 0 24 24" className="openapi-disclosure-group-icon">
3297
+ <path d="m8.25 4.5 7.5 7.5-7.5 7.5" />
3298
+ </svg>}
3299
+ </div>
3300
+
3301
+ <div className="openapi-disclosure-group-label">
3302
+ {group.label}
3303
+
3304
+ {group.tabs ? <div className="openapi-disclosure-group-mediatype" onClick={(e) => e.stopPropagation()}>
3305
+ {group.tabs?.length > 1 ? <OpenAPISelect icon={selectIcon} stateKey={selectStateKey} onSelectionChange={() => {
3306
+ state.expand();
3307
+ }} items={group.tabs} placement="bottom end">
3308
+ {group.tabs.map((tab) => <OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
3309
+ {tab.label}
3310
+ </OpenAPISelectItem>)}
3311
+ </OpenAPISelect> : group.tabs[0]?.label ? <span>{group.tabs[0].label}</span> : null}
3312
+ </div> : null}
3313
+ </div>
3314
+ </div>
3315
+
3316
+ {state.isExpanded && selectedTab && <div className="openapi-disclosure-group-panel" ref={panelRef} {...panelProps}>
3317
+ {selectedTab.body}
3318
+ </div>}
3319
+ </div>;
3320
+ }
3321
+
3322
+ //#endregion
3323
+ //#region src/OpenAPIResponse.tsx
3324
+ /**
3325
+ * Display an interactive response body.
3326
+ */
3327
+ function OpenAPIResponse(props) {
3328
+ const { response, context, mediaType } = props;
3329
+ const headers = Object.entries(response.headers ?? {}).map(([name, header]) => [name, header ?? {}]);
3330
+ const content = Object.entries(mediaType?.schema ?? {});
3331
+ const description = resolveDescription(response);
3332
+ if (content.length === 0 && !description && headers.length === 0) return null;
3333
+ return <div className="openapi-response-body">
3334
+ {headers.length > 0 ? <OpenAPIDisclosure header={<OpenAPISchemaPresentation context={context} property={{
3335
+ propertyName: tString(context.translation, "headers"),
3336
+ schema: { type: "object" },
3337
+ required: null
3338
+ }} />} icon={context.icons.plus} label={(isExpanded) => tString(context.translation, isExpanded ? "hide" : "show", tString(context.translation, headers.length === 1 ? "header" : "headers"))}>
3339
+ <OpenAPISchemaProperties properties={headers.map(([name, header]) => parameterToProperty({
3340
+ name,
3341
+ ...header
3342
+ }))} context={context} />
3343
+ </OpenAPIDisclosure> : null}
3344
+ {mediaType?.schema && <div className="openapi-responsebody">
3345
+ <OpenAPISchemaProperties id={`response-${context.blockKey}`} properties={[{
3346
+ schema: mediaType.schema,
3347
+ propertyName: tString(context.translation, "response"),
3348
+ required: null
3349
+ }]} context={context} />
3350
+ </div>}
3351
+ </div>;
3352
+ }
3353
+
3354
+ //#endregion
3355
+ //#region src/OpenAPIResponses.tsx
3356
+ /**
3357
+ * Display an interactive response body.
3358
+ */
3359
+ function OpenAPIResponses(props) {
3360
+ const { responses, context } = props;
3361
+ const groups = Object.entries(responses).filter(([_, response]) => response && typeof response === "object").map(([statusCode, response]) => {
3362
+ const tabs = (() => {
3363
+ if ((!response.content || !Object.keys(response.content).length) && response.headers && Object.keys(response.headers).length) return [{
3364
+ key: "default",
3365
+ label: "",
3366
+ body: <OpenAPIResponse response={response} mediaType={{}} context={context} />
3367
+ }];
3368
+ if (!response.content) return [{
3369
+ key: "default",
3370
+ label: "",
3371
+ body: <pre className="openapi-example-empty">
3372
+ <p>{t(context.translation, "no_content")}</p>
3373
+ </pre>
3374
+ }];
3375
+ return Object.entries(response.content ?? {}).map(([contentType, mediaType]) => ({
3376
+ key: contentType,
3377
+ label: contentType,
3378
+ body: <OpenAPIResponse response={response} mediaType={mediaType} context={context} />
3379
+ }));
3380
+ })();
3381
+ const description = resolveDescription(response);
3382
+ return {
3383
+ key: statusCode,
3384
+ label: <div className="openapi-response-tab-content">
3385
+ <span className={clsx("openapi-statuscode", `openapi-statuscode-${getStatusCodeClassName(statusCode)}`)}>
3386
+ {statusCode}
3387
+ </span>
3388
+ {description ? <Markdown source={description} className="openapi-response-description" /> : getStatusCodeDefaultLabel(statusCode, context)}
3389
+ </div>,
3390
+ tabs
3391
+ };
3392
+ });
3393
+ const state = useResponseExamplesState(context.blockKey, groups[0]?.key);
3394
+ return <StaticSection header={t(context.translation, "responses")} className="openapi-responses">
3395
+ <OpenAPIDisclosureGroup icon={context.icons.chevronRight} expandedKeys={state.key ? new Set([state.key]) : /* @__PURE__ */ new Set()} onExpandedChange={(keys) => {
3396
+ const key = keys.values().next().value ?? null;
3397
+ state.setKey(key);
3398
+ }} groups={groups} selectIcon={context.icons.chevronDown} selectStateKey={createStateKey("response-media-types", context.blockKey)} />
3399
+ </StaticSection>;
3400
+ }
3401
+
3402
+ //#endregion
3403
+ //#region src/OpenAPISecurities.tsx
3404
+ /**
3405
+ * Present securities authorization that can be used for this operation.
3406
+ */
3407
+ function OpenAPISecurities(props) {
3408
+ const { securityRequirement, securities, context } = props;
3409
+ if (!securities || securities.length === 0) return null;
3410
+ const tabsData = extractOperationSecurityInfo({
3411
+ securityRequirement,
3412
+ securities
3413
+ });
3414
+ return <InteractiveSection header={t(context.translation, "authorizations")} stateKey={createStateKey("securities", context.blockKey)} toggeable defaultOpened={false} toggleIcon={context.icons.chevronRight} selectIcon={context.icons.chevronDown} className="openapi-securities" tabs={tabsData.map(({ key, label, schemes }) => ({
3415
+ key,
3416
+ label,
3417
+ body: <div className="openapi-schema">
3418
+ {schemes.map((security, index) => {
3419
+ const description = resolveDescription(security);
3420
+ return <div key={`${key}-${index}`} className="openapi-schema-presentation">
3421
+ {getLabelForType(security, context)}
3422
+ {description ? <Markdown source={description} className="openapi-securities-description" /> : null}
3423
+ {security.scopes?.length ? <OpenAPISchemaScopes scopes={security.scopes} context={context} /> : null}
3424
+ </div>;
3425
+ })}
3426
+ </div>
3427
+ }))} />;
3428
+ }
3429
+ function getLabelForType(security, context) {
3430
+ switch (security.type) {
3431
+ case "apiKey": return <OpenAPISchemaName context={context} propertyName={security.name ?? "apiKey"} type="string" required={security.required} />;
3432
+ case "http":
3433
+ if (security.scheme === "basic") return <OpenAPISchemaName context={context} propertyName="Authorization" type="string" required={security.required} />;
3434
+ if (security.scheme === "bearer") return <>
3435
+ <OpenAPISchemaName context={context} propertyName="Authorization" type="string" required={security.required} />
3436
+ { /** Show a default description if none is provided */}
3437
+ {!security.description ? <Markdown source={`Bearer authentication header of the form Bearer &lt;token&gt;.`} className="openapi-securities-description" /> : null}
3438
+ </>;
3439
+ return <OpenAPISchemaName context={context} propertyName="HTTP" required={security.required} />;
3440
+ case "oauth2": return <OpenAPISchemaOAuth2Flows context={context} security={security} />;
3441
+ case "openIdConnect": return <OpenAPISchemaName context={context} propertyName="OpenID Connect" required={security.required} />;
3442
+ default: return security.type;
3443
+ }
3444
+ }
3445
+ function OpenAPISchemaOAuth2Flows(props) {
3446
+ const { context, security } = props;
3447
+ const flows = security.flows ? Object.entries(security.flows) : [];
3448
+ return <div className="openapi-securities-oauth-flows">
3449
+ {flows.map(([name, flow], index) => <Fragment key={index}>
3450
+ <OpenAPISchemaOAuth2Item flow={flow} name={name} context={context} security={security} />
3451
+ {index < flows.length - 1 ? <hr /> : null}
3452
+ </Fragment>)}
3453
+ </div>;
3454
+ }
3455
+ function OpenAPISchemaOAuth2Item(props) {
3456
+ const { flow, context, security, name } = props;
3457
+ if (!flow) return null;
3458
+ const scopes = flow.scopes ? Object.entries(flow.scopes) : [];
3459
+ return <div>
3460
+ <OpenAPISchemaName context={context} propertyName="OAuth2" type={name} required={security.required} />
3461
+ <div className="openapi-securities-oauth-content openapi-markdown">
3462
+ {security.description ? <Markdown source={security.description} /> : null}
3463
+ {"authorizationUrl" in flow && flow.authorizationUrl ? <span>
3464
+ Authorization URL:{" "}
3465
+ <OpenAPICopyButton value={flow.authorizationUrl} context={context} className="openapi-securities-url" withTooltip>
3466
+ {flow.authorizationUrl}
3467
+ </OpenAPICopyButton>
3468
+ </span> : null}
3469
+ {"tokenUrl" in flow && flow.tokenUrl ? <span>
3470
+ Token URL:{" "}
3471
+ <OpenAPICopyButton value={flow.tokenUrl} context={context} className="openapi-securities-url" withTooltip>
3472
+ {flow.tokenUrl}
3473
+ </OpenAPICopyButton>
3474
+ </span> : null}
3475
+ {"refreshUrl" in flow && flow.refreshUrl ? <span>
3476
+ Refresh URL:{" "}
3477
+ <OpenAPICopyButton value={flow.refreshUrl} context={context} className="openapi-securities-url" withTooltip>
3478
+ {flow.refreshUrl}
3479
+ </OpenAPICopyButton>
3480
+ </span> : null}
3481
+ {scopes.length ? <OpenAPISchemaScopes scopes={scopes} context={context} /> : null}
3482
+ </div>
3483
+ </div>;
3484
+ }
3485
+ /**
3486
+ * Render a list of available scopes.
3487
+ */
3488
+ function OpenAPISchemaScopes(props) {
3489
+ const { scopes, context } = props;
3490
+ return <div className="openapi-securities-scopes openapi-markdown">
3491
+ <span>{t(context.translation, "required_scopes")}: </span>
3492
+ <ul>
3493
+ {scopes.map((scope) => <OpenAPIScopeItem key={scope[0]} scope={scope} context={context} />)}
3494
+ </ul>
3495
+ </div>;
3496
+ }
3497
+ /**
3498
+ * Display a scope item. Either a key-value pair or a single string.
3499
+ */
3500
+ function OpenAPIScopeItem(props) {
3501
+ const { scope, context } = props;
3502
+ return <li>
3503
+ <OpenAPIScopeItemKey name={scope[0]} context={context} />
3504
+ {scope[1] ? `: ${scope[1]}` : null}
3505
+ </li>;
3506
+ }
3507
+ /**
3508
+ * Displays the scope name within a copyable button.
3509
+ */
3510
+ function OpenAPIScopeItemKey(props) {
3511
+ const { name, context } = props;
3512
+ return <OpenAPICopyButton value={name} context={context} withTooltip>
3513
+ <code>{name}</code>
3514
+ </OpenAPICopyButton>;
3515
+ }
3516
+
3517
+ //#endregion
3518
+ //#region src/OpenAPISpec.tsx
3519
+ function OpenAPISpec(props) {
3520
+ const { data, context } = props;
3521
+ const { operation } = data;
3522
+ const parameterGroups = groupParameters(deduplicateParameters(operation.parameters ?? []), context);
3523
+ const securities = "securities" in data ? data.securities : [];
3524
+ return <>
3525
+ {securities.length > 0 ? <OpenAPISecurities key="securities" securityRequirement={operation.security} securities={securities} context={context} /> : null}
3526
+
3527
+ {parameterGroups.map((group) => {
3528
+ return <StaticSection key={`parameter-${group.key}`} className="openapi-parameters" header={group.label}>
3529
+ <OpenAPISchemaProperties properties={group.parameters.map(parameterToProperty)} context={context} />
3530
+ </StaticSection>;
3531
+ })}
3532
+
3533
+ {operation.requestBody ? <OpenAPIRequestBody key="body" requestBody={operation.requestBody} context={context} data={data} /> : null}
3534
+ {operation.responses ? <OpenAPIResponses key="responses" responses={operation.responses} context={context} /> : null}
3535
+ </>;
3536
+ }
3537
+ function groupParameters(parameters, context) {
3538
+ const sorted = [
3539
+ "path",
3540
+ "query",
3541
+ "header"
3542
+ ];
3543
+ const groups = [];
3544
+ parameters.filter((parameter) => parameter.in).forEach((parameter) => {
3545
+ const key = parameter.in;
3546
+ const label = getParameterGroupName(parameter.in, context);
3547
+ const group = groups.find((group$1) => group$1.key === key);
3548
+ if (group) group.parameters.push(parameter);
3549
+ else groups.push({
3550
+ key,
3551
+ label,
3552
+ parameters: [parameter]
3553
+ });
3554
+ });
3555
+ groups.sort((a, b) => sorted.indexOf(a.key) - sorted.indexOf(b.key));
3556
+ return groups;
3557
+ }
3558
+ function getParameterGroupName(paramIn, context) {
3559
+ switch (paramIn) {
3560
+ case "path": return tString(context.translation, "path_parameters");
3561
+ case "query": return tString(context.translation, "query_parameters");
3562
+ case "header": return tString(context.translation, "header_parameters");
3563
+ default: return paramIn;
3564
+ }
3565
+ }
3566
+ /** Deduplicate parameters by name and in.
3567
+ * Some specs have both parameters define at path and operation level.
3568
+ * We only want to display one of them.
3569
+ * Parameters can have the wrong type (object instead of array) sometimes, we just return an empty array in that case.
3570
+ */
3571
+ function deduplicateParameters(parameters) {
3572
+ const seen = /* @__PURE__ */ new Set();
3573
+ return Array.isArray(parameters) ? parameters.filter((param) => {
3574
+ const key = `${param.name}:${param.in}`;
3575
+ if (seen.has(key)) return false;
3576
+ seen.add(key);
3577
+ return true;
3578
+ }) : [];
3579
+ }
3580
+
3581
+ //#endregion
3582
+ //#region src/common/OpenAPIOperationDescription.tsx
3583
+ function OpenAPIOperationDescription(props) {
3584
+ const { operation } = props;
3585
+ if (operation["x-gitbook-description-document"]) return <div className="openapi-intro">
3586
+ {props.context.renderDocument({ document: operation["x-gitbook-description-document"] })}
3587
+ </div>;
3588
+ const description = resolveDescription(operation);
3589
+ if (!description) return null;
3590
+ return <div className="openapi-intro">
3591
+ <Markdown className="openapi-description" source={description} />
3592
+ </div>;
3593
+ }
3594
+
3595
+ //#endregion
3596
+ //#region src/common/OpenAPIColumnSpec.tsx
3597
+ function OpenAPIColumnSpec(props) {
3598
+ const { data, context } = props;
3599
+ const { operation } = data;
3600
+ const clientContext = getOpenAPIClientContext(context);
3601
+ return <div className="openapi-column-spec">
3602
+ {operation["x-deprecated-sunset"] ? <div className="openapi-deprecated-sunset openapi-description openapi-markdown">
3603
+ {t(context.translation, "deprecated_and_sunset_on", [<span key="date" className="openapi-deprecated-sunset-date">
3604
+ {operation["x-deprecated-sunset"]}
3605
+ </span>])}
3606
+ </div> : null}
3607
+ <OpenAPIOperationDescription operation={operation} context={context} />
3608
+ <OpenAPISpec data={data} context={clientContext} />
3609
+ </div>;
3610
+ }
3611
+
3612
+ //#endregion
3613
+ //#region src/common/OpenAPIStability.tsx
3614
+ const stabilityEnum = {
3615
+ experimental: "Experimental",
3616
+ alpha: "Alpha",
3617
+ beta: "Beta"
3618
+ };
3619
+ function OpenAPIStability(props) {
3620
+ const { stability } = props;
3621
+ const foundStability = stabilityEnum[stability];
3622
+ if (!foundStability) return null;
3623
+ return <div className={`openapi-stability openapi-stability-${foundStability.toLowerCase()}`}>
3624
+ {foundStability}
3625
+ </div>;
3626
+ }
3627
+
3628
+ //#endregion
3629
+ //#region src/common/OpenAPISummary.tsx
3630
+ function OpenAPISummary(props) {
3631
+ const { data, context } = props;
3632
+ const { operation } = data;
3633
+ const title = (() => {
3634
+ if (operation.summary) return operation.summary;
3635
+ if ("name" in data) return data.name;
3636
+ })();
3637
+ return <div className="openapi-summary" id={operation.summary ? void 0 : context.id}>
3638
+ {(operation.deprecated || operation["x-stability"]) && <div className="openapi-summary-tags">
3639
+ {operation.deprecated && <div className="openapi-deprecated">Deprecated</div>}
3640
+ {operation["x-stability"] && <OpenAPIStability stability={operation["x-stability"]} />}
3641
+ </div>}
3642
+ {title ? context.renderHeading({
3643
+ deprecated: operation.deprecated ?? false,
3644
+ stability: operation["x-stability"],
3645
+ title
3646
+ }) : null}
3647
+ {"path" in data ? <OpenAPIPath data={data} context={context} /> : null}
3648
+ </div>;
3649
+ }
3650
+
3651
+ //#endregion
3652
+ //#region src/OpenAPIOperation.tsx
3653
+ /**
3654
+ * Display an interactive OpenAPI operation.
3655
+ */
3656
+ function OpenAPIOperation(props) {
3657
+ const { className, data, context: contextInput } = props;
3658
+ const context = resolveOpenAPIContext(contextInput);
3659
+ return <div className={clsx("openapi-operation", className)}>
3660
+ <OpenAPISummary data={data} context={context} />
3661
+ <div className="openapi-columns">
3662
+ <OpenAPIColumnSpec data={data} context={context} />
3663
+ <div className="openapi-column-preview">
3664
+ <div className="openapi-column-preview-body">
3665
+ <OpenAPICodeSample data={data} context={context} />
3666
+ <OpenAPIResponseExample data={data} context={context} />
3667
+ </div>
3668
+ </div>
3669
+ </div>
3670
+ </div>;
3671
+ }
3672
+
3673
+ //#endregion
3674
+ //#region src/OpenAPIWebhookExample.tsx
3675
+ function OpenAPIWebhookExample(props) {
3676
+ const { data, context } = props;
3677
+ const { operation } = data;
3678
+ const items = (() => {
3679
+ if (!operation.requestBody) return [];
3680
+ return Object.entries(operation.requestBody.content).map(([key, value]) => {
3681
+ if (!value?.schema) return {
3682
+ key,
3683
+ label: key,
3684
+ body: <OpenAPIEmptyExample context={context} />
3685
+ };
3686
+ return {
3687
+ key,
3688
+ label: key,
3689
+ body: <></>,
3690
+ examples: getExamples({
3691
+ mediaTypeObject: value,
3692
+ mediaType: key,
3693
+ context
3694
+ })
3695
+ };
3696
+ });
3697
+ })();
3698
+ return <div className="openapi-panel">
3699
+ <h4 className="openapi-panel-heading">Payload</h4>
3700
+ <div className="openapi-panel-body">
3701
+ <OpenAPIMediaTypeContent selectIcon={context.icons.chevronDown} stateKey={createStateKey("request-body-media-type", context.blockKey)} items={items} context={getOpenAPIClientContext(context)} />
3702
+ </div>
3703
+ </div>;
3704
+ }
3705
+
3706
+ //#endregion
3707
+ //#region src/OpenAPIWebhook.tsx
3708
+ /**
3709
+ * Display an interactive OpenAPI webhook.
3710
+ */
3711
+ function OpenAPIWebhook(props) {
3712
+ const { className, data, context: contextInput } = props;
3713
+ const context = resolveOpenAPIContext(contextInput);
3714
+ return <div className={clsx("openapi-webhook", className)}>
3715
+ <OpenAPISummary data={data} context={context} />
3716
+ <div className="openapi-columns">
3717
+ <OpenAPIColumnSpec data={data} context={context} />
3718
+ <div className="openapi-column-preview">
3719
+ <div className="openapi-column-preview-body">
3720
+ <OpenAPIWebhookExample data={data} context={context} />
3721
+ </div>
3722
+ </div>
3723
+ </div>
3724
+ </div>;
3725
+ }
3726
+
3727
+ //#endregion
3728
+ //#region src/resolveOpenAPIOperation.ts
3729
+ /**
3730
+ * Resolve an OpenAPI operation in a file and compile it to a more usable format.
3731
+ */
3732
+ async function resolveOpenAPIOperation(filesystem, operationDescriptor) {
3733
+ const { path, method } = operationDescriptor;
3734
+ const schema = await dereferenceFilesystem(filesystem);
3735
+ let operation = getOperationByPathAndMethod(schema, path, method);
3736
+ if (!operation) return null;
3737
+ const commonParameters = getPathObjectParameter$1(schema, path);
3738
+ if (commonParameters) operation = {
3739
+ ...operation,
3740
+ parameters: [...commonParameters, ...operation.parameters ?? []]
3741
+ };
3742
+ const servers = "servers" in schema ? schema.servers ?? [] : [];
3743
+ const schemaSecurity = Array.isArray(schema.security) ? schema.security : schema.security ? [schema.security] : [];
3744
+ const security = operation.security ?? schemaSecurity;
3745
+ const isOptionalSecurity = security.some((entry) => Object.keys(entry).length === 0);
3746
+ const flatSecurities = flattenSecurities(security);
3747
+ const securities = [];
3748
+ for (const entry of flatSecurities) {
3749
+ const [securityKey, operationScopes] = Object.entries(entry)[0] ?? [];
3750
+ if (securityKey) {
3751
+ const securityScheme = schema.components?.securitySchemes?.[securityKey];
3752
+ const scopes = resolveSecurityScopes({
3753
+ securityScheme,
3754
+ operationScopes
3755
+ });
3756
+ securities.push([securityKey, {
3757
+ ...securityScheme,
3758
+ required: !isOptionalSecurity,
3759
+ scopes
3760
+ }]);
3761
+ }
3762
+ }
3763
+ return {
3764
+ servers,
3765
+ operation: {
3766
+ ...operation,
3767
+ security
3768
+ },
3769
+ method,
3770
+ path,
3771
+ securities,
3772
+ "x-codeSamples": typeof schema["x-codeSamples"] === "boolean" ? schema["x-codeSamples"] : void 0,
3773
+ "x-hideTryItPanel": typeof schema["x-hideTryItPanel"] === "boolean" ? schema["x-hideTryItPanel"] : void 0
3774
+ };
3775
+ }
3776
+ /**
3777
+ * Get a path object from its path.
3778
+ */
3779
+ function getPathObject$1(schema, path) {
3780
+ return schema.paths?.[path] || null;
3781
+ }
3782
+ /**
3783
+ * Resolve parameters from a path in an OpenAPI schema.
3784
+ */
3785
+ function getPathObjectParameter$1(schema, path) {
3786
+ const pathObject = getPathObject$1(schema, path);
3787
+ if (pathObject?.parameters) return pathObject.parameters;
3788
+ return null;
3789
+ }
3790
+ /**
3791
+ * Get an operation by its path and method.
3792
+ */
3793
+ function getOperationByPathAndMethod(schema, path, method) {
3794
+ const pathObject = getPathObject$1(schema, path);
3795
+ if (!pathObject) return null;
3796
+ const normalizedMethod = method.toLowerCase();
3797
+ if (!pathObject[normalizedMethod]) return null;
3798
+ return pathObject[normalizedMethod];
3799
+ }
3800
+ /**
3801
+ * Flatten security objects in case they are nested.
3802
+ * @example [{bearerAuth:[], basicAuth:[]}] => [{ bearerAuth: [] }, { basicAuth: [] }]
3803
+ */
3804
+ function flattenSecurities(security) {
3805
+ if (!Array.isArray(security) || security.length === 0) return [];
3806
+ return security.flatMap((securityObject) => {
3807
+ return Object.entries(securityObject).map(([authType, config]) => ({ [authType]: config }));
3808
+ });
3809
+ }
3810
+ /**
3811
+ * Resolve the scopes for a security scheme.
3812
+ */
3813
+ function resolveSecurityScopes({ securityScheme, operationScopes }) {
3814
+ if (!securityScheme || checkIsReference(securityScheme) || isOAuthSecurityScheme(securityScheme)) return null;
3815
+ return operationScopes?.map((scope) => [scope, void 0]) || [];
3816
+ }
3817
+ /**
3818
+ * Check if a security scheme is an OAuth or OpenID Connect security scheme.
3819
+ */
3820
+ function isOAuthSecurityScheme(securityScheme) {
3821
+ return securityScheme.type === "oauth2";
3822
+ }
3823
+
3824
+ //#endregion
3825
+ //#region src/resolveOpenAPIWebhook.ts
3826
+ /**
3827
+ * Resolve an OpenAPI webhook in a file and compile it to a more usable format.
3828
+ */
3829
+ async function resolveOpenAPIWebhook(filesystem, webhookDescriptor) {
3830
+ const { name, method } = webhookDescriptor;
3831
+ const schema = await dereferenceFilesystem(filesystem);
3832
+ let operation = getWebhookByNameAndMethod(schema, name, method);
3833
+ if (!operation) return null;
3834
+ const commonParameters = getPathObjectParameter(schema, name);
3835
+ if (commonParameters) operation = {
3836
+ ...operation,
3837
+ parameters: [...commonParameters, ...operation.parameters ?? []]
3838
+ };
3839
+ return {
3840
+ servers: "servers" in schema ? schema.servers ?? [] : [],
3841
+ operation,
3842
+ method,
3843
+ name
3844
+ };
3845
+ }
3846
+ /**
3847
+ * Get a path object from its path.
3848
+ */
3849
+ function getPathObject(schema, name) {
3850
+ if (schema.webhooks?.[name]) return schema.webhooks[name];
3851
+ return null;
3852
+ }
3853
+ /**
3854
+ * Resolve parameters from a path in an OpenAPI schema.
3855
+ */
3856
+ function getPathObjectParameter(schema, path) {
3857
+ const pathObject = getPathObject(schema, path);
3858
+ if (pathObject?.parameters) return pathObject.parameters;
3859
+ return null;
3860
+ }
3861
+ /**
3862
+ * Get an operation by its path and method.
3863
+ */
3864
+ function getWebhookByNameAndMethod(schema, name, method) {
3865
+ const pathObject = getPathObject(schema, name);
3866
+ if (!pathObject) return null;
3867
+ const normalizedMethod = method.toLowerCase();
3868
+ if (!pathObject[normalizedMethod]) return null;
3869
+ return pathObject[normalizedMethod];
3870
+ }
3871
+
3872
+ //#endregion
3873
+ export { OpenAPIOperation, OpenAPIOperationContextProvider, OpenAPIPrefillContextProvider, OpenAPISchemas, OpenAPIWebhook, checkIsValidLocale, resolveOpenAPIOperation, resolveOpenAPISchemas, resolveOpenAPIWebhook, useOpenAPIOperationContext, useOpenAPIPrefillContext };