docusaurus-theme-openapi-docs 1.1.12 → 1.2.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.
- package/lib/theme/ApiDemoPanel/Authorization/auth-types.js +4 -0
- package/lib/theme/ApiDemoPanel/Authorization/index.js +125 -0
- package/lib/theme/ApiDemoPanel/Authorization/slice.js +1 -1
- package/lib/theme/ApiDemoPanel/Body/index.js +7 -6
- package/lib/theme/ApiDemoPanel/Execute/index.js +168 -0
- package/lib/theme/ApiDemoPanel/Execute/makeRequest.js +204 -0
- package/lib/theme/ApiDemoPanel/FormItem/index.js +7 -0
- package/lib/theme/ApiDemoPanel/FormItem/styles.module.css +5 -0
- package/lib/theme/ApiDemoPanel/ParamOptions/index.js +1 -1
- package/lib/theme/ApiDemoPanel/Request/index.js +78 -0
- package/lib/theme/ApiDemoPanel/Request/styles.module.css +17 -0
- package/lib/theme/ApiDemoPanel/Response/index.js +16 -12
- package/lib/theme/ApiDemoPanel/SecuritySchemes/index.js +24 -19
- package/lib/theme/ApiDemoPanel/Server/index.js +1 -0
- package/lib/theme/ApiDemoPanel/buildPostmanRequest.js +25 -3
- package/lib/theme/ApiDemoPanel/index.js +5 -13
- package/lib/theme/ApiDemoPanel/persistanceMiddleware.js +1 -1
- package/lib/theme/ApiDemoPanel/react-modal.d.ts +8 -0
- package/lib/theme/ApiItem/Layout/styles.module.css +56 -0
- package/lib/theme/ParamsItem/index.js +5 -1
- package/lib-next/theme/ApiDemoPanel/Authorization/auth-types.js +4 -0
- package/lib-next/theme/ApiDemoPanel/Authorization/index.js +149 -0
- package/lib-next/theme/ApiDemoPanel/Authorization/slice.js +1 -1
- package/lib-next/theme/ApiDemoPanel/Body/index.js +28 -6
- package/lib-next/theme/ApiDemoPanel/Execute/index.js +170 -0
- package/lib-next/theme/ApiDemoPanel/Execute/makeRequest.js +190 -0
- package/lib-next/theme/ApiDemoPanel/FormItem/index.js +9 -1
- package/lib-next/theme/ApiDemoPanel/FormItem/styles.module.css +5 -0
- package/lib-next/theme/ApiDemoPanel/ParamOptions/index.js +1 -1
- package/lib-next/theme/ApiDemoPanel/Request/index.js +60 -0
- package/lib-next/theme/ApiDemoPanel/Request/styles.module.css +17 -0
- package/lib-next/theme/ApiDemoPanel/Response/index.js +18 -13
- package/lib-next/theme/ApiDemoPanel/SecuritySchemes/index.js +22 -20
- package/lib-next/theme/ApiDemoPanel/Server/index.js +1 -0
- package/lib-next/theme/ApiDemoPanel/buildPostmanRequest.js +25 -3
- package/lib-next/theme/ApiDemoPanel/index.js +4 -13
- package/lib-next/theme/ApiDemoPanel/persistanceMiddleware.js +1 -1
- package/lib-next/theme/ApiDemoPanel/react-modal.d.ts +8 -0
- package/lib-next/theme/ApiItem/Layout/styles.module.css +56 -0
- package/lib-next/theme/ParamsItem/index.js +5 -1
- package/package.json +5 -4
- package/src/theme/ApiDemoPanel/Authorization/auth-types.ts +4 -0
- package/src/theme/ApiDemoPanel/Authorization/index.tsx +154 -0
- package/src/theme/ApiDemoPanel/Authorization/slice.ts +1 -1
- package/src/theme/ApiDemoPanel/Body/index.tsx +28 -6
- package/src/theme/ApiDemoPanel/Execute/index.tsx +188 -0
- package/src/theme/ApiDemoPanel/Execute/makeRequest.ts +197 -0
- package/src/theme/ApiDemoPanel/FormItem/index.tsx +11 -2
- package/src/theme/ApiDemoPanel/FormItem/styles.module.css +5 -0
- package/src/theme/ApiDemoPanel/ParamOptions/index.tsx +1 -1
- package/src/theme/ApiDemoPanel/Request/index.tsx +71 -0
- package/src/theme/ApiDemoPanel/Request/styles.module.css +17 -0
- package/src/theme/ApiDemoPanel/Response/index.tsx +19 -13
- package/src/theme/ApiDemoPanel/SecuritySchemes/index.tsx +22 -17
- package/src/theme/ApiDemoPanel/Server/index.tsx +1 -0
- package/src/theme/ApiDemoPanel/buildPostmanRequest.ts +22 -3
- package/src/theme/ApiDemoPanel/index.tsx +4 -13
- package/src/theme/ApiDemoPanel/persistanceMiddleware.ts +1 -1
- package/src/theme/ApiDemoPanel/react-modal.d.ts +8 -0
- package/src/theme/ApiItem/Layout/styles.module.css +56 -0
- package/src/theme/ParamsItem/index.js +5 -1
|
@@ -0,0 +1,197 @@
|
|
|
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 sdk from "@paloaltonetworks/postman-collection";
|
|
9
|
+
|
|
10
|
+
import { Body } from "../Body/slice";
|
|
11
|
+
|
|
12
|
+
function fetchWithtimeout(
|
|
13
|
+
url: string,
|
|
14
|
+
options: RequestInit,
|
|
15
|
+
timeout = 5000
|
|
16
|
+
): any {
|
|
17
|
+
return Promise.race([
|
|
18
|
+
fetch(url, options),
|
|
19
|
+
new Promise((_, reject) =>
|
|
20
|
+
setTimeout(() => reject(new Error("Request timed out")), timeout)
|
|
21
|
+
),
|
|
22
|
+
]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function loadImage(content: Blob): Promise<string | ArrayBuffer | null> {
|
|
26
|
+
return new Promise((accept, reject) => {
|
|
27
|
+
const reader = new FileReader();
|
|
28
|
+
|
|
29
|
+
reader.onabort = () => {
|
|
30
|
+
console.log("file reading was aborted");
|
|
31
|
+
reject();
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
reader.onerror = () => {
|
|
35
|
+
console.log("file reading has failed");
|
|
36
|
+
reject();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
reader.onload = () => {
|
|
40
|
+
// Do whatever you want with the file contents
|
|
41
|
+
const binaryStr = reader.result;
|
|
42
|
+
accept(binaryStr);
|
|
43
|
+
};
|
|
44
|
+
reader.readAsArrayBuffer(content);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function makeRequest(
|
|
49
|
+
request: sdk.Request,
|
|
50
|
+
proxy: string | undefined,
|
|
51
|
+
_body: Body
|
|
52
|
+
) {
|
|
53
|
+
const headers = request.toJSON().header;
|
|
54
|
+
|
|
55
|
+
let myHeaders = new Headers();
|
|
56
|
+
if (headers) {
|
|
57
|
+
headers.forEach((header: any) => {
|
|
58
|
+
if (header.key && header.value) {
|
|
59
|
+
myHeaders.append(header.key, header.value);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The following code handles multiple files in the same formdata param.
|
|
65
|
+
// It removes the form data params where the src property is an array of filepath strings
|
|
66
|
+
// Splits that array into different form data params with src set as a single filepath string
|
|
67
|
+
// TODO:
|
|
68
|
+
// if (request.body && request.body.mode === 'formdata') {
|
|
69
|
+
// let formdata = request.body.formdata,
|
|
70
|
+
// formdataArray = [];
|
|
71
|
+
// formdata.members.forEach((param) => {
|
|
72
|
+
// let key = param.key,
|
|
73
|
+
// type = param.type,
|
|
74
|
+
// disabled = param.disabled,
|
|
75
|
+
// contentType = param.contentType;
|
|
76
|
+
// // check if type is file or text
|
|
77
|
+
// if (type === 'file') {
|
|
78
|
+
// // if src is not of type string we check for array(multiple files)
|
|
79
|
+
// if (typeof param.src !== 'string') {
|
|
80
|
+
// // if src is an array(not empty), iterate over it and add files as separate form fields
|
|
81
|
+
// if (Array.isArray(param.src) && param.src.length) {
|
|
82
|
+
// param.src.forEach((filePath) => {
|
|
83
|
+
// addFormParam(
|
|
84
|
+
// formdataArray,
|
|
85
|
+
// key,
|
|
86
|
+
// param.type,
|
|
87
|
+
// filePath,
|
|
88
|
+
// disabled,
|
|
89
|
+
// contentType
|
|
90
|
+
// );
|
|
91
|
+
// });
|
|
92
|
+
// }
|
|
93
|
+
// // if src is not an array or string, or is an empty array, add a placeholder for file path(no files case)
|
|
94
|
+
// else {
|
|
95
|
+
// addFormParam(
|
|
96
|
+
// formdataArray,
|
|
97
|
+
// key,
|
|
98
|
+
// param.type,
|
|
99
|
+
// '/path/to/file',
|
|
100
|
+
// disabled,
|
|
101
|
+
// contentType
|
|
102
|
+
// );
|
|
103
|
+
// }
|
|
104
|
+
// }
|
|
105
|
+
// // if src is string, directly add the param with src as filepath
|
|
106
|
+
// else {
|
|
107
|
+
// addFormParam(
|
|
108
|
+
// formdataArray,
|
|
109
|
+
// key,
|
|
110
|
+
// param.type,
|
|
111
|
+
// param.src,
|
|
112
|
+
// disabled,
|
|
113
|
+
// contentType
|
|
114
|
+
// );
|
|
115
|
+
// }
|
|
116
|
+
// }
|
|
117
|
+
// // if type is text, directly add it to formdata array
|
|
118
|
+
// else {
|
|
119
|
+
// addFormParam(
|
|
120
|
+
// formdataArray,
|
|
121
|
+
// key,
|
|
122
|
+
// param.type,
|
|
123
|
+
// param.value,
|
|
124
|
+
// disabled,
|
|
125
|
+
// contentType
|
|
126
|
+
// );
|
|
127
|
+
// }
|
|
128
|
+
// });
|
|
129
|
+
// request.body.update({
|
|
130
|
+
// mode: 'formdata',
|
|
131
|
+
// formdata: formdataArray,
|
|
132
|
+
// });
|
|
133
|
+
// }
|
|
134
|
+
|
|
135
|
+
const body = request.body?.toJSON();
|
|
136
|
+
|
|
137
|
+
let myBody: RequestInit["body"] = undefined;
|
|
138
|
+
if (body !== undefined && Object.keys(body).length > 0) {
|
|
139
|
+
switch (body.mode) {
|
|
140
|
+
case "urlencoded": {
|
|
141
|
+
myBody = new URLSearchParams();
|
|
142
|
+
if (Array.isArray(body.urlencoded)) {
|
|
143
|
+
for (const data of body.urlencoded) {
|
|
144
|
+
if (data.key && data.value) {
|
|
145
|
+
myBody.append(data.key, data.value);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
case "raw": {
|
|
152
|
+
myBody = (body.raw ?? "").toString();
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "formdata": {
|
|
156
|
+
myBody = new FormData();
|
|
157
|
+
if (Array.isArray(body.formdata)) {
|
|
158
|
+
for (const data of body.formdata) {
|
|
159
|
+
if (data.key && data.value) {
|
|
160
|
+
myBody.append(data.key, data.value);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case "file": {
|
|
167
|
+
if (_body.type === "raw" && _body.content?.type === "file") {
|
|
168
|
+
myBody = await loadImage(_body.content.value.content);
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
default:
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const requestOptions: RequestInit = {
|
|
178
|
+
method: request.method,
|
|
179
|
+
headers: myHeaders,
|
|
180
|
+
body: myBody,
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
let finalUrl = request.url.toString();
|
|
184
|
+
if (proxy) {
|
|
185
|
+
// Ensure the proxy ends with a slash.
|
|
186
|
+
let normalizedProxy = proxy.replace(/\/$/, "") + "/";
|
|
187
|
+
finalUrl = normalizedProxy + request.url.toString();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return await fetchWithtimeout(finalUrl, requestOptions).then(
|
|
191
|
+
(response: any) => {
|
|
192
|
+
return response.text();
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export default makeRequest;
|
|
@@ -10,16 +10,25 @@ import React from "react";
|
|
|
10
10
|
import styles from "./styles.module.css";
|
|
11
11
|
|
|
12
12
|
interface Props {
|
|
13
|
-
label
|
|
13
|
+
label?: string;
|
|
14
14
|
type?: string;
|
|
15
|
+
required?: boolean | undefined;
|
|
15
16
|
children?: React.ReactNode;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
function FormItem({ label, type, children }: Props) {
|
|
19
|
+
function FormItem({ label, type, required, children }: Props) {
|
|
19
20
|
return (
|
|
20
21
|
<div className={styles.formItem}>
|
|
21
22
|
<code>{label}</code>
|
|
22
23
|
{type && <span style={{ opacity: 0.6 }}> — {type}</span>}
|
|
24
|
+
{required && (
|
|
25
|
+
<span>
|
|
26
|
+
{" "}
|
|
27
|
+
<small>
|
|
28
|
+
<strong className={styles.required}> required</strong>
|
|
29
|
+
</small>
|
|
30
|
+
</span>
|
|
31
|
+
)}
|
|
23
32
|
<div>{children}</div>
|
|
24
33
|
</div>
|
|
25
34
|
);
|
|
@@ -45,7 +45,7 @@ function ParamOption({ param }: ParamProps) {
|
|
|
45
45
|
|
|
46
46
|
function ParamOptionWrapper({ param }: ParamProps) {
|
|
47
47
|
return (
|
|
48
|
-
<FormItem label={param.name} type={param.in}>
|
|
48
|
+
<FormItem label={param.name} type={param.in} required={param.required}>
|
|
49
49
|
<ParamOption param={param} />
|
|
50
50
|
</FormItem>
|
|
51
51
|
);
|
|
@@ -0,0 +1,71 @@
|
|
|
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 React from "react";
|
|
9
|
+
|
|
10
|
+
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
11
|
+
import sdk from "@paloaltonetworks/postman-collection";
|
|
12
|
+
import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
|
13
|
+
import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
|
|
14
|
+
|
|
15
|
+
import { ThemeConfig } from "../../../types";
|
|
16
|
+
import Accept from "../Accept";
|
|
17
|
+
import Authorization from "../Authorization";
|
|
18
|
+
import Body from "../Body";
|
|
19
|
+
import Execute from "../Execute";
|
|
20
|
+
import { useTypedSelector } from "../hooks";
|
|
21
|
+
import ParamOptions from "../ParamOptions";
|
|
22
|
+
import styles from "./styles.module.css";
|
|
23
|
+
|
|
24
|
+
function Request({ item }: { item: NonNullable<ApiItem> }) {
|
|
25
|
+
const response = useTypedSelector((state) => state.response.value);
|
|
26
|
+
const { siteConfig } = useDocusaurusContext();
|
|
27
|
+
const themeConfig = siteConfig.themeConfig as ThemeConfig;
|
|
28
|
+
const options = themeConfig.api;
|
|
29
|
+
const postman = new sdk.Request(item.postman);
|
|
30
|
+
|
|
31
|
+
const params = {
|
|
32
|
+
path: [] as ParameterObject[],
|
|
33
|
+
query: [] as ParameterObject[],
|
|
34
|
+
header: [] as ParameterObject[],
|
|
35
|
+
cookie: [] as ParameterObject[],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
item.parameters?.forEach(
|
|
39
|
+
(param: { in: "path" | "query" | "header" | "cookie" }) => {
|
|
40
|
+
const paramType = param.in;
|
|
41
|
+
const paramsArray: ParameterObject[] = params[paramType];
|
|
42
|
+
paramsArray.push(param as ParameterObject);
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div>
|
|
48
|
+
<details className={`details__demo-panel`} open={response ? false : true}>
|
|
49
|
+
<summary>
|
|
50
|
+
<div className={`details__request-summary`}>
|
|
51
|
+
<h4>Request</h4>
|
|
52
|
+
{item.servers && (
|
|
53
|
+
<Execute postman={postman} proxy={options?.proxy} />
|
|
54
|
+
)}
|
|
55
|
+
</div>
|
|
56
|
+
</summary>
|
|
57
|
+
<div className={styles.optionsPanel}>
|
|
58
|
+
<Authorization />
|
|
59
|
+
<ParamOptions />
|
|
60
|
+
<Body
|
|
61
|
+
jsonRequestBodyExample={item.jsonRequestBodyExample}
|
|
62
|
+
requestBodyMetadata={item.requestBody}
|
|
63
|
+
/>
|
|
64
|
+
<Accept />
|
|
65
|
+
</div>
|
|
66
|
+
</details>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default Request;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.optionsPanel:empty {
|
|
2
|
+
display: none;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.optionsPanel {
|
|
6
|
+
background: var(--openapi-card-background-color);
|
|
7
|
+
border-radius: var(--openapi-card-border-radius);
|
|
8
|
+
color: var(--ifm-pre-color);
|
|
9
|
+
line-height: var(--ifm-pre-line-height);
|
|
10
|
+
margin-bottom: var(--ifm-spacing-vertical);
|
|
11
|
+
margin-top: 0;
|
|
12
|
+
overflow: auto;
|
|
13
|
+
padding: var(--ifm-pre-padding);
|
|
14
|
+
|
|
15
|
+
/* hack for view calculation when monaco is hidden */
|
|
16
|
+
position: relative;
|
|
17
|
+
}
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
|
|
10
|
+
import CodeBlock from "@theme/CodeBlock";
|
|
11
|
+
|
|
10
12
|
import { useTypedDispatch, useTypedSelector } from "../hooks";
|
|
11
|
-
import FloatingButton from "./../FloatingButton";
|
|
12
13
|
import { clearResponse } from "./slice";
|
|
13
14
|
|
|
14
15
|
// TODO: We probably shouldn't attempt to format XML...
|
|
@@ -43,23 +44,28 @@ function Response() {
|
|
|
43
44
|
try {
|
|
44
45
|
prettyResponse = JSON.stringify(JSON.parse(response), null, 2);
|
|
45
46
|
} catch {
|
|
46
|
-
if (response.startsWith("
|
|
47
|
+
if (response.startsWith("<")) {
|
|
47
48
|
prettyResponse = formatXml(response);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
return (
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
<details className={`details__demo-panel`} open={true}>
|
|
54
|
+
<summary>
|
|
55
|
+
<div className={`details__response-summary`}>
|
|
56
|
+
<h4>Response</h4>
|
|
57
|
+
<button
|
|
58
|
+
className="button button--sm button--secondary"
|
|
59
|
+
onClick={() => dispatch(clearResponse())}
|
|
60
|
+
>
|
|
61
|
+
Clear
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
</summary>
|
|
65
|
+
<CodeBlock language={response.startsWith("<") ? `xml` : `json`}>
|
|
66
|
+
{prettyResponse || "No Response"}
|
|
67
|
+
</CodeBlock>
|
|
68
|
+
</details>
|
|
63
69
|
);
|
|
64
70
|
}
|
|
65
71
|
|
|
@@ -19,58 +19,63 @@ function SecuritySchemes(props: any) {
|
|
|
19
19
|
if (selected === undefined) return null;
|
|
20
20
|
|
|
21
21
|
const selectedAuth = options[selected];
|
|
22
|
-
|
|
23
22
|
return (
|
|
24
|
-
<
|
|
23
|
+
<details className={`details__demo-panel`} open={false}>
|
|
24
|
+
<summary className={`details__request-summary`}>
|
|
25
|
+
<h4>Authorization</h4>
|
|
26
|
+
</summary>
|
|
25
27
|
{selectedAuth.map((auth) => {
|
|
26
28
|
const isApiKey = auth.type === "apiKey";
|
|
27
29
|
const isBearer = auth.type === "http" && auth.key === "Bearer";
|
|
28
|
-
const
|
|
29
|
-
auth.type === "oauth2" && auth.key === "ClientCredentials";
|
|
30
|
+
const isOauth2 = auth.type === "oauth2";
|
|
30
31
|
|
|
31
32
|
if (isApiKey || isBearer) {
|
|
32
33
|
return (
|
|
33
|
-
<React.Fragment key={
|
|
34
|
-
<b>
|
|
35
|
-
Authorization: <Link to={infoAuthPath}>{auth.key}</Link>
|
|
36
|
-
</b>
|
|
34
|
+
<React.Fragment key={auth.key}>
|
|
37
35
|
<pre
|
|
38
36
|
style={{
|
|
39
37
|
display: "flex",
|
|
40
38
|
flexDirection: "column",
|
|
41
39
|
background: "var(--openapi-card-background-color)",
|
|
42
|
-
borderRadius: "var(--openapi-card-border-radius)",
|
|
43
40
|
}}
|
|
44
41
|
>
|
|
45
|
-
<span>name: {auth.name}</span>
|
|
46
|
-
<span>in: {auth.in}</span>
|
|
47
42
|
<span>type: {auth.type}</span>
|
|
43
|
+
<span>
|
|
44
|
+
name: <Link to={infoAuthPath}>{auth.name}</Link>
|
|
45
|
+
</span>
|
|
46
|
+
<span>in: {auth.in}</span>
|
|
48
47
|
</pre>
|
|
49
48
|
</React.Fragment>
|
|
50
49
|
);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
if (
|
|
52
|
+
if (isOauth2) {
|
|
54
53
|
return (
|
|
55
54
|
<React.Fragment key={selected}>
|
|
56
|
-
<b>Authorization: {auth.key}</b>
|
|
57
55
|
<pre
|
|
58
56
|
style={{
|
|
59
57
|
display: "flex",
|
|
60
58
|
flexDirection: "column",
|
|
61
59
|
background: "var(--openapi-card-background-color)",
|
|
62
|
-
borderRadius: "var(--openapi-card-border-radius)",
|
|
63
60
|
}}
|
|
64
61
|
>
|
|
65
|
-
<span>
|
|
62
|
+
<span>
|
|
63
|
+
type: <Link to={infoAuthPath}>{auth.type}</Link>
|
|
64
|
+
</span>
|
|
65
|
+
{Object.keys(auth.flows).map((flow) => {
|
|
66
|
+
return <span key={flow}>flow: {flow}</span>;
|
|
67
|
+
})}
|
|
68
|
+
<span>
|
|
69
|
+
scopes: <code>{auth.scopes.toString()}</code>
|
|
70
|
+
</span>
|
|
66
71
|
</pre>
|
|
67
72
|
</React.Fragment>
|
|
68
73
|
);
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
return
|
|
76
|
+
return undefined;
|
|
72
77
|
})}
|
|
73
|
-
</
|
|
78
|
+
</details>
|
|
74
79
|
);
|
|
75
80
|
}
|
|
76
81
|
|
|
@@ -261,6 +261,25 @@ function buildPostmanRequest(
|
|
|
261
261
|
continue;
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
if (a.type === "oauth2") {
|
|
265
|
+
let token;
|
|
266
|
+
if (auth.data[a.key]) {
|
|
267
|
+
token = auth.data[a.key].token;
|
|
268
|
+
}
|
|
269
|
+
if (token === undefined) {
|
|
270
|
+
otherHeaders.push({
|
|
271
|
+
key: "Authorization",
|
|
272
|
+
value: "Bearer <TOKEN>",
|
|
273
|
+
});
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
otherHeaders.push({
|
|
277
|
+
key: "Authorization",
|
|
278
|
+
value: `Bearer ${token}`,
|
|
279
|
+
});
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
|
|
264
283
|
// Basic Auth
|
|
265
284
|
if (a.type === "http" && a.scheme === "basic") {
|
|
266
285
|
const { username, password } = auth.data[a.key];
|
|
@@ -276,8 +295,8 @@ function buildPostmanRequest(
|
|
|
276
295
|
|
|
277
296
|
// API Key
|
|
278
297
|
if (a.type === "apiKey" && a.in === "header") {
|
|
279
|
-
const {
|
|
280
|
-
if (
|
|
298
|
+
const { apiKey } = auth.data[a.key];
|
|
299
|
+
if (apiKey === undefined) {
|
|
281
300
|
otherHeaders.push({
|
|
282
301
|
key: a.name,
|
|
283
302
|
value: "<API_KEY_VALUE>",
|
|
@@ -286,7 +305,7 @@ function buildPostmanRequest(
|
|
|
286
305
|
}
|
|
287
306
|
otherHeaders.push({
|
|
288
307
|
key: a.name,
|
|
289
|
-
value:
|
|
308
|
+
value: apiKey,
|
|
290
309
|
});
|
|
291
310
|
continue;
|
|
292
311
|
}
|
|
@@ -14,13 +14,11 @@ import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
|
|
|
14
14
|
import { Provider } from "react-redux";
|
|
15
15
|
|
|
16
16
|
import { ThemeConfig } from "../../types";
|
|
17
|
-
import Accept from "./Accept";
|
|
18
17
|
import { createAuth } from "./Authorization/slice";
|
|
19
|
-
import Body from "./Body";
|
|
20
18
|
import Curl from "./Curl";
|
|
21
19
|
import MethodEndpoint from "./MethodEndpoint";
|
|
22
|
-
import ParamOptions from "./ParamOptions";
|
|
23
20
|
import { createPersistanceMiddleware } from "./persistanceMiddleware";
|
|
21
|
+
import Request from "./Request";
|
|
24
22
|
import Response from "./Response";
|
|
25
23
|
import SecuritySchemes from "./SecuritySchemes";
|
|
26
24
|
import Server from "./Server";
|
|
@@ -95,21 +93,14 @@ function ApiDemoPanel({
|
|
|
95
93
|
<Provider store={store2}>
|
|
96
94
|
<div className={styles.apiDemoPanelContainer}>
|
|
97
95
|
<MethodEndpoint method={method} path={path} />
|
|
98
|
-
<SecuritySchemes infoPath={infoPath} />
|
|
99
|
-
<div className={styles.optionsPanel}>
|
|
100
|
-
<ParamOptions />
|
|
101
|
-
<Body
|
|
102
|
-
jsonRequestBodyExample={item.jsonRequestBodyExample}
|
|
103
|
-
requestBodyMetadata={item.requestBody}
|
|
104
|
-
/>
|
|
105
|
-
<Accept />
|
|
106
|
-
</div>
|
|
107
96
|
<Server />
|
|
97
|
+
<SecuritySchemes infoPath={infoPath} />
|
|
98
|
+
<Request item={item} />
|
|
99
|
+
<Response />
|
|
108
100
|
<Curl
|
|
109
101
|
postman={postman}
|
|
110
102
|
codeSamples={(item as any)["x-code-samples"] ?? []}
|
|
111
103
|
/>
|
|
112
|
-
<Response />
|
|
113
104
|
</div>
|
|
114
105
|
</Provider>
|
|
115
106
|
);
|
|
@@ -19,7 +19,7 @@ export function createPersistanceMiddleware(options: ThemeConfig["api"]) {
|
|
|
19
19
|
|
|
20
20
|
const state = storeAPI.getState();
|
|
21
21
|
|
|
22
|
-
const storage = createStorage(
|
|
22
|
+
const storage = createStorage("sessionStorage");
|
|
23
23
|
|
|
24
24
|
if (action.type === setAuthData.type) {
|
|
25
25
|
for (const [key, value] of Object.entries(state.auth.data)) {
|
|
@@ -0,0 +1,8 @@
|
|
|
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
|
+
declare module "react-modal";
|
|
@@ -71,6 +71,62 @@
|
|
|
71
71
|
border-top: unset !important;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
:global(.theme-api-markdown .details__demo-panel) {
|
|
75
|
+
margin-bottom: 1rem;
|
|
76
|
+
background: var(--openapi-card-background-color);
|
|
77
|
+
border-radius: var(--openapi-card-border-radius);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:global(.theme-api-markdown .details__demo-panel > summary) {
|
|
81
|
+
padding-left: 1rem;
|
|
82
|
+
padding-top: 1rem;
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:global(.theme-api-markdown .details__demo-panel > div > div > pre) {
|
|
87
|
+
border-top-left-radius: 0;
|
|
88
|
+
border-top-right-radius: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:global(.theme-api-markdown .details__demo-panel > summary::marker) {
|
|
92
|
+
display: none;
|
|
93
|
+
content: "";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
:global(.theme-api-markdown
|
|
97
|
+
.details__demo-panel
|
|
98
|
+
> summary::-webkit-details-marker) {
|
|
99
|
+
display: none;
|
|
100
|
+
content: "";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:global(.theme-api-markdown .details__demo-panel > pre) {
|
|
104
|
+
margin-bottom: 0;
|
|
105
|
+
padding-top: 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
:global(.theme-api-markdown .details__request-summary) {
|
|
109
|
+
display: flex;
|
|
110
|
+
justify-content: space-between;
|
|
111
|
+
align-items: center;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
:global(.theme-api-markdown .details__request-summary > button) {
|
|
115
|
+
margin-bottom: 1rem;
|
|
116
|
+
margin-right: 1rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
:global(.theme-api-markdown .details__response-summary) {
|
|
120
|
+
display: flex;
|
|
121
|
+
justify-content: space-between;
|
|
122
|
+
align-items: center;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
:global(.theme-api-markdown .details__response-summary > button) {
|
|
126
|
+
margin-bottom: 1rem;
|
|
127
|
+
margin-right: 1rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
74
130
|
:global(.theme-api-markdown code) {
|
|
75
131
|
max-width: 600px;
|
|
76
132
|
max-height: 500px;
|
|
@@ -53,7 +53,11 @@ function ParamsItem({
|
|
|
53
53
|
));
|
|
54
54
|
|
|
55
55
|
const renderDefaultValue = guard(
|
|
56
|
-
schema
|
|
56
|
+
schema && schema.items
|
|
57
|
+
? schema.items.default
|
|
58
|
+
: schema
|
|
59
|
+
? schema.default
|
|
60
|
+
: undefined,
|
|
57
61
|
(value) => (
|
|
58
62
|
<div>
|
|
59
63
|
<ReactMarkdown children={`**Default value:** \`${value}\``} />
|