@gitbook/react-openapi 0.7.1 → 1.0.0

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 (115) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/InteractiveSection.d.ts +4 -6
  3. package/dist/InteractiveSection.jsx +96 -0
  4. package/dist/Markdown.d.ts +1 -2
  5. package/dist/Markdown.jsx +5 -0
  6. package/dist/OpenAPICodeSample.d.ts +2 -4
  7. package/dist/OpenAPICodeSample.jsx +143 -0
  8. package/dist/OpenAPIDisclosure.d.ts +12 -0
  9. package/dist/OpenAPIDisclosure.jsx +32 -0
  10. package/dist/OpenAPIDisclosureGroup.d.ts +19 -0
  11. package/dist/OpenAPIDisclosureGroup.jsx +81 -0
  12. package/dist/OpenAPIOperation.d.ts +2 -4
  13. package/dist/OpenAPIOperation.jsx +51 -0
  14. package/dist/OpenAPIOperationContext.d.ts +16 -0
  15. package/dist/OpenAPIOperationContext.jsx +26 -0
  16. package/dist/OpenAPIPath.d.ts +8 -0
  17. package/dist/OpenAPIPath.jsx +54 -0
  18. package/dist/OpenAPIRequestBody.d.ts +3 -4
  19. package/dist/OpenAPIRequestBody.jsx +19 -0
  20. package/dist/OpenAPIResponse.d.ts +4 -4
  21. package/dist/OpenAPIResponse.jsx +49 -0
  22. package/dist/OpenAPIResponseExample.d.ts +2 -4
  23. package/dist/OpenAPIResponseExample.jsx +108 -0
  24. package/dist/OpenAPIResponses.d.ts +3 -4
  25. package/dist/OpenAPIResponses.jsx +36 -0
  26. package/dist/OpenAPISchema.d.ts +11 -8
  27. package/dist/OpenAPISchema.jsx +295 -0
  28. package/dist/OpenAPISchemaName.d.ts +12 -0
  29. package/dist/OpenAPISchemaName.jsx +15 -0
  30. package/dist/OpenAPISecurities.d.ts +2 -4
  31. package/dist/OpenAPISecurities.jsx +55 -0
  32. package/dist/OpenAPIServerURL.d.ts +2 -3
  33. package/dist/OpenAPIServerURL.jsx +67 -0
  34. package/dist/OpenAPIServerURLVariable.d.ts +2 -3
  35. package/dist/OpenAPIServerURLVariable.jsx +8 -0
  36. package/dist/OpenAPISpec.d.ts +3 -4
  37. package/dist/OpenAPISpec.jsx +91 -0
  38. package/dist/OpenAPITabs.d.ts +25 -0
  39. package/dist/OpenAPITabs.jsx +67 -0
  40. package/dist/ScalarApiButton.d.ts +3 -3
  41. package/dist/ScalarApiButton.jsx +51 -0
  42. package/dist/code-samples.d.ts +4 -0
  43. package/dist/code-samples.js +103 -38
  44. package/dist/fetchOpenAPIOperation.d.ts +9 -54
  45. package/dist/fetchOpenAPIOperation.js +178 -107
  46. package/dist/generateSchemaExample.d.ts +2 -2
  47. package/dist/generateSchemaExample.js +28 -100
  48. package/dist/index.d.ts +3 -2
  49. package/dist/index.js +2 -1
  50. package/dist/resolveOpenAPIOperation.d.ts +11 -0
  51. package/dist/resolveOpenAPIOperation.js +194 -0
  52. package/dist/stringifyOpenAPI.d.ts +4 -0
  53. package/dist/stringifyOpenAPI.js +6 -0
  54. package/dist/tsconfig.build.tsbuildinfo +1 -0
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/dist/types.d.ts +11 -12
  57. package/dist/utils.d.ts +6 -1
  58. package/dist/utils.js +15 -2
  59. package/package.json +11 -10
  60. package/src/InteractiveSection.tsx +119 -78
  61. package/src/Markdown.tsx +2 -3
  62. package/src/OpenAPICodeSample.tsx +35 -21
  63. package/src/OpenAPIDisclosure.tsx +50 -0
  64. package/src/OpenAPIDisclosureGroup.tsx +136 -0
  65. package/src/OpenAPIOperation.tsx +36 -42
  66. package/src/OpenAPIOperationContext.tsx +45 -0
  67. package/src/OpenAPIPath.tsx +65 -0
  68. package/src/OpenAPIRequestBody.tsx +3 -14
  69. package/src/OpenAPIResponse.tsx +39 -43
  70. package/src/OpenAPIResponseExample.tsx +89 -31
  71. package/src/OpenAPIResponses.tsx +51 -15
  72. package/src/OpenAPISchema.test.ts +1 -1
  73. package/src/OpenAPISchema.tsx +124 -92
  74. package/src/OpenAPISchemaName.tsx +27 -0
  75. package/src/OpenAPISecurities.tsx +45 -24
  76. package/src/OpenAPIServerURL.tsx +17 -10
  77. package/src/OpenAPIServerURLVariable.tsx +2 -4
  78. package/src/OpenAPISpec.tsx +56 -53
  79. package/src/OpenAPITabs.tsx +113 -0
  80. package/src/ScalarApiButton.tsx +84 -7
  81. package/src/code-samples.test.ts +51 -0
  82. package/src/code-samples.ts +95 -31
  83. package/src/generateSchemaExample.ts +25 -151
  84. package/src/index.ts +3 -2
  85. package/src/resolveOpenAPIOperation.test.ts +177 -0
  86. package/src/resolveOpenAPIOperation.ts +163 -0
  87. package/src/stringifyOpenAPI.ts +6 -0
  88. package/src/types.ts +17 -10
  89. package/src/utils.ts +17 -2
  90. package/dist/InteractiveSection.js +0 -47
  91. package/dist/Markdown.js +0 -6
  92. package/dist/OpenAPICodeSample.js +0 -110
  93. package/dist/OpenAPIOperation.js +0 -38
  94. package/dist/OpenAPIRequestBody.js +0 -18
  95. package/dist/OpenAPIResponse.js +0 -32
  96. package/dist/OpenAPIResponseExample.js +0 -54
  97. package/dist/OpenAPIResponses.js +0 -18
  98. package/dist/OpenAPISchema.js +0 -235
  99. package/dist/OpenAPISchema.test.d.ts +0 -1
  100. package/dist/OpenAPISchema.test.js +0 -91
  101. package/dist/OpenAPISecurities.js +0 -42
  102. package/dist/OpenAPIServerURL.js +0 -51
  103. package/dist/OpenAPIServerURLVariable.js +0 -10
  104. package/dist/OpenAPISpec.js +0 -70
  105. package/dist/ScalarApiButton.js +0 -14
  106. package/dist/fetchOpenAPIOperation.test.d.ts +0 -1
  107. package/dist/fetchOpenAPIOperation.test.js +0 -152
  108. package/dist/resolveOpenAPIPath.d.ts +0 -7
  109. package/dist/resolveOpenAPIPath.js +0 -112
  110. package/dist/resolveOpenAPIPath.test.d.ts +0 -1
  111. package/dist/resolveOpenAPIPath.test.js +0 -39
  112. package/src/fetchOpenAPIOperation.test.ts +0 -185
  113. package/src/fetchOpenAPIOperation.ts +0 -230
  114. package/src/resolveOpenAPIPath.test.ts +0 -60
  115. package/src/resolveOpenAPIPath.ts +0 -145
