@gitbook/react-openapi 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/OpenAPICodeSample.jsx +17 -16
  3. package/dist/OpenAPIDisclosure.d.ts +2 -1
  4. package/dist/OpenAPIDisclosure.jsx +1 -1
  5. package/dist/OpenAPIDisclosureGroup.d.ts +1 -1
  6. package/dist/OpenAPIDisclosureGroup.jsx +2 -2
  7. package/dist/OpenAPIOperation.jsx +21 -7
  8. package/dist/OpenAPIPath.d.ts +3 -2
  9. package/dist/OpenAPIPath.jsx +4 -15
  10. package/dist/OpenAPIRequestBody.jsx +1 -1
  11. package/dist/OpenAPIResponse.jsx +1 -1
  12. package/dist/OpenAPIResponseExample.jsx +6 -5
  13. package/dist/OpenAPIResponses.d.ts +1 -1
  14. package/dist/OpenAPIResponses.jsx +2 -2
  15. package/dist/OpenAPISchema.d.ts +5 -1
  16. package/dist/OpenAPISchema.jsx +72 -61
  17. package/dist/OpenAPISchemaName.d.ts +5 -3
  18. package/dist/OpenAPISchemaName.jsx +25 -4
  19. package/dist/OpenAPISecurities.jsx +2 -2
  20. package/dist/OpenAPITabs.d.ts +3 -3
  21. package/dist/OpenAPITabs.jsx +17 -14
  22. package/dist/ScalarApiButton.jsx +1 -1
  23. package/dist/code-samples.js +239 -17
  24. package/dist/contentTypeChecks.d.ts +9 -0
  25. package/dist/contentTypeChecks.js +27 -0
  26. package/dist/generateSchemaExample.js +2 -1
  27. package/dist/resolveOpenAPIOperation.d.ts +3 -3
  28. package/dist/resolveOpenAPIOperation.js +1 -1
  29. package/dist/stringifyOpenAPI.d.ts +1 -1
  30. package/dist/stringifyOpenAPI.js +8 -2
  31. package/dist/tsconfig.build.tsbuildinfo +1 -1
  32. package/dist/types.d.ts +14 -2
  33. package/dist/util/server.d.ts +9 -0
  34. package/dist/util/server.js +44 -0
  35. package/dist/utils.d.ts +2 -2
  36. package/dist/utils.js +7 -6
  37. package/package.json +3 -8
  38. package/src/InteractiveSection.tsx +4 -4
  39. package/src/OpenAPICodeSample.tsx +20 -19
  40. package/src/OpenAPIDisclosure.tsx +4 -3
  41. package/src/OpenAPIDisclosureGroup.tsx +5 -5
  42. package/src/OpenAPIOperation.tsx +32 -10
  43. package/src/OpenAPIOperationContext.tsx +1 -1
  44. package/src/OpenAPIPath.tsx +11 -10
  45. package/src/OpenAPIRequestBody.tsx +2 -2
  46. package/src/OpenAPIResponse.tsx +3 -3
  47. package/src/OpenAPIResponseExample.tsx +7 -6
  48. package/src/OpenAPIResponses.tsx +4 -4
  49. package/src/OpenAPISchema.test.ts +5 -5
  50. package/src/OpenAPISchema.tsx +134 -73
  51. package/src/OpenAPISchemaName.tsx +40 -7
  52. package/src/OpenAPISecurities.tsx +3 -3
  53. package/src/OpenAPITabs.tsx +23 -17
  54. package/src/ScalarApiButton.tsx +3 -3
  55. package/src/code-samples.test.ts +594 -2
  56. package/src/code-samples.ts +238 -17
  57. package/src/contentTypeChecks.ts +35 -0
  58. package/src/generateSchemaExample.ts +22 -18
  59. package/src/json2xml.test.ts +1 -1
  60. package/src/resolveOpenAPIOperation.test.ts +6 -6
  61. package/src/resolveOpenAPIOperation.ts +7 -7
  62. package/src/stringifyOpenAPI.ts +13 -2
  63. package/src/types.ts +11 -1
  64. package/src/util/server.test.ts +58 -0
  65. package/src/util/server.ts +47 -0
  66. package/src/utils.ts +9 -5
  67. package/dist/OpenAPIServerURL.d.ts +0 -11
  68. package/dist/OpenAPIServerURL.jsx +0 -67
  69. package/dist/OpenAPIServerURLVariable.d.ts +0 -8
  70. package/dist/OpenAPIServerURLVariable.jsx +0 -8
  71. package/src/OpenAPIServerURL.tsx +0 -73
  72. package/src/OpenAPIServerURLVariable.tsx +0 -14
