docusaurus-theme-openapi-docs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/LICENSE +21 -0
  2. package/babel.config.js +35 -0
  3. package/lib/index.js +48 -0
  4. package/lib/markdown/createDescription.js +20 -0
  5. package/lib/markdown/schema.js +121 -0
  6. package/lib/markdown/utils.js +45 -0
  7. package/lib/theme/ApiDemoPanel/Accept/index.js +41 -0
  8. package/lib/theme/ApiDemoPanel/Accept/slice.js +32 -0
  9. package/lib/theme/ApiDemoPanel/Authorization/auth-types.js +32 -0
  10. package/lib/theme/ApiDemoPanel/Authorization/index.js +174 -0
  11. package/lib/theme/ApiDemoPanel/Authorization/slice.js +137 -0
  12. package/lib/theme/ApiDemoPanel/Body/index.js +185 -0
  13. package/lib/theme/ApiDemoPanel/Body/slice.js +105 -0
  14. package/lib/theme/ApiDemoPanel/ContentType/index.js +41 -0
  15. package/lib/theme/ApiDemoPanel/ContentType/slice.js +32 -0
  16. package/lib/theme/ApiDemoPanel/Curl/index.js +236 -0
  17. package/lib/theme/ApiDemoPanel/Curl/styles.module.css +84 -0
  18. package/lib/theme/ApiDemoPanel/Execute/index.js +85 -0
  19. package/lib/theme/ApiDemoPanel/Execute/makeRequest.js +202 -0
  20. package/lib/theme/ApiDemoPanel/FloatingButton/index.js +32 -0
  21. package/lib/theme/ApiDemoPanel/FloatingButton/styles.module.css +26 -0
  22. package/lib/theme/ApiDemoPanel/FormFileUpload/index.js +97 -0
  23. package/lib/theme/ApiDemoPanel/FormFileUpload/styles.module.css +75 -0
  24. package/lib/theme/ApiDemoPanel/FormItem/index.js +35 -0
  25. package/lib/theme/ApiDemoPanel/FormItem/styles.module.css +7 -0
  26. package/lib/theme/ApiDemoPanel/FormMultiSelect/index.js +52 -0
  27. package/lib/theme/ApiDemoPanel/FormMultiSelect/styles.module.css +38 -0
  28. package/lib/theme/ApiDemoPanel/FormSelect/index.js +39 -0
  29. package/lib/theme/ApiDemoPanel/FormSelect/styles.module.css +51 -0
  30. package/lib/theme/ApiDemoPanel/FormTextInput/index.js +30 -0
  31. package/lib/theme/ApiDemoPanel/FormTextInput/styles.module.css +21 -0
  32. package/lib/theme/ApiDemoPanel/MethodEndpoint/index.js +60 -0
  33. package/lib/theme/ApiDemoPanel/ParamOptions/index.js +248 -0
  34. package/lib/theme/ApiDemoPanel/ParamOptions/slice.js +35 -0
  35. package/lib/theme/ApiDemoPanel/ParamOptions/styles.module.css +180 -0
  36. package/lib/theme/ApiDemoPanel/Response/index.js +75 -0
  37. package/lib/theme/ApiDemoPanel/Response/slice.js +37 -0
  38. package/lib/theme/ApiDemoPanel/SecuritySchemes/index.js +51 -0
  39. package/lib/theme/ApiDemoPanel/Server/index.js +109 -0
  40. package/lib/theme/ApiDemoPanel/Server/slice.js +41 -0
  41. package/lib/theme/ApiDemoPanel/Server/styles.module.css +61 -0
  42. package/lib/theme/ApiDemoPanel/VSCode/index.js +252 -0
  43. package/lib/theme/ApiDemoPanel/VSCode/styles.module.css +19 -0
  44. package/lib/theme/ApiDemoPanel/buildPostmanRequest.js +329 -0
  45. package/lib/theme/ApiDemoPanel/hooks.js +20 -0
  46. package/lib/theme/ApiDemoPanel/index.js +134 -0
  47. package/lib/theme/ApiDemoPanel/persistanceMiddleware.js +44 -0
  48. package/lib/theme/ApiDemoPanel/postman-collection.d.ts +10 -0
  49. package/lib/theme/ApiDemoPanel/storage-utils.js +47 -0
  50. package/lib/theme/ApiDemoPanel/store.js +48 -0
  51. package/lib/theme/ApiDemoPanel/styles.module.css +44 -0
  52. package/lib/theme/ApiItem/index.js +160 -0
  53. package/lib/theme/ApiItem/styles.module.css +109 -0
  54. package/lib/theme/ParamsItem/index.js +68 -0
  55. package/lib/theme/ParamsItem/styles.module.css +24 -0
  56. package/lib/theme/SchemaItem/index.js +58 -0
  57. package/lib/theme/SchemaItem/styles.module.css +24 -0
  58. package/lib/theme/Tabs/index.js +258 -0
  59. package/lib/theme/Tabs/styles.module.css +118 -0
  60. package/lib/theme-classic.d.ts +8 -0
  61. package/lib/theme-openapi.d.ts +48 -0
  62. package/lib/theme-translations.d.ts +9 -0
  63. package/lib/types.js +1 -0
  64. package/lib-next/index.js +38 -0
  65. package/lib-next/markdown/createDescription.js +13 -0
  66. package/lib-next/markdown/schema.js +115 -0
  67. package/lib-next/markdown/utils.js +31 -0
  68. package/lib-next/theme/ApiDemoPanel/Accept/index.js +33 -0
  69. package/lib-next/theme/ApiDemoPanel/Accept/slice.js +19 -0
  70. package/lib-next/theme/ApiDemoPanel/Authorization/auth-types.js +22 -0
  71. package/lib-next/theme/ApiDemoPanel/Authorization/index.js +203 -0
  72. package/lib-next/theme/ApiDemoPanel/Authorization/slice.js +101 -0
  73. package/lib-next/theme/ApiDemoPanel/Body/index.js +210 -0
  74. package/lib-next/theme/ApiDemoPanel/Body/slice.js +89 -0
  75. package/lib-next/theme/ApiDemoPanel/ContentType/index.js +33 -0
  76. package/lib-next/theme/ApiDemoPanel/ContentType/slice.js +19 -0
  77. package/lib-next/theme/ApiDemoPanel/Curl/index.js +264 -0
  78. package/lib-next/theme/ApiDemoPanel/Curl/styles.module.css +84 -0
  79. package/lib-next/theme/ApiDemoPanel/Execute/index.js +74 -0
  80. package/lib-next/theme/ApiDemoPanel/Execute/makeRequest.js +183 -0
  81. package/lib-next/theme/ApiDemoPanel/FloatingButton/index.js +19 -0
  82. package/lib-next/theme/ApiDemoPanel/FloatingButton/styles.module.css +26 -0
  83. package/lib-next/theme/ApiDemoPanel/FormFileUpload/index.js +113 -0
  84. package/lib-next/theme/ApiDemoPanel/FormFileUpload/styles.module.css +75 -0
  85. package/lib-next/theme/ApiDemoPanel/FormItem/index.js +29 -0
  86. package/lib-next/theme/ApiDemoPanel/FormItem/styles.module.css +7 -0
  87. package/lib-next/theme/ApiDemoPanel/FormMultiSelect/index.js +49 -0
  88. package/lib-next/theme/ApiDemoPanel/FormMultiSelect/styles.module.css +38 -0
  89. package/lib-next/theme/ApiDemoPanel/FormSelect/index.js +28 -0
  90. package/lib-next/theme/ApiDemoPanel/FormSelect/styles.module.css +51 -0
  91. package/lib-next/theme/ApiDemoPanel/FormTextInput/index.js +23 -0
  92. package/lib-next/theme/ApiDemoPanel/FormTextInput/styles.module.css +21 -0
  93. package/lib-next/theme/ApiDemoPanel/MethodEndpoint/index.js +53 -0
  94. package/lib-next/theme/ApiDemoPanel/ParamOptions/index.js +284 -0
  95. package/lib-next/theme/ApiDemoPanel/ParamOptions/slice.js +22 -0
  96. package/lib-next/theme/ApiDemoPanel/ParamOptions/styles.module.css +180 -0
  97. package/lib-next/theme/ApiDemoPanel/Response/index.js +65 -0
  98. package/lib-next/theme/ApiDemoPanel/Response/slice.js +22 -0
  99. package/lib-next/theme/ApiDemoPanel/SecuritySchemes/index.js +48 -0
  100. package/lib-next/theme/ApiDemoPanel/Server/index.js +114 -0
  101. package/lib-next/theme/ApiDemoPanel/Server/slice.js +25 -0
  102. package/lib-next/theme/ApiDemoPanel/Server/styles.module.css +61 -0
  103. package/lib-next/theme/ApiDemoPanel/VSCode/index.js +265 -0
  104. package/lib-next/theme/ApiDemoPanel/VSCode/styles.module.css +19 -0
  105. package/lib-next/theme/ApiDemoPanel/buildPostmanRequest.js +310 -0
  106. package/lib-next/theme/ApiDemoPanel/hooks.js +9 -0
  107. package/lib-next/theme/ApiDemoPanel/index.js +110 -0
  108. package/lib-next/theme/ApiDemoPanel/persistanceMiddleware.js +38 -0
  109. package/lib-next/theme/ApiDemoPanel/postman-collection.d.ts +10 -0
  110. package/lib-next/theme/ApiDemoPanel/storage-utils.js +35 -0
  111. package/lib-next/theme/ApiDemoPanel/store.js +30 -0
  112. package/lib-next/theme/ApiDemoPanel/styles.module.css +44 -0
  113. package/lib-next/theme/ApiItem/index.js +171 -0
  114. package/lib-next/theme/ApiItem/styles.module.css +109 -0
  115. package/lib-next/theme/ParamsItem/index.js +68 -0
  116. package/lib-next/theme/ParamsItem/styles.module.css +24 -0
  117. package/lib-next/theme/SchemaItem/index.js +58 -0
  118. package/lib-next/theme/SchemaItem/styles.module.css +24 -0
  119. package/lib-next/theme/Tabs/index.js +258 -0
  120. package/lib-next/theme/Tabs/styles.module.css +118 -0
  121. package/lib-next/theme-classic.d.ts +8 -0
  122. package/lib-next/theme-openapi.d.ts +48 -0
  123. package/lib-next/theme-translations.d.ts +9 -0
  124. package/lib-next/types.js +1 -0
  125. package/package.json +68 -0
  126. package/src/index.ts +42 -0
  127. package/src/markdown/createDescription.ts +13 -0
  128. package/src/markdown/schema.ts +115 -0
  129. package/src/markdown/utils.ts +39 -0
  130. package/src/theme/ApiDemoPanel/Accept/index.tsx +35 -0
  131. package/src/theme/ApiDemoPanel/Accept/slice.ts +29 -0
  132. package/src/theme/ApiDemoPanel/Authorization/auth-types.ts +26 -0
  133. package/src/theme/ApiDemoPanel/Authorization/index.tsx +211 -0
  134. package/src/theme/ApiDemoPanel/Authorization/slice.ts +145 -0
  135. package/src/theme/ApiDemoPanel/Body/index.tsx +218 -0
  136. package/src/theme/ApiDemoPanel/Body/slice.ts +133 -0
  137. package/src/theme/ApiDemoPanel/ContentType/index.tsx +35 -0
  138. package/src/theme/ApiDemoPanel/ContentType/slice.ts +29 -0
  139. package/src/theme/ApiDemoPanel/Curl/index.tsx +280 -0
  140. package/src/theme/ApiDemoPanel/Curl/styles.module.css +84 -0
  141. package/src/theme/ApiDemoPanel/Execute/index.tsx +88 -0
  142. package/src/theme/ApiDemoPanel/Execute/makeRequest.ts +184 -0
  143. package/src/theme/ApiDemoPanel/FloatingButton/index.tsx +27 -0
  144. package/src/theme/ApiDemoPanel/FloatingButton/styles.module.css +26 -0
  145. package/src/theme/ApiDemoPanel/FormFileUpload/index.tsx +116 -0
  146. package/src/theme/ApiDemoPanel/FormFileUpload/styles.module.css +75 -0
  147. package/src/theme/ApiDemoPanel/FormItem/index.tsx +28 -0
  148. package/src/theme/ApiDemoPanel/FormItem/styles.module.css +7 -0
  149. package/src/theme/ApiDemoPanel/FormMultiSelect/index.tsx +54 -0
  150. package/src/theme/ApiDemoPanel/FormMultiSelect/styles.module.css +38 -0
  151. package/src/theme/ApiDemoPanel/FormSelect/index.tsx +36 -0
  152. package/src/theme/ApiDemoPanel/FormSelect/styles.module.css +51 -0
  153. package/src/theme/ApiDemoPanel/FormTextInput/index.tsx +32 -0
  154. package/src/theme/ApiDemoPanel/FormTextInput/styles.module.css +21 -0
  155. package/src/theme/ApiDemoPanel/MethodEndpoint/index.tsx +55 -0
  156. package/src/theme/ApiDemoPanel/ParamOptions/index.tsx +316 -0
  157. package/src/theme/ApiDemoPanel/ParamOptions/slice.ts +37 -0
  158. package/src/theme/ApiDemoPanel/ParamOptions/styles.module.css +180 -0
  159. package/src/theme/ApiDemoPanel/Response/index.tsx +66 -0
  160. package/src/theme/ApiDemoPanel/Response/slice.ts +31 -0
  161. package/src/theme/ApiDemoPanel/SecuritySchemes/index.tsx +49 -0
  162. package/src/theme/ApiDemoPanel/Server/index.tsx +103 -0
  163. package/src/theme/ApiDemoPanel/Server/slice.ts +40 -0
  164. package/src/theme/ApiDemoPanel/Server/styles.module.css +61 -0
  165. package/src/theme/ApiDemoPanel/VSCode/index.tsx +205 -0
  166. package/src/theme/ApiDemoPanel/VSCode/styles.module.css +19 -0
  167. package/src/theme/ApiDemoPanel/buildPostmanRequest.ts +307 -0
  168. package/src/theme/ApiDemoPanel/hooks.ts +13 -0
  169. package/src/theme/ApiDemoPanel/index.tsx +118 -0
  170. package/src/theme/ApiDemoPanel/persistanceMiddleware.ts +46 -0
  171. package/src/theme/ApiDemoPanel/postman-collection.d.ts +10 -0
  172. package/src/theme/ApiDemoPanel/storage-utils.ts +39 -0
  173. package/src/theme/ApiDemoPanel/store.ts +41 -0
  174. package/src/theme/ApiDemoPanel/styles.module.css +44 -0
  175. package/src/theme/ApiItem/index.tsx +171 -0
  176. package/src/theme/ApiItem/styles.module.css +109 -0
  177. package/src/theme/ParamsItem/index.js +68 -0
  178. package/src/theme/ParamsItem/styles.module.css +24 -0
  179. package/src/theme/SchemaItem/index.js +58 -0
  180. package/src/theme/SchemaItem/styles.module.css +24 -0
  181. package/src/theme/Tabs/index.js +258 -0
  182. package/src/theme/Tabs/styles.module.css +118 -0
  183. package/src/theme-classic.d.ts +8 -0
  184. package/src/theme-openapi.d.ts +48 -0
  185. package/src/theme-translations.d.ts +9 -0
  186. package/src/types.ts +70 -0
  187. package/tsconfig.json +10 -0