@@ -1,16 +1,16 @@
1
- import * as React from 'react';
2
- import classNames from 'classnames';
3
- import { OpenAPIV3 } from 'openapi-types';
4
- import { createStateKey, noReference } from './utils';
1
+ import type { OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser';
2
+ import { createStateKey, resolveDescription } from './utils';
5
3
  import { OpenAPIResponse } from './OpenAPIResponse';
6
4
  import { OpenAPIClientContext } from './types';
7
5
  import { InteractiveSection } from './InteractiveSection';
6
+ import { OpenAPIDisclosureGroup } from './OpenAPIDisclosureGroup';
7
+ import { Markdown } from './Markdown';
8
8
 
9
9
  /**
10
10
  * Display an interactive response body.
11
11
  */
12
12
  export function OpenAPIResponses(props: {
13
- responses: OpenAPIV3.ResponsesObject;
13
+ responses: OpenAPIV3.ResponsesObject | OpenAPIV3_1.ResponsesObject;
14
14
  context: OpenAPIClientContext;
15
15
  }) {
16
16
  const { responses, context } = props;
@@ -18,15 +18,51 @@ export function OpenAPIResponses(props: {
18
18
  return (
19
19
  <InteractiveSection
20
20
  stateKey={createStateKey('response', context.blockKey)}
21
- header="Response"
22
- className={classNames('openapi-responses')}
23
- tabs={Object.entries(responses).map(([statusCode, response]) => {
24
- return {
25
- key: statusCode,
26
- label: statusCode,
27
- body: <OpenAPIResponse response={noReference(response)} context={context} />,
28
- };
29
- })}
30
- />
21
+ header="Responses"
22
+ className="openapi-responses"
23
+ >
24
+ <OpenAPIDisclosureGroup
25
+ allowsMultipleExpanded
26
+ icon={context.icons.chevronRight}
27
+ groups={Object.entries(responses).map(
28
+ ([statusCode, response]: [string, OpenAPIV3.ResponseObject]) => {
29
+ const content = Object.entries(response.content ?? {});
30
+ const description = resolveDescription(response);
31
+
32
+ return {
33
+ id: statusCode,
34
+ label: (
35
+ <div
36
+ className="openapi-response-tab-content"
37
+ key={`response-${statusCode}`}
38
+ >
39
+ <span className="openapi-response-statuscode">
40
+ {statusCode}
41
+ </span>
42
+ {description ? (
43
+ <Markdown
44
+ source={description}
45
+ className="openapi-response-description"
46
+ />
47
+ ) : null}
48
+ </div>
49
+ ),
50
+ tabs: content.map(([contentType, mediaType]) => ({
51
+ id: contentType,
52
+ label: contentType,
53
+ body: (
54
+ <OpenAPIResponse
55
+ key={`$response-${statusCode}-${contentType}`}
56
+ response={response}
57
+ mediaType={mediaType}
58
+ context={context}
59
+ />
60
+ ),
61
+ })),
62
+ };
63
+ },
64
+ )}
65
+ />
66
+ </InteractiveSection>
31
67
  );
32
68
  }
@@ -1,6 +1,6 @@
1
1
  import { it, describe, expect } from 'bun:test';
2
2
  import { getSchemaAlternatives } from './OpenAPISchema';
3
- import { OpenAPIV3 } from 'openapi-types';
3
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
4
4
 
5
5
  describe('getSchemaAlternatives', () => {
6
6
  it('should flatten oneOf', () => {
@@ -1,16 +1,18 @@
1
- import classNames from 'classnames';
2
- import { OpenAPIV3 } from 'openapi-types';
3
- import React, { useId } from 'react';
1
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
+ import clsx from 'clsx';
3
+ import { useId } from 'react';
4
4
 
5
5
  import { InteractiveSection } from './InteractiveSection';
6
6
  import { Markdown } from './Markdown';
7
- import { SYMBOL_REF_RESOLVED } from './resolveOpenAPIPath';
8
- import { OpenAPIClientContext } from './types';
9
- import { noReference } from './utils';
7
+ import type { OpenAPIClientContext } from './types';
8
+ import { checkIsReference, noReference, resolveDescription } from './utils';
9
+ import { stringifyOpenAPI } from './stringifyOpenAPI';
10
+ import { OpenAPISchemaName } from './OpenAPISchemaName';
11
+ import { OpenAPIDisclosure } from './OpenAPIDisclosure';
10
12
 
11
13
  type CircularRefsIds = Map<OpenAPIV3.SchemaObject, string>;
12
14
 
13
- interface OpenAPISchemaPropertyEntry {
15
+ export interface OpenAPISchemaPropertyEntry {
14
16
  propertyName?: string;
15
17
  required?: boolean;
16
18
  schema: OpenAPIV3.SchemaObject;
@@ -28,8 +30,6 @@ export function OpenAPISchemaProperty(
28
30
  },
29
31
  ) {
30
32
  const {
31
- propertyName,
32
- required,
33
33
  schema,
34
34
  circularRefs: parentCircularRefs = new Map<OpenAPIV3.SchemaObject, string>(),
35
35
  context,
@@ -47,71 +47,42 @@ export function OpenAPISchemaProperty(
47
47
  ? null
48
48
  : getSchemaAlternatives(schema, new Set(circularRefs.keys()));
49
49
 
50
- const shouldDisplayExample = (schema: OpenAPIV3.SchemaObject): boolean => {
50
+ if ((properties && !!properties.length) || schema.type === 'object') {
51
51
  return (
52
- typeof schema.example === 'string' ||
53
- typeof schema.example === 'number' ||
54
- typeof schema.example === 'boolean'
52
+ <InteractiveSection id={id} className={clsx('openapi-schema', className)}>
53
+ <OpenAPISchemaPresentation {...props} />
54
+ <OpenAPIDisclosure context={context}>
55
+ {properties && properties.length > 0 ? (
56
+ <OpenAPISchemaProperties
57
+ properties={properties}
58
+ circularRefs={circularRefs}
59
+ context={context}
60
+ />
61
+ ) : null}
62
+ </OpenAPIDisclosure>
63
+ </InteractiveSection>
55
64
  );
56
- };
57
- return (
58
- <InteractiveSection
59
- id={id}
60
- className={classNames('openapi-schema', className)}
61
- toggeable={!!properties || !!alternatives}
62
- defaultOpened={!!context.defaultInteractiveOpened}
63
- toggleOpenIcon={context.icons.chevronRight}
64
- toggleCloseIcon={context.icons.chevronDown}
65
- tabs={alternatives?.[0].map((alternative, index) => ({
66
- key: `${index}`,
67
- label: getSchemaTitle(alternative, alternatives[1]),
68
- body: circularRefs.has(alternative) ? (
69
- <OpenAPISchemaCircularRef
70
- id={circularRefs.get(alternative)!}
71
- schema={alternative}
72
- />
73
- ) : (
65
+ }
66
+
67
+ if (alternatives?.[0]?.length) {
68
+ return (
69
+ <InteractiveSection id={id} className={clsx('openapi-schema', className)}>
70
+ <OpenAPISchemaPresentation {...props} />
71
+ {alternatives[0].map((alternative, index) => (
74
72
  <OpenAPISchemaAlternative
73
+ key={index}
75
74
  schema={alternative}
76
75
  circularRefs={circularRefs}
77
76
  context={context}
78
77
  />
79
- ),
80
- }))}
81
- header={
82
- <div className={classNames('openapi-schema-presentation')}>
83
- <div className={classNames('openapi-schema-name')}>
84
- {propertyName ? (
85
- <span className={classNames('openapi-schema-propertyname')}>
86
- {propertyName}
87
- </span>
88
- ) : null}
89
- {required ? (
90
- <span className={classNames('openapi-schema-required')}>*</span>
91
- ) : null}
92
- <span className={classNames('openapi-schema-type')}>
93
- {getSchemaTitle(schema)}
94
- </span>
95
- </div>
96
- {schema.description ? (
97
- <Markdown
98
- source={schema.description}
99
- className="openapi-schema-description"
100
- />
101
- ) : null}
102
- {shouldDisplayExample(schema) ? (
103
- <span className="openapi-schema-example">
104
- Example: <code>{JSON.stringify(schema.example)}</code>
105
- </span>
106
- ) : null}
107
- {schema.pattern ? (
108
- <div className="openapi-schema-pattern">
109
- Pattern: <code>{schema.pattern}</code>
110
- </div>
111
- ) : null}
112
- </div>
113
- }
114
- >
78
+ ))}
79
+ </InteractiveSection>
80
+ );
81
+ }
82
+
83
+ return (
84
+ <InteractiveSection id={id} className={clsx('openapi-schema', className)}>
85
+ <OpenAPISchemaPresentation {...props} />
115
86
  {(properties && properties.length > 0) ||
116
87
  (schema.enum && schema.enum.length > 0) ||
117
88
  parentCircularRef ? (
@@ -123,9 +94,6 @@ export function OpenAPISchemaProperty(
123
94
  context={context}
124
95
  />
125
96
  ) : null}
126
- {schema.enum && schema.enum.length > 0 ? (
127
- <OpenAPISchemaEnum enumValues={schema.enum} />
128
- ) : null}
129
97
  {parentCircularRef ? (
130
98
  <OpenAPISchemaCircularRef id={parentCircularRef} schema={schema} />
131
99
  ) : null}
@@ -151,7 +119,7 @@ export function OpenAPISchemaProperties(props: {
151
119
  }
152
120
 
153
121
  return (
154
- <div id={id} className={classNames('openapi-schema-properties')}>
122
+ <div id={id} className="openapi-schema-properties">
155
123
  {properties.map((property) => (
156
124
  <OpenAPISchemaProperty
157
125
  key={property.propertyName}
@@ -200,12 +168,14 @@ function OpenAPISchemaAlternative(props: {
200
168
  const subProperties = getSchemaProperties(schema);
201
169
 
202
170
  return (
203
- <OpenAPISchemaProperties
204
- id={id}
205
- properties={subProperties ?? [{ schema }]}
206
- circularRefs={subProperties ? new Map(circularRefs).set(schema, id) : circularRefs}
207
- context={context}
208
- />
171
+ <OpenAPIDisclosure context={context}>
172
+ <OpenAPISchemaProperties
173
+ id={id}
174
+ properties={subProperties ?? [{ schema }]}
175
+ circularRefs={subProperties ? new Map(circularRefs).set(schema, id) : circularRefs}
176
+ context={context}
177
+ />
178
+ </OpenAPIDisclosure>
209
179
  );
210
180
  }
211
181
 
@@ -231,9 +201,73 @@ export function OpenAPISchemaEnum(props: { enumValues: any[] }) {
231
201
 
232
202
  return (
233
203
  <div className="openapi-schema-enum">
234
- {enumValues.map((value, index) => (
235
- <span key={index} className="openapi-schema-enum-value">{`${value}`}</span>
236
- ))}
204
+ <span>
205
+ Options:{' '}
206
+ {enumValues.map((value, index) => (
207
+ <span key={index} className="openapi-schema-enum-value">
208
+ <code>{`${value}`}</code>
209
+ {index < enumValues.length - 1 ? ', ' : ''}
210
+ </span>
211
+ ))}
212
+ </span>
213
+ </div>
214
+ );
215
+ }
216
+
217
+ export function OpenAPISchemaPresentation(props: OpenAPISchemaPropertyEntry) {
218
+ const { schema, propertyName, required } = props;
219
+
220
+ const shouldDisplayExample = (schema: OpenAPIV3.SchemaObject): boolean => {
221
+ return (
222
+ typeof schema.example === 'string' ||
223
+ typeof schema.example === 'number' ||
224
+ typeof schema.example === 'boolean' ||
225
+ (Array.isArray(schema.example) && schema.example.length > 0) ||
226
+ (typeof schema.example === 'object' &&
227
+ schema.example !== null &&
228
+ Object.keys(schema.example).length > 0)
229
+ );
230
+ };
231
+
232
+ const description = resolveDescription(schema);
233
+
234
+ return (
235
+ <div className="openapi-schema-presentation">
236
+ <OpenAPISchemaName
237
+ type={getSchemaTitle(schema)}
238
+ propertyName={propertyName}
239
+ required={required}
240
+ deprecated={schema.deprecated}
241
+ />
242
+ {schema['x-deprecated-sunset'] ? (
243
+ <div className="openapi-deprecated-sunset openapi-schema-description openapi-markdown">
244
+ Sunset date:{' '}
245
+ <span className="openapi-deprecated-sunset-date">
246
+ {schema['x-deprecated-sunset']}
247
+ </span>
248
+ </div>
249
+ ) : null}
250
+ {description ? (
251
+ <Markdown source={description} className="openapi-schema-description" />
252
+ ) : null}
253
+ {shouldDisplayExample(schema) ? (
254
+ <div className="openapi-schema-example">
255
+ Example:{' '}
256
+ <code>
257
+ {typeof schema.example === 'string'
258
+ ? schema.example
259
+ : stringifyOpenAPI(schema.example)}
260
+ </code>
261
+ </div>
262
+ ) : null}
263
+ {schema.pattern ? (
264
+ <div className="openapi-schema-pattern">
265
+ Pattern: <code>{schema.pattern}</code>
266
+ </div>
267
+ ) : null}
268
+ {schema.enum && schema.enum.length > 0 ? (
269
+ <OpenAPISchemaEnum enumValues={schema.enum} />
270
+ ) : null}
237
271
  </div>
238
272
  );
239
273
  }
@@ -274,10 +308,10 @@ function getSchemaProperties(schema: OpenAPIV3.SchemaObject): null | OpenAPISche
274
308
 
275
309
  if (schema.properties) {
276
310
  Object.entries(schema.properties).forEach(([propertyName, rawPropertySchema]) => {
277
- const propertySchema = noReference(rawPropertySchema);
278
- if (propertySchema.deprecated) {
279
- return;
280
- }
311
+ const isReference = checkIsReference(rawPropertySchema);
312
+ const propertySchema: OpenAPIV3.SchemaObject = isReference
313
+ ? { propertyName }
314
+ : rawPropertySchema;
281
315
 
282
316
  result.push({
283
317
  propertyName,
@@ -349,7 +383,7 @@ function flattenAlternatives(
349
383
  }, [] as OpenAPIV3.SchemaObject[]);
350
384
  }
351
385
 
352
- function getSchemaTitle(
386
+ export function getSchemaTitle(
353
387
  schema: OpenAPIV3.SchemaObject,
354
388
 
355
389
  /** If the title is inferred in a oneOf with discriminator, we can use it to optimize the title */
@@ -361,7 +395,7 @@ function getSchemaTitle(
361
395
  }
362
396
 
363
397
  // Try using the discriminator
364
- if (discriminator && schema.properties) {
398
+ if (discriminator?.propertyName && schema.properties) {
365
399
  const discriminatorProperty = noReference(schema.properties[discriminator.propertyName]);
366
400
  if (discriminatorProperty) {
367
401
  if (discriminatorProperty.enum) {
@@ -377,12 +411,14 @@ function getSchemaTitle(
377
411
  type = 'enum';
378
412
  // check array AND schema.items as this is sometimes null despite what the type indicates
379
413
  } else if (schema.type === 'array' && !!schema.items) {
380
- type = `array of ${getSchemaTitle(noReference(schema.items))}`;
414
+ type = `${getSchemaTitle(noReference(schema.items))}[]`;
415
+ } else if (Array.isArray(schema.type)) {
416
+ type = schema.type.join(' | ');
381
417
  } else if (schema.type || schema.properties) {
382
418
  type = schema.type ?? 'object';
383
419
 
384
420
  if (schema.format) {
385
- type += ` (${schema.format})`;
421
+ type += ` ${schema.format}`;
386
422
  }
387
423
  } else if ('anyOf' in schema) {
388
424
  type = 'any of';
@@ -394,10 +430,6 @@ function getSchemaTitle(
394
430
  type = 'not';
395
431
  }
396
432
 
397
- if (SYMBOL_REF_RESOLVED in schema) {
398
- type = `${schema[SYMBOL_REF_RESOLVED]} (${type})`;
399
- }
400
-
401
433
  if (schema.nullable) {
402
434
  type = `nullable ${type}`;
403
435
  }
@@ -0,0 +1,27 @@
1
+ interface OpenAPISchemaNameProps {
2
+ propertyName?: string | JSX.Element;
3
+ required?: boolean;
4
+ type?: string;
5
+ deprecated?: boolean;
6
+ }
7
+
8
+ /**
9
+ * Display the schema name row.
10
+ * It includes the property name, type, required and deprecated status.
11
+ */
12
+ export function OpenAPISchemaName(props: OpenAPISchemaNameProps): JSX.Element {
13
+ const { type, propertyName, required, deprecated } = props;
14
+
15
+ return (
16
+ <div className="openapi-schema-name">
17
+ {propertyName ? (
18
+ <span data-deprecated={deprecated} className="openapi-schema-propertyname">
19
+ {propertyName}
20
+ </span>
21
+ ) : null}
22
+ {type ? <span className="openapi-schema-type">{type}</span> : null}
23
+ {required ? <span className="openapi-schema-required">required</span> : null}
24
+ {deprecated ? <span className="openapi-deprecated">Deprecated</span> : null}
25
+ </div>
26
+ );
27
+ }
@@ -1,9 +1,9 @@
1
- import * as React from 'react';
2
- import { OpenAPIV3 } from 'openapi-types';
3
- import { OpenAPIClientContext } from './types';
1
+ import type { OpenAPIV3_1 } from '@gitbook/openapi-parser';
2
+ import type { OpenAPIClientContext, OpenAPIOperationData } from './types';
4
3
  import { InteractiveSection } from './InteractiveSection';
5
4
  import { Markdown } from './Markdown';
6
- import { OpenAPIOperationData } from './fetchOpenAPIOperation';
5
+ import { OpenAPISchemaName } from './OpenAPISchemaName';
6
+ import { resolveDescription } from './utils';
7
7
 
8
8
  /**
9
9
  * Present securities authorization that can be used for this operation.
@@ -20,26 +20,29 @@ export function OpenAPISecurities(props: {
20
20
 
21
21
  return (
22
22
  <InteractiveSection
23
- header="Authorization"
24
- className="openapi-securities"
23
+ header="Authorizations"
25
24
  toggeable
26
25
  defaultOpened={false}
27
- toggleCloseIcon={context.icons.chevronDown}
28
- toggleOpenIcon={context.icons.chevronRight}
26
+ toggleIcon={context.icons.chevronRight}
27
+ className="openapi-securities"
29
28
  tabs={securities.map(([key, security]) => {
29
+ const description = resolveDescription(security);
30
30
  return {
31
31
  key: key,
32
32
  label: key,
33
33
  body: (
34
- <>
35
- <p className="openapi-securities-label">{getLabelForType(security)}</p>
36
- {security.description ? (
37
- <Markdown
38
- source={security.description}
39
- className="openapi-securities-description"
40
- />
41
- ) : null}
42
- </>
34
+ <div className="openapi-schema-body">
35
+ <div className="openapi-schema-presentation">
36
+ {getLabelForType(security)}
37
+
38
+ {description ? (
39
+ <Markdown
40
+ source={description}
41
+ className="openapi-securities-description"
42
+ />
43
+ ) : null}
44
+ </div>
45
+ </div>
43
46
  ),
44
47
  };
45
48
  })}
@@ -47,24 +50,42 @@ export function OpenAPISecurities(props: {
47
50
  );
48
51
  }
49
52
 
50
- function getLabelForType(security: OpenAPIV3.SecuritySchemeObject) {
53
+ function getLabelForType(security: OpenAPIV3_1.SecuritySchemeObject) {
51
54
  switch (security.type) {
52
55
  case 'apiKey':
53
- return 'API Key';
56
+ return (
57
+ <OpenAPISchemaName
58
+ propertyName={security.name ?? 'apiKey'}
59
+ type="string"
60
+ required
61
+ />
62
+ );
54
63
  case 'http':
55
64
  if (security.scheme === 'basic') {
56
- return 'Basic Auth';
65
+ return <OpenAPISchemaName propertyName="Authorization" type="string" required />;
57
66
  }
58
67
 
59
68
  if (security.scheme == 'bearer') {
60
- return `Bearer Token ${security.bearerFormat ? `(${security.bearerFormat})` : ''}`;
69
+ const description = resolveDescription(security);
70
+ return (
71
+ <>
72
+ <OpenAPISchemaName propertyName="Authorization" type="string" required />
73
+ {/** Show a default description if none is provided */}
74
+ {!description ? (
75
+ <Markdown
76
+ source={`Bearer authentication header of the form Bearer ${`&lt;token&gt;`}.`}
77
+ className="openapi-securities-description"
78
+ />
79
+ ) : null}
80
+ </>
81
+ );
61
82
  }
62
83
 
63
- return 'HTTP';
84
+ return <OpenAPISchemaName propertyName="HTTP" required />;
64
85
  case 'oauth2':
65
- return 'OAuth2';
86
+ return <OpenAPISchemaName propertyName="OAuth2" required />;
66
87
  case 'openIdConnect':
67
- return 'OpenID Connect';
88
+ return <OpenAPISchemaName propertyName="OpenID Connect" required />;
68
89
  default:
69
90
  // @ts-ignore
70
91
  return security.type;
@@ -1,5 +1,4 @@
1
- import * as React from 'react';
2
- import { OpenAPIV3 } from 'openapi-types';
1
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
3
2
  import { OpenAPIServerURLVariable } from './OpenAPIServerURLVariable';
4
3
 
5
4
  /**
@@ -9,6 +8,10 @@ export function OpenAPIServerURL(props: { servers: OpenAPIV3.ServerObject[] }) {
9
8
  const { servers } = props;
10
9
  const server = servers[0];
11
10
 
11
+ if (!server) {
12
+ return null;
13
+ }
14
+
12
15
  const parts = parseServerURL(server?.url ?? '');
13
16
 
14
17
  return (
@@ -17,16 +20,13 @@ export function OpenAPIServerURL(props: { servers: OpenAPIV3.ServerObject[] }) {
17
20
  if (part.kind === 'text') {
18
21
  return <span key={i}>{part.text}</span>;
19
22
  } else {
20
- if (!server.variables?.[part.name]) {
23
+ const variable = server.variables?.[part.name];
24
+ if (!variable) {
21
25
  return <span key={i}>{`{${part.name}}`}</span>;
22
26
  }
23
27
 
24
28
  return (
25
- <OpenAPIServerURLVariable
26
- key={i}
27
- name={part.name}
28
- variable={server.variables[part.name]}
29
- />
29
+ <OpenAPIServerURLVariable key={i} name={part.name} variable={variable} />
30
30
  );
31
31
  }
32
32
  })}
@@ -39,6 +39,9 @@ export function OpenAPIServerURL(props: { servers: OpenAPIV3.ServerObject[] }) {
39
39
  */
40
40
  export function getServersURL(servers: OpenAPIV3.ServerObject[]): string {
41
41
  const server = servers[0];
42
+ if (!server) {
43
+ return '';
44
+ }
42
45
  const parts = parseServerURL(server?.url ?? '');
43
46
 
44
47
  return parts
@@ -56,10 +59,14 @@ function parseServerURL(url: string) {
56
59
  const parts = url.split(/{([^}]+)}/g);
57
60
  const result: Array<{ kind: 'variable'; name: string } | { kind: 'text'; text: string }> = [];
58
61
  for (let i = 0; i < parts.length; i++) {
62
+ const part = parts[i];
63
+ if (!part) {
64
+ continue;
65
+ }
59
66
  if (i % 2 === 0) {
60
- result.push({ kind: 'text', text: parts[i] });
67
+ result.push({ kind: 'text', text: part });
61
68
  } else {
62
- result.push({ kind: 'variable', name: parts[i] });
69
+ result.push({ kind: 'variable', name: part });
63
70
  }
64
71
  }
65
72
  return result;
@@ -1,8 +1,6 @@
1
1
  'use client';
2
2
 
3
- import * as React from 'react';
4
- import classNames from 'classnames';
5
- import { OpenAPIV3 } from 'openapi-types';
3
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
6
4
 
7
5
  /**
8
6
  * Interactive component to show the value of a server variable and let the user change it.
@@ -12,5 +10,5 @@ export function OpenAPIServerURLVariable(props: {
12
10
  variable: OpenAPIV3.ServerVariableObject;
13
11
  }) {
14
12
  const { variable } = props;
15
- return <span className={classNames('openapi-url-var')}>{variable.default}</span>;
13
+ return <span className="openapi-url-var">{variable.default}</span>;
16
14
  }