@gitbook/react-openapi 1.0.2 → 1.0.3

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 (41) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/OpenAPICodeSample.jsx +11 -9
  3. package/dist/OpenAPIOperation.jsx +19 -5
  4. package/dist/OpenAPIResponseExample.jsx +3 -2
  5. package/dist/OpenAPISchema.jsx +47 -45
  6. package/dist/OpenAPISchemaName.d.ts +2 -1
  7. package/dist/OpenAPISchemaName.jsx +25 -4
  8. package/dist/OpenAPITabs.jsx +6 -2
  9. package/dist/code-samples.js +232 -10
  10. package/dist/contentTypeChecks.d.ts +9 -0
  11. package/dist/contentTypeChecks.js +27 -0
  12. package/dist/generateSchemaExample.js +1 -1
  13. package/dist/stringifyOpenAPI.d.ts +1 -1
  14. package/dist/stringifyOpenAPI.js +8 -2
  15. package/dist/tsconfig.build.tsbuildinfo +1 -1
  16. package/dist/types.d.ts +14 -2
  17. package/dist/util/server.d.ts +9 -0
  18. package/dist/{OpenAPIServerURL.jsx → util/server.js} +7 -28
  19. package/dist/utils.d.ts +1 -1
  20. package/dist/utils.js +3 -0
  21. package/package.json +2 -2
  22. package/src/OpenAPICodeSample.tsx +11 -9
  23. package/src/OpenAPIOperation.tsx +30 -8
  24. package/src/OpenAPIResponseExample.tsx +3 -2
  25. package/src/OpenAPISchema.tsx +73 -62
  26. package/src/OpenAPISchemaName.tsx +37 -5
  27. package/src/OpenAPITabs.tsx +8 -2
  28. package/src/code-samples.test.ts +594 -2
  29. package/src/code-samples.ts +231 -10
  30. package/src/contentTypeChecks.ts +35 -0
  31. package/src/generateSchemaExample.ts +20 -16
  32. package/src/stringifyOpenAPI.ts +13 -2
  33. package/src/types.ts +11 -1
  34. package/src/util/server.test.ts +58 -0
  35. package/src/util/server.ts +48 -0
  36. package/src/utils.ts +5 -1
  37. package/dist/OpenAPIServerURL.d.ts +0 -11
  38. package/dist/OpenAPIServerURLVariable.d.ts +0 -8
  39. package/dist/OpenAPIServerURLVariable.jsx +0 -8
  40. package/src/OpenAPIServerURL.tsx +0 -73
  41. package/src/OpenAPIServerURLVariable.tsx +0 -14
@@ -9,6 +9,7 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ import { isFormData, isPDF, isFormUrlEncoded, isText, isXML, isCSV, isGraphQL, isPlainObject, } 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,14 +55,23 @@ 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";
74
+ code += "});\n\n";
53
75
  code += "const data = await response.json();";
54
76
  return code;
55
77
  },
@@ -61,15 +83,29 @@ 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';
108
+ code += ')\n\n';
73
109
  code += "data = response.json()";
74
110
  return code;
75
111
  },
@@ -86,6 +122,10 @@ 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')) {
@@ -99,7 +139,7 @@ export var codeSampleGenerators = [
99
139
  })
100
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
  },
@@ -132,3 +172,185 @@ export function parseHostAndPath(url) {
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 += 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 += 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,7 @@ export function generateSchemaExample(schema, options) {
26
26
  binary: 'binary',
27
27
  byte: 'Ynl0ZXM=',
28
28
  password: 'password',
29
- } }, options));
29
+ } }, options), 3);
30
30
  }
31
31
  /**
32
32
  * Generate an example for a media type.
@@ -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
  }