zudoku 0.26.1 → 0.27.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/dist/app/main.d.ts +1 -1
- package/dist/app/main.js +19 -7
- package/dist/app/main.js.map +1 -1
- package/dist/config/loader.js +1 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
- package/dist/config/validators/common.d.ts +67 -0
- package/dist/config/validators/common.js +5 -0
- package/dist/config/validators/common.js.map +1 -1
- package/dist/config/validators/validate.d.ts +29 -0
- package/dist/lib/components/AnchorLink.js +5 -2
- package/dist/lib/components/AnchorLink.js.map +1 -1
- package/dist/lib/components/Header.js +1 -1
- package/dist/lib/components/Header.js.map +1 -1
- package/dist/lib/components/Heading.d.ts +1 -1
- package/dist/lib/components/Markdown.d.ts +2 -2
- package/dist/lib/components/Markdown.js +3 -1
- package/dist/lib/components/Markdown.js.map +1 -1
- package/dist/lib/components/StatusPage.d.ts +7 -0
- package/dist/lib/components/StatusPage.js +71 -0
- package/dist/lib/components/StatusPage.js.map +1 -0
- package/dist/lib/components/SyntaxHighlight.d.ts +2 -1
- package/dist/lib/components/SyntaxHighlight.js +2 -2
- package/dist/lib/components/SyntaxHighlight.js.map +1 -1
- package/dist/lib/components/ThemeSwitch.js +4 -4
- package/dist/lib/components/ThemeSwitch.js.map +1 -1
- package/dist/lib/components/cache.d.ts +6 -0
- package/dist/lib/components/cache.js +13 -0
- package/dist/lib/components/cache.js.map +1 -0
- package/dist/lib/components/context/ViewportAnchorContext.js +16 -4
- package/dist/lib/components/context/ViewportAnchorContext.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.js +2 -1
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/index.d.ts +9 -2
- package/dist/lib/components/index.js +3 -0
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/core/RouteGuard.d.ts +1 -0
- package/dist/lib/core/RouteGuard.js +28 -0
- package/dist/lib/core/RouteGuard.js.map +1 -0
- package/dist/lib/core/ZudokuContext.d.ts +4 -2
- package/dist/lib/core/ZudokuContext.js +9 -7
- package/dist/lib/core/ZudokuContext.js.map +1 -1
- package/dist/lib/oas/graphql/circular.d.ts +3 -0
- package/dist/lib/oas/graphql/circular.js +27 -0
- package/dist/lib/oas/graphql/circular.js.map +1 -0
- package/dist/lib/oas/graphql/index.js +5 -6
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/oas/parser/dereference/index.d.ts +0 -1
- package/dist/lib/oas/parser/dereference/index.js +1 -1
- package/dist/lib/oas/parser/dereference/index.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 +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +2 -2
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/index.js +4 -11
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +7 -2
- 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 +19 -31
- 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 +1 -1
- package/dist/lib/plugins/openapi/schema/SchemaComponents.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/MdxComponents.js +2 -2
- package/dist/lib/util/MdxComponents.js.map +1 -1
- package/dist/lib/util/useScrollToAnchor.d.ts +1 -0
- package/dist/lib/util/useScrollToAnchor.js +26 -15
- package/dist/lib/util/useScrollToAnchor.js.map +1 -1
- package/dist/vite/plugin-api.js +9 -3
- package/dist/vite/plugin-api.js.map +1 -1
- package/dist/vite/prerender.js +1 -0
- package/dist/vite/prerender.js.map +1 -1
- package/dist/zuplo/enrich-with-zuplo.js +1 -1
- package/dist/zuplo/enrich-with-zuplo.js.map +1 -1
- package/dist/zuplo/with-zuplo.d.ts +2 -1
- package/dist/zuplo/with-zuplo.js +3 -1
- package/dist/zuplo/with-zuplo.js.map +1 -1
- package/lib/{AuthenticationPlugin-C9SwOxkc.js → AuthenticationPlugin-CO_YCd2x.js} +3 -3
- package/lib/{AuthenticationPlugin-C9SwOxkc.js.map → AuthenticationPlugin-CO_YCd2x.js.map} +1 -1
- package/lib/{Markdown-DFN6p0J-.js → Markdown-B8o9Qz4q.js} +1197 -1186
- package/lib/{Markdown-DFN6p0J-.js.map → Markdown-B8o9Qz4q.js.map} +1 -1
- package/lib/{MdxPage-D9c4z09Q.js → MdxPage-BxRt3Ly7.js} +5 -5
- package/lib/{MdxPage-D9c4z09Q.js.map → MdxPage-BxRt3Ly7.js.map} +1 -1
- package/lib/OperationList-DH-zIgtq.js +5160 -0
- package/lib/OperationList-DH-zIgtq.js.map +1 -0
- package/lib/{Route-VdmEyOD0.js → Route-DJ0ZlVq1.js} +3 -3
- package/lib/{Route-VdmEyOD0.js.map → Route-DJ0ZlVq1.js.map} +1 -1
- package/lib/{Select-D3O7wISy.js → Select-B7UXR0SB.js} +61 -61
- package/lib/Select-B7UXR0SB.js.map +1 -0
- package/lib/{SlotletProvider-_3zzX_g_.js → SlotletProvider-CtIp8rP3.js} +4 -4
- package/lib/{SlotletProvider-_3zzX_g_.js.map → SlotletProvider-CtIp8rP3.js.map} +1 -1
- package/lib/{SyntaxHighlight-CJCSPG1F.js → SyntaxHighlight-C1w1QPdY.js} +300 -295
- package/lib/{SyntaxHighlight-CJCSPG1F.js.map → SyntaxHighlight-C1w1QPdY.js.map} +1 -1
- package/lib/{ZudokuContext-DeQZEp-x.js → ZudokuContext-8jts0fF3.js} +259 -248
- package/lib/ZudokuContext-8jts0fF3.js.map +1 -0
- package/lib/{chunk-SYFQ2XB5-BF5IDYrB.js → chunk-SYFQ2XB5-BPvC-soB.js} +5 -5
- package/lib/{chunk-SYFQ2XB5-BF5IDYrB.js.map → chunk-SYFQ2XB5-BPvC-soB.js.map} +1 -1
- package/lib/circular-Dgpd6AN-.js +15397 -0
- package/lib/circular-Dgpd6AN-.js.map +1 -0
- package/lib/{createServer-BcaswoFO.js → createServer-BV0tHzLK.js} +3450 -5577
- package/lib/createServer-BV0tHzLK.js.map +1 -0
- package/lib/{hook-BRQEDRbn.js → hook-BG02esyv.js} +2 -2
- package/lib/{hook-BRQEDRbn.js.map → hook-BG02esyv.js.map} +1 -1
- package/lib/index-DmqsUPcm.js +1915 -0
- package/lib/index-DmqsUPcm.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/{useExposedProps-CetwhZpP.js → useExposedProps-BLKFBylA.js} +2 -2
- package/lib/{useExposedProps-CetwhZpP.js.map → useExposedProps-BLKFBylA.js.map} +1 -1
- package/lib/useScrollToAnchor-Bl6mz9_x.js +288 -0
- package/lib/useScrollToAnchor-Bl6mz9_x.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 +753 -991
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +3 -3
- package/lib/zudoku.plugin-api-keys.js +5 -5
- package/lib/zudoku.plugin-custom-pages.js +2 -2
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +4 -4
- package/lib/zudoku.plugin-redirect.js +1 -1
- package/package.json +2 -2
- package/src/app/main.tsx +26 -7
- package/src/lib/components/AnchorLink.tsx +5 -2
- package/src/lib/components/Header.tsx +1 -1
- package/src/lib/components/Markdown.tsx +14 -15
- package/src/lib/components/StatusPage.tsx +91 -0
- package/src/lib/components/SyntaxHighlight.tsx +14 -0
- package/src/lib/components/ThemeSwitch.tsx +14 -15
- package/src/lib/components/cache.ts +15 -0
- package/src/lib/components/context/ViewportAnchorContext.tsx +20 -6
- package/src/lib/components/context/ZudokuContext.ts +3 -1
- package/src/lib/components/index.ts +7 -0
- package/src/lib/core/RouteGuard.tsx +35 -0
- package/src/lib/core/ZudokuContext.ts +9 -8
- package/src/lib/oas/graphql/circular.ts +29 -0
- package/src/lib/oas/graphql/index.ts +9 -9
- package/src/lib/oas/parser/dereference/index.ts +1 -2
- package/src/lib/plugins/openapi/OperationListItem.tsx +0 -2
- package/src/lib/plugins/openapi/ParameterListItem.tsx +1 -0
- package/src/lib/plugins/openapi/Sidecar.tsx +3 -2
- package/src/lib/plugins/openapi/index.tsx +9 -15
- package/src/lib/plugins/openapi/interfaces.ts +10 -2
- 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 +64 -116
- 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 +1 -1
- package/src/lib/ui/Command.tsx +1 -1
- package/src/lib/ui/Select.tsx +1 -1
- package/src/lib/util/MdxComponents.tsx +2 -1
- package/src/lib/util/useScrollToAnchor.ts +32 -15
- 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/lib/AnchorLink-bObQitZv.js +0 -34
- package/lib/AnchorLink-bObQitZv.js.map +0 -1
- package/lib/OperationList-DGJWDx1G.js +0 -5148
- package/lib/OperationList-DGJWDx1G.js.map +0 -1
- package/lib/Select-D3O7wISy.js.map +0 -1
- package/lib/ZudokuContext-DeQZEp-x.js.map +0 -1
- package/lib/createServer-BcaswoFO.js.map +0 -1
- package/lib/index-CXRrqOIl.js +0 -1750
- package/lib/index-CXRrqOIl.js.map +0 -1
- package/lib/index-TaRXY2w1.js +0 -43
- package/lib/index-TaRXY2w1.js.map +0 -1
- package/src/lib/plugins/openapi/playground/ResponseTab.tsx +0 -76
|
@@ -3,6 +3,7 @@ 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
|
+
|
|
6
7
|
import { Label } from "zudoku/ui/Label.js";
|
|
7
8
|
import { RadioGroup, RadioGroupItem } from "zudoku/ui/RadioGroup.js";
|
|
8
9
|
import {
|
|
@@ -15,10 +16,7 @@ import {
|
|
|
15
16
|
import { Textarea } from "zudoku/ui/Textarea.js";
|
|
16
17
|
import { useSelectedServerStore } from "../../../authentication/state.js";
|
|
17
18
|
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";
|
|
19
|
+
import { Card } from "../../../ui/Card.js";
|
|
22
20
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/Tabs.js";
|
|
23
21
|
import { cn } from "../../../util/cn.js";
|
|
24
22
|
import { ColorizedParam } from "../ColorizedParam.js";
|
|
@@ -28,28 +26,17 @@ import ExamplesDropdown from "./ExamplesDropdown.js";
|
|
|
28
26
|
import { Headers } from "./Headers.js";
|
|
29
27
|
import { PathParams } from "./PathParams.js";
|
|
30
28
|
import { QueryParams } from "./QueryParams.js";
|
|
31
|
-
import {
|
|
29
|
+
import { ResultPanel } from "./result-panel/ResultPanel.js";
|
|
30
|
+
import SubmitButton from "./SubmitButton.js";
|
|
32
31
|
|
|
33
32
|
export const NO_IDENTITY = "__none";
|
|
34
33
|
|
|
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
34
|
export type Header = {
|
|
49
35
|
name: string;
|
|
50
36
|
defaultValue?: string;
|
|
51
37
|
defaultActive?: boolean;
|
|
52
38
|
};
|
|
39
|
+
|
|
53
40
|
export type QueryParam = {
|
|
54
41
|
name: string;
|
|
55
42
|
defaultValue?: string;
|
|
@@ -81,6 +68,20 @@ export type PlaygroundForm = {
|
|
|
81
68
|
identity?: string;
|
|
82
69
|
};
|
|
83
70
|
|
|
71
|
+
export type PlaygroundResult = {
|
|
72
|
+
status: number;
|
|
73
|
+
headers: Array<[string, string]>;
|
|
74
|
+
size: number;
|
|
75
|
+
body: string;
|
|
76
|
+
time: number;
|
|
77
|
+
request: {
|
|
78
|
+
method: string;
|
|
79
|
+
url: string;
|
|
80
|
+
headers: Array<[string, string]>;
|
|
81
|
+
body?: string;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
|
|
84
85
|
export type PlaygroundContentProps = {
|
|
85
86
|
server: string;
|
|
86
87
|
servers?: string[];
|
|
@@ -158,20 +159,23 @@ export const Playground = ({
|
|
|
158
159
|
}
|
|
159
160
|
}, [setValue, identities.data]);
|
|
160
161
|
|
|
162
|
+
const formRef = useRef<HTMLFormElement>(null);
|
|
163
|
+
|
|
161
164
|
const queryMutation = useMutation({
|
|
162
165
|
mutationFn: async (data: PlaygroundForm) => {
|
|
163
|
-
const requestUrl = createUrl(selectedServer ?? server, url, data);
|
|
164
166
|
const start = performance.now();
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
167
|
+
const request = new Request(
|
|
168
|
+
createUrl(selectedServer ?? server, url, data),
|
|
169
|
+
{
|
|
170
|
+
method: method.toUpperCase(),
|
|
171
|
+
headers: Object.fromEntries(
|
|
172
|
+
data.headers
|
|
173
|
+
.filter((h) => h.name && h.active)
|
|
174
|
+
.map((header) => [header.name, header.value]),
|
|
175
|
+
),
|
|
176
|
+
body: data.body ? data.body : undefined,
|
|
177
|
+
},
|
|
178
|
+
);
|
|
175
179
|
|
|
176
180
|
if (data.identity !== NO_IDENTITY) {
|
|
177
181
|
identities.data
|
|
@@ -187,13 +191,25 @@ export const Playground = ({
|
|
|
187
191
|
|
|
188
192
|
const body = await response.text();
|
|
189
193
|
|
|
194
|
+
const url = new URL(request.url);
|
|
195
|
+
|
|
190
196
|
return {
|
|
191
197
|
status: response.status,
|
|
192
|
-
headers: response.headers,
|
|
198
|
+
headers: Array.from(response.headers.entries()),
|
|
193
199
|
size: body.length,
|
|
194
200
|
body,
|
|
195
201
|
time,
|
|
196
|
-
|
|
202
|
+
request: {
|
|
203
|
+
method: request.method.toUpperCase(),
|
|
204
|
+
url: request.url,
|
|
205
|
+
headers: [
|
|
206
|
+
["Host", url.host],
|
|
207
|
+
["User-Agent", "Zudoku Playground"],
|
|
208
|
+
...Array.from(request.headers.entries()),
|
|
209
|
+
],
|
|
210
|
+
body: data.body ? data.body : undefined,
|
|
211
|
+
},
|
|
212
|
+
} satisfies PlaygroundResult;
|
|
197
213
|
} catch (error) {
|
|
198
214
|
if (error instanceof TypeError) {
|
|
199
215
|
throw new Error(
|
|
@@ -237,8 +253,6 @@ export const Playground = ({
|
|
|
237
253
|
);
|
|
238
254
|
});
|
|
239
255
|
|
|
240
|
-
const headerEntries = Array.from(queryMutation.data?.headers.entries() ?? []);
|
|
241
|
-
|
|
242
256
|
const urlQueryParams = formState.queryParams
|
|
243
257
|
.filter((p) => p.active)
|
|
244
258
|
.map((p, i, arr) => (
|
|
@@ -282,24 +296,30 @@ export const Playground = ({
|
|
|
282
296
|
<FormProvider
|
|
283
297
|
{...{ register, control, handleSubmit, watch, setValue, ...form }}
|
|
284
298
|
>
|
|
285
|
-
<form
|
|
286
|
-
|
|
299
|
+
<form
|
|
300
|
+
onSubmit={handleSubmit((data) => queryMutation.mutateAsync(data))}
|
|
301
|
+
ref={formRef}
|
|
302
|
+
>
|
|
303
|
+
<div className="grid grid-cols-2 text-sm h-full">
|
|
287
304
|
<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
305
|
<div className="flex gap-2 items-stretch">
|
|
289
306
|
<div className="flex flex-1 items-center w-full border rounded-md">
|
|
290
307
|
<div className="border-r p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono flex items-center">
|
|
291
308
|
{method.toUpperCase()}
|
|
292
309
|
</div>
|
|
293
|
-
<div className="flex items-center flex-wrap p-2 font-mono text-xs">
|
|
310
|
+
<div className="flex items-center flex-wrap p-2 font-mono text-xs break-all">
|
|
294
311
|
{serverSelect}
|
|
295
312
|
{path}
|
|
296
313
|
{urlQueryParams.length > 0 ? "?" : ""}
|
|
297
314
|
{urlQueryParams}
|
|
298
315
|
</div>
|
|
299
316
|
</div>
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
317
|
+
|
|
318
|
+
<SubmitButton
|
|
319
|
+
identities={identities.data ?? []}
|
|
320
|
+
formRef={formRef}
|
|
321
|
+
disabled={form.formState.isSubmitting}
|
|
322
|
+
/>
|
|
303
323
|
</div>
|
|
304
324
|
<Tabs defaultValue="parameters">
|
|
305
325
|
<div className="flex flex-wrap gap-1 justify-between">
|
|
@@ -438,84 +458,12 @@ export const Playground = ({
|
|
|
438
458
|
</TabsContent>
|
|
439
459
|
</Tabs>
|
|
440
460
|
</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>
|
|
461
|
+
<ResultPanel
|
|
462
|
+
queryMutation={queryMutation}
|
|
463
|
+
showPathParamsWarning={formState.pathParams.some(
|
|
464
|
+
(p) => p.value === "",
|
|
517
465
|
)}
|
|
518
|
-
|
|
466
|
+
/>
|
|
519
467
|
</div>
|
|
520
468
|
</form>
|
|
521
469
|
</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;
|