zudoku 0.1.1-dev.45 → 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/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-2oXmSf81.js → Spinner-DEkC7JSn.js} +2089 -1986
- package/lib/zudoku.components.js +507 -608
- package/lib/zudoku.plugins.js +4993 -4892
- package/package.json +1 -1
- 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/package.json
CHANGED
|
@@ -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" ? (
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { SchemaObject } from "../../oas/parser/index.js";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { cn } from "../../util/cn.js";
|
|
4
|
+
import { Markdown } from "../../components/Markdown.js";
|
|
5
|
+
import * as Collapsible from "@radix-ui/react-collapsible";
|
|
6
|
+
import { Button } from "../../ui/Button.js";
|
|
7
|
+
import { ListPlusIcon } from "lucide-react";
|
|
8
|
+
|
|
9
|
+
export const SchemaListView = ({
|
|
10
|
+
name,
|
|
11
|
+
schema,
|
|
12
|
+
level = 0,
|
|
13
|
+
defaultOpen = false,
|
|
14
|
+
}: {
|
|
15
|
+
level?: number;
|
|
16
|
+
defaultOpen?: boolean;
|
|
17
|
+
name?: string;
|
|
18
|
+
schema: SchemaObject;
|
|
19
|
+
}) => {
|
|
20
|
+
const properties = Object.entries(schema.properties ?? {});
|
|
21
|
+
const additionalProperties =
|
|
22
|
+
typeof schema.additionalProperties === "object"
|
|
23
|
+
? Object.entries(schema.additionalProperties)
|
|
24
|
+
: [];
|
|
25
|
+
|
|
26
|
+
const combinedProperties = properties.concat(
|
|
27
|
+
Array.isArray(additionalProperties) ? additionalProperties : [],
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const groups = Object.groupBy(
|
|
31
|
+
combinedProperties,
|
|
32
|
+
([propertyName, property]) => {
|
|
33
|
+
return property.deprecated
|
|
34
|
+
? "deprecated"
|
|
35
|
+
: schema.required?.includes(propertyName)
|
|
36
|
+
? "required"
|
|
37
|
+
: "optional";
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div
|
|
43
|
+
className={cn(
|
|
44
|
+
"not-prose",
|
|
45
|
+
level > 0 && "border border-border rounded text-sm",
|
|
46
|
+
)}
|
|
47
|
+
>
|
|
48
|
+
{(schema.title ?? name) && (
|
|
49
|
+
<div className="ml-2 my-1 font-bold">{schema.title ?? name}</div>
|
|
50
|
+
)}
|
|
51
|
+
{level === 0 && schema.description && (
|
|
52
|
+
<p className="prose">{schema.description}</p>
|
|
53
|
+
)}
|
|
54
|
+
<ul>
|
|
55
|
+
{Object.entries(groups).map(([group, properties]) => {
|
|
56
|
+
return (
|
|
57
|
+
<SchemaListViewItemGroup
|
|
58
|
+
defaultOpen={defaultOpen}
|
|
59
|
+
group={group as any}
|
|
60
|
+
nestingLevel={level}
|
|
61
|
+
properties={properties}
|
|
62
|
+
required={schema.required ?? []}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
})}
|
|
66
|
+
</ul>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const SchemaListViewItemGroup = ({
|
|
72
|
+
group,
|
|
73
|
+
properties,
|
|
74
|
+
nestingLevel,
|
|
75
|
+
required,
|
|
76
|
+
defaultOpen = false,
|
|
77
|
+
}: {
|
|
78
|
+
group: "optional" | "required" | "deprecated";
|
|
79
|
+
defaultOpen?: boolean;
|
|
80
|
+
properties: [string, SchemaObject][];
|
|
81
|
+
nestingLevel: number;
|
|
82
|
+
required: string[];
|
|
83
|
+
}) => {
|
|
84
|
+
const notCollapsible =
|
|
85
|
+
defaultOpen ||
|
|
86
|
+
group === "required" ||
|
|
87
|
+
properties.length === 1 ||
|
|
88
|
+
nestingLevel === 0;
|
|
89
|
+
const [open, setOpen] = useState(notCollapsible);
|
|
90
|
+
if (properties.length === 0) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Collapsible.Root
|
|
96
|
+
className="CollapsibleRoot"
|
|
97
|
+
open={open}
|
|
98
|
+
onOpenChange={setOpen}
|
|
99
|
+
>
|
|
100
|
+
{!open && (
|
|
101
|
+
<Collapsible.Trigger
|
|
102
|
+
className={cn(
|
|
103
|
+
"py-2 hover:bg-muted w-full",
|
|
104
|
+
group === "optional" && "font-semibold",
|
|
105
|
+
group === "deprecated" && "text-muted-foreground",
|
|
106
|
+
)}
|
|
107
|
+
>
|
|
108
|
+
{properties.length} {group} fields
|
|
109
|
+
</Collapsible.Trigger>
|
|
110
|
+
)}
|
|
111
|
+
|
|
112
|
+
<Collapsible.Content>
|
|
113
|
+
{properties.map(([propertyName, property]) => (
|
|
114
|
+
<SchemaListViewItem
|
|
115
|
+
property={property}
|
|
116
|
+
propertyName={propertyName}
|
|
117
|
+
nestingLevel={nestingLevel}
|
|
118
|
+
isRequired={required?.includes(propertyName) ?? false}
|
|
119
|
+
/>
|
|
120
|
+
))}
|
|
121
|
+
</Collapsible.Content>
|
|
122
|
+
</Collapsible.Root>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const SchemaListViewItem = ({
|
|
127
|
+
propertyName,
|
|
128
|
+
property,
|
|
129
|
+
nestingLevel,
|
|
130
|
+
isRequired,
|
|
131
|
+
}: {
|
|
132
|
+
propertyName: string;
|
|
133
|
+
isRequired: boolean;
|
|
134
|
+
property: SchemaObject;
|
|
135
|
+
nestingLevel: number;
|
|
136
|
+
}) => {
|
|
137
|
+
return (
|
|
138
|
+
<div
|
|
139
|
+
key={propertyName}
|
|
140
|
+
className={cn(
|
|
141
|
+
nestingLevel > 0 ? "py-2" : "py-4",
|
|
142
|
+
"px-2 border-t border-border bg-border/20 hover:bg-border/30 flex gap-1 flex-col text-sm",
|
|
143
|
+
property.deprecated && "opacity-50",
|
|
144
|
+
)}
|
|
145
|
+
>
|
|
146
|
+
<div className="flex items-center gap-2 relative">
|
|
147
|
+
<code>
|
|
148
|
+
{propertyName} {property.title}
|
|
149
|
+
</code>
|
|
150
|
+
|
|
151
|
+
{property.type && (
|
|
152
|
+
<span className="text-muted-foreground">{property.type}</span>
|
|
153
|
+
)}
|
|
154
|
+
{property.deprecated && (
|
|
155
|
+
<span className="text-muted-foreground">Deprecated</span>
|
|
156
|
+
)}
|
|
157
|
+
{!isRequired && (
|
|
158
|
+
<span className="py-px px-1.5 font-medium text-xs border border-border rounded-lg">
|
|
159
|
+
optional {property.required}
|
|
160
|
+
</span>
|
|
161
|
+
)}
|
|
162
|
+
{/*{property.type === "object" && (*/}
|
|
163
|
+
{/* <div className="absolute right-3">+</div>*/}
|
|
164
|
+
{/*)}*/}
|
|
165
|
+
</div>
|
|
166
|
+
{property.description && (
|
|
167
|
+
<Markdown
|
|
168
|
+
content={property.description}
|
|
169
|
+
className="text-sm leading-normal line-clamp-4 "
|
|
170
|
+
/>
|
|
171
|
+
)}
|
|
172
|
+
|
|
173
|
+
{property.enum && (
|
|
174
|
+
<span className="text-sm text-muted-foreground flex gap-1 flex-wrap items-center">
|
|
175
|
+
<span>Possible values</span>
|
|
176
|
+
{property.enum
|
|
177
|
+
.filter((value) => value)
|
|
178
|
+
.map((value) => (
|
|
179
|
+
<span
|
|
180
|
+
key={value}
|
|
181
|
+
className="font-mono text-xs border-border border bg-muted rounded px-1"
|
|
182
|
+
>
|
|
183
|
+
{value}
|
|
184
|
+
</span>
|
|
185
|
+
))
|
|
186
|
+
.slice(0, 4)}
|
|
187
|
+
{property.enum.length > 4 && (
|
|
188
|
+
<span className="font-mono text-xs border-border border bg-muted rounded px-1">
|
|
189
|
+
...
|
|
190
|
+
</span>
|
|
191
|
+
)}
|
|
192
|
+
</span>
|
|
193
|
+
)}
|
|
194
|
+
|
|
195
|
+
<Collapsible.Root className="CollapsibleRoot" defaultOpen={false}>
|
|
196
|
+
{property.type === "object" ||
|
|
197
|
+
(property.type === "array" && property.items.type === "object") ? (
|
|
198
|
+
<Collapsible.Trigger asChild>
|
|
199
|
+
<Button variant="ghost" size="sm">
|
|
200
|
+
Show nested fields
|
|
201
|
+
<ListPlusIcon size={18} className="ml-1.5" />
|
|
202
|
+
</Button>
|
|
203
|
+
</Collapsible.Trigger>
|
|
204
|
+
) : null}
|
|
205
|
+
|
|
206
|
+
<Collapsible.Content>
|
|
207
|
+
{property.type === "object" && (
|
|
208
|
+
<div className="mt-2.5">
|
|
209
|
+
<SchemaListView
|
|
210
|
+
schema={property}
|
|
211
|
+
level={nestingLevel + 1}
|
|
212
|
+
defaultOpen
|
|
213
|
+
/>
|
|
214
|
+
</div>
|
|
215
|
+
)}
|
|
216
|
+
{property.type === "array" && property.items.type === "object" && (
|
|
217
|
+
<div className="mt-2.5">
|
|
218
|
+
<SchemaListView
|
|
219
|
+
schema={property.items}
|
|
220
|
+
defaultOpen
|
|
221
|
+
level={nestingLevel + 1}
|
|
222
|
+
/>
|
|
223
|
+
</div>
|
|
224
|
+
)}
|
|
225
|
+
</Collapsible.Content>
|
|
226
|
+
</Collapsible.Root>
|
|
227
|
+
</div>
|
|
228
|
+
);
|
|
229
|
+
};
|