zudoku 0.0.0-f3786a4 → 0.0.0-f3f6db5
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/dist/app/main.js +1 -2
- package/dist/app/main.js.map +1 -1
- package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
- package/dist/lib/components/PathRenderer.d.ts +11 -0
- package/dist/lib/components/PathRenderer.js +25 -0
- package/dist/lib/components/PathRenderer.js.map +1 -0
- package/dist/lib/components/ThemeSwitch.js +4 -4
- package/dist/lib/components/ThemeSwitch.js.map +1 -1
- package/dist/lib/components/index.d.ts +1 -0
- package/dist/lib/components/index.js +4 -2
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/components/navigation/SidebarCategory.js +17 -15
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/oas/graphql/circular.js +17 -6
- package/dist/lib/oas/graphql/circular.js.map +1 -1
- package/dist/lib/oas/graphql/index.d.ts +1 -0
- package/dist/lib/oas/graphql/index.js +41 -23
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/plugins/openapi/ColorizedParam.js +3 -1
- package/dist/lib/plugins/openapi/ColorizedParam.js.map +1 -1
- package/dist/lib/plugins/openapi/Endpoint.js +2 -2
- package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
- package/dist/lib/plugins/openapi/{Route.d.ts → OpenApiRoute.d.ts} +2 -1
- package/dist/lib/plugins/openapi/{Route.js → OpenApiRoute.js} +3 -4
- package/dist/lib/plugins/openapi/OpenApiRoute.js.map +1 -0
- package/dist/lib/plugins/openapi/OperationList.d.ts +4 -1
- package/dist/lib/plugins/openapi/OperationList.js +20 -14
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js +2 -2
- package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.d.ts +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +2 -0
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +6 -11
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/SidecarExamples.js +17 -14
- package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +6 -2
- package/dist/lib/plugins/openapi/graphql/gql.js +3 -2
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +47 -26
- package/dist/lib/plugins/openapi/graphql/graphql.js +20 -16
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/index.js +97 -54
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +1 -0
- package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js +5 -5
- package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Headers.js +17 -16
- package/dist/lib/plugins/openapi/playground/Headers.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/ParamsGrid.d.ts +5 -0
- package/dist/lib/plugins/openapi/playground/ParamsGrid.js +4 -0
- package/dist/lib/plugins/openapi/playground/ParamsGrid.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/PathParams.js +4 -12
- package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.d.ts +13 -0
- package/dist/lib/plugins/openapi/playground/Playground.js +25 -45
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js +1 -1
- package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/QueryParams.js +4 -3
- package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/SubmitButton.d.ts +7 -0
- package/dist/lib/plugins/openapi/playground/SubmitButton.js +22 -0
- package/dist/lib/plugins/openapi/playground/SubmitButton.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.d.ts +7 -0
- package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js +11 -0
- package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.d.ts +8 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +95 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.d.ts +7 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js +16 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.d.ts +10 -0
- package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.js +32 -0
- package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.d.ts +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.js +56 -0
- package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.js.map +1 -0
- package/dist/lib/plugins/openapi/schema/{SchemaComponents.js → SchemaPropertyItem.js} +10 -8
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js.map +1 -0
- package/dist/lib/plugins/openapi/schema/SchemaView.js +1 -1
- package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
- package/dist/lib/plugins/openapi/schema/utils.d.ts +1 -0
- package/dist/lib/plugins/openapi/schema/utils.js +2 -0
- package/dist/lib/plugins/openapi/schema/utils.js.map +1 -1
- package/dist/lib/ui/Command.js +1 -1
- package/dist/lib/ui/Command.js.map +1 -1
- package/dist/lib/ui/Select.js +2 -2
- package/dist/lib/ui/Select.js.map +1 -1
- package/dist/lib/util/joinUrl.js +1 -1
- package/dist/lib/util/joinUrl.js.map +1 -1
- package/dist/lib/util/joinUrl.test.d.ts +1 -0
- package/dist/lib/util/joinUrl.test.js +43 -0
- package/dist/lib/util/joinUrl.test.js.map +1 -0
- package/dist/vite/plugin-api.js +9 -1
- package/dist/vite/plugin-api.js.map +1 -1
- package/dist/vite/prerender.js +0 -1
- package/dist/vite/prerender.js.map +1 -1
- package/lib/{AuthenticationPlugin-CvwlQWjV.js → AuthenticationPlugin-Du8cLBSr.js} +2 -2
- package/lib/{AuthenticationPlugin-CvwlQWjV.js.map → AuthenticationPlugin-Du8cLBSr.js.map} +1 -1
- package/lib/{Markdown-B8o9Qz4q.js → Markdown-Cyrx_JrO.js} +8 -9
- package/lib/{Markdown-B8o9Qz4q.js.map → Markdown-Cyrx_JrO.js.map} +1 -1
- package/lib/{MdxPage-DiWukCrZ.js → MdxPage-BuG8Tuwc.js} +5 -5
- package/lib/{MdxPage-DiWukCrZ.js.map → MdxPage-BuG8Tuwc.js.map} +1 -1
- package/lib/OpenApiRoute-UrC_t0e5.js +36 -0
- package/lib/OpenApiRoute-UrC_t0e5.js.map +1 -0
- package/lib/{OperationList-CyNwMHMV.js → OperationList-CDt1xdc4.js} +1925 -1902
- package/lib/OperationList-CDt1xdc4.js.map +1 -0
- package/lib/{Select-4kIgJ1bc.js → Select-CnCZ4WhS.js} +61 -61
- package/lib/Select-CnCZ4WhS.js.map +1 -0
- package/lib/{SlotletProvider-CtIp8rP3.js → SlotletProvider-mQiPDQIH.js} +2 -2
- package/lib/{SlotletProvider-CtIp8rP3.js.map → SlotletProvider-mQiPDQIH.js.map} +1 -1
- package/lib/{SyntaxHighlight-C1w1QPdY.js → SyntaxHighlight-B0L4SC_N.js} +11 -5
- package/lib/SyntaxHighlight-B0L4SC_N.js.map +1 -0
- package/lib/{ZudokuContext-Bp2uQx1d.js → ZudokuContext-BTUJPpQl.js} +36 -35
- package/lib/{ZudokuContext-Bp2uQx1d.js.map → ZudokuContext-BTUJPpQl.js.map} +1 -1
- package/lib/{circular-Dgpd6AN-.js → circular-DxaIIlWD.js} +251 -239
- package/lib/{circular-Dgpd6AN-.js.map → circular-DxaIIlWD.js.map} +1 -1
- package/lib/{createServer-BV0tHzLK.js → createServer-CjNktZzL.js} +821 -808
- package/lib/{createServer-BV0tHzLK.js.map → createServer-CjNktZzL.js.map} +1 -1
- package/lib/{hook-BDmay56y.js → hook-FT3SJLe_.js} +2 -2
- package/lib/{hook-BDmay56y.js.map → hook-FT3SJLe_.js.map} +1 -1
- package/lib/{index-LNp6rxyU.js → index-CjJS0l4l.js} +2 -2
- package/lib/{index-LNp6rxyU.js.map → index-CjJS0l4l.js.map} +1 -1
- package/lib/index-Eb1oiHbM.js +1997 -0
- package/lib/index-Eb1oiHbM.js.map +1 -0
- package/lib/{joinUrl-BTy9bvoK.js → joinUrl-nLx9pD-Z.js} +2 -2
- package/lib/joinUrl-nLx9pD-Z.js.map +1 -0
- package/lib/ui/Command.js +27 -27
- package/lib/ui/Command.js.map +1 -1
- package/lib/ui/Select.js +2 -2
- package/lib/ui/Select.js.map +1 -1
- package/lib/{useScrollToAnchor-S-NbG5Za.js → useScrollToAnchor-BZsGmBng.js} +86 -90
- package/lib/useScrollToAnchor-BZsGmBng.js.map +1 -0
- package/lib/zudoku.auth-clerk.js +1 -1
- package/lib/zudoku.auth-openid.js +3 -3
- package/lib/zudoku.components.js +364 -348
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +3 -3
- package/lib/zudoku.plugin-api-keys.js +4 -4
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +6 -5
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/package.json +1 -1
- package/src/app/main.tsx +1 -2
- package/src/lib/components/PathRenderer.tsx +59 -0
- package/src/lib/components/ThemeSwitch.tsx +15 -14
- package/src/lib/components/index.ts +7 -5
- package/src/lib/components/navigation/SidebarCategory.tsx +44 -41
- package/src/lib/oas/graphql/circular.ts +27 -6
- package/src/lib/oas/graphql/index.ts +63 -35
- package/src/lib/plugins/openapi/ColorizedParam.tsx +3 -3
- package/src/lib/plugins/openapi/Endpoint.tsx +2 -2
- package/src/lib/plugins/openapi/{Route.tsx → OpenApiRoute.tsx} +3 -3
- package/src/lib/plugins/openapi/OperationList.tsx +34 -12
- package/src/lib/plugins/openapi/OperationListItem.tsx +6 -1
- package/src/lib/plugins/openapi/ParameterListItem.tsx +2 -1
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +2 -0
- package/src/lib/plugins/openapi/Sidecar.tsx +18 -27
- package/src/lib/plugins/openapi/SidecarExamples.tsx +24 -24
- package/src/lib/plugins/openapi/graphql/gql.ts +12 -4
- package/src/lib/plugins/openapi/graphql/graphql.ts +66 -43
- package/src/lib/plugins/openapi/index.tsx +125 -67
- package/src/lib/plugins/openapi/interfaces.ts +1 -0
- package/src/lib/plugins/openapi/playground/ExamplesDropdown.tsx +30 -27
- package/src/lib/plugins/openapi/playground/Headers.tsx +65 -65
- package/src/lib/plugins/openapi/playground/ParamsGrid.tsx +8 -0
- package/src/lib/plugins/openapi/playground/PathParams.tsx +34 -74
- package/src/lib/plugins/openapi/playground/Playground.tsx +86 -148
- package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +1 -1
- package/src/lib/plugins/openapi/playground/QueryParams.tsx +46 -45
- package/src/lib/plugins/openapi/playground/SubmitButton.tsx +75 -0
- package/src/lib/plugins/openapi/playground/result-panel/RequestTab.tsx +73 -0
- package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +210 -0
- package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +101 -0
- package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.test.ts +64 -0
- package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.ts +36 -0
- package/src/lib/plugins/openapi/schema/{SchemaComponents.tsx → SchemaPropertyItem.tsx} +10 -6
- package/src/lib/plugins/openapi/schema/SchemaView.tsx +4 -1
- package/src/lib/plugins/openapi/schema/utils.ts +4 -0
- package/src/lib/ui/Command.tsx +1 -1
- package/src/lib/ui/Select.tsx +1 -1
- package/src/lib/util/joinUrl.test.ts +62 -0
- package/src/lib/util/joinUrl.ts +1 -1
- package/dist/lib/plugins/openapi/Route.js.map +0 -1
- package/dist/lib/plugins/openapi/playground/ResponseTab.d.ts +0 -4
- package/dist/lib/plugins/openapi/playground/ResponseTab.js +0 -42
- package/dist/lib/plugins/openapi/playground/ResponseTab.js.map +0 -1
- package/dist/lib/plugins/openapi/schema/SchemaComponents.js.map +0 -1
- package/lib/OperationList-CyNwMHMV.js.map +0 -1
- package/lib/Route-DH64hIrR.js +0 -35
- package/lib/Route-DH64hIrR.js.map +0 -1
- package/lib/Select-4kIgJ1bc.js.map +0 -1
- package/lib/StaggeredRender-DgsamH_G.js +0 -17
- package/lib/StaggeredRender-DgsamH_G.js.map +0 -1
- package/lib/SyntaxHighlight-C1w1QPdY.js.map +0 -1
- package/lib/index-Bn6Lc9tq.js +0 -9
- package/lib/index-Bn6Lc9tq.js.map +0 -1
- package/lib/index-BtNudmKQ.js +0 -1744
- package/lib/index-BtNudmKQ.js.map +0 -1
- package/lib/joinUrl-BTy9bvoK.js.map +0 -1
- package/lib/useScrollToAnchor-S-NbG5Za.js.map +0 -1
- package/src/lib/plugins/openapi/playground/ResponseTab.tsx +0 -76
- /package/dist/lib/plugins/openapi/schema/{SchemaComponents.d.ts → SchemaPropertyItem.d.ts} +0 -0
|
@@ -3,6 +3,8 @@ import { InfoIcon } from "lucide-react";
|
|
|
3
3
|
import { Fragment, useEffect, useRef, useTransition } from "react";
|
|
4
4
|
import { FormProvider, useForm } from "react-hook-form";
|
|
5
5
|
import { Alert, AlertDescription, AlertTitle } from "zudoku/ui/Alert.js";
|
|
6
|
+
import { PathRenderer } from "../../../components/PathRenderer.js";
|
|
7
|
+
|
|
6
8
|
import { Label } from "zudoku/ui/Label.js";
|
|
7
9
|
import { RadioGroup, RadioGroupItem } from "zudoku/ui/RadioGroup.js";
|
|
8
10
|
import {
|
|
@@ -15,10 +17,7 @@ import {
|
|
|
15
17
|
import { Textarea } from "zudoku/ui/Textarea.js";
|
|
16
18
|
import { useSelectedServerStore } from "../../../authentication/state.js";
|
|
17
19
|
import { useApiIdentities } from "../../../components/context/ZudokuContext.js";
|
|
18
|
-
import {
|
|
19
|
-
import { Button } from "../../../ui/Button.js";
|
|
20
|
-
import { Callout } from "../../../ui/Callout.js";
|
|
21
|
-
import { Card, CardContent, CardHeader, CardTitle } from "../../../ui/Card.js";
|
|
20
|
+
import { Card } from "../../../ui/Card.js";
|
|
22
21
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/Tabs.js";
|
|
23
22
|
import { cn } from "../../../util/cn.js";
|
|
24
23
|
import { ColorizedParam } from "../ColorizedParam.js";
|
|
@@ -28,28 +27,17 @@ import ExamplesDropdown from "./ExamplesDropdown.js";
|
|
|
28
27
|
import { Headers } from "./Headers.js";
|
|
29
28
|
import { PathParams } from "./PathParams.js";
|
|
30
29
|
import { QueryParams } from "./QueryParams.js";
|
|
31
|
-
import {
|
|
30
|
+
import { ResultPanel } from "./result-panel/ResultPanel.js";
|
|
31
|
+
import SubmitButton from "./SubmitButton.js";
|
|
32
32
|
|
|
33
33
|
export const NO_IDENTITY = "__none";
|
|
34
34
|
|
|
35
|
-
const statusCodeMap: Record<number, string> = {
|
|
36
|
-
200: "OK",
|
|
37
|
-
201: "Created",
|
|
38
|
-
202: "Accepted",
|
|
39
|
-
204: "No Content",
|
|
40
|
-
400: "Bad Request",
|
|
41
|
-
401: "Unauthorized",
|
|
42
|
-
403: "Forbidden",
|
|
43
|
-
404: "Not Found",
|
|
44
|
-
405: "Method Not Allowed",
|
|
45
|
-
500: "Internal Server Error",
|
|
46
|
-
};
|
|
47
|
-
|
|
48
35
|
export type Header = {
|
|
49
36
|
name: string;
|
|
50
37
|
defaultValue?: string;
|
|
51
38
|
defaultActive?: boolean;
|
|
52
39
|
};
|
|
40
|
+
|
|
53
41
|
export type QueryParam = {
|
|
54
42
|
name: string;
|
|
55
43
|
defaultValue?: string;
|
|
@@ -81,6 +69,20 @@ export type PlaygroundForm = {
|
|
|
81
69
|
identity?: string;
|
|
82
70
|
};
|
|
83
71
|
|
|
72
|
+
export type PlaygroundResult = {
|
|
73
|
+
status: number;
|
|
74
|
+
headers: Array<[string, string]>;
|
|
75
|
+
size: number;
|
|
76
|
+
body: string;
|
|
77
|
+
time: number;
|
|
78
|
+
request: {
|
|
79
|
+
method: string;
|
|
80
|
+
url: string;
|
|
81
|
+
headers: Array<[string, string]>;
|
|
82
|
+
body?: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
84
86
|
export type PlaygroundContentProps = {
|
|
85
87
|
server: string;
|
|
86
88
|
servers?: string[];
|
|
@@ -158,20 +160,23 @@ export const Playground = ({
|
|
|
158
160
|
}
|
|
159
161
|
}, [setValue, identities.data]);
|
|
160
162
|
|
|
163
|
+
const formRef = useRef<HTMLFormElement>(null);
|
|
164
|
+
|
|
161
165
|
const queryMutation = useMutation({
|
|
162
166
|
mutationFn: async (data: PlaygroundForm) => {
|
|
163
|
-
const requestUrl = createUrl(selectedServer ?? server, url, data);
|
|
164
167
|
const start = performance.now();
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
168
|
+
const request = new Request(
|
|
169
|
+
createUrl(selectedServer ?? server, url, data),
|
|
170
|
+
{
|
|
171
|
+
method: method.toUpperCase(),
|
|
172
|
+
headers: Object.fromEntries(
|
|
173
|
+
data.headers
|
|
174
|
+
.filter((h) => h.name && h.active)
|
|
175
|
+
.map((header) => [header.name, header.value]),
|
|
176
|
+
),
|
|
177
|
+
body: data.body ? data.body : undefined,
|
|
178
|
+
},
|
|
179
|
+
);
|
|
175
180
|
|
|
176
181
|
if (data.identity !== NO_IDENTITY) {
|
|
177
182
|
identities.data
|
|
@@ -187,13 +192,25 @@ export const Playground = ({
|
|
|
187
192
|
|
|
188
193
|
const body = await response.text();
|
|
189
194
|
|
|
195
|
+
const url = new URL(request.url);
|
|
196
|
+
|
|
190
197
|
return {
|
|
191
198
|
status: response.status,
|
|
192
|
-
headers: response.headers,
|
|
199
|
+
headers: Array.from(response.headers.entries()),
|
|
193
200
|
size: body.length,
|
|
194
201
|
body,
|
|
195
202
|
time,
|
|
196
|
-
|
|
203
|
+
request: {
|
|
204
|
+
method: request.method.toUpperCase(),
|
|
205
|
+
url: request.url,
|
|
206
|
+
headers: [
|
|
207
|
+
["Host", url.host],
|
|
208
|
+
["User-Agent", "Zudoku Playground"],
|
|
209
|
+
...Array.from(request.headers.entries()),
|
|
210
|
+
],
|
|
211
|
+
body: data.body ? data.body : undefined,
|
|
212
|
+
},
|
|
213
|
+
} satisfies PlaygroundResult;
|
|
197
214
|
} catch (error) {
|
|
198
215
|
if (error instanceof TypeError) {
|
|
199
216
|
throw new Error(
|
|
@@ -206,38 +223,27 @@ export const Playground = ({
|
|
|
206
223
|
},
|
|
207
224
|
});
|
|
208
225
|
|
|
209
|
-
const path =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
<ColorizedParam
|
|
217
|
-
backgroundOpacity="25%"
|
|
218
|
-
name={part}
|
|
219
|
-
slug={part}
|
|
220
|
-
title={
|
|
221
|
-
!value
|
|
222
|
-
? `Missing value for path parameter \`${replaced}\``
|
|
223
|
-
: undefined
|
|
224
|
-
}
|
|
225
|
-
>
|
|
226
|
-
{value ? encodeURIComponent(value) : part}
|
|
227
|
-
</ColorizedParam>
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
return (
|
|
231
|
-
// eslint-disable-next-line react/no-array-index-key
|
|
232
|
-
<Fragment key={part + i}>
|
|
233
|
-
{isPathParam ? pathParamValue : part}
|
|
234
|
-
{i < arr.length - 1 && "/"}
|
|
235
|
-
<wbr />
|
|
236
|
-
</Fragment>
|
|
237
|
-
);
|
|
238
|
-
});
|
|
226
|
+
const path = (
|
|
227
|
+
<PathRenderer
|
|
228
|
+
path={url}
|
|
229
|
+
renderParam={({ name, originalValue, index }) => {
|
|
230
|
+
const formValue = formState.pathParams.find(
|
|
231
|
+
(param) => param.name === name,
|
|
232
|
+
)?.value;
|
|
239
233
|
|
|
240
|
-
|
|
234
|
+
return (
|
|
235
|
+
<ColorizedParam
|
|
236
|
+
name={name}
|
|
237
|
+
backgroundOpacity="0"
|
|
238
|
+
slug={name}
|
|
239
|
+
onClick={() => form.setFocus(`pathParams.${index}.value`)}
|
|
240
|
+
>
|
|
241
|
+
{formValue || originalValue}
|
|
242
|
+
</ColorizedParam>
|
|
243
|
+
);
|
|
244
|
+
}}
|
|
245
|
+
/>
|
|
246
|
+
);
|
|
241
247
|
|
|
242
248
|
const urlQueryParams = formState.queryParams
|
|
243
249
|
.filter((p) => p.active)
|
|
@@ -254,9 +260,7 @@ export const Playground = ({
|
|
|
254
260
|
{servers && servers.length > 1 ? (
|
|
255
261
|
<Select
|
|
256
262
|
onValueChange={(value) => {
|
|
257
|
-
startTransition(() =>
|
|
258
|
-
setSelectedServer(value);
|
|
259
|
-
});
|
|
263
|
+
startTransition(() => setSelectedServer(value));
|
|
260
264
|
}}
|
|
261
265
|
value={selectedServer}
|
|
262
266
|
defaultValue={selectedServer}
|
|
@@ -282,24 +286,30 @@ export const Playground = ({
|
|
|
282
286
|
<FormProvider
|
|
283
287
|
{...{ register, control, handleSubmit, watch, setValue, ...form }}
|
|
284
288
|
>
|
|
285
|
-
<form
|
|
286
|
-
|
|
289
|
+
<form
|
|
290
|
+
onSubmit={handleSubmit((data) => queryMutation.mutateAsync(data))}
|
|
291
|
+
ref={formRef}
|
|
292
|
+
>
|
|
293
|
+
<div className="grid grid-cols-2 text-sm h-full">
|
|
287
294
|
<div className="flex flex-col gap-4 p-4 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:left-auto">
|
|
288
295
|
<div className="flex gap-2 items-stretch">
|
|
289
296
|
<div className="flex flex-1 items-center w-full border rounded-md">
|
|
290
297
|
<div className="border-r p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono flex items-center">
|
|
291
298
|
{method.toUpperCase()}
|
|
292
299
|
</div>
|
|
293
|
-
<div className="
|
|
300
|
+
<div className="items-center p-2 font-mono text-xs break-words">
|
|
294
301
|
{serverSelect}
|
|
295
302
|
{path}
|
|
296
303
|
{urlQueryParams.length > 0 ? "?" : ""}
|
|
297
304
|
{urlQueryParams}
|
|
298
305
|
</div>
|
|
299
306
|
</div>
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
307
|
+
|
|
308
|
+
<SubmitButton
|
|
309
|
+
identities={identities.data ?? []}
|
|
310
|
+
formRef={formRef}
|
|
311
|
+
disabled={form.formState.isSubmitting}
|
|
312
|
+
/>
|
|
303
313
|
</div>
|
|
304
314
|
<Tabs defaultValue="parameters">
|
|
305
315
|
<div className="flex flex-wrap gap-1 justify-between">
|
|
@@ -438,84 +448,12 @@ export const Playground = ({
|
|
|
438
448
|
</TabsContent>
|
|
439
449
|
</Tabs>
|
|
440
450
|
</div>
|
|
441
|
-
<
|
|
442
|
-
{queryMutation
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
<Callout type="caution">
|
|
446
|
-
Some path parameters are missing values. Please fill them in
|
|
447
|
-
to ensure the request is sent correctly.
|
|
448
|
-
</Callout>
|
|
449
|
-
)}
|
|
450
|
-
<Card>
|
|
451
|
-
<CardHeader>
|
|
452
|
-
<CardTitle>Request failed</CardTitle>
|
|
453
|
-
</CardHeader>
|
|
454
|
-
<CardContent>
|
|
455
|
-
Error:{" "}
|
|
456
|
-
{queryMutation.error.message ||
|
|
457
|
-
String(queryMutation.error) ||
|
|
458
|
-
"Unexpected error"}
|
|
459
|
-
</CardContent>
|
|
460
|
-
</Card>
|
|
461
|
-
</div>
|
|
462
|
-
) : queryMutation.data ? (
|
|
463
|
-
<div className="flex flex-col gap-2">
|
|
464
|
-
<div className="flex gap-2">
|
|
465
|
-
<div className="flex text-xs gap-6">
|
|
466
|
-
<div>
|
|
467
|
-
Status: {queryMutation.data.status}{" "}
|
|
468
|
-
{statusCodeMap[queryMutation.data.status] ?? ""}
|
|
469
|
-
</div>
|
|
470
|
-
<div>Time: {queryMutation.data.time.toFixed(0)}ms</div>
|
|
471
|
-
<div>Size: {queryMutation.data.size} B</div>
|
|
472
|
-
</div>
|
|
473
|
-
</div>
|
|
474
|
-
<Tabs defaultValue="response">
|
|
475
|
-
<TabsList>
|
|
476
|
-
<TabsTrigger value="response">Response</TabsTrigger>
|
|
477
|
-
<TabsTrigger value="headers">
|
|
478
|
-
{headerEntries.length
|
|
479
|
-
? `Headers (${headerEntries.length})`
|
|
480
|
-
: "No headers"}
|
|
481
|
-
</TabsTrigger>
|
|
482
|
-
</TabsList>
|
|
483
|
-
|
|
484
|
-
<TabsContent value="response">
|
|
485
|
-
<ResponseTab
|
|
486
|
-
headers={queryMutation.data.headers}
|
|
487
|
-
body={queryMutation.data.body}
|
|
488
|
-
/>
|
|
489
|
-
</TabsContent>
|
|
490
|
-
<TabsContent value="headers">
|
|
491
|
-
<Card
|
|
492
|
-
// playground dialog has h-5/6 ≈ 83.333vh
|
|
493
|
-
className="max-h-[calc(83.333vh-140px)] overflow-y-auto grid grid-cols-2 w-full gap-2.5 font-mono text-xs shadow-none p-4"
|
|
494
|
-
>
|
|
495
|
-
<div className="font-semibold">Key</div>
|
|
496
|
-
<div className="font-semibold">Value</div>
|
|
497
|
-
{headerEntries.map(([key, value]) => (
|
|
498
|
-
<Fragment key={key}>
|
|
499
|
-
<div>{key}</div>
|
|
500
|
-
<div className="break-words">{value}</div>
|
|
501
|
-
</Fragment>
|
|
502
|
-
))}
|
|
503
|
-
</Card>
|
|
504
|
-
</TabsContent>
|
|
505
|
-
</Tabs>
|
|
506
|
-
</div>
|
|
507
|
-
) : (
|
|
508
|
-
<div className="grid place-items-center h-full">
|
|
509
|
-
<span className="text-[16px] font-semibold text-muted-foreground">
|
|
510
|
-
{queryMutation.isPending ? (
|
|
511
|
-
<Spinner />
|
|
512
|
-
) : (
|
|
513
|
-
"Send a request first to see the response here"
|
|
514
|
-
)}
|
|
515
|
-
</span>
|
|
516
|
-
</div>
|
|
451
|
+
<ResultPanel
|
|
452
|
+
queryMutation={queryMutation}
|
|
453
|
+
showPathParamsWarning={formState.pathParams.some(
|
|
454
|
+
(p) => p.value === "",
|
|
517
455
|
)}
|
|
518
|
-
|
|
456
|
+
/>
|
|
519
457
|
</div>
|
|
520
458
|
</form>
|
|
521
459
|
</FormProvider>
|
|
@@ -47,7 +47,7 @@ const PlaygroundDialog = (props: PlaygroundDialogProps) => {
|
|
|
47
47
|
</DialogTrigger>
|
|
48
48
|
|
|
49
49
|
<DialogContent
|
|
50
|
-
className="max-w-screen-xl w-full h-5/6 overflow-
|
|
50
|
+
className="max-w-screen-xl w-full h-5/6 overflow-hidden p-0"
|
|
51
51
|
aria-describedby={undefined}
|
|
52
52
|
>
|
|
53
53
|
<VisuallyHidden>
|
|
@@ -9,6 +9,7 @@ import { Checkbox } from "zudoku/ui/Checkbox.js";
|
|
|
9
9
|
import { Autocomplete } from "../../../components/Autocomplete.js";
|
|
10
10
|
import { Input } from "../../../ui/Input.js";
|
|
11
11
|
import { InlineInput } from "./InlineInput.js";
|
|
12
|
+
import ParamsGrid from "./ParamsGrid.js";
|
|
12
13
|
import { type PlaygroundForm, type QueryParam } from "./Playground.js";
|
|
13
14
|
|
|
14
15
|
export const QueryParams = ({
|
|
@@ -34,51 +35,51 @@ export const QueryParams = ({
|
|
|
34
35
|
(param) => param.name === field.name,
|
|
35
36
|
);
|
|
36
37
|
return (
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
checked={field.value}
|
|
50
|
-
onCheckedChange={field.onChange}
|
|
51
|
-
/>
|
|
52
|
-
)}
|
|
53
|
-
/>
|
|
54
|
-
<Controller
|
|
55
|
-
control={control}
|
|
56
|
-
render={({ field }) =>
|
|
57
|
-
!requiredFields[i] ? (
|
|
58
|
-
<Autocomplete
|
|
59
|
-
value={field.value}
|
|
60
|
-
options={queryParams.map((param) => param.name)}
|
|
61
|
-
onChange={(e) => {
|
|
62
|
-
field.onChange(e);
|
|
63
|
-
}}
|
|
64
|
-
className="border-0 font-mono text-xs bg-transparent hover:bg-transparent"
|
|
38
|
+
<ParamsGrid key={field.id}>
|
|
39
|
+
<div className="flex items-center">
|
|
40
|
+
<Controller
|
|
41
|
+
control={control}
|
|
42
|
+
name={`queryParams.${i}.active`}
|
|
43
|
+
render={({ field }) => (
|
|
44
|
+
<Checkbox
|
|
45
|
+
variant="outline"
|
|
46
|
+
id={`queryParams.${i}.active`}
|
|
47
|
+
className="mr-2"
|
|
48
|
+
checked={field.value}
|
|
49
|
+
onCheckedChange={field.onChange}
|
|
65
50
|
/>
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
{field.value}
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
51
|
+
)}
|
|
52
|
+
/>
|
|
53
|
+
<Controller
|
|
54
|
+
control={control}
|
|
55
|
+
render={({ field }) =>
|
|
56
|
+
!requiredFields[i] ? (
|
|
57
|
+
<Autocomplete
|
|
58
|
+
value={field.value}
|
|
59
|
+
options={queryParams.map((param) => param.name)}
|
|
60
|
+
onChange={(e) => {
|
|
61
|
+
field.onChange(e);
|
|
62
|
+
}}
|
|
63
|
+
className="border-0 font-mono text-xs bg-transparent hover:bg-transparent"
|
|
64
|
+
/>
|
|
65
|
+
) : (
|
|
66
|
+
<InlineInput asChild>
|
|
67
|
+
<label
|
|
68
|
+
className="flex items-center cursor-pointer gap-1"
|
|
69
|
+
htmlFor={`queryParams.${i}.active`}
|
|
70
|
+
title={
|
|
71
|
+
requiredFields[i] ? "Required field" : undefined
|
|
72
|
+
}
|
|
73
|
+
>
|
|
74
|
+
{field.value}
|
|
75
|
+
{requiredFields[i] && <sup> *</sup>}
|
|
76
|
+
</label>
|
|
77
|
+
</InlineInput>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
name={`queryParams.${i}.name`}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
82
83
|
<div className="flex justify-between items-center">
|
|
83
84
|
<Controller
|
|
84
85
|
control={control}
|
|
@@ -117,7 +118,7 @@ export const QueryParams = ({
|
|
|
117
118
|
name={`queryParams.${i}.value`}
|
|
118
119
|
/>
|
|
119
120
|
</div>
|
|
120
|
-
</
|
|
121
|
+
</ParamsGrid>
|
|
121
122
|
);
|
|
122
123
|
})}
|
|
123
124
|
</div>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { useFormContext } from "react-hook-form";
|
|
4
|
+
import { Button } from "zudoku/ui/Button.js";
|
|
5
|
+
import {
|
|
6
|
+
DropdownMenu,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuItem,
|
|
9
|
+
DropdownMenuTrigger,
|
|
10
|
+
} from "zudoku/ui/DropdownMenu.js";
|
|
11
|
+
import { RadioGroup, RadioGroupItem } from "zudoku/ui/RadioGroup.js";
|
|
12
|
+
import { ApiIdentity } from "../../../core/ZudokuContext.js";
|
|
13
|
+
import { NO_IDENTITY } from "./Playground.js";
|
|
14
|
+
|
|
15
|
+
const SubmitButton = ({
|
|
16
|
+
identities,
|
|
17
|
+
formRef,
|
|
18
|
+
disabled,
|
|
19
|
+
}: {
|
|
20
|
+
identities: ApiIdentity[];
|
|
21
|
+
formRef?: React.RefObject<HTMLFormElement | null>;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}) => {
|
|
24
|
+
const { setValue } = useFormContext();
|
|
25
|
+
const [dropdownValue, setDropdownValue] = useState<string | undefined>();
|
|
26
|
+
if (identities.length === 0) {
|
|
27
|
+
return <Button disabled={disabled}>Send</Button>;
|
|
28
|
+
}
|
|
29
|
+
return (
|
|
30
|
+
<div className="flex">
|
|
31
|
+
<Button
|
|
32
|
+
className="rounded-r-none inset-shadow-sm"
|
|
33
|
+
disabled={disabled}
|
|
34
|
+
onClick={() => formRef?.current?.requestSubmit()}
|
|
35
|
+
>
|
|
36
|
+
Send
|
|
37
|
+
</Button>
|
|
38
|
+
<DropdownMenu>
|
|
39
|
+
<DropdownMenuTrigger asChild>
|
|
40
|
+
<Button
|
|
41
|
+
disabled={disabled}
|
|
42
|
+
className="rounded-l-none border-l border-border/40 inset-shadow-sm w-6"
|
|
43
|
+
size="icon"
|
|
44
|
+
>
|
|
45
|
+
<ChevronDownIcon className="w-4 h-4" />
|
|
46
|
+
</Button>
|
|
47
|
+
</DropdownMenuTrigger>
|
|
48
|
+
<RadioGroup value={dropdownValue}>
|
|
49
|
+
<DropdownMenuContent className="w-56" align="end" alignOffset={-150}>
|
|
50
|
+
{[{ id: NO_IDENTITY, label: "None" }, ...identities].map(
|
|
51
|
+
(identity) => (
|
|
52
|
+
<DropdownMenuItem
|
|
53
|
+
key={identity.id}
|
|
54
|
+
onClick={() => {
|
|
55
|
+
setDropdownValue(identity.id);
|
|
56
|
+
setValue("identity", identity.id);
|
|
57
|
+
formRef?.current?.requestSubmit();
|
|
58
|
+
}}
|
|
59
|
+
onMouseEnter={() => setDropdownValue(identity.id)}
|
|
60
|
+
onMouseLeave={() => setDropdownValue(undefined)}
|
|
61
|
+
>
|
|
62
|
+
<RadioGroupItem value={identity.id} className="mr-2" />
|
|
63
|
+
|
|
64
|
+
{identity.label}
|
|
65
|
+
</DropdownMenuItem>
|
|
66
|
+
),
|
|
67
|
+
)}
|
|
68
|
+
</DropdownMenuContent>
|
|
69
|
+
</RadioGroup>
|
|
70
|
+
</DropdownMenu>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default SubmitButton;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ChevronRightIcon } from "lucide-react";
|
|
2
|
+
import { Fragment } from "react";
|
|
3
|
+
import {
|
|
4
|
+
Collapsible,
|
|
5
|
+
CollapsibleContent,
|
|
6
|
+
CollapsibleTrigger,
|
|
7
|
+
} from "../../../../ui/Collapsible.js";
|
|
8
|
+
import { cn } from "../../../../util/cn.js";
|
|
9
|
+
import { methodForColor } from "../../util/methodToColor.js";
|
|
10
|
+
|
|
11
|
+
export const RequestTab = ({
|
|
12
|
+
method,
|
|
13
|
+
url,
|
|
14
|
+
headers,
|
|
15
|
+
body,
|
|
16
|
+
}: {
|
|
17
|
+
method: string;
|
|
18
|
+
url: string;
|
|
19
|
+
headers: Array<[string, string]>;
|
|
20
|
+
body?: string;
|
|
21
|
+
}) => {
|
|
22
|
+
return (
|
|
23
|
+
<div className="flex flex-col gap-2 font-mono text-xs">
|
|
24
|
+
<div className="gap-2 p-2 bg-muted rounded-md">
|
|
25
|
+
<span className={cn(methodForColor(method), "font-semibold")}>
|
|
26
|
+
{method}
|
|
27
|
+
</span>
|
|
28
|
+
|
|
29
|
+
<span className="break-all">{url}</span>
|
|
30
|
+
<span className="text-muted-foreground">HTTP/1.1</span>
|
|
31
|
+
</div>
|
|
32
|
+
<div className="mx-1.5 flex flex-col gap-3">
|
|
33
|
+
<Collapsible defaultOpen>
|
|
34
|
+
<CollapsibleTrigger className="flex items-center gap-2 hover:text-primary group">
|
|
35
|
+
<ChevronRightIcon className="h-4 w-4 transition-transform duration-200 group-data-[state=open]:rotate-[90deg]" />
|
|
36
|
+
<span className="font-semibold">Headers</span>
|
|
37
|
+
</CollapsibleTrigger>
|
|
38
|
+
<CollapsibleContent>
|
|
39
|
+
<div className="grid grid-cols-[auto,1fr] gap-x-8 gap-y-1 pl-1.5 pt-2">
|
|
40
|
+
{headers.map(([key, value]) => (
|
|
41
|
+
<Fragment key={key}>
|
|
42
|
+
<div className="text-primary">{key}</div>
|
|
43
|
+
<div className="break-words">{value}</div>
|
|
44
|
+
</Fragment>
|
|
45
|
+
))}
|
|
46
|
+
</div>
|
|
47
|
+
</CollapsibleContent>
|
|
48
|
+
</Collapsible>
|
|
49
|
+
|
|
50
|
+
<Collapsible defaultOpen>
|
|
51
|
+
<CollapsibleTrigger className="flex items-center gap-2 hover:text-primary group">
|
|
52
|
+
<ChevronRightIcon className="h-4 w-4 transition-transform duration-200 group-data-[state=open]:rotate-[90deg]" />
|
|
53
|
+
<span className="font-semibold">Body</span>
|
|
54
|
+
</CollapsibleTrigger>
|
|
55
|
+
<CollapsibleContent>
|
|
56
|
+
<div className="pl-0 pt-2">
|
|
57
|
+
<div
|
|
58
|
+
className={cn(
|
|
59
|
+
"whitespace-pre-wrap break-all bg-muted p-2 rounded-md",
|
|
60
|
+
!body && "text-muted-foreground",
|
|
61
|
+
)}
|
|
62
|
+
>
|
|
63
|
+
{body ?? "Empty body"}
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</CollapsibleContent>
|
|
67
|
+
</Collapsible>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default RequestTab;
|