@gitbook/react-openapi 1.2.1 → 1.3.1
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.
- package/CHANGELOG.md +35 -0
- package/dist/OpenAPICodeSample.jsx +7 -4
- package/dist/OpenAPIDisclosure.d.ts +1 -0
- package/dist/OpenAPIDisclosure.jsx +6 -3
- package/dist/OpenAPIDisclosureGroup.jsx +16 -15
- package/dist/OpenAPIRequestBody.jsx +7 -2
- package/dist/OpenAPIRequestBodyHeaderType.d.ts +8 -0
- package/dist/OpenAPIRequestBodyHeaderType.jsx +25 -0
- package/dist/OpenAPIResponse.d.ts +1 -1
- package/dist/OpenAPIResponse.jsx +20 -4
- package/dist/OpenAPIResponseExample.jsx +15 -3
- package/dist/OpenAPIResponses.jsx +6 -1
- package/dist/OpenAPISchema.d.ts +9 -2
- package/dist/OpenAPISchema.jsx +87 -91
- package/dist/OpenAPISchemaName.d.ts +1 -1
- package/dist/OpenAPISchemaName.jsx +5 -5
- package/dist/OpenAPISecurities.jsx +59 -1
- package/dist/OpenAPISelect.jsx +1 -0
- package/dist/OpenAPISpec.jsx +16 -1
- package/dist/OpenAPIWebhookExample.jsx +1 -1
- package/dist/StaticSection.jsx +1 -1
- package/dist/code-samples.js +6 -3
- package/dist/generateSchemaExample.js +19 -14
- package/dist/getDisclosureLabel.d.ts +7 -0
- package/dist/getDisclosureLabel.js +18 -0
- package/dist/schemas/OpenAPISchemaItem.d.ts +7 -0
- package/dist/schemas/OpenAPISchemaItem.jsx +16 -0
- package/dist/schemas/OpenAPISchemas.jsx +3 -9
- package/dist/translations/de.d.ts +7 -1
- package/dist/translations/de.js +10 -4
- package/dist/translations/en.d.ts +7 -1
- package/dist/translations/en.js +9 -3
- package/dist/translations/es.d.ts +7 -1
- package/dist/translations/es.js +10 -4
- package/dist/translations/fr.d.ts +7 -1
- package/dist/translations/fr.js +11 -5
- package/dist/translations/index.d.ts +63 -9
- package/dist/translations/ja.d.ts +7 -1
- package/dist/translations/ja.js +9 -3
- package/dist/translations/nl.d.ts +7 -1
- package/dist/translations/nl.js +9 -3
- package/dist/translations/no.d.ts +7 -1
- package/dist/translations/no.js +10 -4
- package/dist/translations/pt-br.d.ts +7 -1
- package/dist/translations/pt-br.js +10 -4
- package/dist/translations/zh.d.ts +7 -1
- package/dist/translations/zh.js +10 -4
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +38 -0
- package/package.json +2 -2
- package/src/OpenAPICodeSample.tsx +7 -6
- package/src/OpenAPIDisclosure.tsx +7 -3
- package/src/OpenAPIDisclosureGroup.tsx +49 -48
- package/src/OpenAPIRequestBody.tsx +11 -2
- package/src/OpenAPIRequestBodyHeaderType.tsx +36 -0
- package/src/OpenAPIResponse.tsx +37 -5
- package/src/OpenAPIResponseExample.tsx +46 -35
- package/src/OpenAPIResponses.tsx +4 -4
- package/src/OpenAPISchema.tsx +157 -130
- package/src/OpenAPISchemaName.tsx +10 -8
- package/src/OpenAPISecurities.tsx +111 -7
- package/src/OpenAPISelect.tsx +1 -1
- package/src/OpenAPISpec.tsx +21 -1
- package/src/OpenAPIWebhookExample.tsx +2 -2
- package/src/StaticSection.tsx +1 -1
- package/src/code-samples.test.ts +3 -2
- package/src/code-samples.ts +19 -12
- package/src/generateSchemaExample.test.ts +20 -0
- package/src/generateSchemaExample.ts +9 -1
- package/src/getDisclosureLabel.ts +25 -0
- package/src/schemas/OpenAPISchemaItem.tsx +34 -0
- package/src/schemas/OpenAPISchemas.tsx +7 -13
- package/src/translations/de.ts +10 -4
- package/src/translations/en.ts +9 -3
- package/src/translations/es.ts +10 -4
- package/src/translations/fr.ts +11 -5
- package/src/translations/ja.ts +9 -3
- package/src/translations/nl.ts +9 -3
- package/src/translations/no.ts +10 -4
- package/src/translations/pt-br.ts +10 -4
- package/src/translations/zh.ts +10 -4
- package/src/utils.ts +37 -0
package/dist/utils.d.ts
CHANGED
|
@@ -47,3 +47,4 @@ export declare function getStatusCodeClassName(statusCode: number | string): str
|
|
|
47
47
|
* 4xx, 5xx: Error
|
|
48
48
|
*/
|
|
49
49
|
export declare function getStatusCodeDefaultLabel(statusCode: number | string, context: OpenAPIUniversalContext): string;
|
|
50
|
+
export declare function getSchemaTitle(schema: OpenAPIV3.SchemaObject): string;
|
package/dist/utils.js
CHANGED
|
@@ -184,3 +184,41 @@ function getStatusCodeCategory(statusCode) {
|
|
|
184
184
|
var category = Math.floor(code / 100);
|
|
185
185
|
return category;
|
|
186
186
|
}
|
|
187
|
+
export function getSchemaTitle(schema) {
|
|
188
|
+
var _a;
|
|
189
|
+
// Otherwise try to infer a nice title
|
|
190
|
+
var type = 'any';
|
|
191
|
+
if (schema.enum || schema['x-enumDescriptions'] || schema['x-gitbook-enum']) {
|
|
192
|
+
type = "".concat(schema.type, " \u00B7 enum");
|
|
193
|
+
// check array AND schema.items as this is sometimes null despite what the type indicates
|
|
194
|
+
}
|
|
195
|
+
else if (schema.type === 'array' && !!schema.items) {
|
|
196
|
+
type = "".concat(getSchemaTitle(schema.items), "[]");
|
|
197
|
+
}
|
|
198
|
+
else if (Array.isArray(schema.type)) {
|
|
199
|
+
type = schema.type.join(' | ');
|
|
200
|
+
}
|
|
201
|
+
else if (schema.type || schema.properties) {
|
|
202
|
+
type = (_a = schema.type) !== null && _a !== void 0 ? _a : 'object';
|
|
203
|
+
if (schema.format) {
|
|
204
|
+
type += " \u00B7 ".concat(schema.format);
|
|
205
|
+
}
|
|
206
|
+
// Only add the title if it's an object (no need for the title of a string, number, etc.)
|
|
207
|
+
if (type === 'object' && schema.title) {
|
|
208
|
+
type += " \u00B7 ".concat(schema.title.replaceAll(' ', ''));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if ('anyOf' in schema) {
|
|
212
|
+
type = 'any of';
|
|
213
|
+
}
|
|
214
|
+
else if ('oneOf' in schema) {
|
|
215
|
+
type = 'one of';
|
|
216
|
+
}
|
|
217
|
+
else if ('allOf' in schema) {
|
|
218
|
+
type = 'all of';
|
|
219
|
+
}
|
|
220
|
+
else if ('not' in schema) {
|
|
221
|
+
type = 'not';
|
|
222
|
+
}
|
|
223
|
+
return type;
|
|
224
|
+
}
|
package/package.json
CHANGED
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
"default": "./dist/index.js"
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
|
-
"version": "1.
|
|
11
|
+
"version": "1.3.1",
|
|
12
12
|
"sideEffects": false,
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@gitbook/openapi-parser": "workspace:*",
|
|
15
|
-
"@scalar/api-client-react": "^1.
|
|
15
|
+
"@scalar/api-client-react": "^1.3.16",
|
|
16
16
|
"@scalar/oas-utils": "^0.2.130",
|
|
17
17
|
"clsx": "^2.1.1",
|
|
18
18
|
"flatted": "^3.2.9",
|
|
@@ -253,15 +253,11 @@ function getCustomCodeSamples(props: {
|
|
|
253
253
|
if (customSamples && Array.isArray(customSamples)) {
|
|
254
254
|
customCodeSamples = customSamples
|
|
255
255
|
.filter((sample) => {
|
|
256
|
-
return
|
|
257
|
-
typeof sample.label === 'string' &&
|
|
258
|
-
typeof sample.source === 'string' &&
|
|
259
|
-
typeof sample.lang === 'string'
|
|
260
|
-
);
|
|
256
|
+
return typeof sample.source === 'string' && typeof sample.lang === 'string';
|
|
261
257
|
})
|
|
262
258
|
.map((sample, index) => ({
|
|
263
259
|
key: `custom-sample-${sample.lang}-${index}`,
|
|
264
|
-
label: sample.label,
|
|
260
|
+
label: sample.label || sample.lang,
|
|
265
261
|
body: context.renderCodeBlock({
|
|
266
262
|
code: sample.source,
|
|
267
263
|
syntax: sample.lang,
|
|
@@ -312,6 +308,11 @@ function getSecurityHeaders(securities: OpenAPIOperationData['securities']): {
|
|
|
312
308
|
[name]: 'YOUR_API_KEY',
|
|
313
309
|
};
|
|
314
310
|
}
|
|
311
|
+
case 'oauth2': {
|
|
312
|
+
return {
|
|
313
|
+
Authorization: 'Bearer YOUR_OAUTH2_TOKEN',
|
|
314
|
+
};
|
|
315
|
+
}
|
|
315
316
|
default: {
|
|
316
317
|
return {};
|
|
317
318
|
}
|
|
@@ -9,11 +9,12 @@ import { Button, Disclosure, DisclosurePanel } from 'react-aria-components';
|
|
|
9
9
|
*/
|
|
10
10
|
export function OpenAPIDisclosure(props: {
|
|
11
11
|
icon: React.ReactNode;
|
|
12
|
+
header: React.ReactNode;
|
|
12
13
|
children: React.ReactNode;
|
|
13
14
|
label: string | ((isExpanded: boolean) => string);
|
|
14
15
|
className?: string;
|
|
15
16
|
}): React.JSX.Element {
|
|
16
|
-
const { icon,
|
|
17
|
+
const { icon, header, label, children, className } = props;
|
|
17
18
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
18
19
|
|
|
19
20
|
return (
|
|
@@ -31,8 +32,11 @@ export function OpenAPIDisclosure(props: {
|
|
|
31
32
|
: 'none',
|
|
32
33
|
})}
|
|
33
34
|
>
|
|
34
|
-
{
|
|
35
|
-
<
|
|
35
|
+
{header}
|
|
36
|
+
<div className="openapi-disclosure-trigger-label">
|
|
37
|
+
<span>{typeof label === 'function' ? label(isExpanded) : label}</span>
|
|
38
|
+
{icon}
|
|
39
|
+
</div>
|
|
36
40
|
</Button>
|
|
37
41
|
<DisclosurePanel className="openapi-disclosure-panel">
|
|
38
42
|
{isExpanded ? children : null}
|
|
@@ -76,7 +76,7 @@ function DisclosureItem(props: {
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
const panelRef = useRef<HTMLDivElement | null>(null);
|
|
79
|
-
const triggerRef = useRef<
|
|
79
|
+
const triggerRef = useRef<HTMLDivElement | null>(null);
|
|
80
80
|
const isDisabled = groupState?.isDisabled || !group.tabs?.length || false;
|
|
81
81
|
const { buttonProps: triggerProps, panelProps } = useDisclosure(
|
|
82
82
|
{
|
|
@@ -96,55 +96,56 @@ function DisclosureItem(props: {
|
|
|
96
96
|
|
|
97
97
|
return (
|
|
98
98
|
<div className="openapi-disclosure-group" aria-expanded={state.isExpanded}>
|
|
99
|
-
<div
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
</div>
|
|
99
|
+
<div
|
|
100
|
+
slot="trigger"
|
|
101
|
+
ref={triggerRef}
|
|
102
|
+
{...mergeProps(buttonProps, focusProps)}
|
|
103
|
+
aria-disabled={isDisabled}
|
|
104
|
+
style={{
|
|
105
|
+
outline: isFocusVisible
|
|
106
|
+
? '2px solid rgb(var(--primary-color-500)/0.4)'
|
|
107
|
+
: 'none',
|
|
108
|
+
}}
|
|
109
|
+
className="openapi-disclosure-group-trigger"
|
|
110
|
+
>
|
|
111
|
+
<div className="openapi-disclosure-group-icon">
|
|
112
|
+
{icon || (
|
|
113
|
+
<svg viewBox="0 0 24 24" className="openapi-disclosure-group-icon">
|
|
114
|
+
<path d="m8.25 4.5 7.5 7.5-7.5 7.5" />
|
|
115
|
+
</svg>
|
|
116
|
+
)}
|
|
117
|
+
</div>
|
|
119
118
|
|
|
119
|
+
<div className="openapi-disclosure-group-label">
|
|
120
120
|
{group.label}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
121
|
+
|
|
122
|
+
{group.tabs ? (
|
|
123
|
+
<div
|
|
124
|
+
className="openapi-disclosure-group-mediatype"
|
|
125
|
+
onClick={(e) => e.stopPropagation()}
|
|
126
|
+
>
|
|
127
|
+
{group.tabs?.length > 1 ? (
|
|
128
|
+
<OpenAPISelect
|
|
129
|
+
icon={selectIcon}
|
|
130
|
+
stateKey={selectStateKey}
|
|
131
|
+
onSelectionChange={() => {
|
|
132
|
+
state.expand();
|
|
133
|
+
}}
|
|
134
|
+
items={group.tabs}
|
|
135
|
+
placement="bottom end"
|
|
136
|
+
>
|
|
137
|
+
{group.tabs.map((tab) => (
|
|
138
|
+
<OpenAPISelectItem key={tab.key} id={tab.key} value={tab}>
|
|
139
|
+
{tab.label}
|
|
140
|
+
</OpenAPISelectItem>
|
|
141
|
+
))}
|
|
142
|
+
</OpenAPISelect>
|
|
143
|
+
) : group.tabs[0]?.label ? (
|
|
144
|
+
<span>{group.tabs[0].label}</span>
|
|
145
|
+
) : null}
|
|
146
|
+
</div>
|
|
147
|
+
) : null}
|
|
148
|
+
</div>
|
|
148
149
|
</div>
|
|
149
150
|
|
|
150
151
|
{state.isExpanded && selectedTab && (
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
2
|
import { InteractiveSection } from './InteractiveSection';
|
|
3
|
+
import { OpenAPIRequestBodyHeaderType } from './OpenAPIRequestBodyHeaderType';
|
|
3
4
|
import { OpenAPIRootSchema } from './OpenAPISchemaServer';
|
|
4
5
|
import type { OpenAPIClientContext } from './context';
|
|
5
6
|
import { t } from './translate';
|
|
@@ -20,11 +21,18 @@ export function OpenAPIRequestBody(props: {
|
|
|
20
21
|
return null;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
const stateKey = createStateKey('request-body-media-type', context.blockKey);
|
|
25
|
+
|
|
23
26
|
return (
|
|
24
27
|
<InteractiveSection
|
|
25
|
-
header={
|
|
28
|
+
header={
|
|
29
|
+
<>
|
|
30
|
+
<span>{t(context.translation, 'name' in data ? 'payload' : 'body')}</span>
|
|
31
|
+
<OpenAPIRequestBodyHeaderType requestBody={requestBody} stateKey={stateKey} />
|
|
32
|
+
</>
|
|
33
|
+
}
|
|
26
34
|
className="openapi-requestbody"
|
|
27
|
-
stateKey={
|
|
35
|
+
stateKey={stateKey}
|
|
28
36
|
selectIcon={context.icons.chevronDown}
|
|
29
37
|
tabs={Object.entries(requestBody.content ?? {}).map(
|
|
30
38
|
([contentType, mediaTypeObject]) => {
|
|
@@ -35,6 +43,7 @@ export function OpenAPIRequestBody(props: {
|
|
|
35
43
|
<OpenAPIRootSchema
|
|
36
44
|
schema={mediaTypeObject.schema ?? {}}
|
|
37
45
|
context={context}
|
|
46
|
+
key={contentType}
|
|
38
47
|
/>
|
|
39
48
|
),
|
|
40
49
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
4
|
+
import { useSelectState } from './OpenAPISelect';
|
|
5
|
+
import { getSchemaTitle } from './utils';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Display the type of a request body. It only displays the type if the selected content is an array.
|
|
9
|
+
*/
|
|
10
|
+
export function OpenAPIRequestBodyHeaderType(props: {
|
|
11
|
+
requestBody: OpenAPIV3.RequestBodyObject;
|
|
12
|
+
stateKey: string;
|
|
13
|
+
}) {
|
|
14
|
+
const { requestBody, stateKey } = props;
|
|
15
|
+
const content = requestBody.content ?? {};
|
|
16
|
+
const state = useSelectState(stateKey, Object.keys(content)[0]);
|
|
17
|
+
|
|
18
|
+
const selectedContentMediaType = Object.entries(content).find(
|
|
19
|
+
([contentType]) => contentType === state.key
|
|
20
|
+
)?.[1];
|
|
21
|
+
|
|
22
|
+
// If the selected content is not an array, we don't display the type
|
|
23
|
+
if (
|
|
24
|
+
!selectedContentMediaType ||
|
|
25
|
+
!selectedContentMediaType.schema?.type ||
|
|
26
|
+
selectedContentMediaType.schema.type !== 'array'
|
|
27
|
+
) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<span className="openapi-requestbody-header-type">
|
|
33
|
+
{`${getSchemaTitle(selectedContentMediaType.schema)}`}
|
|
34
|
+
</span>
|
|
35
|
+
);
|
|
36
|
+
}
|
package/src/OpenAPIResponse.tsx
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
2
|
import { OpenAPIDisclosure } from './OpenAPIDisclosure';
|
|
3
|
+
import { OpenAPISchemaPresentation } from './OpenAPISchema';
|
|
3
4
|
import { OpenAPISchemaProperties } from './OpenAPISchemaServer';
|
|
4
5
|
import type { OpenAPIClientContext } from './context';
|
|
6
|
+
import { tString } from './translate';
|
|
5
7
|
import { parameterToProperty, resolveDescription } from './utils';
|
|
6
8
|
|
|
7
9
|
/**
|
|
@@ -9,14 +11,14 @@ import { parameterToProperty, resolveDescription } from './utils';
|
|
|
9
11
|
*/
|
|
10
12
|
export function OpenAPIResponse(props: {
|
|
11
13
|
response: OpenAPIV3.ResponseObject;
|
|
12
|
-
mediaType: OpenAPIV3.MediaTypeObject;
|
|
14
|
+
mediaType: OpenAPIV3.MediaTypeObject | null;
|
|
13
15
|
context: OpenAPIClientContext;
|
|
14
16
|
}) {
|
|
15
17
|
const { response, context, mediaType } = props;
|
|
16
18
|
const headers = Object.entries(response.headers ?? {}).map(
|
|
17
19
|
([name, header]) => [name, header ?? {}] as const
|
|
18
20
|
);
|
|
19
|
-
const content = Object.entries(mediaType
|
|
21
|
+
const content = Object.entries(mediaType?.schema ?? {});
|
|
20
22
|
|
|
21
23
|
const description = resolveDescription(response);
|
|
22
24
|
|
|
@@ -27,7 +29,31 @@ export function OpenAPIResponse(props: {
|
|
|
27
29
|
return (
|
|
28
30
|
<div className="openapi-response-body">
|
|
29
31
|
{headers.length > 0 ? (
|
|
30
|
-
<OpenAPIDisclosure
|
|
32
|
+
<OpenAPIDisclosure
|
|
33
|
+
header={
|
|
34
|
+
<OpenAPISchemaPresentation
|
|
35
|
+
context={context}
|
|
36
|
+
property={{
|
|
37
|
+
propertyName: tString(context.translation, 'headers'),
|
|
38
|
+
schema: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
},
|
|
41
|
+
required: null,
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
|
+
}
|
|
45
|
+
icon={context.icons.plus}
|
|
46
|
+
label={(isExpanded) =>
|
|
47
|
+
tString(
|
|
48
|
+
context.translation,
|
|
49
|
+
isExpanded ? 'hide' : 'show',
|
|
50
|
+
tString(
|
|
51
|
+
context.translation,
|
|
52
|
+
headers.length === 1 ? 'header' : 'headers'
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
>
|
|
31
57
|
<OpenAPISchemaProperties
|
|
32
58
|
properties={headers.map(([name, header]) =>
|
|
33
59
|
parameterToProperty({ name, ...header })
|
|
@@ -36,11 +62,17 @@ export function OpenAPIResponse(props: {
|
|
|
36
62
|
/>
|
|
37
63
|
</OpenAPIDisclosure>
|
|
38
64
|
) : null}
|
|
39
|
-
{mediaType
|
|
65
|
+
{mediaType?.schema && (
|
|
40
66
|
<div className="openapi-responsebody">
|
|
41
67
|
<OpenAPISchemaProperties
|
|
42
68
|
id={`response-${context.blockKey}`}
|
|
43
|
-
properties={[
|
|
69
|
+
properties={[
|
|
70
|
+
{
|
|
71
|
+
schema: mediaType.schema,
|
|
72
|
+
propertyName: tString(context.translation, 'response'),
|
|
73
|
+
required: null,
|
|
74
|
+
},
|
|
75
|
+
]}
|
|
44
76
|
context={context}
|
|
45
77
|
/>
|
|
46
78
|
</div>
|
|
@@ -6,8 +6,8 @@ import { OpenAPIResponseExampleContent } from './OpenAPIResponseExampleContent';
|
|
|
6
6
|
import { type OpenAPIContext, getOpenAPIClientContext } from './context';
|
|
7
7
|
import type { OpenAPIOperationData, OpenAPIWebhookData } from './types';
|
|
8
8
|
import { getExampleFromReference, getExamples } from './util/example';
|
|
9
|
-
import { createStateKey, getStatusCodeDefaultLabel } from './utils';
|
|
10
|
-
import { checkIsReference
|
|
9
|
+
import { createStateKey, getStatusCodeDefaultLabel, resolveDescription } from './utils';
|
|
10
|
+
import { checkIsReference } from './utils';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Display an example of the response content.
|
|
@@ -41,45 +41,47 @@ export function OpenAPIResponseExample(props: {
|
|
|
41
41
|
return Number(a) - Number(b);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
const tabs = responses
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
const tabs = responses
|
|
45
|
+
.filter(([_, responseObject]) => responseObject && typeof responseObject === 'object')
|
|
46
|
+
.map(([key, responseObject]) => {
|
|
47
|
+
const description = resolveDescription(responseObject);
|
|
48
|
+
const label = description ? (
|
|
49
|
+
<Markdown source={description} />
|
|
50
|
+
) : (
|
|
51
|
+
getStatusCodeDefaultLabel(key, context)
|
|
52
|
+
);
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
if (checkIsReference(responseObject)) {
|
|
55
|
+
return {
|
|
56
|
+
key: key,
|
|
57
|
+
label,
|
|
58
|
+
statusCode: key,
|
|
59
|
+
body: (
|
|
60
|
+
<OpenAPIExample
|
|
61
|
+
example={getExampleFromReference(responseObject, context)}
|
|
62
|
+
context={context}
|
|
63
|
+
syntax="json"
|
|
64
|
+
/>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!responseObject.content || Object.keys(responseObject.content).length === 0) {
|
|
70
|
+
return {
|
|
71
|
+
key: key,
|
|
72
|
+
label,
|
|
73
|
+
statusCode: key,
|
|
74
|
+
body: <OpenAPIEmptyExample context={context} />,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
66
77
|
|
|
67
|
-
if (!responseObject.content || Object.keys(responseObject.content).length === 0) {
|
|
68
78
|
return {
|
|
69
79
|
key: key,
|
|
70
80
|
label,
|
|
71
81
|
statusCode: key,
|
|
72
|
-
body: <
|
|
82
|
+
body: <OpenAPIResponse context={context} content={responseObject.content} />,
|
|
73
83
|
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
key: key,
|
|
78
|
-
label,
|
|
79
|
-
statusCode: key,
|
|
80
|
-
body: <OpenAPIResponse context={context} content={responseObject.content} />,
|
|
81
|
-
};
|
|
82
|
-
});
|
|
84
|
+
});
|
|
83
85
|
|
|
84
86
|
if (tabs.length === 0) {
|
|
85
87
|
return null;
|
|
@@ -97,7 +99,7 @@ export function OpenAPIResponseExample(props: {
|
|
|
97
99
|
function OpenAPIResponse(props: {
|
|
98
100
|
context: OpenAPIContext;
|
|
99
101
|
content: {
|
|
100
|
-
[media: string]: OpenAPIV3.MediaTypeObject;
|
|
102
|
+
[media: string]: OpenAPIV3.MediaTypeObject | null;
|
|
101
103
|
};
|
|
102
104
|
}) {
|
|
103
105
|
const { context, content } = props;
|
|
@@ -111,6 +113,15 @@ function OpenAPIResponse(props: {
|
|
|
111
113
|
|
|
112
114
|
const tabs = entries.map((entry) => {
|
|
113
115
|
const [mediaType, mediaTypeObject] = entry;
|
|
116
|
+
|
|
117
|
+
if (!mediaTypeObject) {
|
|
118
|
+
return {
|
|
119
|
+
key: mediaType,
|
|
120
|
+
label: mediaType,
|
|
121
|
+
body: <OpenAPIEmptyExample context={context} />,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
114
125
|
return {
|
|
115
126
|
key: mediaType,
|
|
116
127
|
label: mediaType,
|
package/src/OpenAPIResponses.tsx
CHANGED
|
@@ -20,8 +20,9 @@ export function OpenAPIResponses(props: {
|
|
|
20
20
|
}) {
|
|
21
21
|
const { responses, context } = props;
|
|
22
22
|
|
|
23
|
-
const groups = Object.entries(responses)
|
|
24
|
-
([
|
|
23
|
+
const groups = Object.entries(responses)
|
|
24
|
+
.filter(([_, response]) => response && typeof response === 'object')
|
|
25
|
+
.map(([statusCode, response]: [string, OpenAPIV3.ResponseObject]) => {
|
|
25
26
|
const tabs = (() => {
|
|
26
27
|
// If there is no content, but there are headers, we need to show the headers
|
|
27
28
|
if (
|
|
@@ -83,8 +84,7 @@ export function OpenAPIResponses(props: {
|
|
|
83
84
|
),
|
|
84
85
|
tabs,
|
|
85
86
|
};
|
|
86
|
-
}
|
|
87
|
-
);
|
|
87
|
+
});
|
|
88
88
|
|
|
89
89
|
const state = useResponseExamplesState(context.blockKey, groups[0]?.key);
|
|
90
90
|
|