@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
@@ -1,3 +1,13 @@
1
+ import {
2
+ isFormData,
3
+ isPDF,
4
+ isFormUrlEncoded,
5
+ isText,
6
+ isXML,
7
+ isCSV,
8
+ isGraphQL,
9
+ isPlainObject,
10
+ } from './contentTypeChecks';
1
11
  import { stringifyOpenAPI } from './stringifyOpenAPI';
2
12
 
3
13
  export interface CodeSampleInput {
@@ -30,14 +40,27 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
30
40
 
31
41
  lines.push(`--url '${url}'`);
32
42
 
33
- if (headers) {
43
+ if (body) {
44
+ const bodyContent = BodyGenerators.getCurlBody(body, headers);
45
+
46
+ if (bodyContent) {
47
+ body = bodyContent.body;
48
+ headers = bodyContent.headers;
49
+ }
50
+ }
51
+
52
+ if (headers && Object.keys(headers).length > 0) {
34
53
  Object.entries(headers).forEach(([key, value]) => {
35
54
  lines.push(`--header '${key}: ${value}'`);
36
55
  });
37
56
  }
38
57
 
39
- if (body && Object.keys(body).length > 0) {
40
- lines.push(`--data '${stringifyOpenAPI(body)}'`);
58
+ if (body) {
59
+ if (Array.isArray(body)) {
60
+ lines.push(...body);
61
+ } else {
62
+ lines.push(body);
63
+ }
41
64
  }
42
65
 
43
66
  return lines.map((line, index) => (index > 0 ? indent(line, 2) : line)).join(separator);
@@ -50,18 +73,29 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
50
73
  generate: ({ method, url, headers, body }) => {
51
74
  let code = '';
52
75
 
76
+ if (body) {
77
+ const lines = BodyGenerators.getJavaScriptBody(body, headers);
78
+
79
+ if (lines) {
80
+ // add the generated code to the top
81
+ code += lines.code;
82
+ body = lines.body;
83
+ headers = lines.headers;
84
+ }
85
+ }
86
+
53
87
  code += `const response = await fetch('${url}', {
54
88
  method: '${method.toUpperCase()}',\n`;
55
89
 
56
- if (headers) {
90
+ if (headers && Object.keys(headers).length > 0) {
57
91
  code += indent(`headers: ${stringifyOpenAPI(headers, null, 2)},\n`, 4);
58
92
  }
59
93
 
60
94
  if (body) {
61
- code += indent(`body: JSON.stringify(${stringifyOpenAPI(body, null, 2)}),\n`, 4);
95
+ code += indent(`body: ${body}\n`, 4);
62
96
  }
63
97
 
64
- code += `});\n`;
98
+ code += `});\n\n`;
65
99
  code += `const data = await response.json();`;
66
100
 
67
101
  return code;
@@ -73,15 +107,34 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
73
107
  syntax: 'python',
74
108
  generate: ({ method, url, headers, body }) => {
75
109
  let code = 'import requests\n\n';
110
+
111
+ if (body) {
112
+ const lines = BodyGenerators.getPythonBody(body, headers);
113
+
114
+ // add the generated code to the top
115
+ if (lines) {
116
+ code += lines.code;
117
+ body = lines.body;
118
+ headers = lines.headers;
119
+ }
120
+ }
121
+
76
122
  code += `response = requests.${method.toLowerCase()}(\n`;
77
123
  code += indent(`"${url}",\n`, 4);
78
- if (headers) {
124
+
125
+ if (headers && Object.keys(headers).length > 0) {
79
126
  code += indent(`headers=${stringifyOpenAPI(headers)},\n`, 4);
80
127
  }
128
+
81
129
  if (body) {
82
- code += indent(`json=${stringifyOpenAPI(body)}\n`, 4);
130
+ if (body === 'files') {
131
+ code += indent(`files=${body}\n`, 4);
132
+ } else {
133
+ code += indent(`data=${stringifyOpenAPI(body)}\n`, 4);
134
+ }
83
135
  }
84
- code += ')\n';
136
+
137
+ code += ')\n\n';
85
138
  code += `data = response.json()`;
86
139
  return code;
87
140
  },
@@ -99,6 +152,12 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
99
152
  // handle unicode chars with a text encoder
100
153
  const encoder = new TextEncoder();
101
154
 
155
+ const bodyString = BodyGenerators.getHTTPBody(body, headers);
156
+
157
+ if (bodyString) {
158
+ body = bodyString;
159
+ }
160
+
102
161
  headers = {
103
162
  ...headers,
104
163
  'Content-Length': encoder.encode(bodyContent).length.toString(),
@@ -117,7 +176,7 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
117
176
  .join('\n') + '\n'
118
177
  : '';
119
178
 
120
- const bodyString = body ? `\n${stringifyOpenAPI(body, null, 2)}` : '';
179
+ const bodyString = body ? `\n${body}` : '';
121
180
 
122
181
  const httpRequest = `${method.toUpperCase()} ${decodeURI(path)} HTTP/1.1
123
182
  Host: ${host}
@@ -157,3 +216,165 @@ export function parseHostAndPath(url: string) {
157
216
  return { host, path };
158
217
  }
159
218
  }
219
+
220
+ // Body Generators
221
+ const BodyGenerators = {
222
+ getCurlBody(body: any, headers?: Record<string, string>) {
223
+ if (!body || !headers) return undefined;
224
+
225
+ // Copy headers to avoid mutating the original object
226
+ const headersCopy = { ...headers };
227
+ const contentType: string = headersCopy['Content-Type'] || '';
228
+
229
+ if (isFormData(contentType)) {
230
+ body = isPlainObject(body)
231
+ ? Object.entries(body).map(([key, value]) => `--form '${key}=${String(value)}'`)
232
+ : `--form 'file=@${body}'`;
233
+ } else if (isFormUrlEncoded(contentType)) {
234
+ body = isPlainObject(body)
235
+ ? `--data '${Object.entries(body)
236
+ .map(([key, value]) => `${key}=${String(value)}`)
237
+ .join('&')}'`
238
+ : String(body);
239
+ } else if (isText(contentType)) {
240
+ body = `--data '${String(body).replace(/"/g, '')}'`;
241
+ } else if (isXML(contentType) || isCSV(contentType)) {
242
+ // We use --data-binary to avoid cURL converting newlines to \r\n
243
+ body = `--data-binary $'${stringifyOpenAPI(body).replace(/"/g, '')}'`;
244
+ } else if (isGraphQL(contentType)) {
245
+ body = `--data '${stringifyOpenAPI(body)}'`;
246
+ // Set Content-Type to application/json for GraphQL, recommended by GraphQL spec
247
+ headersCopy['Content-Type'] = 'application/json';
248
+ } else if (isPDF(contentType)) {
249
+ // We use --data-binary to avoid cURL converting newlines to \r\n
250
+ body = `--data-binary '@${String(body)}'`;
251
+ } else {
252
+ body = `--data '${stringifyOpenAPI(body, null, 2)}'`;
253
+ }
254
+
255
+ return {
256
+ body,
257
+ headers: headersCopy,
258
+ };
259
+ },
260
+ getJavaScriptBody: (body: any, headers?: Record<string, string>) => {
261
+ if (!body || !headers) return;
262
+
263
+ let code = '';
264
+
265
+ // Copy headers to avoid mutating the original object
266
+ const headersCopy = { ...headers };
267
+ const contentType: string = headersCopy['Content-Type'] || '';
268
+
269
+ // Use FormData for file uploads
270
+ if (isFormData(contentType)) {
271
+ code += 'const formData = new FormData();\n\n';
272
+ if (isPlainObject(body)) {
273
+ Object.entries(body).forEach(([key, value]) => {
274
+ code += `formData.append("${key}", "${String(value)}");\n`;
275
+ });
276
+ } else if (typeof body === 'string') {
277
+ code += `formData.append("file", "${body}");\n`;
278
+ }
279
+ code += '\n';
280
+ body = 'formData';
281
+ } else if (isFormUrlEncoded(contentType)) {
282
+ // Use URLSearchParams for form-urlencoded data
283
+ code += 'const params = new URLSearchParams();\n\n';
284
+ if (isPlainObject(body)) {
285
+ Object.entries(body).forEach(([key, value]) => {
286
+ code += `params.append("${key}", "${String(value)}");\n`;
287
+ });
288
+ }
289
+ code += '\n';
290
+ body = 'params.toString()';
291
+ } else if (isGraphQL(contentType)) {
292
+ if (isPlainObject(body)) {
293
+ Object.entries(body).forEach(([key, value]) => {
294
+ code += `const ${key} = \`\n${indent(String(value), 4)}\`;\n\n`;
295
+ });
296
+ body = `JSON.stringify({ ${Object.keys(body).join(', ')} })`;
297
+ // Set Content-Type to application/json for GraphQL, recommended by GraphQL spec
298
+ headersCopy['Content-Type'] = 'application/json';
299
+ } else {
300
+ code += `const query = \`\n${indent(String(body), 4)}\`;\n\n`;
301
+ body = 'JSON.stringify(query)';
302
+ }
303
+ } else if (isCSV(contentType)) {
304
+ code += 'const csv = `\n';
305
+ code += indent(String(body), 4);
306
+ code += '`;\n\n';
307
+ body = 'csv';
308
+ } else if (isPDF(contentType)) {
309
+ // Use FormData to upload PDF files
310
+ code += 'const formData = new FormData();\n\n';
311
+ code += `formData.append("file", "${body}");\n\n`;
312
+ body = 'formData';
313
+ } else if (isXML(contentType)) {
314
+ code += 'const xml = `\n';
315
+ code += indent(String(body), 4);
316
+ code += '`;\n\n';
317
+ body = 'xml';
318
+ } else if (isText(contentType)) {
319
+ body = stringifyOpenAPI(body, null, 2);
320
+ } else {
321
+ body = `JSON.stringify(${stringifyOpenAPI(body, null, 2)})`;
322
+ }
323
+
324
+ return { body, code, headers: headersCopy };
325
+ },
326
+ getPythonBody: (body: any, headers?: Record<string, string>) => {
327
+ if (!body || !headers) return;
328
+ let code = '';
329
+ const contentType: string = headers['Content-Type'] || '';
330
+
331
+ if (isFormData(contentType)) {
332
+ code += 'files = {\n';
333
+ if (isPlainObject(body)) {
334
+ Object.entries(body).forEach(([key, value]) => {
335
+ code += indent(`"${key}": "${String(value)}",`, 4) + '\n';
336
+ });
337
+ }
338
+ code += '}\n\n';
339
+ body = 'files';
340
+ }
341
+
342
+ if (isPDF(contentType)) {
343
+ code += 'files = {\n';
344
+ code += indent(`"file": "${body}",`, 4) + '\n';
345
+ code += '}\n\n';
346
+ body = 'files';
347
+ }
348
+
349
+ return { body, code, headers };
350
+ },
351
+ getHTTPBody: (body: any, headers?: Record<string, string>) => {
352
+ if (!body || !headers) return undefined;
353
+
354
+ const contentType: string = headers['Content-Type'] || '';
355
+
356
+ const typeHandlers = {
357
+ pdf: () => `${stringifyOpenAPI(body, null, 2)}`,
358
+ formUrlEncoded: () => {
359
+ const encoded = isPlainObject(body)
360
+ ? Object.entries(body)
361
+ .map(([key, value]) => `${key}=${String(value)}`)
362
+ .join('&')
363
+ : String(body);
364
+ return `"${encoded}"`;
365
+ },
366
+ text: () => `"${String(body)}"`,
367
+ xmlOrCsv: () => `"${stringifyOpenAPI(body).replace(/"/g, '')}"`,
368
+ default: () => `${stringifyOpenAPI(body, null, 2)}`,
369
+ };
370
+
371
+ if (isPDF(contentType)) return typeHandlers.pdf();
372
+ if (isFormUrlEncoded(contentType)) return typeHandlers.formUrlEncoded();
373
+ if (isText(contentType)) return typeHandlers.text();
374
+ if (isXML(contentType) || isCSV(contentType)) {
375
+ return typeHandlers.xmlOrCsv();
376
+ }
377
+
378
+ return typeHandlers.default();
379
+ },
380
+ };
@@ -0,0 +1,35 @@
1
+ export function isJSON(contentType?: string): boolean {
2
+ return contentType?.toLowerCase().includes('application/json') || false;
3
+ }
4
+
5
+ export function isXML(contentType?: string): boolean {
6
+ return contentType?.toLowerCase().includes('application/xml') || false;
7
+ }
8
+
9
+ export function isGraphQL(contentType?: string): boolean {
10
+ return contentType?.toLowerCase().includes('application/graphql') || false;
11
+ }
12
+
13
+ export function isCSV(contentType?: string): boolean {
14
+ return contentType?.toLowerCase().includes('text/csv') || false;
15
+ }
16
+
17
+ export function isPDF(contentType?: string): boolean {
18
+ return contentType?.toLowerCase().includes('application/pdf') || false;
19
+ }
20
+
21
+ export function isText(contentType?: string): boolean {
22
+ return contentType?.toLowerCase().includes('text/plain') || false;
23
+ }
24
+
25
+ export function isFormUrlEncoded(contentType?: string): boolean {
26
+ return contentType?.toLowerCase().includes('application/x-www-form-urlencoded') || false;
27
+ }
28
+
29
+ export function isFormData(contentType?: string): boolean {
30
+ return !!contentType && contentType.toLowerCase().includes('multipart/form-data');
31
+ }
32
+
33
+ export function isPlainObject(value: unknown): boolean {
34
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
35
+ }
@@ -16,23 +16,27 @@ export function generateSchemaExample(
16
16
  schema: OpenAPIV3.SchemaObject,
17
17
  options?: GenerateSchemaExampleOptions,
18
18
  ): JSONValue | undefined {
19
- return getExampleFromSchema(schema, {
20
- emptyString: 'text',
21
- variables: {
22
- 'date-time': new Date().toISOString(),
23
- date: new Date().toISOString().split('T')[0],
24
- email: 'name@gmail.com',
25
- hostname: 'example.com',
26
- ipv4: '0.0.0.0',
27
- ipv6: '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
28
- uri: 'https://example.com',
29
- uuid: '123e4567-e89b-12d3-a456-426614174000',
30
- binary: 'binary',
31
- byte: 'Ynl0ZXM=',
32
- password: 'password',
19
+ return getExampleFromSchema(
20
+ schema,
21
+ {
22
+ emptyString: 'text',
23
+ variables: {
24
+ 'date-time': new Date().toISOString(),
25
+ date: new Date().toISOString().split('T')[0],
26
+ email: 'name@gmail.com',
27
+ hostname: 'example.com',
28
+ ipv4: '0.0.0.0',
29
+ ipv6: '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
30
+ uri: 'https://example.com',
31
+ uuid: '123e4567-e89b-12d3-a456-426614174000',
32
+ binary: 'binary',
33
+ byte: 'Ynl0ZXM=',
34
+ password: 'password',
35
+ },
36
+ ...options,
33
37
  },
34
- ...options,
35
- });
38
+ 3, // Max depth for circular references
39
+ );
36
40
  }
37
41
 
38
42
  /**
@@ -1,6 +1,17 @@
1
1
  /**
2
2
  * Stringify an OpenAPI object. Same API as JSON.stringify.
3
3
  */
4
- export function stringifyOpenAPI(body: unknown, transformer?: null, indent?: number): string {
5
- return JSON.stringify(body, transformer, indent);
4
+ export function stringifyOpenAPI(body: unknown, _?: null, indent?: number): string {
5
+ return JSON.stringify(
6
+ body,
7
+ (key, value) => {
8
+ // Ignore internal keys
9
+ if (key.startsWith('x-gitbook-')) {
10
+ return undefined;
11
+ }
12
+
13
+ return value;
14
+ },
15
+ indent,
16
+ );
6
17
  }
package/src/types.ts CHANGED
@@ -5,8 +5,18 @@ import type {
5
5
  } from '@gitbook/openapi-parser';
6
6
 
7
7
  export interface OpenAPIContextProps extends OpenAPIClientContext {
8
- CodeBlock: React.ComponentType<{ code: string; syntax: string }>;
8
+ /**
9
+ * Render a code block.
10
+ */
11
+ renderCodeBlock: (props: { code: string; syntax: string }) => React.ReactNode;
12
+ /**
13
+ * Render the heading of the operation.
14
+ */
9
15
  renderHeading: (props: { deprecated: boolean; title: string }) => React.ReactNode;
16
+ /**
17
+ * Render the document of the operation.
18
+ */
19
+ renderDocument: (props: { document: object }) => React.ReactNode;
10
20
 
11
21
  /** Spec url for the Scalar Api Client */
12
22
  specUrl: string;
@@ -0,0 +1,58 @@
1
+ import { describe, it, expect } from 'bun:test';
2
+ import { interpolateServerURL, getDefaultServerURL } from './server';
3
+ import { OpenAPIV3 } from '@gitbook/openapi-parser';
4
+
5
+ describe('#interpolateServerURL', () => {
6
+ it('interpolates the server URL with the default values of the variables', () => {
7
+ const server: OpenAPIV3.ServerObject = {
8
+ url: 'https://{username}.example.com/{basePath}',
9
+ variables: {
10
+ username: { default: 'user' },
11
+ basePath: { default: 'v1' },
12
+ },
13
+ };
14
+ const result = interpolateServerURL(server);
15
+ expect(result).toBe('https://user.example.com/v1');
16
+ });
17
+
18
+ it('returns the URL with placeholders if no variables are provided', () => {
19
+ const server: OpenAPIV3.ServerObject = {
20
+ url: 'https://{username}.example.com/{basePath}',
21
+ };
22
+ const result = interpolateServerURL(server);
23
+ expect(result).toBe('https://{username}.example.com/{basePath}');
24
+ });
25
+
26
+ it('returns the URL with mixed placeholders and default values', () => {
27
+ const server: OpenAPIV3.ServerObject = {
28
+ url: 'https://{username}.example.com/{basePath}',
29
+ variables: {
30
+ basePath: { default: 'v1' },
31
+ },
32
+ };
33
+ const result = interpolateServerURL(server);
34
+ expect(result).toBe('https://{username}.example.com/v1');
35
+ });
36
+ });
37
+
38
+ describe('#getDefaultServerURL', () => {
39
+ it('returns the default server URL', () => {
40
+ const servers: OpenAPIV3.ServerObject[] = [
41
+ {
42
+ url: 'https://{username}.example.com/{basePath}',
43
+ variables: {
44
+ username: { default: 'user' },
45
+ basePath: { default: 'v1' },
46
+ },
47
+ },
48
+ ];
49
+ const result = getDefaultServerURL(servers);
50
+ expect(result).toBe('https://user.example.com/v1');
51
+ });
52
+
53
+ it('returns empty string if no servers are provided', () => {
54
+ const servers: OpenAPIV3.ServerObject[] = [];
55
+ const result = getDefaultServerURL(servers);
56
+ expect(result).toBe('');
57
+ });
58
+ });
@@ -0,0 +1,48 @@
1
+ import { OpenAPIV3 } from '@gitbook/openapi-parser';
2
+
3
+ /**
4
+ * Get the default URL for the server.
5
+ */
6
+ export function getDefaultServerURL(servers: OpenAPIV3.ServerObject[]): string {
7
+ const server = servers[0];
8
+ if (!server) {
9
+ // Return empty string if no server is found to display nothing
10
+ return '';
11
+ }
12
+
13
+ return interpolateServerURL(server);
14
+ }
15
+
16
+ /**
17
+ * Interpolate the server URL with the default values of the variables.
18
+ */
19
+ export function interpolateServerURL(server: OpenAPIV3.ServerObject) {
20
+ const parts = parseServerURL(server?.url ?? '');
21
+
22
+ return parts
23
+ .map((part) => {
24
+ if (part.kind === 'text') {
25
+ return part.text;
26
+ } else {
27
+ return server.variables?.[part.name]?.default ?? `{${part.name}}`;
28
+ }
29
+ })
30
+ .join('');
31
+ }
32
+
33
+ function parseServerURL(url: string) {
34
+ const parts = url.split(/{([^}]+)}/g);
35
+ const result: Array<{ kind: 'variable'; name: string } | { kind: 'text'; text: string }> = [];
36
+ for (let i = 0; i < parts.length; i++) {
37
+ const part = parts[i];
38
+ if (!part) {
39
+ continue;
40
+ }
41
+ if (i % 2 === 0) {
42
+ result.push({ kind: 'text', text: part });
43
+ } else {
44
+ result.push({ kind: 'variable', name: part });
45
+ }
46
+ }
47
+ return result;
48
+ }
package/src/utils.ts CHANGED
@@ -13,7 +13,11 @@ export function createStateKey(key: string, scope?: string) {
13
13
  /**
14
14
  * Resolve the description of an object.
15
15
  */
16
- export function resolveDescription(object: AnyObject) {
16
+ export function resolveDescription(object: OpenAPIV3.SchemaObject | AnyObject) {
17
+ if ('items' in object && object.items) {
18
+ return resolveDescription(object.items);
19
+ }
20
+
17
21
  return 'x-gitbook-description-html' in object &&
18
22
  typeof object['x-gitbook-description-html'] === 'string'
19
23
  ? object['x-gitbook-description-html'].trim()
@@ -1,11 +0,0 @@
1
- import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
- /**
3
- * Show the url of the server with variables replaced by their default values.
4
- */
5
- export declare function OpenAPIServerURL(props: {
6
- servers: OpenAPIV3.ServerObject[];
7
- }): import("react").JSX.Element | null;
8
- /**
9
- * Get the default URL for the server.
10
- */
11
- export declare function getServersURL(servers: OpenAPIV3.ServerObject[]): string;
@@ -1,8 +0,0 @@
1
- import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
- /**
3
- * Interactive component to show the value of a server variable and let the user change it.
4
- */
5
- export declare function OpenAPIServerURLVariable(props: {
6
- name: string;
7
- variable: OpenAPIV3.ServerVariableObject;
8
- }): import("react").JSX.Element;
@@ -1,8 +0,0 @@
1
- 'use client';
2
- /**
3
- * Interactive component to show the value of a server variable and let the user change it.
4
- */
5
- export function OpenAPIServerURLVariable(props) {
6
- var variable = props.variable;
7
- return <span className="openapi-url-var">{variable.default}</span>;
8
- }
@@ -1,73 +0,0 @@
1
- import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
- import { OpenAPIServerURLVariable } from './OpenAPIServerURLVariable';
3
-
4
- /**
5
- * Show the url of the server with variables replaced by their default values.
6
- */
7
- export function OpenAPIServerURL(props: { servers: OpenAPIV3.ServerObject[] }) {
8
- const { servers } = props;
9
- const server = servers[0];
10
-
11
- if (!server) {
12
- return null;
13
- }
14
-
15
- const parts = parseServerURL(server?.url ?? '');
16
-
17
- return (
18
- <span>
19
- {parts.map((part, i) => {
20
- if (part.kind === 'text') {
21
- return <span key={i}>{part.text}</span>;
22
- } else {
23
- const variable = server.variables?.[part.name];
24
- if (!variable) {
25
- return <span key={i}>{`{${part.name}}`}</span>;
26
- }
27
-
28
- return (
29
- <OpenAPIServerURLVariable key={i} name={part.name} variable={variable} />
30
- );
31
- }
32
- })}
33
- </span>
34
- );
35
- }
36
-
37
- /**
38
- * Get the default URL for the server.
39
- */
40
- export function getServersURL(servers: OpenAPIV3.ServerObject[]): string {
41
- const server = servers[0];
42
- if (!server) {
43
- return '';
44
- }
45
- const parts = parseServerURL(server?.url ?? '');
46
-
47
- return parts
48
- .map((part) => {
49
- if (part.kind === 'text') {
50
- return part.text;
51
- } else {
52
- return server.variables?.[part.name]?.default ?? `{${part.name}}`;
53
- }
54
- })
55
- .join('');
56
- }
57
-
58
- function parseServerURL(url: string) {
59
- const parts = url.split(/{([^}]+)}/g);
60
- const result: Array<{ kind: 'variable'; name: string } | { kind: 'text'; text: string }> = [];
61
- for (let i = 0; i < parts.length; i++) {
62
- const part = parts[i];
63
- if (!part) {
64
- continue;
65
- }
66
- if (i % 2 === 0) {
67
- result.push({ kind: 'text', text: part });
68
- } else {
69
- result.push({ kind: 'variable', name: part });
70
- }
71
- }
72
- return result;
73
- }
@@ -1,14 +0,0 @@
1
- 'use client';
2
-
3
- import type { OpenAPIV3 } from '@gitbook/openapi-parser';
4
-
5
- /**
6
- * Interactive component to show the value of a server variable and let the user change it.
7
- */
8
- export function OpenAPIServerURLVariable(props: {
9
- name: string;
10
- variable: OpenAPIV3.ServerVariableObject;
11
- }) {
12
- const { variable } = props;
13
- return <span className="openapi-url-var">{variable.default}</span>;
14
- }