zudoku 0.1.1-dev.44 → 0.1.1-dev.46
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/components/Select.d.ts +13 -0
- package/dist/lib/components/Select.js +27 -0
- package/dist/lib/components/Select.js.map +1 -0
- package/dist/lib/plugins/api-key/CreateApiKey.js +37 -0
- package/dist/lib/plugins/api-key/CreateApiKey.js.map +1 -0
- package/dist/lib/plugins/api-key/SettingsApiKeys.js +1 -1
- package/dist/lib/plugins/api-key/SettingsApiKeys.js.map +1 -1
- package/dist/lib/plugins/api-key/index.d.ts +1 -1
- package/dist/lib/plugins/api-key/index.js +1 -1
- package/dist/lib/plugins/api-key/index.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +2 -22
- 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/SchemaListView.d.ts +7 -0
- package/dist/lib/plugins/openapi/SchemaListView.js +43 -0
- package/dist/lib/plugins/openapi/SchemaListView.js.map +1 -0
- package/lib/{Spinner-Zry2k_pD.js → Spinner-DEkC7JSn.js} +2090 -1986
- package/lib/zudoku.components.js +507 -608
- package/lib/zudoku.plugins.js +15051 -12558
- package/package.json +3 -2
- package/src/app/main.css +1 -0
- package/src/lib/components/Select.tsx +157 -0
- package/src/lib/plugins/api-key/{CreateApiKeys.tsx → CreateApiKey.tsx} +43 -27
- package/src/lib/plugins/api-key/SettingsApiKeys.tsx +10 -9
- package/src/lib/plugins/api-key/index.tsx +2 -2
- package/src/lib/plugins/openapi/OperationListItem.tsx +7 -121
- package/src/lib/plugins/openapi/ParameterListItem.tsx +1 -1
- package/src/lib/plugins/openapi/SchemaListView.tsx +229 -0
- package/dist/lib/plugins/api-key/CreateApiKeys.js +0 -37
- package/dist/lib/plugins/api-key/CreateApiKeys.js.map +0 -1
- /package/dist/lib/plugins/api-key/{CreateApiKeys.d.ts → CreateApiKey.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zudoku",
|
|
3
|
-
"version": "0.1.1-dev.
|
|
3
|
+
"version": "0.1.1-dev.46",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@mdx-js/rollup": "3.0.1",
|
|
54
54
|
"@monaco-editor/react": "^4.6.0",
|
|
55
55
|
"@pothos/core": "3.41.0",
|
|
56
|
+
"@radix-ui/react-select": "2.1.1",
|
|
56
57
|
"@sentry/node": "8.11.0",
|
|
57
58
|
"@stefanprobst/rehype-extract-toc": "2.2.0",
|
|
58
59
|
"@tailwindcss/typography": "0.5.13",
|
|
@@ -122,8 +123,8 @@
|
|
|
122
123
|
"prism-react-renderer": "2.3.1",
|
|
123
124
|
"prismjs": "1.29.0",
|
|
124
125
|
"react-helmet-async": "2.0.5",
|
|
125
|
-
"react-router-dom": "6.24.1",
|
|
126
126
|
"react-markdown": "9.0.1",
|
|
127
|
+
"react-router-dom": "6.24.1",
|
|
127
128
|
"tailwind-merge": "2.3.0",
|
|
128
129
|
"typescript": "5.5.3",
|
|
129
130
|
"zustand": "4.5.4"
|
package/src/app/main.css
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
3
|
+
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
|
4
|
+
import { cn } from "../util/cn.js";
|
|
5
|
+
|
|
6
|
+
const Select = SelectPrimitive.Root;
|
|
7
|
+
|
|
8
|
+
const SelectGroup = SelectPrimitive.Group;
|
|
9
|
+
|
|
10
|
+
const SelectValue = SelectPrimitive.Value;
|
|
11
|
+
|
|
12
|
+
const SelectTrigger = React.forwardRef<
|
|
13
|
+
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
14
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
15
|
+
>(({ className, children, ...props }, ref) => (
|
|
16
|
+
<SelectPrimitive.Trigger
|
|
17
|
+
ref={ref}
|
|
18
|
+
className={cn(
|
|
19
|
+
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
20
|
+
className,
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
>
|
|
24
|
+
{children}
|
|
25
|
+
<SelectPrimitive.Icon asChild>
|
|
26
|
+
<ChevronDown className="h-4 w-4 opacity-50" />
|
|
27
|
+
</SelectPrimitive.Icon>
|
|
28
|
+
</SelectPrimitive.Trigger>
|
|
29
|
+
));
|
|
30
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
31
|
+
|
|
32
|
+
const SelectScrollUpButton = React.forwardRef<
|
|
33
|
+
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
|
34
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
|
35
|
+
>(({ className, ...props }, ref) => (
|
|
36
|
+
<SelectPrimitive.ScrollUpButton
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={cn(
|
|
39
|
+
"flex cursor-default items-center justify-center py-1",
|
|
40
|
+
className,
|
|
41
|
+
)}
|
|
42
|
+
{...props}
|
|
43
|
+
>
|
|
44
|
+
<ChevronUp className="h-4 w-4" />
|
|
45
|
+
</SelectPrimitive.ScrollUpButton>
|
|
46
|
+
));
|
|
47
|
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
48
|
+
|
|
49
|
+
const SelectScrollDownButton = React.forwardRef<
|
|
50
|
+
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
|
51
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
|
52
|
+
>(({ className, ...props }, ref) => (
|
|
53
|
+
<SelectPrimitive.ScrollDownButton
|
|
54
|
+
ref={ref}
|
|
55
|
+
className={cn(
|
|
56
|
+
"flex cursor-default items-center justify-center py-1",
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
<ChevronDown className="h-4 w-4" />
|
|
62
|
+
</SelectPrimitive.ScrollDownButton>
|
|
63
|
+
));
|
|
64
|
+
SelectScrollDownButton.displayName =
|
|
65
|
+
SelectPrimitive.ScrollDownButton.displayName;
|
|
66
|
+
|
|
67
|
+
const SelectContent = React.forwardRef<
|
|
68
|
+
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
69
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
70
|
+
>(({ className, children, position = "popper", ...props }, ref) => (
|
|
71
|
+
<SelectPrimitive.Portal>
|
|
72
|
+
<SelectPrimitive.Content
|
|
73
|
+
ref={ref}
|
|
74
|
+
className={cn(
|
|
75
|
+
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
76
|
+
position === "popper" &&
|
|
77
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
78
|
+
className,
|
|
79
|
+
)}
|
|
80
|
+
position={position}
|
|
81
|
+
{...props}
|
|
82
|
+
>
|
|
83
|
+
<SelectScrollUpButton />
|
|
84
|
+
<SelectPrimitive.Viewport
|
|
85
|
+
className={cn(
|
|
86
|
+
"p-1",
|
|
87
|
+
position === "popper" &&
|
|
88
|
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
|
|
89
|
+
)}
|
|
90
|
+
>
|
|
91
|
+
{children}
|
|
92
|
+
</SelectPrimitive.Viewport>
|
|
93
|
+
<SelectScrollDownButton />
|
|
94
|
+
</SelectPrimitive.Content>
|
|
95
|
+
</SelectPrimitive.Portal>
|
|
96
|
+
));
|
|
97
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
98
|
+
|
|
99
|
+
const SelectLabel = React.forwardRef<
|
|
100
|
+
React.ElementRef<typeof SelectPrimitive.Label>,
|
|
101
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
|
102
|
+
>(({ className, ...props }, ref) => (
|
|
103
|
+
<SelectPrimitive.Label
|
|
104
|
+
ref={ref}
|
|
105
|
+
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
));
|
|
109
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
110
|
+
|
|
111
|
+
const SelectItem = React.forwardRef<
|
|
112
|
+
React.ElementRef<typeof SelectPrimitive.Item>,
|
|
113
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
114
|
+
>(({ className, children, ...props }, ref) => (
|
|
115
|
+
<SelectPrimitive.Item
|
|
116
|
+
ref={ref}
|
|
117
|
+
className={cn(
|
|
118
|
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
119
|
+
className,
|
|
120
|
+
)}
|
|
121
|
+
{...props}
|
|
122
|
+
>
|
|
123
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
124
|
+
<SelectPrimitive.ItemIndicator>
|
|
125
|
+
<Check className="h-4 w-4" />
|
|
126
|
+
</SelectPrimitive.ItemIndicator>
|
|
127
|
+
</span>
|
|
128
|
+
|
|
129
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
130
|
+
</SelectPrimitive.Item>
|
|
131
|
+
));
|
|
132
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
133
|
+
|
|
134
|
+
const SelectSeparator = React.forwardRef<
|
|
135
|
+
React.ElementRef<typeof SelectPrimitive.Separator>,
|
|
136
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
|
137
|
+
>(({ className, ...props }, ref) => (
|
|
138
|
+
<SelectPrimitive.Separator
|
|
139
|
+
ref={ref}
|
|
140
|
+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
|
141
|
+
{...props}
|
|
142
|
+
/>
|
|
143
|
+
));
|
|
144
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
145
|
+
|
|
146
|
+
export {
|
|
147
|
+
Select,
|
|
148
|
+
SelectGroup,
|
|
149
|
+
SelectValue,
|
|
150
|
+
SelectTrigger,
|
|
151
|
+
SelectContent,
|
|
152
|
+
SelectLabel,
|
|
153
|
+
SelectItem,
|
|
154
|
+
SelectSeparator,
|
|
155
|
+
SelectScrollUpButton,
|
|
156
|
+
SelectScrollDownButton,
|
|
157
|
+
};
|
|
@@ -3,11 +3,18 @@ import { type ApiKeyPluginOptions, ApiKeyService } from "./index.js";
|
|
|
3
3
|
import { useMutation } from "@tanstack/react-query";
|
|
4
4
|
import { Button } from "../../ui/Button.js";
|
|
5
5
|
import { Input } from "../../components/Input.js";
|
|
6
|
-
import { cn } from "../../util/cn.js";
|
|
7
6
|
import { Link, useNavigate } from "react-router-dom";
|
|
8
7
|
import { useForm } from "react-hook-form";
|
|
8
|
+
import {
|
|
9
|
+
Select,
|
|
10
|
+
SelectContent,
|
|
11
|
+
SelectGroup,
|
|
12
|
+
SelectItem,
|
|
13
|
+
SelectTrigger,
|
|
14
|
+
SelectValue,
|
|
15
|
+
} from "../../components/Select.js";
|
|
9
16
|
|
|
10
|
-
type
|
|
17
|
+
type CreateApiKey = { description: string; expiresOn?: string };
|
|
11
18
|
|
|
12
19
|
export const CreateApiKey = ({
|
|
13
20
|
options,
|
|
@@ -18,14 +25,24 @@ export const CreateApiKey = ({
|
|
|
18
25
|
}) => {
|
|
19
26
|
const context = useDevPortal();
|
|
20
27
|
const navigate = useNavigate();
|
|
21
|
-
const form = useForm<
|
|
28
|
+
const form = useForm<CreateApiKey>({
|
|
29
|
+
defaultValues: {
|
|
30
|
+
expiresOn: "30",
|
|
31
|
+
},
|
|
32
|
+
});
|
|
22
33
|
const createKeyMutation = useMutation({
|
|
23
|
-
mutationFn: ({ description,
|
|
34
|
+
mutationFn: ({ description, expiresOn }: CreateApiKey) => {
|
|
24
35
|
if (!service.createKey) {
|
|
25
36
|
throw new Error("deleteKey not implemented");
|
|
26
37
|
}
|
|
27
38
|
|
|
28
|
-
|
|
39
|
+
const expiresOnDate =
|
|
40
|
+
expiresOn !== "never" ? addDaysToDate(Number(expiresOn)) : undefined;
|
|
41
|
+
|
|
42
|
+
return service.createKey(
|
|
43
|
+
{ description: description, expiresOn: expiresOnDate },
|
|
44
|
+
context,
|
|
45
|
+
);
|
|
29
46
|
},
|
|
30
47
|
onSuccess: () => navigate("/settings/api-keys/"),
|
|
31
48
|
});
|
|
@@ -36,35 +53,34 @@ export const CreateApiKey = ({
|
|
|
36
53
|
|
|
37
54
|
return (
|
|
38
55
|
<div className="max-w-screen-lg pt-[--padding-content-top] pb-[--padding-content-bottom]">
|
|
39
|
-
<div className="flex justify-between mb-4 border-b pb-1">
|
|
40
|
-
<h1 className="font-medium text-2xl">New API
|
|
56
|
+
<div className="flex justify-between mb-4 border-b border-border pb-1">
|
|
57
|
+
<h1 className="font-medium text-2xl">New API Key</h1>
|
|
41
58
|
</div>
|
|
42
59
|
<form
|
|
43
|
-
onSubmit={form.handleSubmit((data) =>
|
|
44
|
-
if (data.expiresAt === "never") {
|
|
45
|
-
delete data.expiresAt;
|
|
46
|
-
}
|
|
47
|
-
createKeyMutation.mutate(data);
|
|
48
|
-
})}
|
|
60
|
+
onSubmit={form.handleSubmit((data) => createKeyMutation.mutate(data))}
|
|
49
61
|
>
|
|
50
62
|
<div className="flex gap-2 flex-col">
|
|
51
63
|
Note
|
|
52
64
|
<Input {...form.register("description")} />
|
|
53
65
|
Expiration
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"rounded-md appearance-none bg-zinc-50 hover:bg-white dark:bg-zinc-800 hover:dark:bg-zinc-800/75",
|
|
58
|
-
)}
|
|
59
|
-
{...form.register("expiresAt")}
|
|
66
|
+
<Select
|
|
67
|
+
onValueChange={(value) => form.setValue("expiresOn", value)}
|
|
68
|
+
defaultValue={form.getValues("expiresOn")}
|
|
60
69
|
>
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
70
|
+
<SelectTrigger>
|
|
71
|
+
<SelectValue />
|
|
72
|
+
</SelectTrigger>
|
|
73
|
+
<SelectContent>
|
|
74
|
+
<SelectGroup>
|
|
75
|
+
{[7, 30, 60, 90].map((option) => (
|
|
76
|
+
<SelectItem value={String(option)} key={option}>
|
|
77
|
+
{option} days
|
|
78
|
+
</SelectItem>
|
|
79
|
+
))}
|
|
80
|
+
<SelectItem value="never">Never</SelectItem>
|
|
81
|
+
</SelectGroup>
|
|
82
|
+
</SelectContent>
|
|
83
|
+
</Select>
|
|
68
84
|
<div className="flex gap-2">
|
|
69
85
|
<Button>Generate Key</Button>
|
|
70
86
|
<Button variant="outline" asChild>
|
|
@@ -80,5 +96,5 @@ export const CreateApiKey = ({
|
|
|
80
96
|
const addDaysToDate = (days: number): string => {
|
|
81
97
|
const date = new Date();
|
|
82
98
|
date.setDate(date.getDate() + days);
|
|
83
|
-
return date.toISOString()
|
|
99
|
+
return date.toISOString();
|
|
84
100
|
};
|
|
@@ -40,7 +40,7 @@ export const SettingsApiKeys = ({
|
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
42
|
<div className="max-w-screen-lg pt-[--padding-content-top] pb-[--padding-content-bottom]">
|
|
43
|
-
<div className="flex justify-between mb-4 border-b border-border pb-
|
|
43
|
+
<div className="flex justify-between mb-4 border-b border-border pb-3">
|
|
44
44
|
<h1 className="font-medium text-2xl">API Keys</h1>
|
|
45
45
|
{service.createKey && (
|
|
46
46
|
<Button asChild>
|
|
@@ -58,14 +58,15 @@ export const SettingsApiKeys = ({
|
|
|
58
58
|
>
|
|
59
59
|
<div className="flex flex-col gap-1 text-sm">
|
|
60
60
|
{key.description ?? key.id}
|
|
61
|
-
{key.
|
|
62
|
-
<div
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
{key.createdOn && (
|
|
62
|
+
<div className="text-muted-foreground">
|
|
63
|
+
Created on {new Date(key.createdOn).toLocaleString()}
|
|
64
|
+
</div>
|
|
65
|
+
)}
|
|
66
|
+
{key.expiresOn && (
|
|
67
|
+
<div className="text-muted-foreground">
|
|
68
|
+
Expires on {new Date(key.expiresOn).toLocaleString()}
|
|
69
|
+
</div>
|
|
69
70
|
)}
|
|
70
71
|
</div>
|
|
71
72
|
<div className="items-center flex justify-center">
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
type DevPortalPlugin,
|
|
5
5
|
} from "../../core/plugins.js";
|
|
6
6
|
import { SettingsApiKeys } from "./SettingsApiKeys.js";
|
|
7
|
-
import { CreateApiKey } from "./
|
|
7
|
+
import { CreateApiKey } from "./CreateApiKey.js";
|
|
8
8
|
|
|
9
9
|
export type ApiKeyResults = Promise<ApiKey[]>;
|
|
10
10
|
const DEFAULT_API_KEY_ENDPOINT =
|
|
@@ -20,7 +20,7 @@ export type ApiKeyService = {
|
|
|
20
20
|
) => Promise<void>;
|
|
21
21
|
getUsage?: (apiKeys: string[], context: DevPortalContext) => Promise<void>;
|
|
22
22
|
createKey?: (
|
|
23
|
-
apiKey: { description: string;
|
|
23
|
+
apiKey: { description: string; expiresOn?: string },
|
|
24
24
|
context: DevPortalContext,
|
|
25
25
|
) => Promise<void>;
|
|
26
26
|
};
|
|
@@ -5,10 +5,8 @@ import { OperationsFragment } from "./OperationList.js";
|
|
|
5
5
|
import { ParameterList } from "./ParameterList.js";
|
|
6
6
|
import { Sidecar } from "./Sidecar.js";
|
|
7
7
|
import { FragmentType, useFragment } from "./graphql/index.js";
|
|
8
|
-
import { SchemaObject } from "../../oas/parser/index.js";
|
|
9
|
-
import { useState } from "react";
|
|
10
|
-
import { cn } from "../../util/cn.js";
|
|
11
8
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../ui/Tabs.js";
|
|
9
|
+
import { SchemaListView } from "./SchemaListView.js";
|
|
12
10
|
|
|
13
11
|
export const PARAM_GROUPS = ["path", "query", "header", "cookie"] as const;
|
|
14
12
|
export type ParameterGroup = (typeof PARAM_GROUPS)[number];
|
|
@@ -61,8 +59,9 @@ export const OperationListItem = ({
|
|
|
61
59
|
<TabsTrigger
|
|
62
60
|
value={response.statusCode + response.description}
|
|
63
61
|
key={response.statusCode}
|
|
62
|
+
title={response.description}
|
|
64
63
|
>
|
|
65
|
-
{response.
|
|
64
|
+
{response.statusCode}
|
|
66
65
|
</TabsTrigger>
|
|
67
66
|
))}
|
|
68
67
|
</TabsList>
|
|
@@ -72,7 +71,10 @@ export const OperationListItem = ({
|
|
|
72
71
|
value={response.statusCode + response.description}
|
|
73
72
|
key={response.statusCode}
|
|
74
73
|
>
|
|
75
|
-
<
|
|
74
|
+
<SchemaListView
|
|
75
|
+
schema={response.content?.at(0)?.schema}
|
|
76
|
+
name=""
|
|
77
|
+
/>
|
|
76
78
|
</TabsContent>
|
|
77
79
|
))}
|
|
78
80
|
</ul>
|
|
@@ -83,119 +85,3 @@ export const OperationListItem = ({
|
|
|
83
85
|
</div>
|
|
84
86
|
);
|
|
85
87
|
};
|
|
86
|
-
|
|
87
|
-
const ViewSchema = ({
|
|
88
|
-
name,
|
|
89
|
-
schema,
|
|
90
|
-
level = 0,
|
|
91
|
-
collapsible = false,
|
|
92
|
-
}: {
|
|
93
|
-
level?: number;
|
|
94
|
-
collapsible?: boolean;
|
|
95
|
-
name?: string;
|
|
96
|
-
schema: SchemaObject;
|
|
97
|
-
}) => {
|
|
98
|
-
const [open, setOpen] = useState(!collapsible);
|
|
99
|
-
|
|
100
|
-
const properties = Object.entries(schema.properties ?? {});
|
|
101
|
-
const additionalProperties =
|
|
102
|
-
typeof schema.additionalProperties === "object"
|
|
103
|
-
? Object.entries(schema.additionalProperties)
|
|
104
|
-
: [];
|
|
105
|
-
|
|
106
|
-
return (
|
|
107
|
-
<div
|
|
108
|
-
className={cn(
|
|
109
|
-
"not-prose",
|
|
110
|
-
level > 0 && "border border-border rounded text-sm",
|
|
111
|
-
)}
|
|
112
|
-
onClick={
|
|
113
|
-
collapsible
|
|
114
|
-
? () => {
|
|
115
|
-
setOpen((open) => !open);
|
|
116
|
-
}
|
|
117
|
-
: undefined
|
|
118
|
-
}
|
|
119
|
-
>
|
|
120
|
-
{(schema.title ?? name) && (
|
|
121
|
-
<div className="ml-2 my-1 font-bold">{schema.title ?? name}</div>
|
|
122
|
-
)}
|
|
123
|
-
{level === 0 && <p>schema.description</p>}
|
|
124
|
-
<ul>
|
|
125
|
-
{open &&
|
|
126
|
-
properties
|
|
127
|
-
.concat(additionalProperties)
|
|
128
|
-
.map(([propertyName, property]) => (
|
|
129
|
-
<div
|
|
130
|
-
key={propertyName}
|
|
131
|
-
className={cn(
|
|
132
|
-
level > 0 ? "py-2" : "py-4",
|
|
133
|
-
"px-2 border-t border-border bg-border/20 hover:bg-border/30 flex gap-1 flex-col",
|
|
134
|
-
property.deprecated && "opacity-50",
|
|
135
|
-
)}
|
|
136
|
-
>
|
|
137
|
-
<div className="flex items-center gap-2 relative">
|
|
138
|
-
<code>
|
|
139
|
-
{propertyName} {property.title}
|
|
140
|
-
</code>
|
|
141
|
-
|
|
142
|
-
{property.type && (
|
|
143
|
-
<span className="text-sm text-muted-foreground">
|
|
144
|
-
{property.type}
|
|
145
|
-
</span>
|
|
146
|
-
)}
|
|
147
|
-
{property.deprecated && (
|
|
148
|
-
<span className="text-sm text-muted-foreground">
|
|
149
|
-
Deprecated
|
|
150
|
-
</span>
|
|
151
|
-
)}
|
|
152
|
-
|
|
153
|
-
{!schema.required?.includes(propertyName) &&
|
|
154
|
-
!property.required && (
|
|
155
|
-
<span className="py-px px-1.5 font-medium text-xs border border-border rounded-lg">
|
|
156
|
-
optional
|
|
157
|
-
</span>
|
|
158
|
-
)}
|
|
159
|
-
{/*{property.type === "object" && (*/}
|
|
160
|
-
{/* <div className="absolute right-3">+</div>*/}
|
|
161
|
-
{/*)}*/}
|
|
162
|
-
</div>
|
|
163
|
-
{property.description && (
|
|
164
|
-
<Markdown
|
|
165
|
-
content={property.description}
|
|
166
|
-
className="prose text-sm prose-p:my-1 leading-normal line-clamp-4"
|
|
167
|
-
/>
|
|
168
|
-
)}
|
|
169
|
-
|
|
170
|
-
{property.enum && (
|
|
171
|
-
<span className="text-sm text-muted-foreground flex gap-1 flex-wrap items-center">
|
|
172
|
-
<span>Possible values</span>
|
|
173
|
-
{property.enum
|
|
174
|
-
.filter((value) => value)
|
|
175
|
-
.map((value) => (
|
|
176
|
-
<span
|
|
177
|
-
key={value}
|
|
178
|
-
className="font-mono text-xs border-border border bg-muted rounded px-1"
|
|
179
|
-
>
|
|
180
|
-
{value}
|
|
181
|
-
</span>
|
|
182
|
-
))}
|
|
183
|
-
</span>
|
|
184
|
-
)}
|
|
185
|
-
{property.type === "object" && (
|
|
186
|
-
<div className="mt-2.5">
|
|
187
|
-
<ViewSchema schema={property} level={level + 1} />
|
|
188
|
-
</div>
|
|
189
|
-
)}
|
|
190
|
-
{property.type === "array" &&
|
|
191
|
-
property.items.type === "object" && (
|
|
192
|
-
<div className="mt-2.5">
|
|
193
|
-
<ViewSchema schema={property.items} level={level + 1} />
|
|
194
|
-
</div>
|
|
195
|
-
)}
|
|
196
|
-
</div>
|
|
197
|
-
))}
|
|
198
|
-
</ul>
|
|
199
|
-
</div>
|
|
200
|
-
);
|
|
201
|
-
};
|
|
@@ -28,7 +28,7 @@ export const ParameterListItem = ({
|
|
|
28
28
|
group: ParameterGroup;
|
|
29
29
|
id: string;
|
|
30
30
|
}) => (
|
|
31
|
-
<li className="not-prose px-2 py-4 border-t border-border bg-border/20">
|
|
31
|
+
<li className="not-prose px-2 py-4 border-t border-border bg-border/20 text-sm flex flex-col gap-1">
|
|
32
32
|
<div className="flex items-center gap-2">
|
|
33
33
|
<code>
|
|
34
34
|
{group === "path" ? (
|