@gitbook/react-openapi 1.4.3 → 1.5.2

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 (263) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/InteractiveSection.js +59 -0
  3. package/dist/Markdown.js +10 -0
  4. package/dist/OpenAPICodeSample.js +219 -0
  5. package/dist/OpenAPICodeSampleInteractive.js +66 -0
  6. package/dist/OpenAPICodeSampleSelector.js +45 -0
  7. package/dist/OpenAPICopyButton.js +39 -0
  8. package/dist/OpenAPIDisclosure.js +30 -0
  9. package/dist/OpenAPIDisclosureGroup.js +75 -0
  10. package/dist/OpenAPIExample.js +41 -0
  11. package/dist/OpenAPIMediaType.js +58 -0
  12. package/dist/OpenAPIOperation.d.ts +12 -7
  13. package/dist/OpenAPIOperation.js +30 -0
  14. package/dist/OpenAPIOperationContext.d.ts +10 -6
  15. package/dist/OpenAPIOperationContext.js +30 -0
  16. package/dist/OpenAPIPath.js +51 -0
  17. package/dist/OpenAPIPrefillContextProvider.d.ts +11 -7
  18. package/dist/OpenAPIPrefillContextProvider.js +25 -0
  19. package/dist/OpenAPIRequestBody.js +28 -0
  20. package/dist/OpenAPIRequestBodyHeaderType.js +23 -0
  21. package/dist/OpenAPIResponse.js +39 -0
  22. package/dist/OpenAPIResponseExample.js +75 -0
  23. package/dist/OpenAPIResponseExampleContent.js +61 -0
  24. package/dist/OpenAPIResponses.js +61 -0
  25. package/dist/OpenAPISchema.js +373 -0
  26. package/dist/OpenAPISchemaName.js +45 -0
  27. package/dist/OpenAPISchemaServer.js +13 -0
  28. package/dist/OpenAPISecurities.js +124 -0
  29. package/dist/OpenAPISelect.js +45 -0
  30. package/dist/OpenAPISpec.js +73 -0
  31. package/dist/OpenAPIWebhook.d.ts +12 -7
  32. package/dist/OpenAPIWebhook.js +28 -0
  33. package/dist/OpenAPIWebhookExample.js +40 -0
  34. package/dist/ScalarApiButton.js +87 -0
  35. package/dist/StaticSection.js +37 -0
  36. package/dist/code-samples.js +267 -419
  37. package/dist/common/OpenAPIColumnSpec.js +23 -0
  38. package/dist/common/OpenAPIOperationDescription.js +18 -0
  39. package/dist/common/OpenAPIStability.js +17 -0
  40. package/dist/common/OpenAPISummary.js +27 -0
  41. package/dist/contentTypeChecks.js +24 -20
  42. package/dist/context.d.ts +68 -72
  43. package/dist/context.js +25 -39
  44. package/dist/decycle.js +39 -68
  45. package/dist/dereference.js +20 -64
  46. package/dist/generateSchemaExample.js +188 -332
  47. package/dist/getDisclosureLabel.js +15 -16
  48. package/dist/getOrCreateStoreByKey.js +20 -17
  49. package/dist/index.d.ts +12 -10
  50. package/dist/index.js +11 -8
  51. package/dist/json2xml.js +10 -5
  52. package/dist/resolveOpenAPIOperation.d.ts +11 -7
  53. package/dist/resolveOpenAPIOperation.js +88 -159
  54. package/dist/resolveOpenAPIWebhook.d.ts +11 -7
  55. package/dist/resolveOpenAPIWebhook.js +41 -116
  56. package/dist/schemas/OpenAPISchemaItem.js +26 -0
  57. package/dist/schemas/OpenAPISchemas.d.ts +16 -11
  58. package/dist/schemas/OpenAPISchemas.js +57 -0
  59. package/dist/schemas/resolveOpenAPISchemas.d.ts +9 -4
  60. package/dist/schemas/resolveOpenAPISchemas.js +15 -59
  61. package/dist/stringifyOpenAPI.js +12 -13
  62. package/dist/translate.js +43 -0
  63. package/dist/translations/de.js +47 -42
  64. package/dist/translations/en.d.ts +46 -42
  65. package/dist/translations/en.js +47 -42
  66. package/dist/translations/es.js +47 -42
  67. package/dist/translations/fr.js +47 -42
  68. package/dist/translations/index.d.ts +404 -391
  69. package/dist/translations/index.js +28 -24
  70. package/dist/translations/ja.js +47 -42
  71. package/dist/translations/nl.js +47 -42
  72. package/dist/translations/no.js +47 -42
  73. package/dist/translations/pt-br.js +47 -42
  74. package/dist/translations/types.d.ts +7 -5
  75. package/dist/translations/zh.js +47 -42
  76. package/dist/types.d.ts +30 -24
  77. package/dist/util/example.js +84 -0
  78. package/dist/util/server.js +32 -38
  79. package/dist/util/tryit-prefill.js +135 -121
  80. package/dist/utils.js +135 -196
  81. package/package.json +18 -11
  82. package/dist/InteractiveSection.d.ts +0 -33
  83. package/dist/InteractiveSection.jsx +0 -61
  84. package/dist/Markdown.d.ts +0 -4
  85. package/dist/Markdown.jsx +0 -5
  86. package/dist/OpenAPICodeSample.d.ts +0 -19
  87. package/dist/OpenAPICodeSample.jsx +0 -230
  88. package/dist/OpenAPICodeSampleInteractive.d.ts +0 -14
  89. package/dist/OpenAPICodeSampleInteractive.jsx +0 -73
  90. package/dist/OpenAPICodeSampleSelector.d.ts +0 -14
  91. package/dist/OpenAPICodeSampleSelector.jsx +0 -44
  92. package/dist/OpenAPICopyButton.d.ts +0 -13
  93. package/dist/OpenAPICopyButton.jsx +0 -35
  94. package/dist/OpenAPIDisclosure.d.ts +0 -11
  95. package/dist/OpenAPIDisclosure.jsx +0 -30
  96. package/dist/OpenAPIDisclosureGroup.d.ts +0 -23
  97. package/dist/OpenAPIDisclosureGroup.jsx +0 -83
  98. package/dist/OpenAPIExample.d.ts +0 -16
  99. package/dist/OpenAPIExample.jsx +0 -36
  100. package/dist/OpenAPIMediaType.d.ts +0 -21
  101. package/dist/OpenAPIMediaType.jsx +0 -61
  102. package/dist/OpenAPIOperation.jsx +0 -25
  103. package/dist/OpenAPIOperationContext.jsx +0 -26
  104. package/dist/OpenAPIOperationDescription.d.ts +0 -9
  105. package/dist/OpenAPIOperationDescription.jsx +0 -22
  106. package/dist/OpenAPIOperationStability.d.ts +0 -9
  107. package/dist/OpenAPIOperationStability.jsx +0 -27
  108. package/dist/OpenAPIPath.d.ts +0 -18
  109. package/dist/OpenAPIPath.jsx +0 -55
  110. package/dist/OpenAPIPrefillContextProvider.jsx +0 -19
  111. package/dist/OpenAPIRequestBody.d.ts +0 -11
  112. package/dist/OpenAPIRequestBody.jsx +0 -28
  113. package/dist/OpenAPIRequestBodyHeaderType.d.ts +0 -8
  114. package/dist/OpenAPIRequestBodyHeaderType.jsx +0 -25
  115. package/dist/OpenAPIResponse.d.ts +0 -10
  116. package/dist/OpenAPIResponse.jsx +0 -57
  117. package/dist/OpenAPIResponseExample.d.ts +0 -9
  118. package/dist/OpenAPIResponseExample.jsx +0 -105
  119. package/dist/OpenAPIResponseExampleContent.d.ts +0 -22
  120. package/dist/OpenAPIResponseExampleContent.jsx +0 -60
  121. package/dist/OpenAPIResponses.d.ts +0 -9
  122. package/dist/OpenAPIResponses.jsx +0 -77
  123. package/dist/OpenAPISchema.d.ts +0 -27
  124. package/dist/OpenAPISchema.jsx +0 -400
  125. package/dist/OpenAPISchemaName.d.ts +0 -16
  126. package/dist/OpenAPISchemaName.jsx +0 -43
  127. package/dist/OpenAPISchemaServer.d.ts +0 -12
  128. package/dist/OpenAPISchemaServer.jsx +0 -8
  129. package/dist/OpenAPISecurities.d.ts +0 -9
  130. package/dist/OpenAPISecurities.jsx +0 -114
  131. package/dist/OpenAPISelect.d.ts +0 -22
  132. package/dist/OpenAPISelect.jsx +0 -44
  133. package/dist/OpenAPISpec.d.ts +0 -6
  134. package/dist/OpenAPISpec.jsx +0 -80
  135. package/dist/OpenAPITabs.d.ts +0 -26
  136. package/dist/OpenAPITabs.jsx +0 -109
  137. package/dist/OpenAPIWebhook.jsx +0 -23
  138. package/dist/OpenAPIWebhookExample.d.ts +0 -6
  139. package/dist/OpenAPIWebhookExample.jsx +0 -41
  140. package/dist/ScalarApiButton.d.ts +0 -14
  141. package/dist/ScalarApiButton.jsx +0 -81
  142. package/dist/StaticSection.d.ts +0 -13
  143. package/dist/StaticSection.jsx +0 -32
  144. package/dist/code-samples.d.ts +0 -17
  145. package/dist/common/OpenAPIColumnSpec.d.ts +0 -6
  146. package/dist/common/OpenAPIColumnSpec.jsx +0 -20
  147. package/dist/common/OpenAPIOperationDescription.d.ts +0 -6
  148. package/dist/common/OpenAPIOperationDescription.jsx +0 -19
  149. package/dist/common/OpenAPIStability.d.ts +0 -4
  150. package/dist/common/OpenAPIStability.jsx +0 -15
  151. package/dist/common/OpenAPISummary.d.ts +0 -6
  152. package/dist/common/OpenAPISummary.jsx +0 -30
  153. package/dist/contentTypeChecks.d.ts +0 -10
  154. package/dist/decycle.d.ts +0 -2
  155. package/dist/dereference.d.ts +0 -5
  156. package/dist/generateSchemaExample.d.ts +0 -45
  157. package/dist/getDisclosureLabel.d.ts +0 -7
  158. package/dist/getOrCreateStoreByKey.d.ts +0 -10
  159. package/dist/json2xml.d.ts +0 -4
  160. package/dist/schemas/OpenAPISchemaItem.d.ts +0 -7
  161. package/dist/schemas/OpenAPISchemaItem.jsx +0 -16
  162. package/dist/schemas/OpenAPISchemas.jsx +0 -59
  163. package/dist/schemas/index.d.ts +0 -2
  164. package/dist/schemas/index.js +0 -2
  165. package/dist/stringifyOpenAPI.d.ts +0 -4
  166. package/dist/translate.d.ts +0 -10
  167. package/dist/translate.jsx +0 -75
  168. package/dist/translations/de.d.ts +0 -43
  169. package/dist/translations/es.d.ts +0 -43
  170. package/dist/translations/fr.d.ts +0 -43
  171. package/dist/translations/ja.d.ts +0 -43
  172. package/dist/translations/nl.d.ts +0 -43
  173. package/dist/translations/no.d.ts +0 -43
  174. package/dist/translations/pt-br.d.ts +0 -43
  175. package/dist/translations/types.js +0 -1
  176. package/dist/translations/zh.d.ts +0 -43
  177. package/dist/tsconfig.build.tsbuildinfo +0 -1
  178. package/dist/types.js +0 -1
  179. package/dist/util/example.d.ts +0 -35
  180. package/dist/util/example.jsx +0 -103
  181. package/dist/util/server.d.ts +0 -9
  182. package/dist/util/tryit-prefill.d.ts +0 -20
  183. package/dist/utils.d.ts +0 -50
  184. package/src/InteractiveSection.tsx +0 -147
  185. package/src/Markdown.tsx +0 -12
  186. package/src/OpenAPICodeSample.tsx +0 -330
  187. package/src/OpenAPICodeSampleInteractive.tsx +0 -136
  188. package/src/OpenAPICodeSampleSelector.tsx +0 -94
  189. package/src/OpenAPICopyButton.tsx +0 -72
  190. package/src/OpenAPIDisclosure.tsx +0 -46
  191. package/src/OpenAPIDisclosureGroup.tsx +0 -158
  192. package/src/OpenAPIExample.tsx +0 -55
  193. package/src/OpenAPIMediaType.tsx +0 -139
  194. package/src/OpenAPIOperation.tsx +0 -35
  195. package/src/OpenAPIOperationContext.tsx +0 -45
  196. package/src/OpenAPIOperationDescription.tsx +0 -34
  197. package/src/OpenAPIOperationStability.tsx +0 -39
  198. package/src/OpenAPIPath.tsx +0 -90
  199. package/src/OpenAPIPrefillContextProvider.tsx +0 -40
  200. package/src/OpenAPIRequestBody.tsx +0 -54
  201. package/src/OpenAPIRequestBodyHeaderType.tsx +0 -36
  202. package/src/OpenAPIResponse.tsx +0 -82
  203. package/src/OpenAPIResponseExample.tsx +0 -151
  204. package/src/OpenAPIResponseExampleContent.tsx +0 -125
  205. package/src/OpenAPIResponses.tsx +0 -125
  206. package/src/OpenAPISchema.test.ts +0 -172
  207. package/src/OpenAPISchema.tsx +0 -654
  208. package/src/OpenAPISchemaName.tsx +0 -80
  209. package/src/OpenAPISchemaServer.tsx +0 -34
  210. package/src/OpenAPISecurities.tsx +0 -231
  211. package/src/OpenAPISelect.tsx +0 -96
  212. package/src/OpenAPISpec.tsx +0 -138
  213. package/src/OpenAPITabs.tsx +0 -147
  214. package/src/OpenAPIWebhook.tsx +0 -33
  215. package/src/OpenAPIWebhookExample.tsx +0 -60
  216. package/src/ScalarApiButton.tsx +0 -132
  217. package/src/StaticSection.tsx +0 -91
  218. package/src/__snapshots__/json2xml.test.ts.snap +0 -18
  219. package/src/code-samples.test.ts +0 -714
  220. package/src/code-samples.ts +0 -448
  221. package/src/common/OpenAPIColumnSpec.tsx +0 -31
  222. package/src/common/OpenAPIOperationDescription.tsx +0 -31
  223. package/src/common/OpenAPIStability.tsx +0 -23
  224. package/src/common/OpenAPISummary.tsx +0 -45
  225. package/src/contentTypeChecks.ts +0 -39
  226. package/src/context.ts +0 -99
  227. package/src/decycle.ts +0 -68
  228. package/src/dereference.ts +0 -29
  229. package/src/generateSchemaExample.test.ts +0 -1040
  230. package/src/generateSchemaExample.ts +0 -530
  231. package/src/getDisclosureLabel.ts +0 -25
  232. package/src/getOrCreateStoreByKey.ts +0 -33
  233. package/src/index.ts +0 -10
  234. package/src/json2xml.test.ts +0 -46
  235. package/src/json2xml.ts +0 -8
  236. package/src/resolveOpenAPIOperation.test.ts +0 -177
  237. package/src/resolveOpenAPIOperation.ts +0 -151
  238. package/src/resolveOpenAPIWebhook.ts +0 -99
  239. package/src/schemas/OpenAPISchemaItem.tsx +0 -34
  240. package/src/schemas/OpenAPISchemas.tsx +0 -98
  241. package/src/schemas/index.ts +0 -2
  242. package/src/schemas/resolveOpenAPISchemas.test.ts +0 -174
  243. package/src/schemas/resolveOpenAPISchemas.ts +0 -28
  244. package/src/stringifyOpenAPI.ts +0 -25
  245. package/src/translate.tsx +0 -80
  246. package/src/translations/de.ts +0 -43
  247. package/src/translations/en.ts +0 -43
  248. package/src/translations/es.ts +0 -43
  249. package/src/translations/fr.ts +0 -43
  250. package/src/translations/index.ts +0 -33
  251. package/src/translations/ja.ts +0 -43
  252. package/src/translations/nl.ts +0 -43
  253. package/src/translations/no.ts +0 -43
  254. package/src/translations/pt-br.ts +0 -43
  255. package/src/translations/types.ts +0 -7
  256. package/src/translations/zh.ts +0 -43
  257. package/src/types.ts +0 -46
  258. package/src/util/example.tsx +0 -129
  259. package/src/util/server.test.ts +0 -58
  260. package/src/util/server.ts +0 -47
  261. package/src/util/tryit-prefill.test.ts +0 -311
  262. package/src/util/tryit-prefill.ts +0 -160
  263. package/src/utils.ts +0 -255
