@gitbook/react-openapi 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/InteractiveSection.d.ts +0 -2
  3. package/dist/InteractiveSection.jsx +8 -44
  4. package/dist/OpenAPICodeSample.jsx +12 -12
  5. package/dist/OpenAPIOperation.jsx +8 -5
  6. package/dist/OpenAPIRequestBody.d.ts +2 -2
  7. package/dist/OpenAPIRequestBody.jsx +5 -2
  8. package/dist/OpenAPIResponse.jsx +17 -25
  9. package/dist/OpenAPIResponseExample.jsx +157 -48
  10. package/dist/OpenAPIResponses.jsx +2 -3
  11. package/dist/OpenAPISchema.d.ts +2 -2
  12. package/dist/OpenAPISchema.jsx +28 -29
  13. package/dist/OpenAPISpec.jsx +4 -28
  14. package/dist/OpenAPITabs.d.ts +1 -0
  15. package/dist/OpenAPITabs.jsx +52 -16
  16. package/dist/generateSchemaExample.d.ts +5 -6
  17. package/dist/generateSchemaExample.js +15 -11
  18. package/dist/json2xml.d.ts +4 -0
  19. package/dist/json2xml.js +7 -0
  20. package/dist/resolveOpenAPIOperation.js +4 -4
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/dist/types.d.ts +4 -0
  23. package/dist/useSyncedTabsGlobalState.d.ts +1 -0
  24. package/dist/useSyncedTabsGlobalState.js +16 -0
  25. package/dist/utils.d.ts +26 -3
  26. package/dist/utils.js +72 -9
  27. package/package.json +4 -2
  28. package/src/InteractiveSection.tsx +4 -41
  29. package/src/OpenAPICodeSample.tsx +12 -12
  30. package/src/OpenAPIOperation.tsx +8 -5
  31. package/src/OpenAPIRequestBody.tsx +7 -3
  32. package/src/OpenAPIResponse.tsx +7 -27
  33. package/src/OpenAPIResponseExample.tsx +237 -70
  34. package/src/OpenAPIResponses.tsx +2 -7
  35. package/src/OpenAPISchema.tsx +34 -33
  36. package/src/OpenAPISpec.tsx +4 -22
  37. package/src/OpenAPITabs.tsx +63 -23
  38. package/src/__snapshots__/json2xml.test.ts.snap +18 -0
  39. package/src/generateSchemaExample.ts +11 -10
  40. package/src/json2xml.test.ts +46 -0
  41. package/src/json2xml.ts +8 -0
  42. package/src/resolveOpenAPIOperation.test.ts +1 -1
  43. package/src/resolveOpenAPIOperation.ts +8 -7
  44. package/src/types.ts +1 -0
  45. package/src/useSyncedTabsGlobalState.ts +23 -0
  46. package/src/utils.ts +81 -13
  47. package/dist/fetchOpenAPIOperation.d.ts +0 -27
  48. package/dist/fetchOpenAPIOperation.js +0 -195
  49. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,10 +1,10 @@
1
1
  import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
2
  import { generateSchemaExample } from './generateSchemaExample';
3
3
  import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
4
- import { checkIsReference, noReference, resolveDescription } from './utils';
5
- import { stringifyOpenAPI } from './stringifyOpenAPI';
4
+ import { checkIsReference, createStateKey, resolveDescription } from './utils';
6
5
  import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
7
6
  import { InteractiveSection } from './InteractiveSection';
7
+ import { json2xml } from './json2xml';
8
8
 
