zudoku 0.43.0 → 0.43.2
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/config/validators/common.d.ts +193 -0
- package/dist/config/validators/common.js +2 -0
- package/dist/config/validators/common.js.map +1 -1
- package/dist/config/validators/validate.d.ts +70 -0
- package/dist/lib/components/Banner.js +1 -1
- package/dist/lib/components/Banner.js.map +1 -1
- package/dist/lib/components/Heading.d.ts +2 -2
- package/dist/lib/components/Heading.js +1 -1
- package/dist/lib/components/Heading.js.map +1 -1
- package/dist/lib/components/Layout.js +1 -1
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/Main.js +3 -2
- package/dist/lib/components/Main.js.map +1 -1
- package/dist/lib/components/MobileTopNavigation.js +1 -1
- package/dist/lib/components/MobileTopNavigation.js.map +1 -1
- package/dist/lib/components/Pagination.js +2 -2
- package/dist/lib/components/Pagination.js.map +1 -1
- package/dist/lib/components/Search.js +1 -1
- package/dist/lib/components/Search.js.map +1 -1
- package/dist/lib/components/TopNavigation.js +1 -1
- package/dist/lib/components/TopNavigation.js.map +1 -1
- package/dist/lib/components/navigation/PoweredByZudoku.js +1 -1
- package/dist/lib/components/navigation/PoweredByZudoku.js.map +1 -1
- package/dist/lib/components/navigation/Sidebar.js +1 -1
- package/dist/lib/components/navigation/Sidebar.js.map +1 -1
- package/dist/lib/components/navigation/SidebarCategory.js +9 -5
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/components/navigation/SidebarItem.js +2 -3
- package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
- package/dist/lib/components/navigation/Toc.js +2 -2
- package/dist/lib/components/navigation/Toc.js.map +1 -1
- package/dist/lib/core/ZudokuContext.d.ts +2 -1
- package/dist/lib/core/ZudokuContext.js.map +1 -1
- package/dist/lib/oas/parser/upgrade/index.d.ts +1 -0
- package/dist/lib/oas/parser/upgrade/index.js +76 -24
- package/dist/lib/oas/parser/upgrade/index.js.map +1 -1
- package/dist/lib/plugins/openapi/CollapsibleCode.js +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +4 -2
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/SchemaList.js +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +5 -0
- package/dist/lib/plugins/openapi/client/useCreateQuery.js +10 -4
- package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -1
- package/dist/lib/plugins/openapi/index.d.ts +3 -4
- package/dist/lib/plugins/openapi/index.js +6 -4
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +4 -3
- package/dist/lib/plugins/openapi/playground/IdentitySelector.js +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.js +2 -2
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/QueryParams.d.ts +1 -1
- package/dist/lib/plugins/openapi/playground/QueryParams.js +1 -1
- package/dist/lib/plugins/openapi/playground/SubmitButton.d.ts +1 -1
- package/dist/lib/plugins/openapi/playground/SubmitButton.js +1 -1
- package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js +1 -1
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +1 -1
- package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js +1 -1
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js +2 -2
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js.map +1 -1
- package/dist/lib/plugins/openapi/util/getRoutes.js +33 -3
- package/dist/lib/plugins/openapi/util/getRoutes.js.map +1 -1
- package/dist/lib/ui/SyntaxHighlight.js +1 -1
- package/dist/lib/ui/SyntaxHighlight.js.map +1 -1
- package/dist/lib/util/traverse.d.ts +1 -1
- package/dist/lib/util/traverse.js +6 -5
- package/dist/lib/util/traverse.js.map +1 -1
- package/dist/vite/build.js +1 -0
- package/dist/vite/build.js.map +1 -1
- package/dist/vite/dev-server.js +5 -2
- package/dist/vite/dev-server.js.map +1 -1
- package/dist/vite/html.d.ts +6 -2
- package/dist/vite/html.js +11 -8
- package/dist/vite/html.js.map +1 -1
- package/dist/vite/plugin-api.js +2 -2
- package/dist/vite/plugin-api.js.map +1 -1
- package/lib/{AuthenticationPlugin-ByDF051g.js → AuthenticationPlugin-BxoEZCSJ.js} +4 -4
- package/lib/{AuthenticationPlugin-ByDF051g.js.map → AuthenticationPlugin-BxoEZCSJ.js.map} +1 -1
- package/lib/{Markdown-mFpg_n9p.js → Markdown-DvdVn1O7.js} +1839 -1836
- package/lib/Markdown-DvdVn1O7.js.map +1 -0
- package/lib/{MdxPage-Cm7atiW3.js → MdxPage-DUcuusMU.js} +7 -7
- package/lib/{MdxPage-Cm7atiW3.js.map → MdxPage-DUcuusMU.js.map} +1 -1
- package/lib/{OasProvider-DOs0v9u7.js → OasProvider-CjMm8pB7.js} +8 -9
- package/lib/{OasProvider-DOs0v9u7.js.map → OasProvider-CjMm8pB7.js.map} +1 -1
- package/lib/{OperationList-CKac6iap.js → OperationList-BhJcPgGi.js} +1269 -1261
- package/lib/{OperationList-CKac6iap.js.map → OperationList-BhJcPgGi.js.map} +1 -1
- package/lib/Pagination-BgQxwq5j.js +48 -0
- package/lib/Pagination-BgQxwq5j.js.map +1 -0
- package/lib/{RouteGuard-DRtEu9nh.js → RouteGuard-D2gX29iI.js} +3 -3
- package/lib/{RouteGuard-DRtEu9nh.js.map → RouteGuard-D2gX29iI.js.map} +1 -1
- package/lib/{SchemaList-BTX2mRMW.js → SchemaList-BexhT_Z0.js} +22 -23
- package/lib/{SchemaList-BTX2mRMW.js.map → SchemaList-BexhT_Z0.js.map} +1 -1
- package/lib/{SchemaView-BYRn_-2l.js → SchemaView-Dt_-u8rW.js} +123 -146
- package/lib/SchemaView-Dt_-u8rW.js.map +1 -0
- package/lib/{Select-CT64Ou40.js → Select-CYaEBIYK.js} +3 -3
- package/lib/{Select-CT64Ou40.js.map → Select-CYaEBIYK.js.map} +1 -1
- package/lib/{SlotletProvider-CS_nO-XT.js → SlotletProvider-wWbHYqWf.js} +7 -7
- package/lib/SlotletProvider-wWbHYqWf.js.map +1 -0
- package/lib/{SyntaxHighlight-CxhyyMkF.js → SyntaxHighlight-o7q0acut.js} +81 -81
- package/lib/{SyntaxHighlight-CxhyyMkF.js.map → SyntaxHighlight-o7q0acut.js.map} +1 -1
- package/lib/{Toc-D_tV8_Ri.js → Toc-BnN4zBb3.js} +17 -17
- package/lib/Toc-BnN4zBb3.js.map +1 -0
- package/lib/{chunk-BAXFHI7N-BVBOl9s0.js → chunk-BAXFHI7N-BLTsN6tl.js} +679 -659
- package/lib/{chunk-BAXFHI7N-BVBOl9s0.js.map → chunk-BAXFHI7N-BLTsN6tl.js.map} +1 -1
- package/lib/{circular-ByJI6Mci.js → circular-BWEIet3w.js} +4616 -5567
- package/lib/circular-BWEIet3w.js.map +1 -0
- package/lib/{createServer-IW7v5hWm.js → createServer-BQD3Eeqb.js} +1998 -1970
- package/lib/createServer-BQD3Eeqb.js.map +1 -0
- package/lib/{hook-CldJlP5c.js → hook-8GM2HXNM.js} +24 -24
- package/lib/{hook-CldJlP5c.js.map → hook-8GM2HXNM.js.map} +1 -1
- package/lib/index-CFf9AN-y.js +3208 -0
- package/lib/index-CFf9AN-y.js.map +1 -0
- package/lib/{index-DnQftvP4.js → index-DGNSSXgR.js} +77 -69
- package/lib/{index-DnQftvP4.js.map → index-DGNSSXgR.js.map} +1 -1
- package/lib/{mutation-DBQh7AOZ.js → mutation-Bq5bn7Hf.js} +2 -2
- package/lib/{mutation-DBQh7AOZ.js.map → mutation-Bq5bn7Hf.js.map} +1 -1
- package/lib/processors/traverse.js +9 -7
- package/lib/processors/traverse.js.map +1 -1
- package/lib/ui/SyntaxHighlight.js +1 -1
- package/lib/{useExposedProps-DbIZXspi.js → useExposedProps-DmTJxEXG.js} +2 -2
- package/lib/{useExposedProps-DbIZXspi.js.map → useExposedProps-DmTJxEXG.js.map} +1 -1
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-clerk.js +2 -2
- package/lib/zudoku.auth-openid.js +3 -3
- package/lib/zudoku.components.js +6 -6
- package/lib/zudoku.hooks.js +1 -1
- package/lib/zudoku.plugin-api-catalog.js +5 -5
- package/lib/zudoku.plugin-api-keys.js +4 -4
- package/lib/zudoku.plugin-custom-pages.js +2 -2
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +6 -5
- package/lib/zudoku.plugin-redirect.js +1 -1
- package/lib/zudoku.plugin-search-pagefind.js +3 -3
- package/package.json +3 -3
- package/src/app/demo.html +1 -1
- package/src/app/main.css +2 -2
- package/src/lib/components/Banner.tsx +1 -1
- package/src/lib/components/Heading.tsx +3 -3
- package/src/lib/components/Layout.tsx +1 -4
- package/src/lib/components/Main.tsx +4 -3
- package/src/lib/components/MobileTopNavigation.tsx +2 -2
- package/src/lib/components/Pagination.tsx +3 -3
- package/src/lib/components/Search.tsx +1 -1
- package/src/lib/components/TopNavigation.tsx +1 -1
- package/src/lib/components/navigation/PoweredByZudoku.tsx +6 -1
- package/src/lib/components/navigation/Sidebar.tsx +1 -1
- package/src/lib/components/navigation/SidebarCategory.tsx +9 -5
- package/src/lib/components/navigation/SidebarItem.tsx +2 -3
- package/src/lib/components/navigation/Toc.tsx +4 -4
- package/src/lib/core/ZudokuContext.ts +2 -1
- package/src/lib/oas/parser/upgrade/index.ts +97 -27
- package/src/lib/plugins/openapi/CollapsibleCode.tsx +2 -2
- package/src/lib/plugins/openapi/OperationList.tsx +1 -1
- package/src/lib/plugins/openapi/OperationListItem.tsx +15 -6
- package/src/lib/plugins/openapi/SchemaList.tsx +1 -1
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +23 -4
- package/src/lib/plugins/openapi/index.tsx +8 -7
- package/src/lib/plugins/openapi/interfaces.ts +4 -3
- package/src/lib/plugins/openapi/playground/IdentitySelector.tsx +2 -2
- package/src/lib/plugins/openapi/playground/Playground.tsx +5 -5
- package/src/lib/plugins/openapi/playground/QueryParams.tsx +2 -2
- package/src/lib/plugins/openapi/playground/SubmitButton.tsx +2 -2
- package/src/lib/plugins/openapi/playground/result-panel/RequestTab.tsx +2 -2
- package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +1 -1
- package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +1 -1
- package/src/lib/plugins/openapi/schema/SchemaPropertyItem.tsx +2 -2
- package/src/lib/plugins/openapi/util/getRoutes.tsx +67 -3
- package/src/lib/ui/SyntaxHighlight.tsx +2 -2
- package/src/lib/util/traverse.ts +8 -5
- package/lib/Markdown-mFpg_n9p.js.map +0 -1
- package/lib/Pagination-DLPL5z77.js +0 -48
- package/lib/Pagination-DLPL5z77.js.map +0 -1
- package/lib/SchemaView-BYRn_-2l.js.map +0 -1
- package/lib/SlotletProvider-CS_nO-XT.js.map +0 -1
- package/lib/Toc-D_tV8_Ri.js.map +0 -1
- package/lib/circular-ByJI6Mci.js.map +0 -1
- package/lib/context-Lrf2Y9bR.js +0 -22
- package/lib/context-Lrf2Y9bR.js.map +0 -1
- package/lib/createServer-IW7v5hWm.js.map +0 -1
- package/lib/index-DuB48L78.js +0 -2184
- package/lib/index-DuB48L78.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cva } from "class-variance-authority";
|
|
2
2
|
import { ExternalLinkIcon } from "lucide-react";
|
|
3
|
-
import { NavLink, useLocation
|
|
3
|
+
import { NavLink, useLocation } from "react-router";
|
|
4
4
|
|
|
5
5
|
import type { SidebarItem as SidebarItemType } from "../../../config/validators/SidebarSchema.js";
|
|
6
6
|
import { joinUrl } from "../../util/joinUrl.js";
|
|
@@ -43,7 +43,6 @@ export const SidebarItem = ({
|
|
|
43
43
|
}) => {
|
|
44
44
|
const location = useLocation();
|
|
45
45
|
const { activeAnchor } = useViewportAnchor();
|
|
46
|
-
const [searchParams] = useSearchParams();
|
|
47
46
|
|
|
48
47
|
switch (item.type) {
|
|
49
48
|
case "category":
|
|
@@ -79,7 +78,7 @@ export const SidebarItem = ({
|
|
|
79
78
|
to={{
|
|
80
79
|
pathname: item.href.split("#")[0],
|
|
81
80
|
hash: item.href.split("#")[1],
|
|
82
|
-
search:
|
|
81
|
+
search: location.search,
|
|
83
82
|
}}
|
|
84
83
|
{...{ [DATA_ANCHOR_ATTR]: item.href.split("#")[1] }}
|
|
85
84
|
className={navigationListItem({
|
|
@@ -86,10 +86,10 @@ export const Toc = ({ entries }: { entries: TocEntry[] }) => {
|
|
|
86
86
|
On this page
|
|
87
87
|
</div>
|
|
88
88
|
<div className="relative ms-2 ps-4">
|
|
89
|
-
<div className="absolute inset-0
|
|
89
|
+
<div className="absolute inset-0 end-auto bg-border w-[2px]" />
|
|
90
90
|
<div
|
|
91
91
|
className={cn(
|
|
92
|
-
"absolute -
|
|
92
|
+
"absolute -start-px -translate-y-1 h-6 w-[4px] rounded bg-primary",
|
|
93
93
|
paintedOnce.current &&
|
|
94
94
|
"ease-out [transition:top_150ms,opacity_325ms]",
|
|
95
95
|
)}
|
|
@@ -104,10 +104,10 @@ export const Toc = ({ entries }: { entries: TocEntry[] }) => {
|
|
|
104
104
|
isActive={item.id === activeAnchor}
|
|
105
105
|
key={item.id}
|
|
106
106
|
item={item}
|
|
107
|
-
className="
|
|
107
|
+
className="ps-0"
|
|
108
108
|
>
|
|
109
109
|
{item.children && (
|
|
110
|
-
<ul className="list-none
|
|
110
|
+
<ul className="list-none ps-4 pt-2 space-y-2">
|
|
111
111
|
{item.children.map((child) => (
|
|
112
112
|
<TocItem
|
|
113
113
|
item={child}
|
|
@@ -10,7 +10,7 @@ import type { OpenAPIDocument } from "../index.js";
|
|
|
10
10
|
|
|
11
11
|
export const upgradeSchema = (schema: RecordAny): OpenAPIDocument => {
|
|
12
12
|
if (schema.openapi?.startsWith("3.0")) {
|
|
13
|
-
schema.openapi = "3.1.
|
|
13
|
+
schema.openapi = "3.1.1";
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
schema = traverse(schema, (sub) => {
|
|
@@ -40,26 +40,17 @@ export const upgradeSchema = (schema: RecordAny): OpenAPIDocument => {
|
|
|
40
40
|
return sub;
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
schema = traverse(schema, (sub) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
(sub.example.summary !== undefined ||
|
|
49
|
-
sub.example.description !== undefined ||
|
|
50
|
-
sub.example.value !== undefined ||
|
|
51
|
-
sub.example.externalValue !== undefined);
|
|
52
|
-
|
|
53
|
-
const exampleValue = isExampleObject
|
|
54
|
-
? sub.example
|
|
55
|
-
: { value: sub.example };
|
|
56
|
-
|
|
57
|
-
if (!sub.examples) {
|
|
58
|
-
sub.examples = { default: exampleValue };
|
|
43
|
+
schema = traverse(schema, (sub, path) => {
|
|
44
|
+
if (sub.example !== undefined) {
|
|
45
|
+
// Arrays in schemas
|
|
46
|
+
if (isSchemaPath(path ?? [])) {
|
|
47
|
+
sub.examples = [sub.example];
|
|
59
48
|
} else {
|
|
49
|
+
// Objects everywhere else
|
|
60
50
|
sub.examples = {
|
|
61
|
-
default:
|
|
62
|
-
|
|
51
|
+
default: {
|
|
52
|
+
value: sub.example,
|
|
53
|
+
},
|
|
63
54
|
};
|
|
64
55
|
}
|
|
65
56
|
delete sub.example;
|
|
@@ -67,17 +58,54 @@ export const upgradeSchema = (schema: RecordAny): OpenAPIDocument => {
|
|
|
67
58
|
return sub;
|
|
68
59
|
});
|
|
69
60
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
61
|
+
// Multipart file uploads with a binary file
|
|
62
|
+
schema = traverse(schema, (schema, path) => {
|
|
63
|
+
if (schema.type === "object" && schema.properties !== undefined) {
|
|
64
|
+
// Check if this is a multipart request body schema
|
|
65
|
+
const parentPath = path?.slice(0, -1);
|
|
66
|
+
const isMultipart = parentPath?.some((segment, index) => {
|
|
67
|
+
return (
|
|
68
|
+
segment === "content" && path?.[index + 1] === "multipart/form-data"
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (isMultipart) {
|
|
73
|
+
// Types
|
|
74
|
+
const entries: [string, any][] = Object.entries(schema.properties);
|
|
75
|
+
|
|
76
|
+
for (const [, value] of entries) {
|
|
77
|
+
if (
|
|
78
|
+
typeof value === "object" &&
|
|
79
|
+
value.type === "string" &&
|
|
80
|
+
value.format === "binary"
|
|
81
|
+
) {
|
|
82
|
+
value.contentMediaType = "application/octet-stream";
|
|
83
|
+
delete value.format;
|
|
84
|
+
}
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
87
|
}
|
|
80
|
-
|
|
88
|
+
|
|
89
|
+
return schema;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Uploading a binary file in a POST request
|
|
93
|
+
schema = traverse(schema, (schema, path) => {
|
|
94
|
+
if (
|
|
95
|
+
path?.includes("content") &&
|
|
96
|
+
path.includes("application/octet-stream")
|
|
97
|
+
) {
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (schema.type === "string" && schema.format === "binary") {
|
|
102
|
+
return {
|
|
103
|
+
type: "string",
|
|
104
|
+
contentMediaType: "application/octet-stream",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return schema;
|
|
81
109
|
});
|
|
82
110
|
|
|
83
111
|
schema = traverse(schema, (sub) => {
|
|
@@ -88,6 +116,7 @@ export const upgradeSchema = (schema: RecordAny): OpenAPIDocument => {
|
|
|
88
116
|
return sub;
|
|
89
117
|
});
|
|
90
118
|
|
|
119
|
+
// Uploading an image with base64 encoding
|
|
91
120
|
schema = traverse(schema, (sub) => {
|
|
92
121
|
if (sub.type === "string" && sub.format === "base64") {
|
|
93
122
|
return {
|
|
@@ -99,5 +128,46 @@ export const upgradeSchema = (schema: RecordAny): OpenAPIDocument => {
|
|
|
99
128
|
return sub;
|
|
100
129
|
});
|
|
101
130
|
|
|
131
|
+
schema = traverse(schema, (schema, path) => {
|
|
132
|
+
if (schema.type === "string" && schema.format === "byte") {
|
|
133
|
+
const parentPath = path?.slice(0, -1);
|
|
134
|
+
const contentMediaType = parentPath?.find(
|
|
135
|
+
(_, index) => path?.[index - 1] === "content",
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
type: "string",
|
|
140
|
+
contentEncoding: "base64",
|
|
141
|
+
contentMediaType,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return schema;
|
|
146
|
+
});
|
|
147
|
+
|
|
102
148
|
return schema as OpenAPIDocument;
|
|
103
149
|
};
|
|
150
|
+
|
|
151
|
+
export function isSchemaPath(path: string[]): boolean {
|
|
152
|
+
const schemaLocations = [
|
|
153
|
+
["components", "schemas"],
|
|
154
|
+
"properties",
|
|
155
|
+
"items",
|
|
156
|
+
"allOf",
|
|
157
|
+
"anyOf",
|
|
158
|
+
"oneOf",
|
|
159
|
+
"not",
|
|
160
|
+
"additionalProperties",
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
schemaLocations.some((location) => {
|
|
165
|
+
if (Array.isArray(location)) {
|
|
166
|
+
return location.every((segment, index) => path[index] === segment);
|
|
167
|
+
}
|
|
168
|
+
return path.includes(location);
|
|
169
|
+
}) ||
|
|
170
|
+
path.includes("schema") ||
|
|
171
|
+
path.some((segment) => segment.endsWith("Schema"))
|
|
172
|
+
);
|
|
173
|
+
}
|
|
@@ -59,7 +59,7 @@ export const CollapsibleCode = ({
|
|
|
59
59
|
>
|
|
60
60
|
<div>
|
|
61
61
|
<Button variant="outline" className="hidden group-hover:flex">
|
|
62
|
-
<UnfoldVerticalIcon size={14} className="
|
|
62
|
+
<UnfoldVerticalIcon size={14} className="me-1.5" />
|
|
63
63
|
Click to expand
|
|
64
64
|
</Button>
|
|
65
65
|
</div>
|
|
@@ -73,7 +73,7 @@ export const CollapsibleCode = ({
|
|
|
73
73
|
<CollapsibleTrigger asChild>
|
|
74
74
|
<Button variant="outline" size="sm">
|
|
75
75
|
Collapse
|
|
76
|
-
<FoldVerticalIcon size={14} className="
|
|
76
|
+
<FoldVerticalIcon size={14} className="ms-1.5" />
|
|
77
77
|
</Button>
|
|
78
78
|
</CollapsibleTrigger>
|
|
79
79
|
</div>
|
|
@@ -246,7 +246,7 @@ export const OperationList = ({
|
|
|
246
246
|
>
|
|
247
247
|
{schema.tag.name ?? "Other endpoints"}
|
|
248
248
|
{showVersions && (
|
|
249
|
-
<span className="text-xl text-muted-foreground
|
|
249
|
+
<span className="text-xl text-muted-foreground ms-1.5">
|
|
250
250
|
{" "}
|
|
251
251
|
({version})
|
|
252
252
|
</span>
|
|
@@ -11,6 +11,7 @@ import { OperationsFragment } from "./OperationList.js";
|
|
|
11
11
|
import { ParameterList } from "./ParameterList.js";
|
|
12
12
|
import { Sidecar } from "./Sidecar.js";
|
|
13
13
|
import { SelectOnClick } from "./components/SelectOnClick.js";
|
|
14
|
+
import { useOasConfig } from "./context.js";
|
|
14
15
|
import { type FragmentType, useFragment } from "./graphql/index.js";
|
|
15
16
|
import { SchemaView } from "./schema/SchemaView.js";
|
|
16
17
|
import { methodForColor } from "./util/methodToColor.js";
|
|
@@ -30,6 +31,7 @@ export const OperationListItem = ({
|
|
|
30
31
|
operation.parameters ?? [],
|
|
31
32
|
(param) => param.in,
|
|
32
33
|
);
|
|
34
|
+
const { options } = useOasConfig();
|
|
33
35
|
|
|
34
36
|
const first = operation.responses.at(0);
|
|
35
37
|
const [selectedResponse, setSelectedResponse] = useState(first?.statusCode);
|
|
@@ -72,7 +74,12 @@ export const OperationListItem = ({
|
|
|
72
74
|
</SelectOnClick>
|
|
73
75
|
</div>
|
|
74
76
|
|
|
75
|
-
<div
|
|
77
|
+
<div
|
|
78
|
+
className={cn(
|
|
79
|
+
"flex flex-col gap-4",
|
|
80
|
+
options?.disableSidecar && "col-span-full",
|
|
81
|
+
)}
|
|
82
|
+
>
|
|
76
83
|
{operation.description && (
|
|
77
84
|
<Markdown
|
|
78
85
|
className={`${ProseClasses} max-w-full prose-img:max-w-prose`}
|
|
@@ -165,11 +172,13 @@ export const OperationListItem = ({
|
|
|
165
172
|
)}
|
|
166
173
|
</div>
|
|
167
174
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
175
|
+
{renderIf(!options?.disableSidecar, () => (
|
|
176
|
+
<Sidecar
|
|
177
|
+
selectedResponse={selectedResponse}
|
|
178
|
+
onSelectResponse={setSelectedResponse}
|
|
179
|
+
operation={operation}
|
|
180
|
+
/>
|
|
181
|
+
))}
|
|
173
182
|
</div>
|
|
174
183
|
</div>
|
|
175
184
|
);
|
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
import { stripIgnoredCharacters } from "graphql";
|
|
2
2
|
import { use } from "react";
|
|
3
3
|
import type { TypedDocumentString } from "../graphql/graphql.js";
|
|
4
|
+
import type { GraphQLClient } from "./GraphQLClient.js";
|
|
4
5
|
import { GraphQLContext } from "./GraphQLContext.js";
|
|
5
6
|
|
|
6
7
|
type NoExtraProps<T, U extends T = T> = U & {
|
|
7
8
|
[K in Exclude<keyof U, keyof T>]?: never;
|
|
8
9
|
};
|
|
9
10
|
|
|
11
|
+
type VarArgs<TVariables> =
|
|
12
|
+
TVariables extends Record<string, never> ? [] : [NoExtraProps<TVariables>];
|
|
13
|
+
|
|
14
|
+
export const createQuery = <TResult, TVariables>(
|
|
15
|
+
client: GraphQLClient,
|
|
16
|
+
query: TypedDocumentString<TResult, TVariables>,
|
|
17
|
+
...[variables]: TVariables extends Record<string, never>
|
|
18
|
+
? []
|
|
19
|
+
: [NoExtraProps<TVariables>]
|
|
20
|
+
) => {
|
|
21
|
+
return {
|
|
22
|
+
queryFn: () => client.fetch(query, variables),
|
|
23
|
+
queryKey: [stripIgnoredCharacters(query.toString()), variables],
|
|
24
|
+
} as const;
|
|
25
|
+
};
|
|
26
|
+
|
|
10
27
|
export const useCreateQuery = <TResult, TVariables>(
|
|
11
28
|
query: TypedDocumentString<TResult, TVariables>,
|
|
12
29
|
...[variables]: TVariables extends Record<string, never>
|
|
@@ -19,8 +36,10 @@ export const useCreateQuery = <TResult, TVariables>(
|
|
|
19
36
|
throw new Error("useGraphQL must be used within a GraphQLProvider");
|
|
20
37
|
}
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
const args =
|
|
40
|
+
variables === undefined
|
|
41
|
+
? ([] as VarArgs<TVariables>)
|
|
42
|
+
: ([variables] as VarArgs<TVariables>);
|
|
43
|
+
|
|
44
|
+
return createQuery(graphQLClient, query, ...args);
|
|
26
45
|
};
|
|
@@ -6,7 +6,8 @@ import { type ZudokuPlugin } from "../../core/plugins.js";
|
|
|
6
6
|
import { Button } from "../../ui/Button.js";
|
|
7
7
|
import { joinUrl } from "../../util/joinUrl.js";
|
|
8
8
|
import { GraphQLClient } from "./client/GraphQLClient.js";
|
|
9
|
-
import
|
|
9
|
+
import { createQuery } from "./client/useCreateQuery.js";
|
|
10
|
+
import type { GetSidebarOperationsQuery as GetSidebarOperationsQueryResult } from "./graphql/graphql.js";
|
|
10
11
|
import { graphql } from "./graphql/index.js";
|
|
11
12
|
import { type OasPluginConfig } from "./interfaces.js";
|
|
12
13
|
import type { PlaygroundContentProps } from "./playground/Playground.js";
|
|
@@ -14,7 +15,7 @@ import { PlaygroundDialog } from "./playground/PlaygroundDialog.js";
|
|
|
14
15
|
import { createSidebarCategory } from "./util/createSidebarCategory.js";
|
|
15
16
|
import { getRoutes, getVersions } from "./util/getRoutes.js";
|
|
16
17
|
|
|
17
|
-
const GetSidebarOperationsQuery = graphql(`
|
|
18
|
+
export const GetSidebarOperationsQuery = graphql(`
|
|
18
19
|
query GetSidebarOperations($input: JSON!, $type: SchemaType!) {
|
|
19
20
|
schema(input: $input, type: $type) {
|
|
20
21
|
tags {
|
|
@@ -39,7 +40,7 @@ const GetSidebarOperationsQuery = graphql(`
|
|
|
39
40
|
`);
|
|
40
41
|
|
|
41
42
|
export type OperationResult =
|
|
42
|
-
|
|
43
|
+
GetSidebarOperationsQueryResult["schema"]["tags"][number]["operations"][number];
|
|
43
44
|
|
|
44
45
|
export type OpenApiPluginOptions = OasPluginConfig;
|
|
45
46
|
|
|
@@ -132,11 +133,11 @@ export const openApiPlugin = (config: OasPluginConfig): ZudokuPlugin => {
|
|
|
132
133
|
const { type } = config;
|
|
133
134
|
const input = type === "file" ? config.input[version!] : config.input;
|
|
134
135
|
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
client.fetch(GetSidebarOperationsQuery, { type, input }),
|
|
136
|
+
const query = createQuery(client, GetSidebarOperationsQuery, {
|
|
137
|
+
type,
|
|
138
|
+
input,
|
|
139
139
|
});
|
|
140
|
+
const data = await context.queryClient.ensureQueryData(query);
|
|
140
141
|
|
|
141
142
|
const categories = data.schema.tags.flatMap((tag) => {
|
|
142
143
|
if (!tag.name || tag.operations.length === 0) return [];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AuthState } from "../../authentication/state.js";
|
|
2
|
-
import { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
1
|
+
import { type AuthState } from "../../authentication/state.js";
|
|
2
|
+
import { type ZudokuContext } from "../../core/ZudokuContext.js";
|
|
3
3
|
import type { SchemaImports } from "../../oas/graphql/index.js";
|
|
4
|
-
import { OperationListItemResult } from "./OperationList.js";
|
|
4
|
+
import { type OperationListItemResult } from "./OperationList.js";
|
|
5
5
|
|
|
6
6
|
type DynamicInput = () => Promise<unknown>;
|
|
7
7
|
|
|
@@ -49,6 +49,7 @@ type BaseOasConfig = {
|
|
|
49
49
|
options?: {
|
|
50
50
|
examplesLanguage?: string;
|
|
51
51
|
disablePlayground?: boolean;
|
|
52
|
+
disableSidecar?: boolean;
|
|
52
53
|
showVersionSelect?: "always" | "if-available" | "hide";
|
|
53
54
|
expandAllTags?: boolean;
|
|
54
55
|
transformExamples?: transformExamples;
|
|
@@ -29,7 +29,7 @@ const IdentitySelector = ({
|
|
|
29
29
|
<RadioGroupItem value={NO_IDENTITY} id="none">
|
|
30
30
|
None
|
|
31
31
|
</RadioGroupItem>
|
|
32
|
-
<Label htmlFor="none" className="
|
|
32
|
+
<Label htmlFor="none" className="ms-2">
|
|
33
33
|
None
|
|
34
34
|
</Label>
|
|
35
35
|
</Label>
|
|
@@ -41,7 +41,7 @@ const IdentitySelector = ({
|
|
|
41
41
|
<RadioGroupItem value={identity.id} id={identity.id}>
|
|
42
42
|
{identity.label}
|
|
43
43
|
</RadioGroupItem>
|
|
44
|
-
<Label htmlFor={identity.id} className="
|
|
44
|
+
<Label htmlFor={identity.id} className="ms-2">
|
|
45
45
|
{identity.label}
|
|
46
46
|
</Label>
|
|
47
47
|
</Label>
|
|
@@ -379,7 +379,7 @@ export const Playground = ({
|
|
|
379
379
|
/>
|
|
380
380
|
|
|
381
381
|
<div className="grid grid-cols-2 text-sm h-full">
|
|
382
|
-
<div className="flex flex-col gap-4 p-4 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:
|
|
382
|
+
<div className="flex flex-col gap-4 p-4 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:start-auto">
|
|
383
383
|
<div className="flex gap-2 items-stretch">
|
|
384
384
|
<div className="flex flex-1 items-center w-full border rounded-md">
|
|
385
385
|
<div className="border-r p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono flex items-center">
|
|
@@ -406,25 +406,25 @@ export const Playground = ({
|
|
|
406
406
|
Parameters
|
|
407
407
|
{(formState.pathParams.some((p) => p.value !== "") ||
|
|
408
408
|
formState.queryParams.some((p) => p.active)) && (
|
|
409
|
-
<div className="w-2 h-2 rounded-full bg-blue-400
|
|
409
|
+
<div className="w-2 h-2 rounded-full bg-blue-400 ms-2" />
|
|
410
410
|
)}
|
|
411
411
|
</TabsTrigger>
|
|
412
412
|
<TabsTrigger value="headers">
|
|
413
413
|
Headers
|
|
414
414
|
{formState.headers.filter((h) => h.active).length > 0 && (
|
|
415
|
-
<div className="w-2 h-2 rounded-full bg-blue-400
|
|
415
|
+
<div className="w-2 h-2 rounded-full bg-blue-400 ms-2" />
|
|
416
416
|
)}
|
|
417
417
|
</TabsTrigger>
|
|
418
418
|
<TabsTrigger value="auth">
|
|
419
419
|
Auth
|
|
420
420
|
{formState.identity !== NO_IDENTITY && (
|
|
421
|
-
<div className="w-2 h-2 rounded-full bg-blue-400
|
|
421
|
+
<div className="w-2 h-2 rounded-full bg-blue-400 ms-2" />
|
|
422
422
|
)}
|
|
423
423
|
</TabsTrigger>
|
|
424
424
|
<TabsTrigger value="body">
|
|
425
425
|
Body
|
|
426
426
|
{formState.body && (
|
|
427
|
-
<div className="w-2 h-2 rounded-full bg-blue-400
|
|
427
|
+
<div className="w-2 h-2 rounded-full bg-blue-400 ms-2" />
|
|
428
428
|
)}
|
|
429
429
|
</TabsTrigger>
|
|
430
430
|
</TabsList>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Control,
|
|
2
|
+
type Control,
|
|
3
3
|
Controller,
|
|
4
4
|
useFieldArray,
|
|
5
5
|
useFormContext,
|
|
@@ -44,7 +44,7 @@ export const QueryParams = ({
|
|
|
44
44
|
render={({ field }) => (
|
|
45
45
|
<Checkbox
|
|
46
46
|
id={`queryParams.${i}.active`}
|
|
47
|
-
className="
|
|
47
|
+
className="me-2"
|
|
48
48
|
checked={field.value}
|
|
49
49
|
onCheckedChange={field.onChange}
|
|
50
50
|
/>
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
DropdownMenuTrigger,
|
|
10
10
|
} from "zudoku/ui/DropdownMenu.js";
|
|
11
11
|
import { RadioGroup, RadioGroupItem } from "zudoku/ui/RadioGroup.js";
|
|
12
|
-
import { ApiIdentity } from "../../../core/ZudokuContext.js";
|
|
12
|
+
import { type ApiIdentity } from "../../../core/ZudokuContext.js";
|
|
13
13
|
import { NO_IDENTITY } from "./Playground.js";
|
|
14
14
|
|
|
15
15
|
const SubmitButton = ({
|
|
@@ -59,7 +59,7 @@ const SubmitButton = ({
|
|
|
59
59
|
onMouseEnter={() => setDropdownValue(identity.id)}
|
|
60
60
|
onMouseLeave={() => setDropdownValue(undefined)}
|
|
61
61
|
>
|
|
62
|
-
<RadioGroupItem value={identity.id} className="
|
|
62
|
+
<RadioGroupItem value={identity.id} className="me-2" />
|
|
63
63
|
|
|
64
64
|
{identity.label}
|
|
65
65
|
</DropdownMenuItem>
|
|
@@ -36,7 +36,7 @@ export const RequestTab = ({
|
|
|
36
36
|
<span className="font-semibold">Headers</span>
|
|
37
37
|
</CollapsibleTrigger>
|
|
38
38
|
<CollapsibleContent>
|
|
39
|
-
<div className="grid grid-cols-[auto,1fr] gap-x-8 gap-y-1
|
|
39
|
+
<div className="grid grid-cols-[auto,1fr] gap-x-8 gap-y-1 ps-1.5 pt-2">
|
|
40
40
|
{headers.map(([key, value]) => (
|
|
41
41
|
<Fragment key={key}>
|
|
42
42
|
<div className="text-primary">{key}</div>
|
|
@@ -53,7 +53,7 @@ export const RequestTab = ({
|
|
|
53
53
|
<span className="font-semibold">Body</span>
|
|
54
54
|
</CollapsibleTrigger>
|
|
55
55
|
<CollapsibleContent>
|
|
56
|
-
<div className="
|
|
56
|
+
<div className="ps-0 pt-2">
|
|
57
57
|
<div
|
|
58
58
|
className={cn(
|
|
59
59
|
"whitespace-pre-wrap break-all bg-muted p-2 rounded-md",
|
|
@@ -135,7 +135,7 @@ export const ResponseTab = ({
|
|
|
135
135
|
<span className="font-semibold">Headers</span>
|
|
136
136
|
</CollapsibleTrigger>
|
|
137
137
|
<CollapsibleContent>
|
|
138
|
-
<div className="grid grid-cols-[auto,1fr] gap-x-8 gap-y-1
|
|
138
|
+
<div className="grid grid-cols-[auto,1fr] gap-x-8 gap-y-1 ps-1.5 pt-2 font-mono text-xs">
|
|
139
139
|
{sortedHeaders.slice(0, 5).map(([key, value]) => (
|
|
140
140
|
<Fragment key={key}>
|
|
141
141
|
<div className="text-primary whitespace-pre">{key}</div>
|
|
@@ -69,7 +69,7 @@ export const SchemaPropertyItem = ({
|
|
|
69
69
|
return (
|
|
70
70
|
<li className="p-4 bg-border/20 hover:bg-border/30">
|
|
71
71
|
<div className="flex flex-col gap-2.5 justify-between text-sm">
|
|
72
|
-
<div className="space-x-2">
|
|
72
|
+
<div className="space-x-2 rtl:space-x-reverse">
|
|
73
73
|
<code>{name}</code>
|
|
74
74
|
<ParamInfos
|
|
75
75
|
schema={schema}
|
|
@@ -85,7 +85,7 @@ export const SchemaPropertyItem = ({
|
|
|
85
85
|
return (
|
|
86
86
|
<li className="p-4 bg-border/20 hover:bg-border/30">
|
|
87
87
|
<div className="flex flex-col gap-2.5 justify-between text-sm">
|
|
88
|
-
<div className="space-x-2">
|
|
88
|
+
<div className="space-x-2 rtl:space-x-reverse">
|
|
89
89
|
<SelectOnClick asChild>
|
|
90
90
|
<code>{name}</code>
|
|
91
91
|
</SelectOnClick>
|
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
2
|
+
import {
|
|
3
|
+
generatePath,
|
|
4
|
+
Navigate,
|
|
5
|
+
redirect,
|
|
6
|
+
type RouteObject,
|
|
7
|
+
useLocation,
|
|
8
|
+
useParams,
|
|
9
|
+
} from "react-router";
|
|
2
10
|
import { joinUrl } from "../../../util/joinUrl.js";
|
|
3
11
|
import type { GraphQLClient } from "../client/GraphQLClient.js";
|
|
4
|
-
import {
|
|
12
|
+
import { useCreateQuery } from "../client/useCreateQuery.js";
|
|
13
|
+
import { useOasConfig } from "../context.js";
|
|
14
|
+
import {
|
|
15
|
+
GetSidebarOperationsQuery,
|
|
16
|
+
type OpenApiPluginOptions,
|
|
17
|
+
UNTAGGED_PATH,
|
|
18
|
+
} from "../index.js";
|
|
5
19
|
import type { OasPluginConfig } from "../interfaces.js";
|
|
6
20
|
|
|
7
21
|
// Creates the main provider route that wraps operation routes.
|
|
@@ -47,6 +61,56 @@ const createRoute = ({
|
|
|
47
61
|
},
|
|
48
62
|
});
|
|
49
63
|
|
|
64
|
+
const NonTagPagesOperationList = ({
|
|
65
|
+
render,
|
|
66
|
+
path,
|
|
67
|
+
}: {
|
|
68
|
+
render: (tag: string) => React.ReactNode;
|
|
69
|
+
path: string;
|
|
70
|
+
}) => {
|
|
71
|
+
const { type, input } = useOasConfig();
|
|
72
|
+
const { tag: currentTag } = useParams();
|
|
73
|
+
const location = useLocation();
|
|
74
|
+
const query = useCreateQuery(GetSidebarOperationsQuery, { type, input });
|
|
75
|
+
const {
|
|
76
|
+
data: { schema },
|
|
77
|
+
} = useSuspenseQuery(query);
|
|
78
|
+
|
|
79
|
+
const firstTag = schema.tags.at(0);
|
|
80
|
+
|
|
81
|
+
if (!currentTag && firstTag?.slug) {
|
|
82
|
+
return (
|
|
83
|
+
<Navigate
|
|
84
|
+
to={{
|
|
85
|
+
pathname: generatePath(path, { tag: firstTag.slug }),
|
|
86
|
+
search: location.search,
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (currentTag && schema.tags.some((t) => t.slug === currentTag)) {
|
|
93
|
+
return render(currentTag);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return null;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const createNonTagPagesRoute = ({ path }: { path: string }): RouteObject => ({
|
|
100
|
+
path,
|
|
101
|
+
async lazy() {
|
|
102
|
+
const { OperationList } = await import("../OperationList.js");
|
|
103
|
+
return {
|
|
104
|
+
element: (
|
|
105
|
+
<NonTagPagesOperationList
|
|
106
|
+
path={path}
|
|
107
|
+
render={(tag) => <OperationList tag={tag} />}
|
|
108
|
+
/>
|
|
109
|
+
),
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
50
114
|
const createAdditionalRoutes = (basePath: string) => [
|
|
51
115
|
// Category without tagged operations
|
|
52
116
|
createRoute({
|
|
@@ -106,7 +170,7 @@ export const getRoutes = ({
|
|
|
106
170
|
basePath,
|
|
107
171
|
routePath: basePath,
|
|
108
172
|
routes: [
|
|
109
|
-
|
|
173
|
+
createNonTagPagesRoute({ path: basePath + "/:tag?" }),
|
|
110
174
|
...createAdditionalRoutes(basePath),
|
|
111
175
|
],
|
|
112
176
|
client,
|