@@ -0,0 +1,373 @@
1
+ 'use client';
2
+
3
+
4
+ import { stringifyOpenAPI } from "./stringifyOpenAPI.js";
5
+ import { tString } from "./translate.js";
6
+ import { Markdown } from "./Markdown.js";
7
+ import { OpenAPICopyButton } from "./OpenAPICopyButton.js";
8
+ import { OpenAPIDisclosure } from "./OpenAPIDisclosure.js";
9
+ import { OpenAPISchemaName } from "./OpenAPISchemaName.js";
10
+ import { retrocycle } from "./decycle.js";
11
+ import { getDisclosureLabel } from "./getDisclosureLabel.js";
12
+ import { checkIsReference, getSchemaTitle, resolveDescription, resolveFirstExample } from "./utils.js";
13
+ import clsx from "classnames";
14
+ import { useId } from "react";
15
+
16
+ //#region src/OpenAPISchema.tsx
17
+ /**
18
+ * Render a property of an OpenAPI schema.
19
+ */
20
+ function OpenAPISchemaProperty(props) {
21
+ const { circularRefs: parentCircularRefs, context, className, property,...rest } = props;
22
+ const { schema } = property;
23
+ const id = useId();
24
+ const circularRefId = parentCircularRefs.get(schema);
25
+ if (circularRefId) return <OpenAPISchemaCircularRef id={circularRefId} schema={schema} />;
26
+ const circularRefs = new Map(parentCircularRefs);
27
+ circularRefs.set(schema, id);
28
+ const properties = getSchemaProperties(schema);
29
+ const alternatives = getSchemaAlternatives(schema, new Set(circularRefs.keys()));
30
+ const header = <OpenAPISchemaPresentation context={context} property={property} />;
31
+ const content = (() => {
32
+ if (alternatives?.schemas) {
33
+ const { schemas, discriminator } = alternatives;
34
+ return <div className="openapi-schema-alternatives">
35
+ {schemas.map((alternativeSchema, index) => <div key={index} className="openapi-schema-alternative">
36
+ <OpenAPISchemaAlternative schema={alternativeSchema} discriminator={discriminator} circularRefs={circularRefs} context={context} />
37
+ {index < schemas.length - 1 ? <OpenAPISchemaAlternativeSeparator schema={schema} context={context} /> : null}
38
+ </div>)}
39
+ </div>;
40
+ }
41
+ if (properties?.length) return <OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context} />;
42
+ return null;
43
+ })();
44
+ if (properties?.length) return <OpenAPIDisclosure icon={context.icons.plus} className={clsx("openapi-schema", className)} header={header} label={(isExpanded) => getDisclosureLabel({
45
+ schema,
46
+ isExpanded,
47
+ context
48
+ })} {...rest}>
49
+ {content}
50
+ </OpenAPIDisclosure>;
51
+ return <div id={id} {...rest} className={clsx("openapi-schema", className)}>
52
+ {header}
53
+ {content}
54
+ </div>;
55
+ }
56
+ /**
57
+ * Render a set of properties of an OpenAPI schema.
58
+ */
59
+ function OpenAPISchemaProperties(props) {
60
+ const { id, properties, circularRefs = /* @__PURE__ */ new Map(), context } = props;
61
+ return <div id={id} className="openapi-schema-properties">
62
+ {properties.map((property, index) => {
63
+ return <OpenAPISchemaProperty key={index} circularRefs={circularRefs} property={property} context={context} style={{ animationDelay: `${index * .02}s` }} />;
64
+ })}
65
+ </div>;
66
+ }
67
+ function OpenAPISchemaPropertiesFromServer(props) {
68
+ return <OpenAPISchemaProperties id={props.id} properties={JSON.parse(props.properties, retrocycle())} context={props.context} />;
69
+ }
70
+ /**
71
+ * Render a root schema (such as the request body or response body).
72
+ */
73
+ function OpenAPIRootSchema(props) {
74
+ const { schema, context, circularRefs: parentCircularRefs = /* @__PURE__ */ new Map() } = props;
75
+ const id = useId();
76
+ const properties = getSchemaProperties(schema);
77
+ const description = resolveDescription(schema);
78
+ if (properties?.length) {
79
+ const circularRefs = new Map(parentCircularRefs);
80
+ circularRefs.set(schema, id);
81
+ return <>
82
+ {description ? <Markdown source={description} className="openapi-schema-root-description" /> : null}
83
+ <OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context} />
84
+ </>;
85
+ }
86
+ return <OpenAPISchemaProperty className="openapi-schema-root" property={{ schema }} context={context} circularRefs={parentCircularRefs} />;
87
+ }
88
+ function OpenAPIRootSchemaFromServer(props) {
89
+ return <OpenAPIRootSchema schema={JSON.parse(props.schema, retrocycle())} context={props.context} />;
90
+ }
91
+ /**
92
+ * Render a tab for an alternative schema.
93
+ * It renders directly the properties if relevant;
94
+ * for primitives, it renders the schema itself.
95
+ */
96
+ function OpenAPISchemaAlternative(props) {
97
+ const { schema, discriminator, circularRefs, context } = props;
98
+ const properties = getSchemaProperties(schema, discriminator);
99
+ return properties?.length ? <OpenAPIDisclosure icon={context.icons.plus} header={<OpenAPISchemaPresentation property={{ schema }} context={context} />} label={(isExpanded) => getDisclosureLabel({
100
+ schema,
101
+ isExpanded,
102
+ context
103
+ })}>
104
+ <OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context} />
105
+ </OpenAPIDisclosure> : <OpenAPISchemaProperty property={{ schema }} circularRefs={circularRefs} context={context} />;
106
+ }
107
+ function OpenAPISchemaAlternativeSeparator(props) {
108
+ const { schema, context } = props;
109
+ const anyOf = schema.anyOf || schema.items?.anyOf;
110
+ const oneOf = schema.oneOf || schema.items?.oneOf;
111
+ const allOf = schema.allOf || schema.items?.allOf;
112
+ if (!anyOf && !oneOf && !allOf) return null;
113
+ return <span className="openapi-schema-alternative-separator">
114
+ {(anyOf || oneOf) && tString(context.translation, "or")}
115
+ {allOf && tString(context.translation, "and")}
116
+ </span>;
117
+ }
118
+ /**
119
+ * Render a circular reference to a schema.
120
+ */
121
+ function OpenAPISchemaCircularRef(props) {
122
+ const { id, schema } = props;
123
+ return <div className="openapi-schema-circular">
124
+ Circular reference to <a href={`#${id}`}>{getSchemaTitle(schema)}</a>{" "}
125
+ <span className="openapi-schema-circular-glyph">↩</span>
126
+ </div>;
127
+ }
128
+ /**
129
+ * Render the enum value for a schema.
130
+ */
131
+ function OpenAPISchemaEnum(props) {
132
+ const { schema, context } = props;
133
+ const enumValues = (() => {
134
+ if (schema["x-gitbook-enum"]) return Object.entries(schema["x-gitbook-enum"]).map(([name, { description }]) => {
135
+ return {
136
+ value: name,
137
+ description
138
+ };
139
+ });
140
+ if (schema["x-enumDescriptions"]) return Object.entries(schema["x-enumDescriptions"]).map(([value, description]) => {
141
+ return {
142
+ value,
143
+ description
144
+ };
145
+ });
146
+ return schema.enum?.map((value) => {
147
+ return {
148
+ value,
149
+ description: void 0
150
+ };
151
+ });
152
+ })();
153
+ if (!enumValues?.length) return null;
154
+ return <span className="openapi-schema-enum">
155
+ {tString(context.translation, "possible_values")}:{" "}
156
+ {enumValues.map((item, index) => <span key={index} className="openapi-schema-enum-value">
157
+ <OpenAPICopyButton value={item.value} label={item.description} withTooltip={!!item.description} context={context}>
158
+ <code>{`${item.value}`}</code>
159
+ </OpenAPICopyButton>
160
+ </span>)}
161
+ </span>;
162
+ }
163
+ /**
164
+ * Render the top row of a schema. e.g: name, type, and required status.
165
+ */
166
+ function OpenAPISchemaPresentation(props) {
167
+ const { property: { schema, propertyName, required, isDiscriminatorProperty }, context } = props;
168
+ const description = resolveDescription(schema);
169
+ const example = resolveFirstExample(schema);
170
+ return <div className="openapi-schema-presentation">
171
+ <OpenAPISchemaName schema={schema} type={getSchemaTitle(schema)} propertyName={propertyName} isDiscriminatorProperty={isDiscriminatorProperty} required={required} context={context} />
172
+ {typeof schema["x-deprecated-sunset"] === "string" ? <div className="openapi-deprecated-sunset openapi-schema-description openapi-markdown">
173
+ Sunset date:{" "}
174
+ <span className="openapi-deprecated-sunset-date">
175
+ {schema["x-deprecated-sunset"]}
176
+ </span>
177
+ </div> : null}
178
+ {description ? <Markdown source={description} className="openapi-schema-description" /> : null}
179
+ {schema.default !== void 0 ? <span className="openapi-schema-default">
180
+ Default:{" "}
181
+ <code>
182
+ {typeof schema.default === "string" && schema.default ? schema.default : stringifyOpenAPI(schema.default)}
183
+ </code>
184
+ </span> : null}
185
+ {typeof example === "string" ? <span className="openapi-schema-example">
186
+ Example: <code>{example}</code>
187
+ </span> : null}
188
+ {schema.pattern ? <span className="openapi-schema-pattern">
189
+ Pattern: <code>{schema.pattern}</code>
190
+ </span> : null}
191
+ <OpenAPISchemaEnum schema={schema} context={context} />
192
+ </div>;
193
+ }
194
+ /**
195
+ * Get the sub-properties of a schema.
196
+ */
197
+ function getSchemaProperties(schema, discriminator) {
198
+ if (schema.type === "array" && schema.items && !checkIsReference(schema.items)) {
199
+ const items = schema.items;
200
+ const itemProperties = getSchemaProperties(items);
201
+ if (itemProperties) return itemProperties.map((prop) => ({
202
+ ...prop,
203
+ isDiscriminatorProperty: discriminator?.propertyName === prop.propertyName
204
+ }));
205
+ if ((items.type === "string" || items.type === "number" || items.type === "boolean" || items.type === "integer") && !items.enum) return null;
206
+ return [{
207
+ propertyName: "items",
208
+ schema: items
209
+ }];
210
+ }
211
+ if (schema.type === "object" || schema.properties) {
212
+ const result = [];
213
+ if (schema.properties) Object.entries(schema.properties).forEach(([propertyName, propertySchema]) => {
214
+ if (checkIsReference(propertySchema)) return;
215
+ result.push({
216
+ propertyName,
217
+ required: Array.isArray(schema.required) ? schema.required.includes(propertyName) : void 0,
218
+ isDiscriminatorProperty: discriminator?.propertyName === propertyName,
219
+ schema: propertySchema
220
+ });
221
+ });
222
+ if (schema.additionalProperties && !checkIsReference(schema.additionalProperties)) result.push({
223
+ propertyName: "Other properties",
224
+ schema: schema.additionalProperties === true ? {} : schema.additionalProperties
225
+ });
226
+ return result;
227
+ }
228
+ return null;
229
+ }
230
+ /**
231
+ * Get the alternatives to display for a schema.
232
+ */
233
+ function getSchemaAlternatives(schema, ancestors = /* @__PURE__ */ new Set()) {
234
+ if (schema.items && ("oneOf" in schema.items || "allOf" in schema.items || "anyOf" in schema.items)) return getSchemaAlternatives(schema.items, ancestors);
235
+ const alternatives = (() => {
236
+ if (schema.anyOf) return [
237
+ "anyOf",
238
+ schema.anyOf,
239
+ schema.discriminator
240
+ ];
241
+ if (schema.oneOf) return [
242
+ "oneOf",
243
+ schema.oneOf,
244
+ schema.discriminator
245
+ ];
246
+ if (schema.allOf) return [
247
+ "allOf",
248
+ schema.allOf,
249
+ schema.discriminator
250
+ ];
251
+ return null;
252
+ })();
253
+ if (!alternatives) return null;
254
+ const [type, schemas, discriminator] = alternatives;
255
+ return {
256
+ type,
257
+ schemas: mergeAlternatives(type, flattenAlternatives(type, schemas, new Set(ancestors).add(schema))) ?? [],
258
+ discriminator
259
+ };
260
+ }
261
+ const safeExtensions = [
262
+ "description",
263
+ "title",
264
+ "example",
265
+ "examples",
266
+ "default",
267
+ "readOnly",
268
+ "writeOnly",
269
+ "deprecated"
270
+ ];
271
+ /**
272
+ * Determine if a schema is safe to merge based on its properties
273
+ */
274
+ function isSafeToMerge(schema) {
275
+ const keys = Object.keys(schema);
276
+ const coreProperties = [
277
+ "type",
278
+ "properties",
279
+ "required",
280
+ "nullable"
281
+ ];
282
+ const coreKeys = keys.filter((key) => coreProperties.includes(key));
283
+ const unknownKeys = keys.filter((key) => !coreProperties.includes(key) && !safeExtensions.includes(key) && !key.startsWith("x-"));
284
+ return coreKeys.length > 0 && unknownKeys.length === 0;
285
+ }
286
+ /**
287
+ * Merge alternatives of the same type into a single schema.
288
+ * - Merge string enums
289
+ * - Safely merge object schemas with compatible properties
290
+ */
291
+ function mergeAlternatives(alternativeType, schemasOrRefs) {
292
+ switch (alternativeType) {
293
+ case "oneOf": return schemasOrRefs.reduce((acc, schemaOrRef) => {
294
+ const latest = acc.at(-1);
295
+ if (latest && latest.type === "string" && latest.enum && schemaOrRef.type === "string" && schemaOrRef.enum) {
296
+ latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
297
+ latest.nullable = latest.nullable || schemaOrRef.nullable;
298
+ return acc;
299
+ }
300
+ acc.push(schemaOrRef);
301
+ return acc;
302
+ }, []);
303
+ case "allOf": return schemasOrRefs.reduce((acc, schemaOrRef) => {
304
+ const latest = acc.at(-1);
305
+ if (latest && latest.type === "string" && latest.enum && schemaOrRef.type === "string" && schemaOrRef.enum) {
306
+ if (Object.keys(schemaOrRef).every((key) => [
307
+ "type",
308
+ "enum",
309
+ "nullable"
310
+ ].includes(key))) {
311
+ latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
312
+ latest.nullable = latest.nullable || schemaOrRef.nullable;
313
+ return acc;
314
+ }
315
+ }
316
+ if (latest && latest.type === "object" && schemaOrRef.type === "object") {
317
+ const keys = Object.keys(schemaOrRef);
318
+ if (isSafeToMerge(schemaOrRef)) {
319
+ const safeKeys = keys.filter((key) => safeExtensions.includes(key));
320
+ const vendorKeys = keys.filter((key) => key.startsWith("x-"));
321
+ latest.properties = {
322
+ ...latest.properties || {},
323
+ ...schemaOrRef.properties || {}
324
+ };
325
+ latest.required = Array.from(new Set([...latest.required && Array.isArray(latest.required) ? latest.required : [], ...schemaOrRef.required && Array.isArray(schemaOrRef.required) ? schemaOrRef.required : []]));
326
+ latest.nullable = latest.nullable || schemaOrRef.nullable;
327
+ [...vendorKeys, ...safeKeys].forEach((key) => {
328
+ if (typeof latest[key] === "object" && typeof schemaOrRef[key] === "object") latest[key] = {
329
+ ...latest[key],
330
+ ...schemaOrRef[key]
331
+ };
332
+ else latest[key] = schemaOrRef[key];
333
+ });
334
+ return acc;
335
+ }
336
+ }
337
+ acc.push(schemaOrRef);
338
+ return acc;
339
+ }, []);
340
+ default: return schemasOrRefs;
341
+ }
342
+ }
343
+ function flattenAlternatives(alternativeType, schemasOrRefs, ancestors) {
344
+ const latestAncestor = Array.from(ancestors).pop();
345
+ return schemasOrRefs.reduce((acc, schemaOrRef) => {
346
+ if (checkIsReference(schemaOrRef)) return acc;
347
+ if (schemaOrRef[alternativeType] && !ancestors.has(schemaOrRef)) {
348
+ const alternatives = getSchemaAlternatives(schemaOrRef, ancestors);
349
+ if (alternatives?.schemas) acc.push(...alternatives.schemas.map((schema$1) => ({
350
+ ...schema$1,
351
+ required: mergeRequiredFields(schema$1, latestAncestor)
352
+ })));
353
+ return acc;
354
+ }
355
+ const schema = {
356
+ ...schemaOrRef,
357
+ required: mergeRequiredFields(schemaOrRef, latestAncestor)
358
+ };
359
+ acc.push(schema);
360
+ return acc;
361
+ }, []);
362
+ }
363
+ /**
364
+ * Merge the required fields of a schema with the required fields of its latest ancestor.
365
+ */
366
+ function mergeRequiredFields(schemaOrRef, latestAncestor) {
367
+ if (!schemaOrRef.required && !latestAncestor?.required) return;
368
+ if (checkIsReference(schemaOrRef)) return latestAncestor?.required;
369
+ return Array.from(new Set([...latestAncestor?.required || [], ...schemaOrRef.required || []]));
370
+ }
371
+
372
+ //#endregion
373
+ export { OpenAPIRootSchemaFromServer, OpenAPISchemaPresentation, OpenAPISchemaPropertiesFromServer };
@@ -0,0 +1,45 @@
1
+ import { t, tString } from "./translate.js";
2
+
3
+ //#region src/OpenAPISchemaName.tsx
4
+ /**
5
+ * Display the schema name row.
6
+ * It includes the property name, type, required and deprecated status.
7
+ */
8
+ function OpenAPISchemaName(props) {
9
+ const { schema, type, propertyName, required, isDiscriminatorProperty, context } = props;
10
+ const additionalItems = schema && getAdditionalItems(schema, context);
11
+ return <span className="openapi-schema-name">
12
+ {propertyName ? <span data-deprecated={schema?.deprecated} className="openapi-schema-propertyname">
13
+ {propertyName}
14
+ </span> : null}
15
+ {isDiscriminatorProperty ? <span className="openapi-schema-discriminator">
16
+ {t(context.translation, "discriminator")}
17
+ </span> : null}
18
+ {type || additionalItems ? <span>
19
+ {schema?.const ? <span className="openapi-schema-type">const: {schema?.const}</span> : type ? <span className="openapi-schema-type">{type}</span> : null}
20
+ {additionalItems ? <span className="openapi-schema-type">{additionalItems}</span> : null}
21
+ </span> : null}
22
+ {schema?.readOnly ? <span className="openapi-schema-readonly">
23
+ {t(context.translation, "read_only")}
24
+ </span> : null}
25
+ {schema?.writeOnly ? <span className="openapi-schema-writeonly">
26
+ {t(context.translation, "write_only")}
27
+ </span> : null}
28
+ {required === null ? null : required ? <span className="openapi-schema-required">
29
+ {t(context.translation, "required")}
30
+ </span> : <span className="openapi-schema-optional">
31
+ {t(context.translation, "optional")}
32
+ </span>}
33
+ {schema?.deprecated ? <span className="openapi-deprecated">{t(context.translation, "deprecated")}</span> : null}
34
+ </span>;
35
+ }
36
+ function getAdditionalItems(schema, context) {
37
+ let additionalItems = "";
38
+ if (schema.minimum || schema.minLength || schema.minItems) additionalItems += ` · ${tString(context.translation, "min").toLowerCase()}: ${schema.minimum || schema.minLength || schema.minItems}`;
39
+ if (schema.maximum || schema.maxLength || schema.maxItems) additionalItems += ` · ${tString(context.translation, "max").toLowerCase()}: ${schema.maximum || schema.maxLength || schema.maxItems}`;
40
+ if (schema.nullable) additionalItems = ` | ${tString(context.translation, "nullable").toLowerCase()}`;
41
+ return additionalItems;
42
+ }
43
+
44
+ //#endregion
45
+ export { OpenAPISchemaName };
@@ -0,0 +1,13 @@
1
+ import { decycle } from "./decycle.js";
2
+ import { OpenAPIRootSchemaFromServer, OpenAPISchemaPropertiesFromServer } from "./OpenAPISchema.js";
3
+
4
+ //#region src/OpenAPISchemaServer.tsx
5
+ function OpenAPISchemaProperties(props) {
6
+ return <OpenAPISchemaPropertiesFromServer id={props.id} properties={JSON.stringify(props.properties, decycle())} context={props.context} />;
7
+ }
8
+ function OpenAPIRootSchema(props) {
9
+ return <OpenAPIRootSchemaFromServer schema={JSON.stringify(props.schema, decycle())} context={props.context} />;
10
+ }
11
+
12
+ //#endregion
13
+ export { OpenAPIRootSchema, OpenAPISchemaProperties };
@@ -0,0 +1,124 @@
1
+ import { t } from "./translate.js";
2
+ import { Markdown } from "./Markdown.js";
3
+ import { OpenAPICopyButton } from "./OpenAPICopyButton.js";
4
+ import { OpenAPISchemaName } from "./OpenAPISchemaName.js";
5
+ import { createStateKey, extractOperationSecurityInfo, resolveDescription } from "./utils.js";
6
+ import { InteractiveSection } from "./InteractiveSection.js";
7
+ import { Fragment } from "react";
8
+
9
+ //#region src/OpenAPISecurities.tsx
10
+ /**
11
+ * Present securities authorization that can be used for this operation.
12
+ */
13
+ function OpenAPISecurities(props) {
14
+ const { securityRequirement, securities, context } = props;
15
+ if (!securities || securities.length === 0) return null;
16
+ const tabsData = extractOperationSecurityInfo({
17
+ securityRequirement,
18
+ securities
19
+ });
20
+ 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 }) => ({
21
+ key,
22
+ label,
23
+ body: <div className="openapi-schema">
24
+ {schemes.map((security, index) => {
25
+ const description = resolveDescription(security);
26
+ return <div key={`${key}-${index}`} className="openapi-schema-presentation">
27
+ {getLabelForType(security, context)}
28
+ {description ? <Markdown source={description} className="openapi-securities-description" /> : null}
29
+ {security.scopes?.length ? <OpenAPISchemaScopes scopes={security.scopes} context={context} /> : null}
30
+ </div>;
31
+ })}
32
+ </div>
33
+ }))} />;
34
+ }
35
+ function getLabelForType(security, context) {
36
+ switch (security.type) {
37
+ case "apiKey": return <OpenAPISchemaName context={context} propertyName={security.name ?? "apiKey"} type="string" required={security.required} />;
38
+ case "http":
39
+ if (security.scheme === "basic") return <OpenAPISchemaName context={context} propertyName="Authorization" type="string" required={security.required} />;
40
+ if (security.scheme === "bearer") return <>
41
+ <OpenAPISchemaName context={context} propertyName="Authorization" type="string" required={security.required} />
42
+ { /** Show a default description if none is provided */}
43
+ {!security.description ? <Markdown source={`Bearer authentication header of the form Bearer &lt;token&gt;.`} className="openapi-securities-description" /> : null}
44
+ </>;
45
+ return <OpenAPISchemaName context={context} propertyName="HTTP" required={security.required} />;
46
+ case "oauth2": return <OpenAPISchemaOAuth2Flows context={context} security={security} />;
47
+ case "openIdConnect": return <OpenAPISchemaName context={context} propertyName="OpenID Connect" required={security.required} />;
48
+ default: return security.type;
49
+ }
50
+ }
51
+ function OpenAPISchemaOAuth2Flows(props) {
52
+ const { context, security } = props;
53
+ const flows = security.flows ? Object.entries(security.flows) : [];
54
+ return <div className="openapi-securities-oauth-flows">
55
+ {flows.map(([name, flow], index) => <Fragment key={index}>
56
+ <OpenAPISchemaOAuth2Item flow={flow} name={name} context={context} security={security} />
57
+ {index < flows.length - 1 ? <hr /> : null}
58
+ </Fragment>)}
59
+ </div>;
60
+ }
61
+ function OpenAPISchemaOAuth2Item(props) {
62
+ const { flow, context, security, name } = props;
63
+ if (!flow) return null;
64
+ const scopes = flow.scopes ? Object.entries(flow.scopes) : [];
65
+ return <div>
66
+ <OpenAPISchemaName context={context} propertyName="OAuth2" type={name} required={security.required} />
67
+ <div className="openapi-securities-oauth-content openapi-markdown">
68
+ {security.description ? <Markdown source={security.description} /> : null}
69
+ {"authorizationUrl" in flow && flow.authorizationUrl ? <span>
70
+ Authorization URL:{" "}
71
+ <OpenAPICopyButton value={flow.authorizationUrl} context={context} className="openapi-securities-url" withTooltip>
72
+ {flow.authorizationUrl}
73
+ </OpenAPICopyButton>
74
+ </span> : null}
75
+ {"tokenUrl" in flow && flow.tokenUrl ? <span>
76
+ Token URL:{" "}
77
+ <OpenAPICopyButton value={flow.tokenUrl} context={context} className="openapi-securities-url" withTooltip>
78
+ {flow.tokenUrl}
79
+ </OpenAPICopyButton>
80
+ </span> : null}
81
+ {"refreshUrl" in flow && flow.refreshUrl ? <span>
82
+ Refresh URL:{" "}
83
+ <OpenAPICopyButton value={flow.refreshUrl} context={context} className="openapi-securities-url" withTooltip>
84
+ {flow.refreshUrl}
85
+ </OpenAPICopyButton>
86
+ </span> : null}
87
+ {scopes.length ? <OpenAPISchemaScopes scopes={scopes} context={context} /> : null}
88
+ </div>
89
+ </div>;
90
+ }
91
+ /**
92
+ * Render a list of available scopes.
93
+ */
94
+ function OpenAPISchemaScopes(props) {
95
+ const { scopes, context } = props;
96
+ return <div className="openapi-securities-scopes openapi-markdown">
97
+ <span>{t(context.translation, "required_scopes")}: </span>
98
+ <ul>
99
+ {scopes.map((scope) => <OpenAPIScopeItem key={scope[0]} scope={scope} context={context} />)}
100
+ </ul>
101
+ </div>;
102
+ }
103
+ /**
104
+ * Display a scope item. Either a key-value pair or a single string.
105
+ */
106
+ function OpenAPIScopeItem(props) {
107
+ const { scope, context } = props;
108
+ return <li>
109
+ <OpenAPIScopeItemKey name={scope[0]} context={context} />
110
+ {scope[1] ? `: ${scope[1]}` : null}
111
+ </li>;
112
+ }
113
+ /**
114
+ * Displays the scope name within a copyable button.
115
+ */
116
+ function OpenAPIScopeItemKey(props) {
117
+ const { name, context } = props;
118
+ return <OpenAPICopyButton value={name} context={context} withTooltip>
119
+ <code>{name}</code>
120
+ </OpenAPICopyButton>;
121
+ }
122
+
123
+ //#endregion
124
+ export { OpenAPISecurities };
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+
3
+
4
+ import { getOrCreateStoreByKey } from "./getOrCreateStoreByKey.js";
5
+ import clsx from "classnames";
6
+ import { useCallback } from "react";
7
+ import { Button, ListBox, ListBoxItem, Popover, Select, SelectValue } from "react-aria-components";
8
+ import { useStore } from "zustand";
9
+
10
+ //#region src/OpenAPISelect.tsx
11
+ function useSelectState(stateKey = "select-state", initialKey = "default") {
12
+ const store = useStore(getOrCreateStoreByKey(stateKey, initialKey));
13
+ return {
14
+ key: store.key,
15
+ setKey: useCallback((key) => store.setKey(key), [store.setKey])
16
+ };
17
+ }
18
+ function OpenAPISelect(props) {
19
+ const { icon = "▼", items, children, className, placement, stateKey, selectedKey, onSelectionChange } = props;
20
+ const state = useSelectState(stateKey, items[0]?.key);
21
+ const selected = items.find((item) => item.key === state.key) || items[0];
22
+ return <Select aria-label="OpenAPI Select" {...props} value={selectedKey || selected?.key} onChange={(key) => {
23
+ onSelectionChange?.(key);
24
+ state.setKey(key);
25
+ }} className={clsx("openapi-select", className)}>
26
+ <Button>
27
+ <SelectValue />
28
+ {icon}
29
+ </Button>
30
+ <Popover placement={placement} className="openapi-select-popover">
31
+ <ListBox className="openapi-select-listbox" items={items}>
32
+ {children}
33
+ </ListBox>
34
+ </Popover>
35
+ </Select>;
36
+ }
37
+ function OpenAPISelectItem(props) {
38
+ return <ListBoxItem {...props} className={({ isFocused, isSelected }) => clsx("openapi-select-item", {
39
+ "openapi-select-item-focused": isFocused,
40
+ "openapi-select-item-selected": isSelected
41
+ })} />;
42
+ }
43
+
44
+ //#endregion
45
+ export { OpenAPISelect, OpenAPISelectItem, useSelectState };
@@ -0,0 +1,73 @@
1
+ import { tString } from "./translate.js";
2
+ import { parameterToProperty } from "./utils.js";
3
+ import { OpenAPISchemaProperties } from "./OpenAPISchemaServer.js";
4
+ import { StaticSection } from "./StaticSection.js";
5
+ import { OpenAPIRequestBody } from "./OpenAPIRequestBody.js";
6
+ import { OpenAPIResponses } from "./OpenAPIResponses.js";
7
+ import { OpenAPISecurities } from "./OpenAPISecurities.js";
8
+
9
+ //#region src/OpenAPISpec.tsx
10
+ function OpenAPISpec(props) {
11
+ const { data, context } = props;
12
+ const { operation } = data;
13
+ const parameterGroups = groupParameters(deduplicateParameters(operation.parameters ?? []), context);
14
+ const securities = "securities" in data ? data.securities : [];
15
+ return <>
16
+ {securities.length > 0 ? <OpenAPISecurities key="securities" securityRequirement={operation.security} securities={securities} context={context} /> : null}
17
+
18
+ {parameterGroups.map((group) => {
19
+ return <StaticSection key={`parameter-${group.key}`} className="openapi-parameters" header={group.label}>
20
+ <OpenAPISchemaProperties properties={group.parameters.map(parameterToProperty)} context={context} />
21
+ </StaticSection>;
22
+ })}
23
+
24
+ {operation.requestBody ? <OpenAPIRequestBody key="body" requestBody={operation.requestBody} context={context} data={data} /> : null}
25
+ {operation.responses ? <OpenAPIResponses key="responses" responses={operation.responses} context={context} /> : null}
26
+ </>;
27
+ }
28
+ function groupParameters(parameters, context) {
29
+ const sorted = [
30
+ "path",
31
+ "query",
32
+ "header"
33
+ ];
34
+ const groups = [];
35
+ parameters.filter((parameter) => parameter.in).forEach((parameter) => {
36
+ const key = parameter.in;
37
+ const label = getParameterGroupName(parameter.in, context);
38
+ const group = groups.find((group$1) => group$1.key === key);
39
+ if (group) group.parameters.push(parameter);
40
+ else groups.push({
41
+ key,
42
+ label,
43
+ parameters: [parameter]
44
+ });
45
+ });
46
+ groups.sort((a, b) => sorted.indexOf(a.key) - sorted.indexOf(b.key));
47
+ return groups;
48
+ }
49
+ function getParameterGroupName(paramIn, context) {
50
+ switch (paramIn) {
51
+ case "path": return tString(context.translation, "path_parameters");
52
+ case "query": return tString(context.translation, "query_parameters");
53
+ case "header": return tString(context.translation, "header_parameters");
54
+ default: return paramIn;
55
+ }
56
+ }
57
+ /** Deduplicate parameters by name and in.
58
+ * Some specs have both parameters define at path and operation level.
59
+ * We only want to display one of them.
60
+ * Parameters can have the wrong type (object instead of array) sometimes, we just return an empty array in that case.
61
+ */
62
+ function deduplicateParameters(parameters) {
63
+ const seen = /* @__PURE__ */ new Set();
64
+ return Array.isArray(parameters) ? parameters.filter((param) => {
65
+ const key = `${param.name}:${param.in}`;
66
+ if (seen.has(key)) return false;
67
+ seen.add(key);
68
+ return true;
69
+ }) : [];
70
+ }
71
+
72
+ //#endregion
73
+ export { OpenAPISpec };