9
9
  /**
10
10
  * Display an example of the response content.
@@ -38,84 +38,51 @@ export function OpenAPIResponseExample(props: {
38
38
  return Number(a) - Number(b);
39
39
  });
40
40
 
41
- const examples = responses
42
- .map(([key, value]) => {
43
- const responseObject = noReference(value);
44
- const mediaTypeObject = (() => {
45
- if (!responseObject.content) {
46
- return null;
47
- }
48
- const key = Object.keys(responseObject.content)[0];
49
- return (
50
- responseObject.content['application/json'] ??
51
- (key ? responseObject.content[key] : null)
52
- );
53
- })();
54
-
55
- if (!mediaTypeObject) {
41
+ const tabs = responses
42
+ .map(([key, responseObject]) => {
43
+ const description = resolveDescription(responseObject);
44
+
45
+ if (checkIsReference(responseObject)) {
56
46
  return {
57
47
  key: key,
58
48
  label: key,
59
- description: resolveDescription(responseObject),
60
- body: <OpenAPIEmptyResponseExample />,
49
+ description,
50
+ body: (
51
+ <OpenAPIExample
52
+ example={getExampleFromReference(responseObject)}
53
+ context={context}
54
+ syntax="json"
55
+ />
56
+ ),
61
57
  };
62
58
  }
63
59
 
64
- const example = handleUnresolvedReference(
65
- (() => {
66
- const { examples, example } = mediaTypeObject;
67
- if (examples) {
68
- const key = Object.keys(examples)[0];
69
- if (key) {
70
- // @TODO handle multiple examples
71
- const firstExample = noReference(examples[key]);
72
- if (firstExample) {
73
- return firstExample;
74
- }
75
- }
76
- }
77
-
78
- if (example) {
79
- return { value: example };
80
- }
81
-
82
- const schema = noReference(mediaTypeObject.schema);
83
- if (!schema) {
84
- return null;
85
- }
86
-
87
- return { value: generateSchemaExample(schema) };
88
- })(),
89
- );
60
+ if (!responseObject.content || Object.keys(responseObject.content).length === 0) {
61
+ return {
62
+ key: key,
63
+ label: key,
64
+ description,
65
+ body: <OpenAPIEmptyResponseExample />,
66
+ };
67
+ }
90
68
 
91
69
  return {
92
70
  key: key,
93
71
  label: key,
94
72
  description: resolveDescription(responseObject),
95
- body: example?.value ? (
96
- <context.CodeBlock
97
- code={
98
- typeof example.value === 'string'
99
- ? example.value
100
- : stringifyOpenAPI(example.value, null, 2)
101
- }
102
- syntax="json"
103
- />
104
- ) : (
105
- <OpenAPIEmptyResponseExample />
106
- ),
73
+ body: <OpenAPIResponse context={context} content={responseObject.content} />,
107
74
  };
108
75
  })
109
76
  .filter((val): val is { key: string; label: string; body: any; description: string } =>
110
77
  Boolean(val),
111
78
  );
112
79
 
113
- if (examples.length === 0) {
80
+ if (tabs.length === 0) {
114
81
  return null;
115
82
  }
116
83
 
117
84
  return (
118
- <OpenAPITabs items={examples}>
85
+ <OpenAPITabs stateKey={createStateKey('response-example')} items={tabs}>
119
86
  <InteractiveSection header={<OpenAPITabsList />} className="openapi-response-example">
120
87
  <OpenAPITabsPanels />
121
88
  </InteractiveSection>
@@ -123,6 +90,212 @@ export function OpenAPIResponseExample(props: {
123
90
  );
124
91
  }
125
92
 
93
+ function OpenAPIResponse(props: {
94
+ context: OpenAPIContextProps;
95
+ content: {
96
+ [media: string]: OpenAPIV3.MediaTypeObject;
97
+ };
98
+ }) {
99
+ const { context, content } = props;
100
+
101
+ const entries = Object.entries(content);
102
+ const firstEntry = entries[0];
103
+
104
+ if (!firstEntry) {
105
+ throw new Error('One media type is required');
106
+ }
107
+
108
+ if (entries.length === 1) {
109
+ const [mediaType, mediaTypeObject] = firstEntry;
110
+ return (
111
+ <OpenAPIResponseMediaType
112
+ context={context}
113
+ mediaType={mediaType}
114
+ mediaTypeObject={mediaTypeObject}
115
+ />
116
+ );
117
+ }
118
+
119
+ const tabs = entries.map((entry) => {
120
+ const [mediaType, mediaTypeObject] = entry;
121
+ return {
122
+ key: mediaType,
123
+ label: mediaType,
124
+ body: (
125
+ <OpenAPIResponseMediaType
126
+ context={context}
127
+ mediaType={mediaType}
128
+ mediaTypeObject={mediaTypeObject}
129
+ />
130
+ ),
131
+ };
132
+ });
133
+
134
+ return (
135
+ <OpenAPITabs stateKey={createStateKey('response-media-types')} items={tabs}>
136
+ <InteractiveSection
137
+ header={<OpenAPITabsList />}
138
+ className="openapi-response-media-types"
139
+ >
140
+ <OpenAPITabsPanels />
141
+ </InteractiveSection>
142
+ </OpenAPITabs>
143
+ );
144
+ }
145
+
146
+ function OpenAPIResponseMediaType(props: {
147
+ mediaTypeObject: OpenAPIV3.MediaTypeObject;
148
+ mediaType: string;
149
+ context: OpenAPIContextProps;
150
+ }) {
151
+ const { mediaTypeObject, mediaType } = props;
152
+ const examples = getExamplesFromMediaTypeObject({ mediaTypeObject, mediaType });
153
+ const syntax = getSyntaxFromMediaType(mediaType);
154
+ const firstExample = examples[0];
155
+
156
+ if (!firstExample) {
157
+ return <OpenAPIEmptyResponseExample />;
158
+ }
159
+
160
+ if (examples.length === 1) {
161
+ return (
162
+ <OpenAPIExample
163
+ example={firstExample.example}
164
+ context={props.context}
165
+ syntax={syntax}
166
+ />
167
+ );
168
+ }
169
+
170
+ const tabs = examples.map((example) => {
171
+ return {
172
+ key: example.key,
173
+ label: example.example.summary || example.key,
174
+ body: (
175
+ <OpenAPIExample
176
+ example={firstExample.example}
177
+ context={props.context}
178
+ syntax={syntax}
179
+ />
180
+ ),
181
+ };
182
+ });
183
+
184
+ return (
185
+ <OpenAPITabs stateKey={createStateKey('response-media-type-examples')} items={tabs}>
186
+ <InteractiveSection
187
+ header={<OpenAPITabsList />}
188
+ className="openapi-response-media-type-examples"
189
+ >
190
+ <OpenAPITabsPanels />
191
+ </InteractiveSection>
192
+ </OpenAPITabs>
193
+ );
194
+ }
195
+
196
+ /**
197
+ * Display an example.
198
+ */
199
+ function OpenAPIExample(props: {
200
+ example: OpenAPIV3.ExampleObject;
201
+ context: OpenAPIContextProps;
202
+ syntax: string;
203
+ }) {
204
+ const { example, context, syntax } = props;
205
+ const code = stringifyExample({ example, xml: syntax === 'xml' });
206
+
207
+ if (code === null) {
208
+ return <OpenAPIEmptyResponseExample />;
209
+ }
210
+
211
+ return <context.CodeBlock code={code} syntax={syntax} />;
212
+ }
213
+
214
+ function stringifyExample(args: { example: OpenAPIV3.ExampleObject; xml: boolean }): string | null {
215
+ const { example, xml } = args;
216
+
217
+ if (!example.value) {
218
+ return null;
219
+ }
220
+
221
+ if (typeof example.value === 'string') {
222
+ return example.value;
223
+ }
224
+
225
+ if (xml) {
226
+ return json2xml(example.value);
227
+ }
228
+
229
+ return JSON.stringify(example.value, null, 2);
230
+ }
231
+
232
+ /**
233
+ * Get the syntax from a media type.
234
+ */
235
+ function getSyntaxFromMediaType(mediaType: string): string {
236
+ if (mediaType.includes('json')) {
237
+ return 'json';
238
+ }
239
+
240
+ if (mediaType === 'application/xml') {
241
+ return 'xml';
242
+ }
243
+
244
+ return 'text';
245
+ }
246
+
247
+ /**
248
+ * Get examples from a media type object.
249
+ */
250
+ function getExamplesFromMediaTypeObject(args: {
251
+ mediaType: string;
252
+ mediaTypeObject: OpenAPIV3.MediaTypeObject;
253
+ }): { key: string; example: OpenAPIV3.ExampleObject }[] {
254
+ const { mediaTypeObject, mediaType } = args;
255
+ if (mediaTypeObject.examples) {
256
+ return Object.entries(mediaTypeObject.examples).map(([key, example]) => {
257
+ return {
258
+ key,
259
+ example: checkIsReference(example) ? getExampleFromReference(example) : example,
260
+ };
261
+ });
262
+ }
263
+
264
+ if (mediaTypeObject.example) {
265
+ return [{ key: 'default', example: { value: mediaTypeObject.example } }];
266
+ }
267
+
268
+ if (mediaTypeObject.schema) {
269
+ if (mediaType === 'application/xml') {
270
+ // @TODO normally we should use the name of the schema but we don't have it
271
+ // fix it when we got the reference name
272
+ const root = mediaTypeObject.schema.xml?.name ?? 'object';
273
+ return [
274
+ {
275
+ key: 'default',
276
+ example: {
277
+ value: {
278
+ [root]: generateSchemaExample(mediaTypeObject.schema, {
279
+ xml: mediaType === 'application/xml',
280
+ }),
281
+ },
282
+ },
283
+ },
284
+ ];
285
+ }
286
+ return [
287
+ {
288
+ key: 'default',
289
+ example: { value: generateSchemaExample(mediaTypeObject.schema) },
290
+ },
291
+ ];
292
+ }
293
+ return [];
294
+ }
295
+
296
+ /**
297
+ * Empty response example.
298
+ */
126
299
  function OpenAPIEmptyResponseExample() {
127
300
  return (
128
301
  <pre className="openapi-response-example-empty">
@@ -131,15 +304,9 @@ function OpenAPIEmptyResponseExample() {
131
304
  );
132
305
  }
133
306
 
134
- function handleUnresolvedReference(
135
- input: OpenAPIV3.ExampleObject | null,
136
- ): OpenAPIV3.ExampleObject | null {
137
- const isReference = checkIsReference(input?.value);
138
-
139
- if (isReference) {
140
- // If we find a reference that wasn't resolved or needed to be resolved externally, render out the URL
141
- return { value: input.value.$ref };
142
- }
143
-
144
- return input;
307
+ /**
308
+ * Generate an example from a reference object.
309
+ */
310
+ function getExampleFromReference(ref: OpenAPIV3.ReferenceObject): OpenAPIV3.ExampleObject {
311
+ return { summary: 'Unresolved reference', value: { $ref: ref.$ref } };
145
312
  }
@@ -1,5 +1,4 @@
1
1
  import type { OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser';
2
- import { createStateKey, resolveDescription } from './utils';
3
2
  import { OpenAPIResponse } from './OpenAPIResponse';
4
3
  import { OpenAPIClientContext } from './types';
5
4
  import { InteractiveSection } from './InteractiveSection';
@@ -16,18 +15,14 @@ export function OpenAPIResponses(props: {
16
15
  const { responses, context } = props;
17
16
 
18
17
  return (
19
- <InteractiveSection
20
- stateKey={createStateKey('response', context.blockKey)}
21
- header="Responses"
22
- className="openapi-responses"
23
- >
18
+ <InteractiveSection header="Responses" className="openapi-responses">
24
19
  <OpenAPIDisclosureGroup
25
20
  allowsMultipleExpanded
26
21
  icon={context.icons.chevronRight}
27
22
  groups={Object.entries(responses).map(
28
23
  ([statusCode, response]: [string, OpenAPIV3.ResponseObject]) => {
29
24
  const content = Object.entries(response.content ?? {});
30
- const description = resolveDescription(response);
25
+ const description = response.description;
31
26
 
32
27
  return {
33
28
  id: statusCode,
@@ -5,7 +5,7 @@ import { useId } from 'react';
5
5
  import { InteractiveSection } from './InteractiveSection';
6
6
  import { Markdown } from './Markdown';
7
7
  import type { OpenAPIClientContext } from './types';
8
- import { checkIsReference, noReference, resolveDescription } from './utils';
8
+ import { checkIsReference, resolveDescription } from './utils';
9
9
  import { stringifyOpenAPI } from './stringifyOpenAPI';
10
10
  import { OpenAPISchemaName } from './OpenAPISchemaName';
11
11
  import { OpenAPIDisclosure } from './OpenAPIDisclosure';
@@ -13,8 +13,8 @@ import { OpenAPIDisclosure } from './OpenAPIDisclosure';
13
13
  type CircularRefsIds = Map<OpenAPIV3.SchemaObject, string>;
14
14
 
15
15
  export interface OpenAPISchemaPropertyEntry {
16
- propertyName?: string;
17
- required?: boolean;
16
+ propertyName?: string | undefined;
17
+ required?: boolean | undefined;
18
18
  schema: OpenAPIV3.SchemaObject;
19
19
  }
20
20
 
@@ -47,19 +47,19 @@ export function OpenAPISchemaProperty(
47
47
  ? null
48
48
  : getSchemaAlternatives(schema, new Set(circularRefs.keys()));
49
49
 
50
- if ((properties && !!properties.length) || schema.type === 'object') {
50
+ if ((properties && properties.length > 0) || schema.type === 'object') {
51
51
  return (
52
52
  <InteractiveSection id={id} className={clsx('openapi-schema', className)}>
53
53
  <OpenAPISchemaPresentation {...props} />
54
- <OpenAPIDisclosure context={context}>
55
- {properties && properties.length > 0 ? (
54
+ {properties && properties.length > 0 ? (
55
+ <OpenAPIDisclosure context={context}>
56
56
  <OpenAPISchemaProperties
57
57
  properties={properties}
58
58
  circularRefs={circularRefs}
59
59
  context={context}
60
60
  />
61
- ) : null}
62
- </OpenAPIDisclosure>
61
+ </OpenAPIDisclosure>
62
+ ) : null}
63
63
  </InteractiveSection>
64
64
  );
65
65
  }
@@ -70,7 +70,7 @@ export function OpenAPISchemaProperty(
70
70
  <OpenAPISchemaPresentation {...props} />
71
71
  {alternatives[0].map((alternative, index) => (
72
72
  <OpenAPISchemaAlternative
73
- key={index}
73
+ key={`alternative-${index}`}
74
74
  schema={alternative}
75
75
  circularRefs={circularRefs}
76
76
  context={context}
@@ -278,9 +278,9 @@ export function OpenAPISchemaPresentation(props: OpenAPISchemaPropertyEntry) {
278
278
  function getSchemaProperties(schema: OpenAPIV3.SchemaObject): null | OpenAPISchemaPropertyEntry[] {
279
279
  if (schema.allOf) {
280
280
  return schema.allOf.reduce((acc, subSchema) => {
281
- const properties = getSchemaProperties(noReference(subSchema)) ?? [
281
+ const properties = getSchemaProperties(subSchema) ?? [
282
282
  {
283
- schema: noReference(subSchema),
283
+ schema: subSchema,
284
284
  },
285
285
  ];
286
286
  return [...acc, ...properties];
@@ -289,7 +289,7 @@ function getSchemaProperties(schema: OpenAPIV3.SchemaObject): null | OpenAPISche
289
289
 
290
290
  // check array AND schema.items as this is sometimes null despite what the type indicates
291
291
  if (schema.type === 'array' && !!schema.items) {
292
- const items = noReference(schema.items);
292
+ const items = schema.items;
293
293
  const itemProperties = getSchemaProperties(items);
294
294
  if (itemProperties) {
295
295
  return itemProperties;
@@ -307,12 +307,7 @@ function getSchemaProperties(schema: OpenAPIV3.SchemaObject): null | OpenAPISche
307
307
  const result: OpenAPISchemaPropertyEntry[] = [];
308
308
 
309
309
  if (schema.properties) {
310
- Object.entries(schema.properties).forEach(([propertyName, rawPropertySchema]) => {
311
- const isReference = checkIsReference(rawPropertySchema);
312
- const propertySchema: OpenAPIV3.SchemaObject = isReference
313
- ? { propertyName }
314
- : rawPropertySchema;
315
-
310
+ Object.entries(schema.properties).forEach(([propertyName, propertySchema]) => {
316
311
  result.push({
317
312
  propertyName,
318
313
  required: Array.isArray(schema.required)
@@ -324,7 +319,7 @@ function getSchemaProperties(schema: OpenAPIV3.SchemaObject): null | OpenAPISche
324
319
  }
325
320
 
326
321
  if (schema.additionalProperties) {
327
- const additionalProperties = noReference(schema.additionalProperties);
322
+ const additionalProperties = schema.additionalProperties;
328
323
 
329
324
  result.push({
330
325
  propertyName: 'Other properties',
@@ -348,17 +343,11 @@ export function getSchemaAlternatives(
348
343
  const downAncestors = new Set(ancestors).add(schema);
349
344
 
350
345
  if (schema.anyOf) {
351
- return [
352
- flattenAlternatives('anyOf', schema.anyOf.map(noReference), downAncestors),
353
- noReference(schema.discriminator),
354
- ];
346
+ return [flattenAlternatives('anyOf', schema.anyOf, downAncestors), schema.discriminator];
355
347
  }
356
348
 
357
349
  if (schema.oneOf) {
358
- return [
359
- flattenAlternatives('oneOf', schema.oneOf.map(noReference), downAncestors),
360
- noReference(schema.discriminator),
361
- ];
350
+ return [flattenAlternatives('oneOf', schema.oneOf, downAncestors), schema.discriminator];
362
351
  }
363
352
 
364
353
  if (schema.allOf) {
@@ -396,8 +385,8 @@ export function getSchemaTitle(
396
385
 
397
386
  // Try using the discriminator
398
387
  if (discriminator?.propertyName && schema.properties) {
399
- const discriminatorProperty = noReference(schema.properties[discriminator.propertyName]);
400
- if (discriminatorProperty) {
388
+ const discriminatorProperty = schema.properties[discriminator.propertyName];
389
+ if (discriminatorProperty && !checkIsReference(discriminatorProperty)) {
401
390
  if (discriminatorProperty.enum) {
402
391
  return discriminatorProperty.enum.map((value) => value.toString()).join(' | ');
403
392
  }
@@ -408,17 +397,17 @@ export function getSchemaTitle(
408
397
  let type = 'any';
409
398
 
410
399
  if (schema.enum) {
411
- type = 'enum';
400
+ type = `${schema.type} · enum`;
412
401
  // check array AND schema.items as this is sometimes null despite what the type indicates
413
402
  } else if (schema.type === 'array' && !!schema.items) {
414
- type = `${getSchemaTitle(noReference(schema.items))}[]`;
403
+ type = `${getSchemaTitle(schema.items)}[]`;
415
404
  } else if (Array.isArray(schema.type)) {
416
405
  type = schema.type.join(' | ');
417
406
  } else if (schema.type || schema.properties) {
418
407
  type = schema.type ?? 'object';
419
408
 
420
409
  if (schema.format) {
421
- type += ` ${schema.format}`;
410
+ type += ` · ${schema.format}`;
422
411
  }
423
412
  } else if ('anyOf' in schema) {
424
413
  type = 'any of';
@@ -430,8 +419,20 @@ export function getSchemaTitle(
430
419
  type = 'not';
431
420
  }
432
421
 
422
+ if (schema.minimum || schema.minLength) {
423
+ type += ` · min: ${schema.minimum || schema.minLength}`;
424
+ }
425
+
426
+ if (schema.maximum || schema.maxLength) {
427
+ type += ` · max: ${schema.maximum || schema.maxLength}`;
428
+ }
429
+
430
+ if (schema.default) {
431
+ type += ` · default: ${schema.default}`;
432
+ }
433
+
433
434
  if (schema.nullable) {
434
- type = `nullable ${type}`;
435
+ type = `${type} | nullable`;
435
436
  }
436
437
 
437
438
  return type;
@@ -8,7 +8,7 @@ import { OpenAPIResponses } from './OpenAPIResponses';
8
8
  import { OpenAPISchemaProperties } from './OpenAPISchema';
9
9
  import { OpenAPISecurities } from './OpenAPISecurities';
10
10
  import type { OpenAPIClientContext, OpenAPIOperationData } from './types';
11
- import { noReference, resolveDescription } from './utils';
11
+ import { parameterToProperty } from './utils';
12
12
 
13
13
  /**
14
14
  * Client component to render the spec for the request and response.
@@ -38,22 +38,7 @@ export function OpenAPISpec(props: { data: OpenAPIOperationData; context: OpenAP
38
38
  header={group.label}
39
39
  >
40
40
  <OpenAPISchemaProperties
41
- properties={group.parameters.map((parameter) => {
42
- const description = resolveDescription(parameter);
43
- return {
44
- propertyName: parameter.name,
45
- schema: {
46
- // Description of the parameter is defined at the parameter level
47
- // we use display it if the schema doesn't override it
48
- description: description,
49
- example: parameter.example,
50
- // Deprecated can be defined at the parameter level
51
- deprecated: parameter.deprecated,
52
- ...(noReference(parameter.schema) ?? {}),
53
- },
54
- required: parameter.required,
55
- };
56
- })}
41
+ properties={group.parameters.map(parameterToProperty)}
57
42
  context={context}
58
43
  />
59
44
  </InteractiveSection>
@@ -61,13 +46,10 @@ export function OpenAPISpec(props: { data: OpenAPIOperationData; context: OpenAP
61
46
  })}
62
47
 
63
48
  {operation.requestBody ? (
64
- <OpenAPIRequestBody
65
- requestBody={noReference(operation.requestBody)}
66
- context={context}
67
- />
49
+ <OpenAPIRequestBody requestBody={operation.requestBody} context={context} />
68
50
  ) : null}
69
51
  {operation.responses ? (
70
- <OpenAPIResponses responses={noReference(operation.responses)} context={context} />
52
+ <OpenAPIResponses responses={operation.responses} context={context} />
71
53
  ) : null}
72
54
  </>
73
55
  );