@@ -35,12 +35,12 @@ function getLabelForType(security) {
35
35
  if (security.scheme === 'basic') {
36
36
  return <OpenAPISchemaName propertyName="Authorization" type="string" required/>;
37
37
  }
38
- if (security.scheme == 'bearer') {
38
+ if (security.scheme === 'bearer') {
39
39
  var description = resolveDescription(security);
40
40
  return (<>
41
41
  <OpenAPISchemaName propertyName="Authorization" type="string" required/>
42
42
  {/** Show a default description if none is provided */}
43
- {!description ? (<Markdown source={"Bearer authentication header of the form Bearer ".concat("&lt;token&gt;", ".")} className="openapi-securities-description"/>) : null}
43
+ {!description ? (<Markdown source={"Bearer authentication header of the form Bearer ".concat('&lt;token&gt;', ".")} className="openapi-securities-description"/>) : null}
44
44
  </>);
45
45
  }
46
46
  return <OpenAPISchemaName propertyName="HTTP" required/>;
@@ -1,5 +1,5 @@
1
- import { Key, TabsProps } from 'react-aria-components';
2
- export type Tab = {
1
+ import { type Key, type TabsProps } from 'react-aria-components';
2
+ export type TabItem = {
3
3
  key: Key;
4
4
  label: string;
5
5
  body: React.ReactNode;
@@ -9,7 +9,7 @@ export type Tab = {
9
9
  * The OpenAPI Tabs wrapper component.
10
10
  */
11
11
  export declare function OpenAPITabs(props: React.PropsWithChildren<TabsProps & {
12
- items: Tab[];
12
+ items: TabItem[];
13
13
  stateKey?: string;
14
14
  }>): import("react").JSX.Element;
15
15
  /**
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
  import { createContext, useContext, useEffect, useMemo, useState } from 'react';
3
3
  import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
4
+ import { useIntersectionObserver } from 'usehooks-ts';
4
5
  import { Markdown } from './Markdown';
5
6
  import { useSyncedTabsGlobalState } from './useSyncedTabsGlobalState';
6
- import { useIntersectionObserver } from 'usehooks-ts';
7
7
  var OpenAPITabsContext = createContext(null);
8
8
  function useOpenAPITabsContext() {
9
9
  var context = useContext(OpenAPITabsContext);
@@ -17,23 +17,22 @@ function useOpenAPITabsContext() {
17
17
  */
18
18
  export function OpenAPITabs(props) {
19
19
  var children = props.children, items = props.items, stateKey = props.stateKey;
20
- var isVisible = stateKey
21
- ? useIntersectionObserver({
22
- threshold: 0.1,
23
- rootMargin: '200px',
24
- })
25
- : true;
20
+ var _a = useIntersectionObserver({
21
+ threshold: 0.1,
22
+ rootMargin: '200px',
23
+ }), ref = _a[0], isIntersectionVisible = _a[1];
24
+ var isVisible = stateKey ? isIntersectionVisible : true;
26
25
  var defaultTab = items[0];
27
- var _a = useSyncedTabsGlobalState(), syncedTabs = _a[0], setSyncedTabs = _a[1];
28
- var _b = useState(function () {
26
+ var _b = useSyncedTabsGlobalState(), syncedTabs = _b[0], setSyncedTabs = _b[1];
27
+ var _c = useState(function () {
29
28
  var _a, _b, _c;
30
29
  if (isVisible && stateKey && syncedTabs && syncedTabs.has(stateKey)) {
31
30
  var tabFromState = syncedTabs.get(stateKey);
32
31
  return (_a = tabFromState === null || tabFromState === void 0 ? void 0 : tabFromState.key) !== null && _a !== void 0 ? _a : (_b = items[0]) === null || _b === void 0 ? void 0 : _b.key;
33
32
  }
34
33
  return (_c = items[0]) === null || _c === void 0 ? void 0 : _c.key;
35
- }), selectedTabKey = _b[0], setSelectedTabKey = _b[1];
36
- var _c = useState(defaultTab), selectedTab = _c[0], setSelectedTab = _c[1];
34
+ }), selectedTabKey = _c[0], setSelectedTabKey = _c[1];
35
+ var _d = useState(defaultTab), selectedTab = _d[0], setSelectedTab = _d[1];
37
36
  var handleSelectionChange = function (key) {
38
37
  setSelectedTabKey(key);
39
38
  if (stateKey) {
@@ -52,16 +51,20 @@ export function OpenAPITabs(props) {
52
51
  if (isVisible && stateKey && syncedTabs && syncedTabs.has(stateKey)) {
53
52
  var tabFromState_1 = syncedTabs.get(stateKey);
54
53
  if (!items.some(function (item) { return item.key === (tabFromState_1 === null || tabFromState_1 === void 0 ? void 0 : tabFromState_1.key); })) {
55
- return;
54
+ return setSelectedTab(defaultTab);
56
55
  }
57
56
  if (tabFromState_1 && (tabFromState_1 === null || tabFromState_1 === void 0 ? void 0 : tabFromState_1.key) !== (selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.key)) {
58
- setSelectedTab(tabFromState_1);
57
+ var tabFromItems = items.find(function (item) { return item.key === tabFromState_1.key; });
58
+ if (!tabFromItems) {
59
+ return;
60
+ }
61
+ setSelectedTab(tabFromItems);
59
62
  }
60
63
  }
61
64
  }, [isVisible, stateKey, syncedTabs, selectedTabKey]);
62
65
  var contextValue = useMemo(function () { return ({ items: items, selectedTab: selectedTab }); }, [items, selectedTab]);
63
66
  return (<OpenAPITabsContext.Provider value={contextValue}>
64
- <Tabs className="openapi-tabs" onSelectionChange={handleSelectionChange} selectedKey={selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.key}>
67
+ <Tabs ref={ref} className="openapi-tabs" onSelectionChange={handleSelectionChange} selectedKey={selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.key}>
65
68
  {children}
66
69
  </Tabs>
67
70
  </OpenAPITabsContext.Provider>);
@@ -2,8 +2,8 @@
2
2
  import { ApiClientModalProvider, useApiClientModal } from '@scalar/api-client-react';
3
3
  import { useEffect, useImperativeHandle, useRef, useState } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
- import { useOpenAPIOperationContext } from './OpenAPIOperationContext';
6
5
  import { useEventCallback } from 'usehooks-ts';
6
+ import { useOpenAPIOperationContext } from './OpenAPIOperationContext';
7
7
  /**
8
8
  * Button which launches the Scalar API Client
9
9
  */
@@ -9,6 +9,7 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ import { isCSV, isFormData, isFormUrlEncoded, isGraphQL, isPDF, isPlainObject, isText, isXML, } from './contentTypeChecks';
12
13
  import { stringifyOpenAPI } from './stringifyOpenAPI';
13
14
  export var codeSampleGenerators = [
14
15
  {
@@ -23,14 +24,26 @@ export var codeSampleGenerators = [
23
24
  lines.push("--request ".concat(method.toUpperCase()));
24
25
  }
25
26
  lines.push("--url '".concat(url, "'"));
26
- if (headers) {
27
+ if (body) {
28
+ var bodyContent = BodyGenerators.getCurlBody(body, headers);
29
+ if (bodyContent) {
30
+ body = bodyContent.body;
31
+ headers = bodyContent.headers;
32
+ }
33
+ }
34
+ if (headers && Object.keys(headers).length > 0) {
27
35
  Object.entries(headers).forEach(function (_a) {
28
36
  var key = _a[0], value = _a[1];
29
37
  lines.push("--header '".concat(key, ": ").concat(value, "'"));
30
38
  });
31
39
  }
32
- if (body && Object.keys(body).length > 0) {
33
- lines.push("--data '".concat(stringifyOpenAPI(body), "'"));
40
+ if (body) {
41
+ if (Array.isArray(body)) {
42
+ lines.push.apply(lines, body);
43
+ }
44
+ else {
45
+ lines.push(body);
46
+ }
34
47
  }
35
48
  return lines.map(function (line, index) { return (index > 0 ? indent(line, 2) : line); }).join(separator);
36
49
  },
@@ -42,15 +55,24 @@ export var codeSampleGenerators = [
42
55
  generate: function (_a) {
43
56
  var method = _a.method, url = _a.url, headers = _a.headers, body = _a.body;
44
57
  var code = '';
58
+ if (body) {
59
+ var lines = BodyGenerators.getJavaScriptBody(body, headers);
60
+ if (lines) {
61
+ // add the generated code to the top
62
+ code += lines.code;
63
+ body = lines.body;
64
+ headers = lines.headers;
65
+ }
66
+ }
45
67
  code += "const response = await fetch('".concat(url, "', {\n method: '").concat(method.toUpperCase(), "',\n");
46
- if (headers) {
68
+ if (headers && Object.keys(headers).length > 0) {
47
69
  code += indent("headers: ".concat(stringifyOpenAPI(headers, null, 2), ",\n"), 4);
48
70
  }
49
71
  if (body) {
50
- code += indent("body: JSON.stringify(".concat(stringifyOpenAPI(body, null, 2), "),\n"), 4);
72
+ code += indent("body: ".concat(body, "\n"), 4);
51
73
  }
52
- code += "});\n";
53
- code += "const data = await response.json();";
74
+ code += '});\n\n';
75
+ code += 'const data = await response.json();';
54
76
  return code;
55
77
  },
56
78
  },
@@ -61,16 +83,30 @@ export var codeSampleGenerators = [
61
83
  generate: function (_a) {
62
84
  var method = _a.method, url = _a.url, headers = _a.headers, body = _a.body;
63
85
  var code = 'import requests\n\n';
86
+ if (body) {
87
+ var lines = BodyGenerators.getPythonBody(body, headers);
88
+ // add the generated code to the top
89
+ if (lines) {
90
+ code += lines.code;
91
+ body = lines.body;
92
+ headers = lines.headers;
93
+ }
94
+ }
64
95
  code += "response = requests.".concat(method.toLowerCase(), "(\n");
65
96
  code += indent("\"".concat(url, "\",\n"), 4);
66
- if (headers) {
97
+ if (headers && Object.keys(headers).length > 0) {
67
98
  code += indent("headers=".concat(stringifyOpenAPI(headers), ",\n"), 4);
68
99
  }
69
100
  if (body) {
70
- code += indent("json=".concat(stringifyOpenAPI(body), "\n"), 4);
101
+ if (body === 'files') {
102
+ code += indent("files=".concat(body, "\n"), 4);
103
+ }
104
+ else {
105
+ code += indent("data=".concat(stringifyOpenAPI(body), "\n"), 4);
106
+ }
71
107
  }
72
- code += ')\n';
73
- code += "data = response.json()";
108
+ code += ')\n\n';
109
+ code += 'data = response.json()';
74
110
  return code;
75
111
  },
76
112
  },
@@ -86,20 +122,24 @@ export var codeSampleGenerators = [
86
122
  var bodyContent = body ? stringifyOpenAPI(body) : '';
87
123
  // handle unicode chars with a text encoder
88
124
  var encoder = new TextEncoder();
125
+ var bodyString_1 = BodyGenerators.getHTTPBody(body, headers);
126
+ if (bodyString_1) {
127
+ body = bodyString_1;
128
+ }
89
129
  headers = __assign(__assign({}, headers), { 'Content-Length': encoder.encode(bodyContent).length.toString() });
90
130
  }
91
131
  if (!headers.hasOwnProperty('Accept')) {
92
132
  headers.Accept = '*/*';
93
133
  }
94
134
  var headerString = headers
95
- ? Object.entries(headers)
135
+ ? "".concat(Object.entries(headers)
96
136
  .map(function (_a) {
97
137
  var key = _a[0], value = _a[1];
98
- return key.toLowerCase() !== 'host' ? "".concat(key, ": ").concat(value) : "";
138
+ return key.toLowerCase() !== 'host' ? "".concat(key, ": ").concat(value) : '';
99
139
  })
100
- .join('\n') + '\n'
140
+ .join('\n'), "\n")
101
141
  : '';
102
- var bodyString = body ? "\n".concat(stringifyOpenAPI(body, null, 2)) : '';
142
+ var bodyString = body ? "\n".concat(body) : '';
103
143
  var httpRequest = "".concat(method.toUpperCase(), " ").concat(decodeURI(path), " HTTP/1.1\nHost: ").concat(host, "\n").concat(headerString).concat(bodyString);
104
144
  return httpRequest;
105
145
  },
@@ -118,7 +158,7 @@ export function parseHostAndPath(url) {
118
158
  var path = urlObj.pathname || '/';
119
159
  return { host: urlObj.host, path: path };
120
160
  }
121
- catch (e) {
161
+ catch (_e) {
122
162
  // If the URL was invalid do our best to parse the URL.
123
163
  // Check for the protocol part and pull it off to grab the host
124
164
  var splitted = url.split('//');
@@ -128,7 +168,189 @@ export function parseHostAndPath(url) {
128
168
  // pull off the host (mutates)
129
169
  var host = parts.shift();
130
170
  // add a leading slash and join the paths again
131
- var path = '/' + parts.join('/');
171
+ var path = "/".concat(parts.join('/'));
132
172
  return { host: host, path: path };
133
173
  }
134
174
  }
175
+ // Body Generators
176
+ var BodyGenerators = {
177
+ getCurlBody: function (body, headers) {
178
+ if (!body || !headers)
179
+ return undefined;
180
+ // Copy headers to avoid mutating the original object
181
+ var headersCopy = __assign({}, headers);
182
+ var contentType = headersCopy['Content-Type'] || '';
183
+ if (isFormData(contentType)) {
184
+ body = isPlainObject(body)
185
+ ? Object.entries(body).map(function (_a) {
186
+ var key = _a[0], value = _a[1];
187
+ return "--form '".concat(key, "=").concat(String(value), "'");
188
+ })
189
+ : "--form 'file=@".concat(body, "'");
190
+ }
191
+ else if (isFormUrlEncoded(contentType)) {
192
+ body = isPlainObject(body)
193
+ ? "--data '".concat(Object.entries(body)
194
+ .map(function (_a) {
195
+ var key = _a[0], value = _a[1];
196
+ return "".concat(key, "=").concat(String(value));
197
+ })
198
+ .join('&'), "'")
199
+ : String(body);
200
+ }
201
+ else if (isText(contentType)) {
202
+ body = "--data '".concat(String(body).replace(/"/g, ''), "'");
203
+ }
204
+ else if (isXML(contentType) || isCSV(contentType)) {
205
+ // We use --data-binary to avoid cURL converting newlines to \r\n
206
+ body = "--data-binary $'".concat(stringifyOpenAPI(body).replace(/"/g, ''), "'");
207
+ }
208
+ else if (isGraphQL(contentType)) {
209
+ body = "--data '".concat(stringifyOpenAPI(body), "'");
210
+ // Set Content-Type to application/json for GraphQL, recommended by GraphQL spec
211
+ headersCopy['Content-Type'] = 'application/json';
212
+ }
213
+ else if (isPDF(contentType)) {
214
+ // We use --data-binary to avoid cURL converting newlines to \r\n
215
+ body = "--data-binary '@".concat(String(body), "'");
216
+ }
217
+ else {
218
+ body = "--data '".concat(stringifyOpenAPI(body, null, 2), "'");
219
+ }
220
+ return {
221
+ body: body,
222
+ headers: headersCopy,
223
+ };
224
+ },
225
+ getJavaScriptBody: function (body, headers) {
226
+ if (!body || !headers)
227
+ return;
228
+ var code = '';
229
+ // Copy headers to avoid mutating the original object
230
+ var headersCopy = __assign({}, headers);
231
+ var contentType = headersCopy['Content-Type'] || '';
232
+ // Use FormData for file uploads
233
+ if (isFormData(contentType)) {
234
+ code += 'const formData = new FormData();\n\n';
235
+ if (isPlainObject(body)) {
236
+ Object.entries(body).forEach(function (_a) {
237
+ var key = _a[0], value = _a[1];
238
+ code += "formData.append(\"".concat(key, "\", \"").concat(String(value), "\");\n");
239
+ });
240
+ }
241
+ else if (typeof body === 'string') {
242
+ code += "formData.append(\"file\", \"".concat(body, "\");\n");
243
+ }
244
+ code += '\n';
245
+ body = 'formData';
246
+ }
247
+ else if (isFormUrlEncoded(contentType)) {
248
+ // Use URLSearchParams for form-urlencoded data
249
+ code += 'const params = new URLSearchParams();\n\n';
250
+ if (isPlainObject(body)) {
251
+ Object.entries(body).forEach(function (_a) {
252
+ var key = _a[0], value = _a[1];
253
+ code += "params.append(\"".concat(key, "\", \"").concat(String(value), "\");\n");
254
+ });
255
+ }
256
+ code += '\n';
257
+ body = 'params.toString()';
258
+ }
259
+ else if (isGraphQL(contentType)) {
260
+ if (isPlainObject(body)) {
261
+ Object.entries(body).forEach(function (_a) {
262
+ var key = _a[0], value = _a[1];
263
+ code += "const ".concat(key, " = `\n").concat(indent(String(value), 4), "`;\n\n");
264
+ });
265
+ body = "JSON.stringify({ ".concat(Object.keys(body).join(', '), " })");
266
+ // Set Content-Type to application/json for GraphQL, recommended by GraphQL spec
267
+ headersCopy['Content-Type'] = 'application/json';
268
+ }
269
+ else {
270
+ code += "const query = `\n".concat(indent(String(body), 4), "`;\n\n");
271
+ body = 'JSON.stringify(query)';
272
+ }
273
+ }
274
+ else if (isCSV(contentType)) {
275
+ code += 'const csv = `\n';
276
+ code += indent(String(body), 4);
277
+ code += '`;\n\n';
278
+ body = 'csv';
279
+ }
280
+ else if (isPDF(contentType)) {
281
+ // Use FormData to upload PDF files
282
+ code += 'const formData = new FormData();\n\n';
283
+ code += "formData.append(\"file\", \"".concat(body, "\");\n\n");
284
+ body = 'formData';
285
+ }
286
+ else if (isXML(contentType)) {
287
+ code += 'const xml = `\n';
288
+ code += indent(String(body), 4);
289
+ code += '`;\n\n';
290
+ body = 'xml';
291
+ }
292
+ else if (isText(contentType)) {
293
+ body = stringifyOpenAPI(body, null, 2);
294
+ }
295
+ else {
296
+ body = "JSON.stringify(".concat(stringifyOpenAPI(body, null, 2), ")");
297
+ }
298
+ return { body: body, code: code, headers: headersCopy };
299
+ },
300
+ getPythonBody: function (body, headers) {
301
+ if (!body || !headers)
302
+ return;
303
+ var code = '';
304
+ var contentType = headers['Content-Type'] || '';
305
+ if (isFormData(contentType)) {
306
+ code += 'files = {\n';
307
+ if (isPlainObject(body)) {
308
+ Object.entries(body).forEach(function (_a) {
309
+ var key = _a[0], value = _a[1];
310
+ code += "".concat(indent("\"".concat(key, "\": \"").concat(String(value), "\","), 4), "\n");
311
+ });
312
+ }
313
+ code += '}\n\n';
314
+ body = 'files';
315
+ }
316
+ if (isPDF(contentType)) {
317
+ code += 'files = {\n';
318
+ code += "".concat(indent("\"file\": \"".concat(body, "\","), 4), "\n");
319
+ code += '}\n\n';
320
+ body = 'files';
321
+ }
322
+ return { body: body, code: code, headers: headers };
323
+ },
324
+ getHTTPBody: function (body, headers) {
325
+ if (!body || !headers)
326
+ return undefined;
327
+ var contentType = headers['Content-Type'] || '';
328
+ var typeHandlers = {
329
+ pdf: function () { return "".concat(stringifyOpenAPI(body, null, 2)); },
330
+ formUrlEncoded: function () {
331
+ var encoded = isPlainObject(body)
332
+ ? Object.entries(body)
333
+ .map(function (_a) {
334
+ var key = _a[0], value = _a[1];
335
+ return "".concat(key, "=").concat(String(value));
336
+ })
337
+ .join('&')
338
+ : String(body);
339
+ return "\"".concat(encoded, "\"");
340
+ },
341
+ text: function () { return "\"".concat(String(body), "\""); },
342
+ xmlOrCsv: function () { return "\"".concat(stringifyOpenAPI(body).replace(/"/g, ''), "\""); },
343
+ default: function () { return "".concat(stringifyOpenAPI(body, null, 2)); },
344
+ };
345
+ if (isPDF(contentType))
346
+ return typeHandlers.pdf();
347
+ if (isFormUrlEncoded(contentType))
348
+ return typeHandlers.formUrlEncoded();
349
+ if (isText(contentType))
350
+ return typeHandlers.text();
351
+ if (isXML(contentType) || isCSV(contentType)) {
352
+ return typeHandlers.xmlOrCsv();
353
+ }
354
+ return typeHandlers.default();
355
+ },
356
+ };
@@ -0,0 +1,9 @@
1
+ export declare function isJSON(contentType?: string): boolean;
2
+ export declare function isXML(contentType?: string): boolean;
3
+ export declare function isGraphQL(contentType?: string): boolean;
4
+ export declare function isCSV(contentType?: string): boolean;
5
+ export declare function isPDF(contentType?: string): boolean;
6
+ export declare function isText(contentType?: string): boolean;
7
+ export declare function isFormUrlEncoded(contentType?: string): boolean;
8
+ export declare function isFormData(contentType?: string): boolean;
9
+ export declare function isPlainObject(value: unknown): boolean;
@@ -0,0 +1,27 @@
1
+ export function isJSON(contentType) {
2
+ return (contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().includes('application/json')) || false;
3
+ }
4
+ export function isXML(contentType) {
5
+ return (contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().includes('application/xml')) || false;
6
+ }
7
+ export function isGraphQL(contentType) {
8
+ return (contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().includes('application/graphql')) || false;
9
+ }
10
+ export function isCSV(contentType) {
11
+ return (contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().includes('text/csv')) || false;
12
+ }
13
+ export function isPDF(contentType) {
14
+ return (contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().includes('application/pdf')) || false;
15
+ }
16
+ export function isText(contentType) {
17
+ return (contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().includes('text/plain')) || false;
18
+ }
19
+ export function isFormUrlEncoded(contentType) {
20
+ return (contentType === null || contentType === void 0 ? void 0 : contentType.toLowerCase().includes('application/x-www-form-urlencoded')) || false;
21
+ }
22
+ export function isFormData(contentType) {
23
+ return !!contentType && contentType.toLowerCase().includes('multipart/form-data');
24
+ }
25
+ export function isPlainObject(value) {
26
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
27
+ }
@@ -26,7 +26,8 @@ export function generateSchemaExample(schema, options) {
26
26
  binary: 'binary',
27
27
  byte: 'Ynl0ZXM=',
28
28
  password: 'password',
29
- } }, options));
29
+ } }, options), 3 // Max depth for circular references
30
+ );
30
31
  }
31
32
  /**
32
33
  * Generate an example for a media type.
@@ -1,6 +1,6 @@
1
- import { toJSON, fromJSON } from 'flatted';
2
- import { type OpenAPIV3xDocument, type Filesystem } from '@gitbook/openapi-parser';
3
- import { OpenAPIOperationData } from './types';
1
+ import { fromJSON, toJSON } from 'flatted';
2
+ import { type Filesystem, type OpenAPIV3xDocument } from '@gitbook/openapi-parser';
3
+ import type { OpenAPIOperationData } from './types';
4
4
  export { toJSON, fromJSON };
5
5
  /**
6
6
  * Resolve an OpenAPI operation in a file and compile it to a more usable format.
@@ -54,7 +54,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
54
54
  }
55
55
  return to.concat(ar || Array.prototype.slice.call(from));
56
56
  };
57
- import { toJSON, fromJSON } from 'flatted';
57
+ import { fromJSON, toJSON } from 'flatted';
58
58
  import { dereference, } from '@gitbook/openapi-parser';
59
59
  import { checkIsReference } from './utils';
60
60
  export { toJSON, fromJSON };
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * Stringify an OpenAPI object. Same API as JSON.stringify.
3
3
  */
4
- export declare function stringifyOpenAPI(body: unknown, transformer?: null, indent?: number): string;
4
+ export declare function stringifyOpenAPI(body: unknown, _?: null, indent?: number): string;
@@ -1,6 +1,12 @@
1
1
  /**
2
2
  * Stringify an OpenAPI object. Same API as JSON.stringify.
3
3
  */
4
- export function stringifyOpenAPI(body, transformer, indent) {
5
- return JSON.stringify(body, transformer, indent);
4
+ export function stringifyOpenAPI(body, _, indent) {
5
+ return JSON.stringify(body, function (key, value) {
6
+ // Ignore internal keys
7
+ if (key.startsWith('x-gitbook-')) {
8
+ return undefined;
9
+ }
10
+ return value;
11
+ }, indent);
6
12
  }