@@ -0,0 +1,39 @@
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
+ export type Children = string | undefined | (string | undefined)[];
9
+
10
+ export type Props = Record<string, any> & { children?: Children };
11
+
12
+ export function create(tag: string, props: Props): string {
13
+ const { children, ...rest } = props;
14
+
15
+ let propString = "";
16
+ for (const [key, value] of Object.entries(rest)) {
17
+ propString += ` ${key}={${JSON.stringify(value)}}`;
18
+ }
19
+
20
+ return `<${tag}${propString}>${render(children)}</${tag}>`;
21
+ }
22
+
23
+ export function guard<T>(
24
+ value: T | undefined,
25
+ cb: (value: T) => Children
26
+ ): string {
27
+ if (value) {
28
+ const children = cb(value);
29
+ return render(children);
30
+ }
31
+ return "";
32
+ }
33
+
34
+ export function render(children: Children): string {
35
+ if (Array.isArray(children)) {
36
+ return children.filter((c) => c !== undefined).join("");
37
+ }
38
+ return children ?? "";
39
+ }
@@ -0,0 +1,35 @@
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 { useTypedDispatch, useTypedSelector } from "../hooks";
11
+ import FormItem from "./../FormItem";
12
+ import FormSelect from "./../FormSelect";
13
+ import { setAccept } from "./slice";
14
+
15
+ function Accept() {
16
+ const value = useTypedSelector((state) => state.accept.value);
17
+ const options = useTypedSelector((state) => state.accept.options);
18
+ const dispatch = useTypedDispatch();
19
+
20
+ if (options.length <= 1) {
21
+ return null;
22
+ }
23
+
24
+ return (
25
+ <FormItem label="Accept">
26
+ <FormSelect
27
+ value={value}
28
+ options={options}
29
+ onChange={(e) => dispatch(setAccept(e.target.value))}
30
+ />
31
+ </FormItem>
32
+ );
33
+ }
34
+
35
+ export default Accept;
@@ -0,0 +1,29 @@
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
+ export interface State {
11
+ value: string;
12
+ options: string[];
13
+ }
14
+
15
+ const initialState: State = {} as any;
16
+
17
+ export const slice = createSlice({
18
+ name: "accept",
19
+ initialState,
20
+ reducers: {
21
+ setAccept: (state, action: PayloadAction<string>) => {
22
+ state.value = action.payload;
23
+ },
24
+ },
25
+ });
26
+
27
+ export const { setAccept } = slice.actions;
28
+
29
+ export default slice.reducer;
@@ -0,0 +1,26 @@
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
+ export function getAuthDataKeys(security: { [key: string]: any }) {
9
+ // Bearer Auth
10
+ if (security.type === "http" && security.scheme === "bearer") {
11
+ return ["token"];
12
+ }
13
+
14
+ // Basic Auth
15
+ if (security.type === "http" && security.scheme === "basic") {
16
+ return ["username", "password"];
17
+ }
18
+
19
+ // API Auth
20
+ if (security.type === "apiKey") {
21
+ return ["apiKey"];
22
+ }
23
+
24
+ // none
25
+ return [];
26
+ }
@@ -0,0 +1,211 @@
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, { useState } from "react";
9
+
10
+ import clsx from "clsx";
11
+
12
+ import FormItem from "../FormItem";
13
+ import FormSelect from "../FormSelect";
14
+ import FormTextInput from "../FormTextInput";
15
+ import { useTypedDispatch, useTypedSelector } from "../hooks";
16
+ import styles from "../styles.module.css";
17
+ import { AuthState, Scheme, setAuthData, setSelectedAuth } from "./slice";
18
+
19
+ type Props = {
20
+ mode: "locked" | "unlocked";
21
+ } & JSX.IntrinsicElements["button"];
22
+
23
+ function LockButton({ mode, children, style, ...rest }: Props) {
24
+ return (
25
+ <button
26
+ className={clsx("button", "button--primary", {
27
+ "button--outline": mode !== "locked",
28
+ })}
29
+ style={{
30
+ marginLeft: "auto",
31
+ display: "flex",
32
+ alignItems: "center",
33
+ marginBottom: "var(--ifm-spacing-vertical)",
34
+ ...style,
35
+ }}
36
+ {...rest}
37
+ >
38
+ <span>{children}</span>
39
+
40
+ <svg
41
+ style={{
42
+ marginLeft: "12px",
43
+ width: "18px",
44
+ height: "18px",
45
+ fill: "currentColor",
46
+ }}
47
+ viewBox="0 0 20 20"
48
+ id={mode}
49
+ >
50
+ {mode === "locked" ? (
51
+ <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"></path>
52
+ ) : (
53
+ <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
54
+ )}
55
+ </svg>
56
+ </button>
57
+ );
58
+ }
59
+
60
+ function validateData(selectedAuth: Scheme[], data: AuthState["data"]) {
61
+ for (const scheme of selectedAuth) {
62
+ if (data[scheme.key] === undefined) {
63
+ return false;
64
+ }
65
+ const hasMissingKeys = Object.values(data[scheme.key]).includes(undefined);
66
+ if (hasMissingKeys) {
67
+ return false;
68
+ }
69
+ }
70
+ return true;
71
+ }
72
+
73
+ function Authorization() {
74
+ const [editing, setEditing] = useState(false);
75
+
76
+ const data = useTypedSelector((state) => state.auth.data);
77
+ const options = useTypedSelector((state) => state.auth.options);
78
+ const selected = useTypedSelector((state) => state.auth.selected);
79
+
80
+ const dispatch = useTypedDispatch();
81
+
82
+ if (selected === undefined) {
83
+ return null;
84
+ }
85
+
86
+ const selectedAuth = options[selected];
87
+
88
+ const authenticated = validateData(selectedAuth, data);
89
+
90
+ const optionKeys = Object.keys(options);
91
+
92
+ if (editing) {
93
+ return (
94
+ <div className={styles.optionsPanel}>
95
+ {optionKeys.length > 1 && (
96
+ <FormItem label="Security Scheme">
97
+ <FormSelect
98
+ options={optionKeys}
99
+ value={selected}
100
+ onChange={(e) => {
101
+ dispatch(setSelectedAuth(e.target.value));
102
+ }}
103
+ />
104
+ </FormItem>
105
+ )}
106
+ {selectedAuth.map((a) => {
107
+ if (a.type === "http" && a.scheme === "bearer") {
108
+ return (
109
+ <FormItem label="Bearer Token" key={selected + "-bearer"}>
110
+ <FormTextInput
111
+ placeholder="Bearer Token"
112
+ value={data[a.key].token ?? ""}
113
+ onChange={(e) => {
114
+ const value = e.target.value.trim();
115
+ dispatch(
116
+ setAuthData({
117
+ scheme: a.key,
118
+ key: "token",
119
+ value: value ? value : undefined,
120
+ })
121
+ );
122
+ }}
123
+ />
124
+ </FormItem>
125
+ );
126
+ }
127
+
128
+ if (a.type === "http" && a.scheme === "basic") {
129
+ return (
130
+ <React.Fragment key={selected + "-basic"}>
131
+ <FormItem label="Username">
132
+ <FormTextInput
133
+ placeholder="Username"
134
+ value={data[a.key].username ?? ""}
135
+ onChange={(e) => {
136
+ const value = e.target.value.trim();
137
+ dispatch(
138
+ setAuthData({
139
+ scheme: a.key,
140
+ key: "username",
141
+ value: value ? value : undefined,
142
+ })
143
+ );
144
+ }}
145
+ />
146
+ </FormItem>
147
+ <FormItem label="Password">
148
+ <FormTextInput
149
+ placeholder="Password"
150
+ password
151
+ value={data[a.key].password ?? ""}
152
+ onChange={(e) => {
153
+ const value = e.target.value.trim();
154
+ dispatch(
155
+ setAuthData({
156
+ scheme: a.key,
157
+ key: "password",
158
+ value: value ? value : undefined,
159
+ })
160
+ );
161
+ }}
162
+ />
163
+ </FormItem>
164
+ </React.Fragment>
165
+ );
166
+ }
167
+
168
+ return null;
169
+ })}
170
+ <LockButton
171
+ mode="unlocked"
172
+ style={{
173
+ marginTop: "var(--ifm-spacing-vertical)",
174
+ marginBottom: 0,
175
+ }}
176
+ onClick={() => {
177
+ setEditing(false);
178
+ }}
179
+ >
180
+ Save
181
+ </LockButton>
182
+ </div>
183
+ );
184
+ }
185
+
186
+ if (authenticated) {
187
+ return (
188
+ <LockButton
189
+ mode="locked"
190
+ onClick={() => {
191
+ setEditing(true);
192
+ }}
193
+ >
194
+ Authorized
195
+ </LockButton>
196
+ );
197
+ }
198
+
199
+ return (
200
+ <LockButton
201
+ mode="unlocked"
202
+ onClick={() => {
203
+ setEditing(true);
204
+ }}
205
+ >
206
+ Authorize
207
+ </LockButton>
208
+ );
209
+ }
210
+
211
+ export default Authorization;
@@ -0,0 +1,145 @@
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
+ import {
10
+ SecurityRequirementObject,
11
+ SecuritySchemeObject,
12
+ } from "docusaurus-plugin-openapi-docs/src/openapi/types";
13
+
14
+ import { ThemeConfig } from "../../../types";
15
+ import { createStorage, hashArray } from "../storage-utils";
16
+ import { getAuthDataKeys } from "./auth-types";
17
+
18
+ // The global definitions
19
+ // "securitySchemes": {
20
+ // "BearerAuth": { "type": "http", "scheme": "BeAreR" },
21
+ // "BasicAuth": { "type": "http", "scheme": "basic" }
22
+ // },
23
+
24
+ // The operation level requirements
25
+ // "security": [
26
+ // { "BearerAuth": [] },
27
+ // { "BearerAuth": [], "BasicAuth": [] }
28
+ // ],
29
+
30
+ // SLICE_STATE
31
+ // data:
32
+ // BearerAuth:
33
+ // token=xxx
34
+ // BasicAuth:
35
+ // username=xxx
36
+ // password=xxx
37
+ //
38
+ // options:
39
+ // "BearerAuth": [{ key: "BearerAuth", scopes: [], ...rest }]
40
+ // "BearerAuth and BasicAuth": [{ key: "BearerAuth", scopes: [], ...rest }, { key: "BasicAuth", scopes: [], ...rest }]
41
+ //
42
+ // selected: "BearerAuth and BasicAuth"
43
+
44
+ // LOCAL_STORAGE
45
+ // hash(SLICE_STATE.options) -> "BearerAuth and BasicAuth"
46
+ // BearerAuth -> { token: xxx }
47
+ // BasicAuth -> { username: xxx, password: xxx }
48
+
49
+ export function createAuth({
50
+ security,
51
+ securitySchemes,
52
+ options: opts,
53
+ }: {
54
+ security?: SecurityRequirementObject[];
55
+ securitySchemes?: {
56
+ [key: string]: SecuritySchemeObject;
57
+ };
58
+ options?: ThemeConfig["api"];
59
+ }): AuthState {
60
+ const storage = createStorage(opts?.authPersistance);
61
+
62
+ let data: AuthState["data"] = {};
63
+ let options: AuthState["options"] = {};
64
+
65
+ for (const option of security ?? []) {
66
+ const id = Object.keys(option).join(" and ");
67
+ for (const [schemeID, scopes] of Object.entries(option)) {
68
+ const scheme = securitySchemes?.[schemeID];
69
+ if (scheme) {
70
+ if (options[id] === undefined) {
71
+ options[id] = [];
72
+ }
73
+ const dataKeys = getAuthDataKeys(scheme);
74
+ for (const key of dataKeys) {
75
+ if (data[schemeID] === undefined) {
76
+ data[schemeID] = {};
77
+ }
78
+
79
+ let persisted = undefined;
80
+ try {
81
+ persisted = JSON.parse(storage.getItem(schemeID) ?? "")[key];
82
+ } catch {}
83
+
84
+ data[schemeID][key] = persisted;
85
+ }
86
+ options[id].push({
87
+ ...scheme,
88
+ key: schemeID,
89
+ scopes,
90
+ });
91
+ }
92
+ }
93
+ }
94
+
95
+ let persisted = undefined;
96
+ try {
97
+ persisted = storage.getItem(hashArray(Object.keys(options))) ?? undefined;
98
+ } catch {}
99
+
100
+ return {
101
+ data,
102
+ options,
103
+ selected: persisted ?? Object.keys(options)[0],
104
+ };
105
+ }
106
+
107
+ export type Scheme = {
108
+ key: string;
109
+ scopes: string[];
110
+ } & SecuritySchemeObject;
111
+
112
+ export interface AuthState {
113
+ data: {
114
+ [scheme: string]: {
115
+ [key: string]: string | undefined;
116
+ };
117
+ };
118
+ options: {
119
+ [key: string]: Scheme[];
120
+ };
121
+ selected?: string;
122
+ }
123
+
124
+ const initialState: AuthState = {} as any;
125
+
126
+ export const slice = createSlice({
127
+ name: "auth",
128
+ initialState,
129
+ reducers: {
130
+ setAuthData: (
131
+ state,
132
+ action: PayloadAction<{ scheme: string; key: string; value?: string }>
133
+ ) => {
134
+ const { scheme, key, value } = action.payload;
135
+ state.data[scheme][key] = value;
136
+ },
137
+ setSelectedAuth: (state, action: PayloadAction<string>) => {
138
+ state.selected = action.payload;
139
+ },
140
+ },
141
+ });
142
+
143
+ export const { setAuthData, setSelectedAuth } = slice.actions;
144
+
145
+ export default slice.reducer;
@@ -0,0 +1,218 @@
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 { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
11
+
12
+ import ContentType from "../ContentType";
13
+ import FormSelect from "../FormSelect";
14
+ import { useTypedDispatch, useTypedSelector } from "../hooks";
15
+ import FormFileUpload from "./../FormFileUpload";
16
+ import FormItem from "./../FormItem";
17
+ import FormTextInput from "./../FormTextInput";
18
+ import VSCode from "./../VSCode";
19
+ import {
20
+ clearFormBodyKey,
21
+ clearRawBody,
22
+ setFileFormBody,
23
+ setFileRawBody,
24
+ setStringFormBody,
25
+ setStringRawBody,
26
+ } from "./slice";
27
+
28
+ interface Props {
29
+ jsonRequestBodyExample: string;
30
+ requestBodyMetadata?: RequestBodyObject;
31
+ }
32
+
33
+ function BodyWrap({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
34
+ const contentType = useTypedSelector((state) => state.contentType.value);
35
+
36
+ // NOTE: We used to check if body was required, but opted to always show the request body
37
+ // to reduce confusion, see: https://github.com/cloud-annotations/docusaurus-openapi/issues/145
38
+
39
+ // No body
40
+ if (contentType === undefined) {
41
+ return null;
42
+ }
43
+
44
+ return (
45
+ <>
46
+ <ContentType />
47
+ <Body
48
+ requestBodyMetadata={requestBodyMetadata}
49
+ jsonRequestBodyExample={jsonRequestBodyExample}
50
+ />
51
+ </>
52
+ );
53
+ }
54
+
55
+ function Body({ requestBodyMetadata, jsonRequestBodyExample }: Props) {
56
+ const contentType = useTypedSelector((state) => state.contentType.value);
57
+
58
+ const dispatch = useTypedDispatch();
59
+
60
+ // Lot's of possible content-types:
61
+ // - application/json
62
+ // - application/xml
63
+ // - text/plain
64
+ // - text/css
65
+ // - text/html
66
+ // - text/javascript
67
+ // - application/javascript
68
+ // - multipart/form-data
69
+ // - application/x-www-form-urlencoded
70
+ // - image/svg+xml;charset=US-ASCII
71
+
72
+ // Show editor:
73
+ // - application/json
74
+ // - application/xml
75
+ // - */*
76
+
77
+ // Show form:
78
+ // - multipart/form-data
79
+ // - application/x-www-form-urlencoded
80
+
81
+ const schema = requestBodyMetadata?.content?.[contentType]?.schema;
82
+
83
+ if (schema?.format === "binary") {
84
+ return (
85
+ <FormItem label="Body">
86
+ <FormFileUpload
87
+ placeholder={schema.description || "Body"}
88
+ onChange={(file) => {
89
+ if (file === undefined) {
90
+ dispatch(clearRawBody());
91
+ return;
92
+ }
93
+ dispatch(
94
+ setFileRawBody({
95
+ src: `/path/to/${file.name}`,
96
+ content: file,
97
+ })
98
+ );
99
+ }}
100
+ />
101
+ </FormItem>
102
+ );
103
+ }
104
+
105
+ if (
106
+ (contentType === "multipart/form-data" ||
107
+ contentType === "application/x-www-form-urlencoded") &&
108
+ schema?.type === "object"
109
+ ) {
110
+ return (
111
+ <FormItem label="Body">
112
+ <div
113
+ style={{
114
+ marginTop: "calc(var(--ifm-pre-padding) / 2)",
115
+ borderRadius: "4px",
116
+ padding: "var(--ifm-pre-padding)",
117
+ border: "1px solid var(--openapi-monaco-border-color)",
118
+ }}
119
+ >
120
+ {Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
121
+ if (val.format === "binary") {
122
+ return (
123
+ <FormItem key={key} label={key}>
124
+ <FormFileUpload
125
+ placeholder={val.description || key}
126
+ onChange={(file) => {
127
+ if (file === undefined) {
128
+ dispatch(clearFormBodyKey(key));
129
+ return;
130
+ }
131
+ dispatch(
132
+ setFileFormBody({
133
+ key: key,
134
+ value: {
135
+ src: `/path/to/${file.name}`,
136
+ content: file,
137
+ },
138
+ })
139
+ );
140
+ }}
141
+ />
142
+ </FormItem>
143
+ );
144
+ }
145
+
146
+ if (val.enum) {
147
+ return (
148
+ <FormItem key={key} label={key}>
149
+ <FormSelect
150
+ options={["---", ...val.enum]}
151
+ onChange={(e) => {
152
+ const val = e.target.value;
153
+ if (val === "---") {
154
+ dispatch(clearFormBodyKey(key));
155
+ } else {
156
+ dispatch(
157
+ setStringFormBody({
158
+ key: key,
159
+ value: val,
160
+ })
161
+ );
162
+ }
163
+ }}
164
+ />
165
+ </FormItem>
166
+ );
167
+ }
168
+ // TODO: support all the other types.
169
+ return (
170
+ <FormItem key={key} label={key}>
171
+ <FormTextInput
172
+ placeholder={val.description || key}
173
+ onChange={(e) => {
174
+ dispatch(
175
+ setStringFormBody({ key: key, value: e.target.value })
176
+ );
177
+ }}
178
+ />
179
+ </FormItem>
180
+ );
181
+ })}
182
+ </div>
183
+ </FormItem>
184
+ );
185
+ }
186
+
187
+ let language = "plaintext";
188
+ let exampleBodyString = ""; //"body content";
189
+
190
+ if (contentType === "application/json") {
191
+ if (jsonRequestBodyExample) {
192
+ exampleBodyString = JSON.stringify(jsonRequestBodyExample, null, 2);
193
+ }
194
+ language = "json";
195
+ }
196
+
197
+ if (contentType === "application/xml") {
198
+ language = "xml";
199
+ }
200
+
201
+ return (
202
+ <FormItem label="Body">
203
+ <VSCode
204
+ value={exampleBodyString}
205
+ language={language}
206
+ onChange={(value) => {
207
+ if (value.trim() === "") {
208
+ dispatch(clearRawBody());
209
+ return;
210
+ }
211
+ dispatch(setStringRawBody(value));
212
+ }}
213
+ />
214
+ </FormItem>
215
+ );
216
+ }
217
+
218
+ export default BodyWrap;