docusaurus-theme-openapi-docs 0.0.0-1160 → 0.0.0-1162
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/lib/theme/ApiExplorer/Body/FormBodyItem/index.d.ts +2 -1
- package/lib/theme/ApiExplorer/Body/FormBodyItem/index.js +47 -0
- package/lib/theme/ApiExplorer/Body/index.js +4 -0
- package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -1
- package/lib/theme/ApiExplorer/CodeSnippets/index.js +4 -0
- package/lib/theme/ApiExplorer/ContentType/index.js +5 -1
- package/lib/theme/ApiExplorer/EncodingSelection/slice.d.ts +17 -0
- package/lib/theme/ApiExplorer/EncodingSelection/slice.js +29 -0
- package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.d.ts +12 -0
- package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.js +39 -0
- package/lib/theme/ApiExplorer/Request/index.js +7 -1
- package/lib/theme/ApiExplorer/Request/makeRequest.d.ts +3 -1
- package/lib/theme/ApiExplorer/Request/makeRequest.js +17 -3
- package/lib/theme/ApiExplorer/buildPostmanRequest.d.ts +4 -1
- package/lib/theme/ApiExplorer/buildPostmanRequest.js +46 -5
- package/lib/theme/ApiExplorer/index.js +1 -0
- package/lib/theme/ApiExplorer/persistenceMiddleware.d.ts +2 -0
- package/lib/theme/ApiItem/hooks.d.ts +1 -0
- package/lib/theme/ApiItem/index.js +1 -0
- package/lib/theme/ApiItem/store.d.ts +6 -0
- package/lib/theme/ApiItem/store.js +11 -7
- package/lib/theme/RequestSchema/index.js +172 -109
- package/package.json +3 -3
- package/src/theme/ApiExplorer/Body/FormBodyItem/index.tsx +55 -10
- package/src/theme/ApiExplorer/Body/index.tsx +5 -0
- package/src/theme/ApiExplorer/CodeSnippets/index.tsx +9 -1
- package/src/theme/ApiExplorer/ContentType/index.tsx +5 -3
- package/src/theme/ApiExplorer/EncodingSelection/slice.ts +31 -0
- package/src/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.ts +43 -0
- package/src/theme/ApiExplorer/Request/index.tsx +6 -1
- package/src/theme/ApiExplorer/Request/makeRequest.ts +17 -3
- package/src/theme/ApiExplorer/buildPostmanRequest.ts +52 -5
- package/src/theme/ApiExplorer/index.tsx +1 -0
- package/src/theme/ApiItem/index.tsx +1 -0
- package/src/theme/ApiItem/store.ts +2 -0
- package/src/theme/RequestSchema/index.tsx +141 -83
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -17,7 +17,9 @@ const Translate_1 = require("@docusaurus/Translate");
|
|
|
17
17
|
const Details_1 = __importDefault(require("@theme/Details"));
|
|
18
18
|
const Markdown_1 = __importDefault(require("@theme/Markdown"));
|
|
19
19
|
const MimeTabs_1 = __importDefault(require("@theme/MimeTabs")); // Assume these components exist
|
|
20
|
+
const ResponseExamples_1 = require("@theme/ResponseExamples");
|
|
20
21
|
const Schema_1 = __importDefault(require("@theme/Schema"));
|
|
22
|
+
const SchemaTabs_1 = __importDefault(require("@theme/SchemaTabs"));
|
|
21
23
|
const SkeletonLoader_1 = __importDefault(require("@theme/SkeletonLoader"));
|
|
22
24
|
const TabItem_1 = __importDefault(require("@theme/TabItem"));
|
|
23
25
|
const translationIds_1 = require("@theme/translationIds");
|
|
@@ -36,7 +38,10 @@ const RequestSchemaComponent = ({ title, body, style }) => {
|
|
|
36
38
|
MimeTabs_1.default,
|
|
37
39
|
{ className: "openapi-tabs__mime", schemaType: "request", lazy: true },
|
|
38
40
|
mimeTypes.map((mimeType) => {
|
|
39
|
-
const
|
|
41
|
+
const mediaTypeObject = body.content[mimeType];
|
|
42
|
+
const firstBody = mediaTypeObject?.schema;
|
|
43
|
+
const requestExamples = mediaTypeObject?.examples;
|
|
44
|
+
const requestExample = mediaTypeObject?.example;
|
|
40
45
|
if (
|
|
41
46
|
firstBody === undefined ||
|
|
42
47
|
(firstBody.properties &&
|
|
@@ -50,68 +55,96 @@ const RequestSchemaComponent = ({ title, body, style }) => {
|
|
|
50
55
|
TabItem_1.default,
|
|
51
56
|
{ key: mimeType, label: mimeType, value: mimeType },
|
|
52
57
|
react_1.default.createElement(
|
|
53
|
-
|
|
54
|
-
{
|
|
58
|
+
SchemaTabs_1.default,
|
|
59
|
+
{ className: "openapi-tabs__schema" },
|
|
55
60
|
react_1.default.createElement(
|
|
56
|
-
|
|
57
|
-
{
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
react_1.default.createElement(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
(0, Translate_1.translate)({
|
|
75
|
-
id: translationIds_1.OPENAPI_REQUEST.BODY_TITLE,
|
|
76
|
-
message: title,
|
|
77
|
-
}),
|
|
78
|
-
body.required === true &&
|
|
61
|
+
TabItem_1.default,
|
|
62
|
+
{ key: title, label: title, value: title },
|
|
63
|
+
react_1.default.createElement(
|
|
64
|
+
"div",
|
|
65
|
+
{ style: { marginTop: "1rem" } },
|
|
66
|
+
react_1.default.createElement(
|
|
67
|
+
Details_1.default,
|
|
68
|
+
{
|
|
69
|
+
className: "openapi-markdown__details mime",
|
|
70
|
+
"data-collapsed": false,
|
|
71
|
+
open: true,
|
|
72
|
+
style: style,
|
|
73
|
+
summary: react_1.default.createElement(
|
|
74
|
+
react_1.default.Fragment,
|
|
75
|
+
null,
|
|
76
|
+
react_1.default.createElement(
|
|
77
|
+
"summary",
|
|
78
|
+
null,
|
|
79
79
|
react_1.default.createElement(
|
|
80
|
-
"
|
|
81
|
-
{
|
|
80
|
+
"h3",
|
|
81
|
+
{
|
|
82
|
+
className:
|
|
83
|
+
"openapi-markdown__details-summary-header-body",
|
|
84
|
+
},
|
|
82
85
|
(0, Translate_1.translate)({
|
|
83
|
-
id: translationIds_1.
|
|
84
|
-
message:
|
|
85
|
-
})
|
|
86
|
+
id: translationIds_1.OPENAPI_REQUEST.BODY_TITLE,
|
|
87
|
+
message: title,
|
|
88
|
+
}),
|
|
89
|
+
body.required === true &&
|
|
90
|
+
react_1.default.createElement(
|
|
91
|
+
"span",
|
|
92
|
+
{ className: "openapi-schema__required" },
|
|
93
|
+
(0, Translate_1.translate)({
|
|
94
|
+
id: translationIds_1.OPENAPI_SCHEMA_ITEM
|
|
95
|
+
.REQUIRED,
|
|
96
|
+
message: "required",
|
|
97
|
+
})
|
|
98
|
+
)
|
|
86
99
|
)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
},
|
|
91
|
-
react_1.default.createElement(
|
|
92
|
-
"div",
|
|
93
|
-
{ style: { textAlign: "left", marginLeft: "1rem" } },
|
|
94
|
-
body.description &&
|
|
100
|
+
)
|
|
101
|
+
),
|
|
102
|
+
},
|
|
95
103
|
react_1.default.createElement(
|
|
96
104
|
"div",
|
|
97
|
-
{ style: {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
{ style: { textAlign: "left", marginLeft: "1rem" } },
|
|
106
|
+
body.description &&
|
|
107
|
+
react_1.default.createElement(
|
|
108
|
+
"div",
|
|
109
|
+
{
|
|
110
|
+
style: { marginTop: "1rem", marginBottom: "1rem" },
|
|
111
|
+
},
|
|
112
|
+
react_1.default.createElement(
|
|
113
|
+
Markdown_1.default,
|
|
114
|
+
null,
|
|
115
|
+
body.description
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
),
|
|
119
|
+
react_1.default.createElement(
|
|
120
|
+
"ul",
|
|
121
|
+
{ style: { marginLeft: "1rem" } },
|
|
122
|
+
react_1.default.createElement(Schema_1.default, {
|
|
123
|
+
schema: firstBody,
|
|
124
|
+
schemaType: "request",
|
|
125
|
+
schemaPath: "requestBody",
|
|
126
|
+
})
|
|
103
127
|
)
|
|
104
|
-
|
|
105
|
-
react_1.default.createElement(
|
|
106
|
-
"ul",
|
|
107
|
-
{ style: { marginLeft: "1rem" } },
|
|
108
|
-
react_1.default.createElement(Schema_1.default, {
|
|
109
|
-
schema: firstBody,
|
|
110
|
-
schemaType: "request",
|
|
111
|
-
schemaPath: "requestBody",
|
|
112
|
-
})
|
|
128
|
+
)
|
|
113
129
|
)
|
|
114
|
-
)
|
|
130
|
+
),
|
|
131
|
+
firstBody &&
|
|
132
|
+
!requestExample &&
|
|
133
|
+
!requestExamples &&
|
|
134
|
+
(0, ResponseExamples_1.ExampleFromSchema)({
|
|
135
|
+
schema: firstBody,
|
|
136
|
+
mimeType: mimeType,
|
|
137
|
+
}),
|
|
138
|
+
requestExamples &&
|
|
139
|
+
(0, ResponseExamples_1.ResponseExamples)({
|
|
140
|
+
responseExamples: requestExamples,
|
|
141
|
+
mimeType,
|
|
142
|
+
}),
|
|
143
|
+
requestExample &&
|
|
144
|
+
(0, ResponseExamples_1.ResponseExample)({
|
|
145
|
+
responseExample: requestExample,
|
|
146
|
+
mimeType,
|
|
147
|
+
})
|
|
115
148
|
)
|
|
116
149
|
)
|
|
117
150
|
);
|
|
@@ -119,8 +152,10 @@ const RequestSchemaComponent = ({ title, body, style }) => {
|
|
|
119
152
|
);
|
|
120
153
|
}
|
|
121
154
|
const randomFirstKey = mimeTypes[0];
|
|
122
|
-
const
|
|
123
|
-
|
|
155
|
+
const mediaTypeObject = body.content[randomFirstKey];
|
|
156
|
+
const firstBody = mediaTypeObject?.schema ?? body.content[randomFirstKey];
|
|
157
|
+
const requestExamples = mediaTypeObject?.examples;
|
|
158
|
+
const requestExample = mediaTypeObject?.example;
|
|
124
159
|
if (firstBody === undefined) {
|
|
125
160
|
return null;
|
|
126
161
|
}
|
|
@@ -131,67 +166,95 @@ const RequestSchemaComponent = ({ title, body, style }) => {
|
|
|
131
166
|
TabItem_1.default,
|
|
132
167
|
{ label: randomFirstKey, value: `${randomFirstKey}-schema` },
|
|
133
168
|
react_1.default.createElement(
|
|
134
|
-
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
react_1.default.createElement(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}),
|
|
153
|
-
firstBody.type === "array" &&
|
|
154
|
-
react_1.default.createElement(
|
|
155
|
-
"span",
|
|
156
|
-
{ style: { opacity: "0.6" } },
|
|
157
|
-
" array"
|
|
158
|
-
),
|
|
159
|
-
body.required &&
|
|
169
|
+
SchemaTabs_1.default,
|
|
170
|
+
{ className: "openapi-tabs__schema" },
|
|
171
|
+
react_1.default.createElement(
|
|
172
|
+
TabItem_1.default,
|
|
173
|
+
{ key: title, label: title, value: title },
|
|
174
|
+
react_1.default.createElement(
|
|
175
|
+
Details_1.default,
|
|
176
|
+
{
|
|
177
|
+
className: "openapi-markdown__details mime",
|
|
178
|
+
"data-collapsed": false,
|
|
179
|
+
open: true,
|
|
180
|
+
style: style,
|
|
181
|
+
summary: react_1.default.createElement(
|
|
182
|
+
react_1.default.Fragment,
|
|
183
|
+
null,
|
|
184
|
+
react_1.default.createElement(
|
|
185
|
+
"summary",
|
|
186
|
+
null,
|
|
160
187
|
react_1.default.createElement(
|
|
161
|
-
"
|
|
162
|
-
{
|
|
188
|
+
"h3",
|
|
189
|
+
{
|
|
190
|
+
className:
|
|
191
|
+
"openapi-markdown__details-summary-header-body",
|
|
192
|
+
},
|
|
163
193
|
(0, Translate_1.translate)({
|
|
164
|
-
id: translationIds_1.
|
|
165
|
-
message:
|
|
166
|
-
})
|
|
194
|
+
id: translationIds_1.OPENAPI_REQUEST.BODY_TITLE,
|
|
195
|
+
message: title,
|
|
196
|
+
}),
|
|
197
|
+
firstBody.type === "array" &&
|
|
198
|
+
react_1.default.createElement(
|
|
199
|
+
"span",
|
|
200
|
+
{ style: { opacity: "0.6" } },
|
|
201
|
+
" array"
|
|
202
|
+
),
|
|
203
|
+
body.required &&
|
|
204
|
+
react_1.default.createElement(
|
|
205
|
+
"strong",
|
|
206
|
+
{ className: "openapi-schema__required" },
|
|
207
|
+
(0, Translate_1.translate)({
|
|
208
|
+
id: translationIds_1.OPENAPI_SCHEMA_ITEM.REQUIRED,
|
|
209
|
+
message: "required",
|
|
210
|
+
})
|
|
211
|
+
)
|
|
167
212
|
)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
},
|
|
172
|
-
react_1.default.createElement(
|
|
173
|
-
"div",
|
|
174
|
-
{ style: { textAlign: "left", marginLeft: "1rem" } },
|
|
175
|
-
body.description &&
|
|
213
|
+
)
|
|
214
|
+
),
|
|
215
|
+
},
|
|
176
216
|
react_1.default.createElement(
|
|
177
217
|
"div",
|
|
178
|
-
{ style: {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
218
|
+
{ style: { textAlign: "left", marginLeft: "1rem" } },
|
|
219
|
+
body.description &&
|
|
220
|
+
react_1.default.createElement(
|
|
221
|
+
"div",
|
|
222
|
+
{ style: { marginTop: "1rem", marginBottom: "1rem" } },
|
|
223
|
+
react_1.default.createElement(
|
|
224
|
+
Markdown_1.default,
|
|
225
|
+
null,
|
|
226
|
+
body.description
|
|
227
|
+
)
|
|
228
|
+
)
|
|
229
|
+
),
|
|
230
|
+
react_1.default.createElement(
|
|
231
|
+
"ul",
|
|
232
|
+
{ style: { marginLeft: "1rem" } },
|
|
233
|
+
react_1.default.createElement(Schema_1.default, {
|
|
234
|
+
schema: firstBody,
|
|
235
|
+
schemaType: "request",
|
|
236
|
+
schemaPath: "requestBody",
|
|
237
|
+
})
|
|
184
238
|
)
|
|
239
|
+
)
|
|
185
240
|
),
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
241
|
+
firstBody &&
|
|
242
|
+
!requestExample &&
|
|
243
|
+
!requestExamples &&
|
|
244
|
+
(0, ResponseExamples_1.ExampleFromSchema)({
|
|
190
245
|
schema: firstBody,
|
|
191
|
-
|
|
192
|
-
|
|
246
|
+
mimeType: randomFirstKey,
|
|
247
|
+
}),
|
|
248
|
+
requestExamples &&
|
|
249
|
+
(0, ResponseExamples_1.ResponseExamples)({
|
|
250
|
+
responseExamples: requestExamples,
|
|
251
|
+
mimeType: randomFirstKey,
|
|
252
|
+
}),
|
|
253
|
+
requestExample &&
|
|
254
|
+
(0, ResponseExamples_1.ResponseExample)({
|
|
255
|
+
responseExample: requestExample,
|
|
256
|
+
mimeType: randomFirstKey,
|
|
193
257
|
})
|
|
194
|
-
)
|
|
195
258
|
)
|
|
196
259
|
)
|
|
197
260
|
);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docusaurus-theme-openapi-docs",
|
|
3
3
|
"description": "OpenAPI theme for Docusaurus.",
|
|
4
|
-
"version": "0.0.0-
|
|
4
|
+
"version": "0.0.0-1162",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@types/postman-collection": "^3.5.11",
|
|
39
39
|
"@types/react-modal": "^3.16.3",
|
|
40
40
|
"concurrently": "^9.2.0",
|
|
41
|
-
"docusaurus-plugin-openapi-docs": "0.0.0-
|
|
41
|
+
"docusaurus-plugin-openapi-docs": "0.0.0-1162",
|
|
42
42
|
"docusaurus-plugin-sass": "^0.2.6",
|
|
43
43
|
"eslint-plugin-prettier": "^5.5.1"
|
|
44
44
|
},
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"engines": {
|
|
83
83
|
"node": ">=14"
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "91084c914a86e2522437018b04dd0a811e463451"
|
|
86
86
|
}
|
|
@@ -17,6 +17,7 @@ import type { SchemaObject } from "docusaurus-plugin-openapi-docs/src/openapi/ty
|
|
|
17
17
|
|
|
18
18
|
import FileArrayFormBodyItem from "../FileArrayFormBodyItem";
|
|
19
19
|
import { clearFormBodyKey, setFileFormBody, setStringFormBody } from "../slice";
|
|
20
|
+
import { setFieldEncoding } from "../../EncodingSelection/slice";
|
|
20
21
|
|
|
21
22
|
interface FormBodyItemProps {
|
|
22
23
|
schemaObject: SchemaObject;
|
|
@@ -25,6 +26,7 @@ interface FormBodyItemProps {
|
|
|
25
26
|
label?: string;
|
|
26
27
|
required?: boolean;
|
|
27
28
|
exampleValue?: SchemaObject["example"];
|
|
29
|
+
fieldEncoding?: string;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export default function FormBodyItem({
|
|
@@ -34,8 +36,37 @@ export default function FormBodyItem({
|
|
|
34
36
|
label,
|
|
35
37
|
required,
|
|
36
38
|
exampleValue,
|
|
39
|
+
fieldEncoding,
|
|
37
40
|
}: FormBodyItemProps): React.JSX.Element {
|
|
38
41
|
const dispatch = useTypedDispatch();
|
|
42
|
+
|
|
43
|
+
// Parse comma-separated encoding contentType into selectable options
|
|
44
|
+
const encodingOptions = fieldEncoding
|
|
45
|
+
? fieldEncoding
|
|
46
|
+
.split(",")
|
|
47
|
+
.map((t) => t.trim())
|
|
48
|
+
.filter(Boolean)
|
|
49
|
+
: [];
|
|
50
|
+
const hasMultipleEncodings = encodingOptions.length > 1;
|
|
51
|
+
|
|
52
|
+
// Initialize with the first declared content type
|
|
53
|
+
const [selectedEncoding, setSelectedEncoding] = useState<string>(
|
|
54
|
+
encodingOptions[0] ?? ""
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Seed Redux with the first declared encoding on mount so the code snippet
|
|
58
|
+
// reflects a content type immediately, even before the user interacts.
|
|
59
|
+
// The empty dep array is intentional: `fieldEncoding` comes from a static
|
|
60
|
+
// spec value that never changes for the lifetime of this component instance,
|
|
61
|
+
// and re-seeding on every render would fight user selections.
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (encodingOptions[0]) {
|
|
64
|
+
dispatch(
|
|
65
|
+
setFieldEncoding({ field: id, contentType: encodingOptions[0] })
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
69
|
+
}, []);
|
|
39
70
|
const [value, setValue] = useState(() => {
|
|
40
71
|
let initialValue = exampleValue ?? "";
|
|
41
72
|
|
|
@@ -71,6 +102,20 @@ export default function FormBodyItem({
|
|
|
71
102
|
return (
|
|
72
103
|
<>
|
|
73
104
|
{label && <FormLabel label={label} required={required} />}
|
|
105
|
+
{hasMultipleEncodings && (
|
|
106
|
+
<div style={{ marginTop: "0.5rem" }}>
|
|
107
|
+
<FormSelect
|
|
108
|
+
label="Content-Type"
|
|
109
|
+
options={encodingOptions}
|
|
110
|
+
value={selectedEncoding}
|
|
111
|
+
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
|
|
112
|
+
const ct = e.target.value;
|
|
113
|
+
setSelectedEncoding(ct);
|
|
114
|
+
dispatch(setFieldEncoding({ field: id, contentType: ct }));
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
74
119
|
<FormFileUpload
|
|
75
120
|
placeholder={schemaObject.description || id}
|
|
76
121
|
onChange={(file: any) => {
|
|
@@ -95,16 +140,16 @@ export default function FormBodyItem({
|
|
|
95
140
|
|
|
96
141
|
if (schemaObject.type === "object") {
|
|
97
142
|
return (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
143
|
+
<>
|
|
144
|
+
{label && <FormLabel label={label} required={required} />}
|
|
145
|
+
<LiveApp
|
|
146
|
+
action={(code: string) =>
|
|
147
|
+
dispatch(setStringFormBody({ key: id, value: code }))
|
|
148
|
+
}
|
|
149
|
+
>
|
|
150
|
+
{value}
|
|
151
|
+
</LiveApp>
|
|
152
|
+
</>
|
|
108
153
|
);
|
|
109
154
|
}
|
|
110
155
|
|
|
@@ -93,6 +93,8 @@ function Body({
|
|
|
93
93
|
const rawSchema = requestBodyMetadata?.content?.[contentType]?.schema;
|
|
94
94
|
const example = requestBodyMetadata?.content?.[contentType]?.example;
|
|
95
95
|
const examples = requestBodyMetadata?.content?.[contentType]?.examples;
|
|
96
|
+
const encoding: Record<string, { contentType?: string }> | undefined =
|
|
97
|
+
requestBodyMetadata?.content?.[contentType]?.encoding;
|
|
96
98
|
|
|
97
99
|
// Resolve the schema based on user's anyOf/oneOf tab selections
|
|
98
100
|
const schema = useMemo(() => {
|
|
@@ -339,6 +341,7 @@ function Body({
|
|
|
339
341
|
Array.isArray(schema.required) &&
|
|
340
342
|
schema.required.includes(key)
|
|
341
343
|
}
|
|
344
|
+
fieldEncoding={encoding?.[key]?.contentType}
|
|
342
345
|
></FormBodyItem>
|
|
343
346
|
</FormItem>
|
|
344
347
|
);
|
|
@@ -361,6 +364,7 @@ function Body({
|
|
|
361
364
|
Array.isArray(schema.required) &&
|
|
362
365
|
schema.required.includes(schemaKey)
|
|
363
366
|
}
|
|
367
|
+
fieldEncoding={encoding?.[schemaKey]?.contentType}
|
|
364
368
|
></FormBodyItem>
|
|
365
369
|
</FormItem>
|
|
366
370
|
);
|
|
@@ -387,6 +391,7 @@ function Body({
|
|
|
387
391
|
Array.isArray(schema.required) &&
|
|
388
392
|
schema.required.includes(schemaKey)
|
|
389
393
|
}
|
|
394
|
+
fieldEncoding={encoding?.[schemaKey]?.contentType}
|
|
390
395
|
></FormBodyItem>
|
|
391
396
|
</FormItem>
|
|
392
397
|
);
|
|
@@ -11,6 +11,7 @@ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
|
11
11
|
import ApiCodeBlock from "@theme/ApiExplorer/ApiCodeBlock";
|
|
12
12
|
import buildPostmanRequest from "@theme/ApiExplorer/buildPostmanRequest";
|
|
13
13
|
import CodeTabs from "@theme/ApiExplorer/CodeTabs";
|
|
14
|
+
import { useResolvedEncoding } from "@theme/ApiExplorer/EncodingSelection/useResolvedEncoding";
|
|
14
15
|
import { useTypedSelector } from "@theme/ApiItem/hooks";
|
|
15
16
|
import cloneDeep from "lodash/cloneDeep";
|
|
16
17
|
import codegen from "postman-code-generators";
|
|
@@ -30,6 +31,7 @@ export interface Props {
|
|
|
30
31
|
postman: sdk.Request;
|
|
31
32
|
codeSamples: CodeSample[];
|
|
32
33
|
maskCredentials?: boolean;
|
|
34
|
+
requestBody?: import("docusaurus-plugin-openapi-docs/src/openapi/types").RequestBodyObject;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
function CodeTab({ children, hidden, className }: any): React.JSX.Element {
|
|
@@ -44,6 +46,7 @@ function CodeSnippets({
|
|
|
44
46
|
postman,
|
|
45
47
|
codeSamples,
|
|
46
48
|
maskCredentials: propMaskCredentials,
|
|
49
|
+
requestBody,
|
|
47
50
|
}: Props) {
|
|
48
51
|
const { siteConfig } = useDocusaurusContext();
|
|
49
52
|
|
|
@@ -76,7 +79,9 @@ function CodeSnippets({
|
|
|
76
79
|
const authOptions =
|
|
77
80
|
clonedAuth?.options?.[key] ??
|
|
78
81
|
clonedAuth?.options?.[comboAuthId];
|
|
79
|
-
placeholder = authOptions?.find(
|
|
82
|
+
placeholder = authOptions?.find(
|
|
83
|
+
(opt: any) => opt.key === key
|
|
84
|
+
)?.name;
|
|
80
85
|
obj[key] = cleanCredentials(obj[key]);
|
|
81
86
|
} else {
|
|
82
87
|
obj[key] = `<${placeholder ?? key}>`;
|
|
@@ -93,6 +98,8 @@ function CodeSnippets({
|
|
|
93
98
|
})()
|
|
94
99
|
: auth;
|
|
95
100
|
|
|
101
|
+
const encoding = useResolvedEncoding(requestBody);
|
|
102
|
+
|
|
96
103
|
// Create a Postman request object using cleanedAuth or original auth
|
|
97
104
|
const cleanedPostmanRequest = buildPostmanRequest(postman, {
|
|
98
105
|
queryParams,
|
|
@@ -104,6 +111,7 @@ function CodeSnippets({
|
|
|
104
111
|
body,
|
|
105
112
|
server,
|
|
106
113
|
auth: cleanedAuth,
|
|
114
|
+
encoding,
|
|
107
115
|
});
|
|
108
116
|
|
|
109
117
|
// User-defined languages array
|
|
@@ -12,6 +12,7 @@ import FormSelect from "@theme/ApiExplorer/FormSelect";
|
|
|
12
12
|
import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
|
|
13
13
|
|
|
14
14
|
import { setContentType } from "./slice";
|
|
15
|
+
import { clearEncodingSelection } from "@theme/ApiExplorer/EncodingSelection/slice";
|
|
15
16
|
|
|
16
17
|
function ContentType() {
|
|
17
18
|
const value = useTypedSelector((state: any) => state.contentType.value);
|
|
@@ -28,9 +29,10 @@ function ContentType() {
|
|
|
28
29
|
label="Content-Type"
|
|
29
30
|
value={value}
|
|
30
31
|
options={options}
|
|
31
|
-
onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
|
|
32
|
-
dispatch(setContentType(e.target.value))
|
|
33
|
-
|
|
32
|
+
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
|
|
33
|
+
dispatch(setContentType(e.target.value));
|
|
34
|
+
dispatch(clearEncodingSelection());
|
|
35
|
+
}}
|
|
34
36
|
/>
|
|
35
37
|
</FormItem>
|
|
36
38
|
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|
9
|
+
|
|
10
|
+
// Maps form field name → user-selected content type
|
|
11
|
+
export type State = Record<string, string>;
|
|
12
|
+
|
|
13
|
+
const initialState: State = {};
|
|
14
|
+
|
|
15
|
+
export const slice = createSlice({
|
|
16
|
+
name: "encodingSelection",
|
|
17
|
+
initialState,
|
|
18
|
+
reducers: {
|
|
19
|
+
setFieldEncoding: (
|
|
20
|
+
state,
|
|
21
|
+
action: PayloadAction<{ field: string; contentType: string }>
|
|
22
|
+
) => {
|
|
23
|
+
state[action.payload.field] = action.payload.contentType;
|
|
24
|
+
},
|
|
25
|
+
clearEncodingSelection: () => initialState,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const { setFieldEncoding, clearEncodingSelection } = slice.actions;
|
|
30
|
+
|
|
31
|
+
export default slice.reducer;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import { useTypedSelector } from "@theme/ApiItem/hooks";
|
|
9
|
+
import type { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Merges the spec-declared `encoding` for the active content type with any
|
|
13
|
+
* per-field content-type selections the user has made in the UI. User picks
|
|
14
|
+
* take precedence over the spec default.
|
|
15
|
+
*
|
|
16
|
+
* Returns `undefined` when no encoding is declared for the current content
|
|
17
|
+
* type so callers can skip the encoding path entirely.
|
|
18
|
+
*/
|
|
19
|
+
export function useResolvedEncoding(
|
|
20
|
+
requestBody: RequestBodyObject | undefined
|
|
21
|
+
): Record<string, { contentType?: string }> | undefined {
|
|
22
|
+
const contentType = useTypedSelector((state: any) => state.contentType.value);
|
|
23
|
+
const encodingSelection = useTypedSelector(
|
|
24
|
+
(state: any) => state.encodingSelection
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const specEncoding: Record<string, { contentType?: string }> =
|
|
28
|
+
requestBody?.content?.[contentType]?.encoding ?? {};
|
|
29
|
+
|
|
30
|
+
if (!Object.keys(specEncoding).length) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return Object.fromEntries(
|
|
35
|
+
Object.entries(specEncoding).map(([field, enc]) => [
|
|
36
|
+
field,
|
|
37
|
+
{
|
|
38
|
+
...enc,
|
|
39
|
+
contentType: encodingSelection[field] ?? enc.contentType,
|
|
40
|
+
},
|
|
41
|
+
])
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
clearHeaders,
|
|
26
26
|
} from "@theme/ApiExplorer/Response/slice";
|
|
27
27
|
import Server from "@theme/ApiExplorer/Server";
|
|
28
|
+
import { useResolvedEncoding } from "@theme/ApiExplorer/EncodingSelection/useResolvedEncoding";
|
|
28
29
|
import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
|
|
29
30
|
import { OPENAPI_REQUEST } from "@theme/translationIds";
|
|
30
31
|
import type { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
|
@@ -76,6 +77,8 @@ function Request({ item }: { item: ApiItem }) {
|
|
|
76
77
|
...headerParams,
|
|
77
78
|
];
|
|
78
79
|
|
|
80
|
+
const encoding = useResolvedEncoding(item.requestBody);
|
|
81
|
+
|
|
79
82
|
const postmanRequest = buildPostmanRequest(postman, {
|
|
80
83
|
queryParams,
|
|
81
84
|
pathParams,
|
|
@@ -86,6 +89,7 @@ function Request({ item }: { item: ApiItem }) {
|
|
|
86
89
|
body,
|
|
87
90
|
server,
|
|
88
91
|
auth,
|
|
92
|
+
encoding,
|
|
89
93
|
});
|
|
90
94
|
|
|
91
95
|
const delay = (ms: number) =>
|
|
@@ -175,7 +179,8 @@ function Request({ item }: { item: ApiItem }) {
|
|
|
175
179
|
proxy,
|
|
176
180
|
body,
|
|
177
181
|
requestTimeout,
|
|
178
|
-
requestCredentials
|
|
182
|
+
requestCredentials,
|
|
183
|
+
encoding
|
|
179
184
|
);
|
|
180
185
|
if (res.headers.get("content-type")?.includes("text/event-stream")) {
|
|
181
186
|
await handleEventStream(res);
|