zudoku 0.3.0-dev.10 → 0.3.0-dev.11
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/lib/authentication/authentication.d.ts +2 -2
- package/dist/lib/components/DevPortal.js +12 -7
- package/dist/lib/components/DevPortal.js.map +1 -1
- package/dist/lib/components/context/DevPortalProvider.d.ts +1 -1
- package/dist/lib/components/context/DevPortalProvider.js +2 -2
- package/dist/lib/components/context/DevPortalProvider.js.map +1 -1
- package/dist/lib/core/DevPortalContext.js +1 -1
- package/dist/lib/core/DevPortalContext.js.map +1 -1
- package/dist/lib/core/plugins.d.ts +7 -4
- package/dist/lib/core/plugins.js +1 -0
- package/dist/lib/core/plugins.js.map +1 -1
- package/dist/lib/oas/graphql/index.js +1 -1
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/oas/parser/index.js +3 -1
- package/dist/lib/oas/parser/index.js.map +1 -1
- package/dist/lib/plugins/openapi/{MakeRequest.d.ts → PlaygroundDialogWrapper.d.ts} +1 -1
- package/dist/lib/plugins/openapi/{MakeRequest.js → PlaygroundDialogWrapper.js} +4 -4
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -0
- 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 +8 -0
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.d.ts +4 -4
- package/dist/lib/plugins/openapi/playground/Playground.js +7 -11
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/PlaygroundDialog.d.ts +3 -0
- package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js +10 -0
- package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js.map +1 -0
- package/dist/lib/plugins/openapi/worker/worker.js +25 -1
- package/dist/lib/plugins/openapi/worker/worker.js.map +1 -1
- package/lib/{Spinner-DCwVN24H.js → Spinner-CzCKCaUK.js} +487 -484
- package/lib/assets/{worker-BCcpCNJ7.js → worker-DGvzLstc.js} +9843 -9800
- package/lib/zudoku.components.js +156 -144
- package/lib/zudoku.openapi-worker.js +12 -12
- package/lib/zudoku.plugins.js +1931 -1923
- package/package.json +2 -1
- package/src/lib/authentication/authentication.ts +2 -5
- package/src/lib/components/DevPortal.tsx +9 -3
- package/src/lib/components/context/DevPortalProvider.ts +2 -2
- package/src/lib/core/DevPortalContext.ts +1 -1
- package/src/lib/core/plugins.ts +10 -5
- package/src/lib/oas/graphql/index.ts +2 -2
- package/src/lib/oas/parser/index.ts +3 -1
- package/src/lib/plugins/openapi/{MakeRequest.tsx → PlaygroundDialogWrapper.tsx} +3 -3
- package/src/lib/plugins/openapi/Sidecar.tsx +2 -2
- package/src/lib/plugins/openapi/index.tsx +17 -4
- package/src/lib/plugins/openapi/playground/Playground.tsx +157 -187
- package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +34 -0
- package/src/lib/plugins/openapi/worker/worker.ts +27 -1
- package/dist/lib/plugins/openapi/MakeRequest.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zudoku",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
+
"@envelop/core": "5.0.1",
|
|
56
57
|
"@graphql-typed-document-node/core": "3.2.0",
|
|
57
58
|
"@lekoarts/rehype-meta-as-attributes": "3.0.1",
|
|
58
59
|
"@mdx-js/react": "3.0.1",
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
InitializationPlugin,
|
|
3
|
-
NavigationPlugin,
|
|
4
|
-
} from "../../lib/core/plugins.js";
|
|
1
|
+
import { CommonPlugin, NavigationPlugin } from "../../lib/core/plugins.js";
|
|
5
2
|
|
|
6
|
-
type AuthenticationPlugin = NavigationPlugin &
|
|
3
|
+
type AuthenticationPlugin = NavigationPlugin & CommonPlugin;
|
|
7
4
|
|
|
8
5
|
export interface AuthenticationProvider extends AuthenticationPlugin {
|
|
9
6
|
login(): Promise<void>;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { MDXProvider } from "@mdx-js/react";
|
|
2
2
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
3
|
-
import { memo, Suspense, useEffect, useMemo } from "react";
|
|
3
|
+
import { Fragment, memo, Suspense, useEffect, useMemo } from "react";
|
|
4
4
|
import {
|
|
5
5
|
DevPortalContext,
|
|
6
6
|
queryClient,
|
|
7
7
|
type NavigationItem,
|
|
8
8
|
} from "../core/DevPortalContext.js";
|
|
9
|
-
import { HelmetProvider } from "../core/helmet.js";
|
|
10
|
-
import { type DevPortalPlugin } from "../core/plugins.js";
|
|
9
|
+
import { Helmet, HelmetProvider } from "../core/helmet.js";
|
|
10
|
+
import { hasHead, type DevPortalPlugin } from "../core/plugins.js";
|
|
11
11
|
|
|
12
12
|
import { AuthenticationProvider } from "../authentication/authentication.js";
|
|
13
13
|
import {
|
|
@@ -64,9 +64,15 @@ const DevPortalInner = (props: DevPortalProps) => {
|
|
|
64
64
|
void devPortalContext.initialize();
|
|
65
65
|
}, [devPortalContext]);
|
|
66
66
|
|
|
67
|
+
const heads = props.plugins
|
|
68
|
+
?.filter(hasHead)
|
|
69
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
70
|
+
.map((plugin, i) => <Fragment key={i}>{plugin.getHead?.()}</Fragment>);
|
|
71
|
+
|
|
67
72
|
return (
|
|
68
73
|
<QueryClientProvider client={queryClient}>
|
|
69
74
|
<HelmetProvider>
|
|
75
|
+
<Helmet>{heads}</Helmet>
|
|
70
76
|
<DevPortalProvider value={devPortalContext}>
|
|
71
77
|
<MDXProvider components={mdxComponents}>
|
|
72
78
|
<ThemeProvider>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
1
|
+
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
|
2
2
|
import { createContext, useContext } from "react";
|
|
3
3
|
import { matchPath, useLocation } from "react-router-dom";
|
|
4
4
|
import { DevPortalContext } from "../../core/DevPortalContext.js";
|
|
@@ -21,7 +21,7 @@ export const useDevPortal = () => {
|
|
|
21
21
|
|
|
22
22
|
export const useApiIdentities = () => {
|
|
23
23
|
const { getApiIdentities } = useDevPortal();
|
|
24
|
-
return
|
|
24
|
+
return useQuery({
|
|
25
25
|
queryFn: getApiIdentities,
|
|
26
26
|
queryKey: ["api-identities"],
|
|
27
27
|
});
|
package/src/lib/core/plugins.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
1
2
|
import { type RouteObject } from "react-router-dom";
|
|
2
3
|
import {
|
|
3
4
|
DevPortalContext,
|
|
@@ -10,9 +11,9 @@ export type PluginNavigationCategory = {
|
|
|
10
11
|
} & NavigationCategory;
|
|
11
12
|
|
|
12
13
|
export type DevPortalPlugin =
|
|
14
|
+
| CommonPlugin
|
|
13
15
|
| NavigationPlugin
|
|
14
|
-
| ApiIdentityPlugin
|
|
15
|
-
| InitializationPlugin;
|
|
16
|
+
| ApiIdentityPlugin;
|
|
16
17
|
|
|
17
18
|
export interface NavigationPlugin {
|
|
18
19
|
getRoutes: () => RouteObject[];
|
|
@@ -23,8 +24,9 @@ export interface ApiIdentityPlugin {
|
|
|
23
24
|
getIdentities: (context: DevPortalContext) => Promise<ApiIdentity[]>;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
export interface
|
|
27
|
-
initialize
|
|
27
|
+
export interface CommonPlugin {
|
|
28
|
+
initialize?: (context: DevPortalContext) => Promise<void> | void;
|
|
29
|
+
getHead?: () => ReactElement | undefined;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export const isNavigationPlugin = (
|
|
@@ -34,9 +36,12 @@ export const isNavigationPlugin = (
|
|
|
34
36
|
|
|
35
37
|
export const needsInitialization = (
|
|
36
38
|
obj: DevPortalPlugin,
|
|
37
|
-
): obj is
|
|
39
|
+
): obj is CommonPlugin =>
|
|
38
40
|
"initialize" in obj && typeof obj.initialize === "function";
|
|
39
41
|
|
|
42
|
+
export const hasHead = (obj: DevPortalPlugin): obj is CommonPlugin =>
|
|
43
|
+
"getHead" in obj && typeof obj.getHead === "function";
|
|
44
|
+
|
|
40
45
|
export const isApiIdentityPlugin = (
|
|
41
46
|
obj: DevPortalPlugin,
|
|
42
47
|
): obj is ApiIdentityPlugin =>
|
|
@@ -45,7 +45,7 @@ export const slugifyOperation = (operation: OperationLike, tag?: string) => {
|
|
|
45
45
|
);
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
const cache = new LRUCache<string, OpenAPIDocument
|
|
48
|
+
const cache = new LRUCache<string, Promise<OpenAPIDocument>>({
|
|
49
49
|
ttl: 60 * 10 * 1000,
|
|
50
50
|
ttlAutopurge: true,
|
|
51
51
|
});
|
|
@@ -384,7 +384,7 @@ const loadOpenAPISchema = async (input: NonNullable<unknown>) => {
|
|
|
384
384
|
return cache.get(hash)!;
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
const schema =
|
|
387
|
+
const schema = validate(input);
|
|
388
388
|
|
|
389
389
|
cache.set(hash, schema);
|
|
390
390
|
|
|
@@ -54,7 +54,9 @@ const parseSchemaInput = async (
|
|
|
54
54
|
return JSON.parse(schemaInput);
|
|
55
55
|
}
|
|
56
56
|
if (schemaInput.includes("://")) {
|
|
57
|
-
const response = await fetch(schemaInput
|
|
57
|
+
const response = await fetch(schemaInput, {
|
|
58
|
+
cache: "force-cache",
|
|
59
|
+
});
|
|
58
60
|
return (await response.json()) as JSONSchema;
|
|
59
61
|
}
|
|
60
62
|
const yaml = await import("yaml");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { graphql } from "./graphql/index.js";
|
|
2
2
|
import { useOasConfig } from "./index.js";
|
|
3
3
|
import type { OperationListItemResult } from "./OperationList.js";
|
|
4
|
-
import {
|
|
4
|
+
import { PlaygroundDialog } from "./playground/PlaygroundDialog.js";
|
|
5
5
|
|
|
6
6
|
import { useQuery } from "urql";
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ const GetServerQuery = graphql(/* GraphQL */ `
|
|
|
13
13
|
}
|
|
14
14
|
`);
|
|
15
15
|
|
|
16
|
-
export const
|
|
16
|
+
export const PlaygroundDialogWrapper = ({
|
|
17
17
|
operation,
|
|
18
18
|
}: {
|
|
19
19
|
operation: OperationListItemResult;
|
|
@@ -50,7 +50,7 @@ export const MakeRequest = ({
|
|
|
50
50
|
false;
|
|
51
51
|
|
|
52
52
|
return (
|
|
53
|
-
<
|
|
53
|
+
<PlaygroundDialog
|
|
54
54
|
host={server.data?.schema.url ?? ""}
|
|
55
55
|
method={operation.method}
|
|
56
56
|
url={operation.path}
|
|
@@ -5,9 +5,9 @@ import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
|
|
|
5
5
|
import type { SchemaObject } from "../../oas/parser/index.js";
|
|
6
6
|
import { cn } from "../../util/cn.js";
|
|
7
7
|
import { ColorizedParam } from "./ColorizedParam.js";
|
|
8
|
-
import { MakeRequest } from "./MakeRequest.js";
|
|
9
8
|
import { MethodTextColorMap } from "./MethodBadge.js";
|
|
10
9
|
import type { OperationListItemResult } from "./OperationList.js";
|
|
10
|
+
import { PlaygroundDialogWrapper } from "./PlaygroundDialogWrapper.js";
|
|
11
11
|
import { RequestBodySidecarBox } from "./RequestBodySidecarBox.js";
|
|
12
12
|
import { ResponsesSidecarBox } from "./ResponsesSidecarBox.js";
|
|
13
13
|
import * as SidecarBox from "./SidecarBox.js";
|
|
@@ -142,7 +142,7 @@ export const Sidecar = ({
|
|
|
142
142
|
{ value: "swift", label: "Swift" },
|
|
143
143
|
]}
|
|
144
144
|
/>
|
|
145
|
-
<
|
|
145
|
+
<PlaygroundDialogWrapper operation={operation} />
|
|
146
146
|
</div>
|
|
147
147
|
</SidecarBox.Head>
|
|
148
148
|
<SidecarBox.Body>
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
} from "./util/urql.js";
|
|
16
16
|
|
|
17
17
|
import { createSharedWorkerClient } from "virtual:zudoku-openapi-worker";
|
|
18
|
-
import type { createSharedWorkerClient as createSharedWorkerClientType } from "./worker/createSharedWorkerClient.js";
|
|
19
18
|
|
|
20
19
|
const OasContext = createContext<{ config: OasPluginConfig } | undefined>(
|
|
21
20
|
undefined,
|
|
@@ -85,11 +84,25 @@ export const openApiPlugin = (config: OasPluginConfig): DevPortalPlugin => {
|
|
|
85
84
|
url: config.server,
|
|
86
85
|
exchanges: [cacheExchange, fetchExchange],
|
|
87
86
|
})
|
|
88
|
-
:
|
|
89
|
-
typeof createSharedWorkerClientType
|
|
90
|
-
>);
|
|
87
|
+
: createSharedWorkerClient();
|
|
91
88
|
|
|
92
89
|
return {
|
|
90
|
+
getHead: () => {
|
|
91
|
+
if (config.type === "url") {
|
|
92
|
+
return (
|
|
93
|
+
<link
|
|
94
|
+
rel="preload"
|
|
95
|
+
href={config.input}
|
|
96
|
+
as="fetch"
|
|
97
|
+
crossOrigin="anonymous"
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (config.server) {
|
|
103
|
+
return <link rel="preconnect" href={config.server} />;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
93
106
|
getNavigation: async (path: string) => {
|
|
94
107
|
if (!matchPath({ path: basePath, end: false }, path)) {
|
|
95
108
|
return [];
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
2
1
|
import { useMutation } from "@tanstack/react-query";
|
|
3
|
-
import { CirclePlayIcon } from "lucide-react";
|
|
4
2
|
import { Fragment } from "react";
|
|
5
3
|
import { FormProvider, useForm } from "react-hook-form";
|
|
6
4
|
import { useApiIdentities } from "../../../components/context/DevPortalProvider.js";
|
|
7
|
-
import {
|
|
8
|
-
Dialog,
|
|
9
|
-
DialogContent,
|
|
10
|
-
DialogTitle,
|
|
11
|
-
DialogTrigger,
|
|
12
|
-
} from "../../../components/Dialog.js";
|
|
13
5
|
import {
|
|
14
6
|
Select,
|
|
15
7
|
SelectContent,
|
|
@@ -28,6 +20,8 @@ import { Headers } from "./Headers.js";
|
|
|
28
20
|
import { PathParams } from "./PathParams.js";
|
|
29
21
|
import { QueryParams } from "./QueryParams.js";
|
|
30
22
|
|
|
23
|
+
export const NO_IDENTITY = "__none";
|
|
24
|
+
|
|
31
25
|
function mimeTypeToLanguage(mimeType: string) {
|
|
32
26
|
const mimeTypeMapping = {
|
|
33
27
|
"application/json": "json",
|
|
@@ -81,17 +75,7 @@ export type PlaygroundForm = {
|
|
|
81
75
|
identity?: string;
|
|
82
76
|
};
|
|
83
77
|
|
|
84
|
-
export
|
|
85
|
-
|
|
86
|
-
const Playground = ({
|
|
87
|
-
url,
|
|
88
|
-
host,
|
|
89
|
-
method,
|
|
90
|
-
headers = [{ name: "", value: "" }],
|
|
91
|
-
queryParams = [],
|
|
92
|
-
pathParams = [],
|
|
93
|
-
hasParams,
|
|
94
|
-
}: {
|
|
78
|
+
export type PlaygroundContentProps = {
|
|
95
79
|
host: string;
|
|
96
80
|
url: string;
|
|
97
81
|
method: string;
|
|
@@ -99,7 +83,17 @@ const Playground = ({
|
|
|
99
83
|
queryParams?: QueryParam[];
|
|
100
84
|
pathParams?: PathParam[];
|
|
101
85
|
hasParams: boolean;
|
|
102
|
-
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const Playground = ({
|
|
89
|
+
host,
|
|
90
|
+
url,
|
|
91
|
+
method,
|
|
92
|
+
headers = [{ name: "", value: "" }],
|
|
93
|
+
queryParams = [],
|
|
94
|
+
pathParams = [],
|
|
95
|
+
hasParams,
|
|
96
|
+
}: PlaygroundContentProps) => {
|
|
103
97
|
const { register, control, handleSubmit, watch, ...form } =
|
|
104
98
|
useForm<PlaygroundForm>({
|
|
105
99
|
defaultValues: {
|
|
@@ -129,7 +123,7 @@ const Playground = ({
|
|
|
129
123
|
|
|
130
124
|
if (data.identity !== NO_IDENTITY) {
|
|
131
125
|
identities.data
|
|
132
|
-
|
|
126
|
+
?.find((i) => i.id === data.identity)
|
|
133
127
|
?.authorizeRequest(request);
|
|
134
128
|
}
|
|
135
129
|
const response = await fetch(request);
|
|
@@ -181,181 +175,157 @@ const Playground = ({
|
|
|
181
175
|
<wbr />
|
|
182
176
|
</Fragment>
|
|
183
177
|
));
|
|
184
|
-
|
|
185
178
|
return (
|
|
186
|
-
<
|
|
187
|
-
<
|
|
188
|
-
<
|
|
189
|
-
className="
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<
|
|
206
|
-
<div className="flex
|
|
207
|
-
<
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
{
|
|
215
|
-
|
|
179
|
+
<FormProvider {...{ register, control, handleSubmit, watch, ...form }}>
|
|
180
|
+
<form onSubmit={handleSubmit((data) => queryMutation.mutateAsync(data))}>
|
|
181
|
+
<div className="grid grid-cols-2 text-sm h-full">
|
|
182
|
+
<div className="flex flex-col gap-4 p-8 bg-muted/50 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:left-auto">
|
|
183
|
+
<div className="flex gap-2 items-stretch">
|
|
184
|
+
<div className="flex flex-1 items-center w-full border rounded-md border-border">
|
|
185
|
+
<div className="border-r border-border p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono">
|
|
186
|
+
{method.toUpperCase()}
|
|
187
|
+
</div>
|
|
188
|
+
<div className="p-2 font-mono text-xs">
|
|
189
|
+
{path}
|
|
190
|
+
{urlQueryParams.length > 0 ? "?" : ""}
|
|
191
|
+
{urlQueryParams}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
<Button type="submit" className="h-auto flex gap-1">
|
|
195
|
+
Send
|
|
196
|
+
</Button>
|
|
197
|
+
</div>
|
|
198
|
+
<Tabs defaultValue={hasParams ? "parameters" : "headers"}>
|
|
199
|
+
<div className="flex justify-between">
|
|
200
|
+
<TabsList>
|
|
201
|
+
{hasParams && (
|
|
202
|
+
<TabsTrigger value="parameters">Parameters</TabsTrigger>
|
|
203
|
+
)}
|
|
204
|
+
<TabsTrigger value="headers">
|
|
205
|
+
Headers{" "}
|
|
206
|
+
{formState.headers.length > 0 &&
|
|
207
|
+
`(${formState.headers.length})`}
|
|
208
|
+
</TabsTrigger>
|
|
209
|
+
<TabsTrigger
|
|
210
|
+
value="body"
|
|
211
|
+
disabled={["POST", "PUT", "PATCH", "DELETE"].includes(
|
|
212
|
+
method.toUpperCase(),
|
|
213
|
+
)}
|
|
214
|
+
>
|
|
215
|
+
Body
|
|
216
|
+
</TabsTrigger>
|
|
217
|
+
</TabsList>
|
|
218
|
+
<div className="flex gap-2 items-center">
|
|
219
|
+
Auth:
|
|
220
|
+
<Select
|
|
221
|
+
onValueChange={(value) => form.setValue("identity", value)}
|
|
222
|
+
defaultValue={formState.identity}
|
|
223
|
+
>
|
|
224
|
+
<SelectTrigger className="w-[180px] flex">
|
|
225
|
+
{identities.isPending ? <Spinner /> : <SelectValue />}
|
|
226
|
+
</SelectTrigger>
|
|
227
|
+
<SelectContent align="center">
|
|
228
|
+
<SelectItem value={NO_IDENTITY}>None</SelectItem>
|
|
229
|
+
{identities.data?.map((identity) => (
|
|
230
|
+
<SelectItem key={identity.id} value={identity.id}>
|
|
231
|
+
{identity.label}
|
|
232
|
+
</SelectItem>
|
|
233
|
+
))}
|
|
234
|
+
</SelectContent>
|
|
235
|
+
</Select>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
<TabsContent value="headers">
|
|
239
|
+
<Headers control={control} register={register} />
|
|
240
|
+
</TabsContent>
|
|
241
|
+
<TabsContent value="parameters">
|
|
242
|
+
<div className="grid grid-cols-[min-content_1fr_1fr_auto]">
|
|
243
|
+
{pathParams.length > 0 && (
|
|
244
|
+
<div className="font-semibold my-3 col-span-3">
|
|
245
|
+
Path Parameters
|
|
216
246
|
</div>
|
|
217
|
-
|
|
218
|
-
<
|
|
219
|
-
|
|
220
|
-
|
|
247
|
+
)}
|
|
248
|
+
<PathParams control={control} register={register} />
|
|
249
|
+
{queryParams.length > 0 && (
|
|
250
|
+
<span className="font-semibold my-3 col-span-3">
|
|
251
|
+
Query Parameters
|
|
252
|
+
</span>
|
|
253
|
+
)}
|
|
254
|
+
<QueryParams control={control} />
|
|
221
255
|
</div>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
</TabsList>
|
|
242
|
-
<div className="flex gap-2 items-center">
|
|
243
|
-
Auth:
|
|
244
|
-
<Select
|
|
245
|
-
onValueChange={(value) =>
|
|
246
|
-
form.setValue("identity", value)
|
|
247
|
-
}
|
|
248
|
-
defaultValue={formState.identity}
|
|
249
|
-
>
|
|
250
|
-
<SelectTrigger className="w-[180px]">
|
|
251
|
-
<SelectValue />
|
|
252
|
-
</SelectTrigger>
|
|
253
|
-
<SelectContent align="center">
|
|
254
|
-
<SelectItem value={NO_IDENTITY}>None</SelectItem>
|
|
255
|
-
{identities.data.map((identity) => (
|
|
256
|
-
<SelectItem key={identity.id} value={identity.id}>
|
|
257
|
-
{identity.label}
|
|
258
|
-
</SelectItem>
|
|
259
|
-
))}
|
|
260
|
-
</SelectContent>
|
|
261
|
-
</Select>
|
|
256
|
+
</TabsContent>
|
|
257
|
+
<TabsContent value="body">
|
|
258
|
+
<textarea
|
|
259
|
+
{...register("body")}
|
|
260
|
+
className="border border-border w-full rounded p-2 bg-muted h-40"
|
|
261
|
+
/>
|
|
262
|
+
</TabsContent>
|
|
263
|
+
</Tabs>
|
|
264
|
+
</div>
|
|
265
|
+
<div className="flex flex-col gap-4 p-8 bg-muted/70">
|
|
266
|
+
{queryMutation.error ? (
|
|
267
|
+
<div>{queryMutation.error.message}</div>
|
|
268
|
+
) : queryMutation.data ? (
|
|
269
|
+
<div className="flex flex-col gap-2">
|
|
270
|
+
<div className="flex gap-2">
|
|
271
|
+
<div className="flex text-xs gap-6">
|
|
272
|
+
<div>
|
|
273
|
+
Status: {queryMutation.data.status}{" "}
|
|
274
|
+
{statusCodeMap[queryMutation.data.status] ?? ""}
|
|
262
275
|
</div>
|
|
276
|
+
<div>Time: {queryMutation.data.time.toFixed(0)}ms</div>
|
|
277
|
+
<div>Size: {queryMutation.data.size} B</div>
|
|
263
278
|
</div>
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
<
|
|
268
|
-
<
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
279
|
+
</div>
|
|
280
|
+
{/*<UrlDisplay host={host} path={url} />*/}
|
|
281
|
+
<Tabs defaultValue="response">
|
|
282
|
+
<TabsList>
|
|
283
|
+
<TabsTrigger value="response">Response</TabsTrigger>
|
|
284
|
+
<TabsTrigger value="headers">
|
|
285
|
+
{headerEntries.length
|
|
286
|
+
? `Headers (${headerEntries.length})`
|
|
287
|
+
: "No headers"}
|
|
288
|
+
</TabsTrigger>
|
|
289
|
+
</TabsList>
|
|
290
|
+
|
|
291
|
+
<TabsContent value="response">
|
|
292
|
+
<Card className="shadow-none p-4">
|
|
293
|
+
<SyntaxHighlight
|
|
294
|
+
language={lang ?? "json"}
|
|
295
|
+
noBackground
|
|
296
|
+
className="overflow-x-auto "
|
|
297
|
+
code={queryMutation.data.body ?? JSON.stringify("")}
|
|
298
|
+
/>
|
|
299
|
+
</Card>
|
|
282
300
|
</TabsContent>
|
|
283
|
-
<TabsContent value="
|
|
284
|
-
<
|
|
285
|
-
|
|
286
|
-
className="
|
|
287
|
-
|
|
301
|
+
<TabsContent value="headers">
|
|
302
|
+
<Card className="grid grid-cols-2 w-full gap-2.5 font-mono text-xs shadow-none p-4">
|
|
303
|
+
<div className="font-semibold">Key</div>
|
|
304
|
+
<div className="font-semibold">Value</div>
|
|
305
|
+
{headerEntries.map(([key, value]) => (
|
|
306
|
+
<Fragment key={key}>
|
|
307
|
+
<div>{key}</div>
|
|
308
|
+
<div>{value}</div>
|
|
309
|
+
</Fragment>
|
|
310
|
+
))}
|
|
311
|
+
</Card>
|
|
288
312
|
</TabsContent>
|
|
289
313
|
</Tabs>
|
|
290
314
|
</div>
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
{statusCodeMap[queryMutation.data.status] ?? ""}
|
|
301
|
-
</div>
|
|
302
|
-
<div>Time: {queryMutation.data.time.toFixed(0)}ms</div>
|
|
303
|
-
<div>Size: {queryMutation.data.size} B</div>
|
|
304
|
-
</div>
|
|
305
|
-
</div>
|
|
306
|
-
{/*<UrlDisplay host={host} path={url} />*/}
|
|
307
|
-
<Tabs defaultValue="response">
|
|
308
|
-
<TabsList>
|
|
309
|
-
<TabsTrigger value="response">Response</TabsTrigger>
|
|
310
|
-
<TabsTrigger value="headers">
|
|
311
|
-
{headerEntries.length
|
|
312
|
-
? `Headers (${headerEntries.length})`
|
|
313
|
-
: "No headers"}
|
|
314
|
-
</TabsTrigger>
|
|
315
|
-
</TabsList>
|
|
316
|
-
|
|
317
|
-
<TabsContent value="response">
|
|
318
|
-
<Card className="shadow-none p-4">
|
|
319
|
-
<SyntaxHighlight
|
|
320
|
-
language={lang ?? "json"}
|
|
321
|
-
noBackground
|
|
322
|
-
className="overflow-x-auto "
|
|
323
|
-
code={queryMutation.data.body ?? JSON.stringify("")}
|
|
324
|
-
/>
|
|
325
|
-
</Card>
|
|
326
|
-
</TabsContent>
|
|
327
|
-
<TabsContent value="headers">
|
|
328
|
-
<Card className="grid grid-cols-2 w-full gap-2.5 font-mono text-xs shadow-none p-4">
|
|
329
|
-
<div className="font-semibold">Key</div>
|
|
330
|
-
<div className="font-semibold">Value</div>
|
|
331
|
-
{headerEntries.map(([key, value]) => (
|
|
332
|
-
<Fragment key={key}>
|
|
333
|
-
<div>{key}</div>
|
|
334
|
-
<div>{value}</div>
|
|
335
|
-
</Fragment>
|
|
336
|
-
))}
|
|
337
|
-
</Card>
|
|
338
|
-
</TabsContent>
|
|
339
|
-
</Tabs>
|
|
340
|
-
</div>
|
|
341
|
-
) : (
|
|
342
|
-
<div className="grid place-items-center h-full">
|
|
343
|
-
<span className="text-[16px] font-semibold text-muted-foreground">
|
|
344
|
-
{queryMutation.isPending ? (
|
|
345
|
-
<Spinner />
|
|
346
|
-
) : (
|
|
347
|
-
"Send a request first to see the response here"
|
|
348
|
-
)}
|
|
349
|
-
</span>
|
|
350
|
-
</div>
|
|
351
|
-
)}
|
|
315
|
+
) : (
|
|
316
|
+
<div className="grid place-items-center h-full">
|
|
317
|
+
<span className="text-[16px] font-semibold text-muted-foreground">
|
|
318
|
+
{queryMutation.isPending ? (
|
|
319
|
+
<Spinner />
|
|
320
|
+
) : (
|
|
321
|
+
"Send a request first to see the response here"
|
|
322
|
+
)}
|
|
323
|
+
</span>
|
|
352
324
|
</div>
|
|
353
|
-
|
|
354
|
-
</
|
|
355
|
-
</
|
|
356
|
-
</
|
|
357
|
-
</
|
|
325
|
+
)}
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
</form>
|
|
329
|
+
</FormProvider>
|
|
358
330
|
);
|
|
359
331
|
};
|
|
360
|
-
|
|
361
|
-
export { Playground };
|