zudoku 0.27.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/main.js +1 -2
- package/dist/app/main.js.map +1 -1
- package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
- package/dist/lib/components/PathRenderer.d.ts +11 -0
- package/dist/lib/components/PathRenderer.js +25 -0
- package/dist/lib/components/PathRenderer.js.map +1 -0
- package/dist/lib/components/ThemeSwitch.js +4 -4
- package/dist/lib/components/ThemeSwitch.js.map +1 -1
- package/dist/lib/components/index.d.ts +1 -0
- package/dist/lib/components/index.js +4 -2
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/components/navigation/SidebarCategory.js +17 -15
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/oas/graphql/circular.js +17 -6
- package/dist/lib/oas/graphql/circular.js.map +1 -1
- package/dist/lib/oas/graphql/index.d.ts +1 -0
- package/dist/lib/oas/graphql/index.js +41 -23
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/plugins/openapi/ColorizedParam.js +3 -1
- package/dist/lib/plugins/openapi/ColorizedParam.js.map +1 -1
- package/dist/lib/plugins/openapi/Endpoint.js +2 -2
- package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
- package/dist/lib/plugins/openapi/{Route.d.ts → OpenApiRoute.d.ts} +2 -1
- package/dist/lib/plugins/openapi/{Route.js → OpenApiRoute.js} +3 -4
- package/dist/lib/plugins/openapi/OpenApiRoute.js.map +1 -0
- package/dist/lib/plugins/openapi/OperationList.d.ts +4 -1
- package/dist/lib/plugins/openapi/OperationList.js +20 -14
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.d.ts +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +2 -0
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +6 -11
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/SidecarExamples.js +17 -14
- package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +6 -2
- package/dist/lib/plugins/openapi/graphql/gql.js +3 -2
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +47 -26
- package/dist/lib/plugins/openapi/graphql/graphql.js +20 -16
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/index.js +97 -54
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +1 -0
- package/dist/lib/plugins/openapi/playground/PathParams.js +1 -1
- package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.js +7 -15
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/schema/{SchemaComponents.js → SchemaPropertyItem.js} +10 -8
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js.map +1 -0
- package/dist/lib/plugins/openapi/schema/SchemaView.js +1 -1
- package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
- package/dist/lib/plugins/openapi/schema/utils.d.ts +1 -0
- package/dist/lib/plugins/openapi/schema/utils.js +2 -0
- package/dist/lib/plugins/openapi/schema/utils.js.map +1 -1
- package/dist/lib/util/joinUrl.js +1 -1
- package/dist/lib/util/joinUrl.js.map +1 -1
- package/dist/lib/util/joinUrl.test.d.ts +1 -0
- package/dist/lib/util/joinUrl.test.js +43 -0
- package/dist/lib/util/joinUrl.test.js.map +1 -0
- package/dist/vite/plugin-api.js +9 -1
- package/dist/vite/plugin-api.js.map +1 -1
- package/dist/vite/prerender.js +0 -1
- package/dist/vite/prerender.js.map +1 -1
- package/lib/{AuthenticationPlugin-CO_YCd2x.js → AuthenticationPlugin-Du8cLBSr.js} +2 -2
- package/lib/{AuthenticationPlugin-CO_YCd2x.js.map → AuthenticationPlugin-Du8cLBSr.js.map} +1 -1
- package/lib/{Markdown-B8o9Qz4q.js → Markdown-Cyrx_JrO.js} +8 -9
- package/lib/{Markdown-B8o9Qz4q.js.map → Markdown-Cyrx_JrO.js.map} +1 -1
- package/lib/{MdxPage-BxRt3Ly7.js → MdxPage-BuG8Tuwc.js} +5 -5
- package/lib/{MdxPage-BxRt3Ly7.js.map → MdxPage-BuG8Tuwc.js.map} +1 -1
- package/lib/OpenApiRoute-UrC_t0e5.js +36 -0
- package/lib/OpenApiRoute-UrC_t0e5.js.map +1 -0
- package/lib/{OperationList-DH-zIgtq.js → OperationList-CDt1xdc4.js} +1312 -1303
- package/lib/OperationList-CDt1xdc4.js.map +1 -0
- package/lib/{Select-B7UXR0SB.js → Select-CnCZ4WhS.js} +3 -3
- package/lib/{Select-B7UXR0SB.js.map → Select-CnCZ4WhS.js.map} +1 -1
- package/lib/{SlotletProvider-CtIp8rP3.js → SlotletProvider-mQiPDQIH.js} +2 -2
- package/lib/{SlotletProvider-CtIp8rP3.js.map → SlotletProvider-mQiPDQIH.js.map} +1 -1
- package/lib/{SyntaxHighlight-C1w1QPdY.js → SyntaxHighlight-B0L4SC_N.js} +11 -5
- package/lib/SyntaxHighlight-B0L4SC_N.js.map +1 -0
- package/lib/{ZudokuContext-8jts0fF3.js → ZudokuContext-BTUJPpQl.js} +21 -21
- package/lib/{ZudokuContext-8jts0fF3.js.map → ZudokuContext-BTUJPpQl.js.map} +1 -1
- package/lib/{circular-Dgpd6AN-.js → circular-DxaIIlWD.js} +251 -239
- package/lib/{circular-Dgpd6AN-.js.map → circular-DxaIIlWD.js.map} +1 -1
- package/lib/{createServer-BV0tHzLK.js → createServer-CjNktZzL.js} +821 -808
- package/lib/{createServer-BV0tHzLK.js.map → createServer-CjNktZzL.js.map} +1 -1
- package/lib/{hook-BG02esyv.js → hook-FT3SJLe_.js} +2 -2
- package/lib/{hook-BG02esyv.js.map → hook-FT3SJLe_.js.map} +1 -1
- package/lib/{index-LNp6rxyU.js → index-CjJS0l4l.js} +2 -2
- package/lib/{index-LNp6rxyU.js.map → index-CjJS0l4l.js.map} +1 -1
- package/lib/{index-DmqsUPcm.js → index-Eb1oiHbM.js} +881 -799
- package/lib/index-Eb1oiHbM.js.map +1 -0
- package/lib/{joinUrl-BTy9bvoK.js → joinUrl-nLx9pD-Z.js} +2 -2
- package/lib/joinUrl-nLx9pD-Z.js.map +1 -0
- package/lib/{useScrollToAnchor-Bl6mz9_x.js → useScrollToAnchor-BZsGmBng.js} +86 -90
- package/lib/useScrollToAnchor-BZsGmBng.js.map +1 -0
- package/lib/zudoku.auth-clerk.js +1 -1
- package/lib/zudoku.auth-openid.js +3 -3
- package/lib/zudoku.components.js +364 -348
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +3 -3
- package/lib/zudoku.plugin-api-keys.js +4 -4
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +6 -5
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/package.json +1 -1
- package/src/app/main.tsx +1 -2
- package/src/lib/components/PathRenderer.tsx +59 -0
- package/src/lib/components/ThemeSwitch.tsx +15 -14
- package/src/lib/components/index.ts +7 -5
- package/src/lib/components/navigation/SidebarCategory.tsx +44 -41
- package/src/lib/oas/graphql/circular.ts +27 -6
- package/src/lib/oas/graphql/index.ts +63 -35
- package/src/lib/plugins/openapi/ColorizedParam.tsx +3 -3
- package/src/lib/plugins/openapi/Endpoint.tsx +2 -2
- package/src/lib/plugins/openapi/{Route.tsx → OpenApiRoute.tsx} +3 -3
- package/src/lib/plugins/openapi/OperationList.tsx +34 -12
- package/src/lib/plugins/openapi/OperationListItem.tsx +6 -1
- package/src/lib/plugins/openapi/ParameterListItem.tsx +1 -1
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +2 -0
- package/src/lib/plugins/openapi/Sidecar.tsx +18 -27
- package/src/lib/plugins/openapi/SidecarExamples.tsx +24 -24
- package/src/lib/plugins/openapi/graphql/gql.ts +12 -4
- package/src/lib/plugins/openapi/graphql/graphql.ts +66 -43
- package/src/lib/plugins/openapi/index.tsx +125 -67
- package/src/lib/plugins/openapi/interfaces.ts +1 -0
- package/src/lib/plugins/openapi/playground/PathParams.tsx +1 -1
- package/src/lib/plugins/openapi/playground/Playground.tsx +23 -33
- package/src/lib/plugins/openapi/schema/{SchemaComponents.tsx → SchemaPropertyItem.tsx} +10 -6
- package/src/lib/plugins/openapi/schema/SchemaView.tsx +4 -1
- package/src/lib/plugins/openapi/schema/utils.ts +4 -0
- package/src/lib/util/joinUrl.test.ts +62 -0
- package/src/lib/util/joinUrl.ts +1 -1
- package/dist/lib/plugins/openapi/Route.js.map +0 -1
- package/dist/lib/plugins/openapi/schema/SchemaComponents.js.map +0 -1
- package/lib/OperationList-DH-zIgtq.js.map +0 -1
- package/lib/Route-DJ0ZlVq1.js +0 -35
- package/lib/Route-DJ0ZlVq1.js.map +0 -1
- package/lib/StaggeredRender-DgsamH_G.js +0 -17
- package/lib/StaggeredRender-DgsamH_G.js.map +0 -1
- package/lib/SyntaxHighlight-C1w1QPdY.js.map +0 -1
- package/lib/index-Bn6Lc9tq.js +0 -9
- package/lib/index-Bn6Lc9tq.js.map +0 -1
- package/lib/index-DmqsUPcm.js.map +0 -1
- package/lib/joinUrl-BTy9bvoK.js.map +0 -1
- package/lib/useScrollToAnchor-Bl6mz9_x.js.map +0 -1
- /package/dist/lib/plugins/openapi/schema/{SchemaComponents.d.ts → SchemaPropertyItem.d.ts} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-Bdg6XQ1m.js";
|
|
2
|
-
import { s as j } from "./index-
|
|
3
|
-
import { u as b } from "./ZudokuContext-
|
|
2
|
+
import { s as j } from "./index-CjJS0l4l.js";
|
|
3
|
+
import { u as b } from "./ZudokuContext-BTUJPpQl.js";
|
|
4
4
|
import { b as y } from "./chunk-SYFQ2XB5-BPvC-soB.js";
|
|
5
5
|
import { Head as v, Link as N } from "./zudoku.components.js";
|
|
6
6
|
import { u as w } from "./state-mM7uaXTW.js";
|
|
7
|
-
import { M as C } from "./Markdown-
|
|
7
|
+
import { M as C } from "./Markdown-Cyrx_JrO.js";
|
|
8
8
|
import { c as h } from "./cn-qaFjX9_3.js";
|
|
9
9
|
const f = (r, n) => j(`${r}-${n}`), k = ({
|
|
10
10
|
items: r,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-Bdg6XQ1m.js";
|
|
2
2
|
import { RotateCwIcon as g, TrashIcon as f, EyeOffIcon as j, EyeIcon as v, CheckIcon as w, CopyIcon as b, FileKey2Icon as K } from "lucide-react";
|
|
3
|
-
import { D as k, S as m, R as N } from "./SlotletProvider-
|
|
3
|
+
import { D as k, S as m, R as N } from "./SlotletProvider-mQiPDQIH.js";
|
|
4
4
|
import { i as c } from "./invariant-Caa8-XvF.js";
|
|
5
|
-
import { u as d, S as I, a as S, b as A, c as C, d as E, e as x } from "./Select-
|
|
5
|
+
import { u as d, S as I, a as S, b as A, c as C, d as E, e as x } from "./Select-CnCZ4WhS.js";
|
|
6
6
|
import { a as P } from "./index.esm-CrSoEshU.js";
|
|
7
7
|
import { a as D, L as u, O as R } from "./chunk-SYFQ2XB5-BPvC-soB.js";
|
|
8
|
-
import { a as y, e as q, u as O } from "./ZudokuContext-
|
|
8
|
+
import { a as y, e as q, u as O } from "./ZudokuContext-BTUJPpQl.js";
|
|
9
9
|
import { Button as l } from "./ui/Button.js";
|
|
10
10
|
import { Input as z } from "./ui/Input.js";
|
|
11
|
-
import { u as F } from "./hook-
|
|
11
|
+
import { u as F } from "./hook-FT3SJLe_.js";
|
|
12
12
|
import { useState as p } from "react";
|
|
13
13
|
import { c as T } from "./cn-qaFjX9_3.js";
|
|
14
14
|
const L = ({ service: t }) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as o } from "./jsx-runtime-Bdg6XQ1m.js";
|
|
2
2
|
import a from "react";
|
|
3
|
-
import { P as n } from "./Markdown-
|
|
3
|
+
import { P as n } from "./Markdown-Cyrx_JrO.js";
|
|
4
4
|
import { c } from "./cn-qaFjX9_3.js";
|
|
5
5
|
import { u as p } from "./useExposedProps-BLKFBylA.js";
|
|
6
6
|
const u = ({
|
|
@@ -74,7 +74,7 @@ const C = (n) => ({
|
|
|
74
74
|
const h = {
|
|
75
75
|
path: r,
|
|
76
76
|
lazy: async () => {
|
|
77
|
-
const { MdxPage: l } = await import("./MdxPage-
|
|
77
|
+
const { MdxPage: l } = await import("./MdxPage-BuG8Tuwc.js"), { default: p, ...g } = await a();
|
|
78
78
|
return {
|
|
79
79
|
element: /* @__PURE__ */ P.jsx(
|
|
80
80
|
l,
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import "./jsx-runtime-Bdg6XQ1m.js";
|
|
2
|
-
import "./
|
|
3
|
-
import { o as a } from "./index-DmqsUPcm.js";
|
|
2
|
+
import "./index-CjJS0l4l.js";
|
|
4
3
|
import "lucide-react";
|
|
5
|
-
import "./
|
|
4
|
+
import "./chunk-SYFQ2XB5-BPvC-soB.js";
|
|
5
|
+
import "./hook-FT3SJLe_.js";
|
|
6
6
|
import "./ui/Button.js";
|
|
7
|
-
import "./
|
|
7
|
+
import "./joinUrl-nLx9pD-Z.js";
|
|
8
|
+
import { o as f } from "./index-Eb1oiHbM.js";
|
|
8
9
|
export {
|
|
9
|
-
|
|
10
|
+
f as openApiPlugin
|
|
10
11
|
};
|
|
11
12
|
//# sourceMappingURL=zudoku.plugin-openapi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
package/package.json
CHANGED
package/src/app/main.tsx
CHANGED
|
@@ -11,12 +11,11 @@ import { configuredRedirectPlugin } from "virtual:zudoku-redirect-plugin";
|
|
|
11
11
|
import { configuredSearchPlugin } from "virtual:zudoku-search-plugin";
|
|
12
12
|
import { configuredSidebar } from "virtual:zudoku-sidebar";
|
|
13
13
|
import "virtual:zudoku-theme.css";
|
|
14
|
-
import { Layout, RouterError, Zudoku } from "zudoku/components";
|
|
14
|
+
import { Layout, RouteGuard, RouterError, Zudoku } from "zudoku/components";
|
|
15
15
|
import type { ZudokuConfig } from "../config/config.js";
|
|
16
16
|
import { StatusPage } from "../lib/components/StatusPage.js";
|
|
17
17
|
import type { ZudokuContextOptions } from "../lib/core/ZudokuContext.js";
|
|
18
18
|
import { isNavigationPlugin } from "../lib/core/plugins.js";
|
|
19
|
-
import { RouteGuard } from "../lib/core/RouteGuard.js";
|
|
20
19
|
|
|
21
20
|
export const convertZudokuConfigToOptions = (
|
|
22
21
|
config: ZudokuConfig,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Fragment, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
type PathParamProps = {
|
|
4
|
+
name: string;
|
|
5
|
+
index: number;
|
|
6
|
+
originalValue?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const PathRenderer = ({
|
|
10
|
+
path,
|
|
11
|
+
renderParam,
|
|
12
|
+
}: {
|
|
13
|
+
path: string;
|
|
14
|
+
renderParam: (props: PathParamProps) => ReactNode;
|
|
15
|
+
}) =>
|
|
16
|
+
path.split("/").map((part, i, arr) => {
|
|
17
|
+
const matches = Array.from(part.matchAll(/{([^}]+)}/g));
|
|
18
|
+
const elements: ReactNode[] = [];
|
|
19
|
+
let lastIndex = 0;
|
|
20
|
+
|
|
21
|
+
matches.forEach((match, matchIndex) => {
|
|
22
|
+
const [originalValue, name] = match;
|
|
23
|
+
if (!name) return;
|
|
24
|
+
const startIndex = match.index!;
|
|
25
|
+
|
|
26
|
+
if (startIndex > lastIndex) {
|
|
27
|
+
elements.push(
|
|
28
|
+
<Fragment key={`text-${lastIndex}-${startIndex}`}>
|
|
29
|
+
{part.slice(lastIndex, startIndex)}
|
|
30
|
+
</Fragment>,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
elements.push(
|
|
35
|
+
<Fragment key={`param-${name}`}>
|
|
36
|
+
{renderParam({ name, originalValue, index: matchIndex })}
|
|
37
|
+
</Fragment>,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
lastIndex = startIndex + originalValue.length;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (lastIndex < part.length) {
|
|
44
|
+
elements.push(
|
|
45
|
+
<Fragment key={`text-${lastIndex}-${part.length}`}>
|
|
46
|
+
{part.slice(lastIndex)}
|
|
47
|
+
</Fragment>,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
53
|
+
<Fragment key={`${part}-${i}`}>
|
|
54
|
+
{elements}
|
|
55
|
+
{i < arr.length - 1 && "/"}
|
|
56
|
+
<wbr />
|
|
57
|
+
</Fragment>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { MoonStarIcon, SunIcon } from "lucide-react";
|
|
2
2
|
import { useTheme } from "next-themes";
|
|
3
3
|
import { Button } from "zudoku/ui/Button.js";
|
|
4
|
-
import {
|
|
4
|
+
import { ClientOnly } from "./ClientOnly.js";
|
|
5
5
|
|
|
6
6
|
export const ThemeSwitch = () => {
|
|
7
7
|
const { resolvedTheme, setTheme } = useTheme();
|
|
8
8
|
const ThemeIcon = resolvedTheme === "dark" ? MoonStarIcon : SunIcon;
|
|
9
9
|
|
|
10
10
|
return (
|
|
11
|
-
<Button
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
<ClientOnly fallback={<Button variant="ghost" size="icon" />}>
|
|
12
|
+
<Button
|
|
13
|
+
variant="ghost"
|
|
14
|
+
size="icon"
|
|
15
|
+
aria-label={
|
|
16
|
+
resolvedTheme === "dark"
|
|
17
|
+
? "Switch to light mode"
|
|
18
|
+
: "Switch to dark mode"
|
|
19
|
+
}
|
|
20
|
+
onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
|
|
21
|
+
>
|
|
22
|
+
<ThemeIcon size={18} />
|
|
23
|
+
</Button>
|
|
24
|
+
</ClientOnly>
|
|
24
25
|
);
|
|
25
26
|
};
|
|
@@ -2,6 +2,7 @@ import { useMDXComponents as useMDXComponentsImport } from "@mdx-js/react";
|
|
|
2
2
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
3
3
|
import { Link as LinkImport } from "react-router";
|
|
4
4
|
import { useAuth as useAuthImport } from "../authentication/hook.js";
|
|
5
|
+
import { RouteGuard as RouteGuardImport } from "../core/RouteGuard.js";
|
|
5
6
|
import { RouterError as RouterErrorImport } from "../errors/RouterError.js";
|
|
6
7
|
import { ServerError as ServerErrorImport } from "../errors/ServerError.js";
|
|
7
8
|
import { Button as ButtonImport } from "../ui/Button.js";
|
|
@@ -10,16 +11,16 @@ import {
|
|
|
10
11
|
Bootstrap as BootstrapImport,
|
|
11
12
|
BootstrapStatic as BootstrapStaticImport,
|
|
12
13
|
} from "./Bootstrap.js";
|
|
13
|
-
import { ClientOnly as ClientOnlyImport } from "./ClientOnly.js";
|
|
14
|
-
import { Layout as LayoutImport } from "./Layout.js";
|
|
15
|
-
import { Markdown as MarkdownImport } from "./Markdown.js";
|
|
16
|
-
import { Spinner as SpinnerImport } from "./Spinner.js";
|
|
17
|
-
import { Zudoku as ZudokuImport } from "./Zudoku.js";
|
|
18
14
|
import {
|
|
19
15
|
CACHE_KEYS as CACHE_KEYS_IMPORT,
|
|
20
16
|
useCache as useCacheImport,
|
|
21
17
|
} from "./cache.js";
|
|
18
|
+
import { ClientOnly as ClientOnlyImport } from "./ClientOnly.js";
|
|
22
19
|
import { useZudoku as useZudokuImport } from "./context/ZudokuContext.js";
|
|
20
|
+
import { Layout as LayoutImport } from "./Layout.js";
|
|
21
|
+
import { Markdown as MarkdownImport } from "./Markdown.js";
|
|
22
|
+
import { Spinner as SpinnerImport } from "./Spinner.js";
|
|
23
|
+
import { Zudoku as ZudokuImport } from "./Zudoku.js";
|
|
23
24
|
|
|
24
25
|
export const useMDXComponents = /*@__PURE__*/ useMDXComponentsImport;
|
|
25
26
|
export const Layout = /*@__PURE__*/ LayoutImport;
|
|
@@ -27,6 +28,7 @@ export const RouterError = /*@__PURE__*/ RouterErrorImport;
|
|
|
27
28
|
export const ServerError = /*@__PURE__*/ ServerErrorImport;
|
|
28
29
|
export const Bootstrap = /*@__PURE__*/ BootstrapImport;
|
|
29
30
|
export const BootstrapStatic = /*@__PURE__*/ BootstrapStaticImport;
|
|
31
|
+
export const RouteGuard = /*@__PURE__*/ RouteGuardImport;
|
|
30
32
|
|
|
31
33
|
export const Head = /*@__PURE__*/ Helmet;
|
|
32
34
|
|
|
@@ -53,6 +53,22 @@ export const SidebarCategory = ({
|
|
|
53
53
|
</button>
|
|
54
54
|
);
|
|
55
55
|
|
|
56
|
+
const icon = category.icon && (
|
|
57
|
+
<category.icon
|
|
58
|
+
size={16}
|
|
59
|
+
className={cn("align-[-0.125em] ", isActive && "text-primary")}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const styles = navigationListItem({
|
|
64
|
+
className: [
|
|
65
|
+
"text-start font-medium",
|
|
66
|
+
isCollapsible || typeof category.link !== "undefined"
|
|
67
|
+
? "cursor-pointer"
|
|
68
|
+
: "cursor-default hover:bg-transparent",
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
|
|
56
72
|
return (
|
|
57
73
|
<Collapsible.Root
|
|
58
74
|
className="flex flex-col"
|
|
@@ -61,57 +77,44 @@ export const SidebarCategory = ({
|
|
|
61
77
|
onOpenChange={() => setOpen(true)}
|
|
62
78
|
>
|
|
63
79
|
<Collapsible.Trigger className="group" asChild disabled={!isCollapsible}>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{category.link?.type === "doc" ? (
|
|
83
|
-
<NavLink
|
|
84
|
-
to={joinPath(category.link.id)}
|
|
85
|
-
className="flex-1"
|
|
86
|
-
onClick={() => {
|
|
87
|
-
// if it is the current path and closed then open it because there's no path change to trigger the open
|
|
88
|
-
if (isActive && !open) {
|
|
89
|
-
setOpen(true);
|
|
90
|
-
}
|
|
91
|
-
}}
|
|
80
|
+
{category.link?.type === "doc" ? (
|
|
81
|
+
<NavLink
|
|
82
|
+
to={joinPath(category.link.id)}
|
|
83
|
+
className={styles}
|
|
84
|
+
onClick={() => {
|
|
85
|
+
setHasInteracted(true);
|
|
86
|
+
// if it is the current path and closed then open it because there's no path change to trigger the open
|
|
87
|
+
if (isActive && !open) {
|
|
88
|
+
setOpen(true);
|
|
89
|
+
}
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{icon}
|
|
93
|
+
<div
|
|
94
|
+
className={cn(
|
|
95
|
+
"flex items-center gap-2 justify-between w-full",
|
|
96
|
+
isActive ? "text-primary" : "text-foreground/80",
|
|
97
|
+
)}
|
|
92
98
|
>
|
|
93
|
-
<div
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
{ToggleButton}
|
|
101
|
-
</div>
|
|
102
|
-
</NavLink>
|
|
103
|
-
) : (
|
|
99
|
+
<div className="truncate">{category.label}</div>
|
|
100
|
+
{ToggleButton}
|
|
101
|
+
</div>
|
|
102
|
+
</NavLink>
|
|
103
|
+
) : (
|
|
104
|
+
<div onClick={() => setHasInteracted(true)} className={styles}>
|
|
105
|
+
{icon}
|
|
104
106
|
<div className="flex items-center justify-between w-full">
|
|
105
107
|
<div className="flex gap-2 truncate w-full">{category.label}</div>
|
|
106
108
|
{ToggleButton}
|
|
107
109
|
</div>
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
</div>
|
|
111
|
+
)}
|
|
110
112
|
</Collapsible.Trigger>
|
|
111
113
|
<Collapsible.Content
|
|
112
114
|
className={cn(
|
|
113
115
|
// CollapsibleContent class is used to animate and it should only be applied when the user has triggered the toggle
|
|
114
116
|
hasInteracted && "CollapsibleContent",
|
|
117
|
+
category.items.length === 0 && "hidden",
|
|
115
118
|
"ms-6 my-1",
|
|
116
119
|
)}
|
|
117
120
|
>
|
|
@@ -1,25 +1,46 @@
|
|
|
1
1
|
import { GraphQLJSON } from "graphql-type-json";
|
|
2
2
|
import { GraphQLScalarType } from "graphql/index.js";
|
|
3
|
+
import { RecordAny } from "../../util/traverse.js";
|
|
3
4
|
|
|
4
5
|
export const CIRCULAR_REF = "$[Circular Reference]";
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
const handleCircularRefs = (
|
|
8
|
+
obj: any,
|
|
9
|
+
visited = new Map<string, string[]>(),
|
|
10
|
+
path: string[] = [],
|
|
11
|
+
): any => {
|
|
6
12
|
if (obj === CIRCULAR_REF) return CIRCULAR_REF;
|
|
7
13
|
if (obj === null || typeof obj !== "object") return obj;
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
const currentPath = path.join(".");
|
|
16
|
+
|
|
17
|
+
if (obj.type === "object" && obj.properties) {
|
|
18
|
+
const schemaKey = Object.keys(obj.properties).sort().join("-");
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
if (visited.has(schemaKey)) {
|
|
21
|
+
const prevPaths = visited.get(schemaKey)!;
|
|
22
|
+
if (prevPaths.some((prev) => currentPath.startsWith(prev))) {
|
|
23
|
+
return CIRCULAR_REF;
|
|
24
|
+
}
|
|
25
|
+
visited.set(schemaKey, [...prevPaths, currentPath]);
|
|
26
|
+
} else {
|
|
27
|
+
visited.set(schemaKey, [currentPath]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
12
30
|
|
|
13
31
|
if (Array.isArray(obj)) {
|
|
14
|
-
return obj.map((item) =>
|
|
32
|
+
return obj.map((item, index) =>
|
|
33
|
+
handleCircularRefs(item, visited, [...path, `${index}`]),
|
|
34
|
+
);
|
|
15
35
|
}
|
|
16
36
|
|
|
17
|
-
const result:
|
|
37
|
+
const result: RecordAny = {};
|
|
18
38
|
for (const [key, value] of Object.entries(obj)) {
|
|
19
|
-
result[key] = handleCircularRefs(value, visited);
|
|
39
|
+
result[key] = handleCircularRefs(value, visited, [...path, key]);
|
|
20
40
|
}
|
|
21
41
|
return result;
|
|
22
42
|
};
|
|
43
|
+
|
|
23
44
|
export const GraphQLJSONSchema = new GraphQLScalarType({
|
|
24
45
|
...GraphQLJSON,
|
|
25
46
|
name: "JSONSchema",
|
|
@@ -67,15 +67,26 @@ const builder = new SchemaBuilder<{
|
|
|
67
67
|
};
|
|
68
68
|
Context: {
|
|
69
69
|
schema: OpenAPIDocument;
|
|
70
|
+
operations: GraphQLOperationObject[];
|
|
71
|
+
tags: TagObject[];
|
|
70
72
|
schemaImports?: SchemaImports;
|
|
73
|
+
currentTag?: string;
|
|
74
|
+
slugify: CountableSlugify;
|
|
71
75
|
};
|
|
72
76
|
}>({});
|
|
73
77
|
|
|
78
|
+
type GraphQLOperationObject = OperationObject & {
|
|
79
|
+
path: string;
|
|
80
|
+
method: string;
|
|
81
|
+
slug?: string;
|
|
82
|
+
parentTag?: string;
|
|
83
|
+
};
|
|
84
|
+
|
|
74
85
|
const JSONScalar = builder.addScalarType("JSON", GraphQLJSON);
|
|
75
86
|
const JSONObjectScalar = builder.addScalarType("JSONObject", GraphQLJSONObject);
|
|
76
87
|
const JSONSchemaScalar = builder.addScalarType("JSONSchema", GraphQLJSONSchema);
|
|
77
88
|
|
|
78
|
-
const getAllTags = (schema: OpenAPIDocument): TagObject[] => {
|
|
89
|
+
export const getAllTags = (schema: OpenAPIDocument): TagObject[] => {
|
|
79
90
|
const tags = schema.tags ?? [];
|
|
80
91
|
|
|
81
92
|
// Extract tags from operations
|
|
@@ -94,10 +105,10 @@ const getAllTags = (schema: OpenAPIDocument): TagObject[] => {
|
|
|
94
105
|
return [...tags, ...uniqueOperationTags.map((tag) => ({ name: tag }))];
|
|
95
106
|
};
|
|
96
107
|
|
|
97
|
-
const getAllOperations = (paths?: PathsObject
|
|
98
|
-
const
|
|
108
|
+
const getAllOperations = (paths?: PathsObject) => {
|
|
109
|
+
const start = performance.now();
|
|
99
110
|
|
|
100
|
-
|
|
111
|
+
const operations = Object.entries(paths ?? {}).flatMap(([path, value]) =>
|
|
101
112
|
HttpMethods.flatMap((method) => {
|
|
102
113
|
if (!value?.[method]) return [];
|
|
103
114
|
|
|
@@ -118,23 +129,17 @@ const getAllOperations = (paths?: PathsObject, tag?: string) => {
|
|
|
118
129
|
...operationParameters,
|
|
119
130
|
];
|
|
120
131
|
|
|
121
|
-
const slugData = {
|
|
122
|
-
summary: operation.summary,
|
|
123
|
-
operationId: operation.operationId,
|
|
124
|
-
path,
|
|
125
|
-
method,
|
|
126
|
-
};
|
|
127
|
-
|
|
128
132
|
return {
|
|
129
133
|
...operation,
|
|
130
134
|
method,
|
|
131
135
|
path,
|
|
132
136
|
parameters,
|
|
133
137
|
tags: operation.tags ?? [],
|
|
134
|
-
slug: createOperationSlug(slugify, slugData, tag),
|
|
135
138
|
};
|
|
136
139
|
}),
|
|
137
140
|
);
|
|
141
|
+
|
|
142
|
+
return operations;
|
|
138
143
|
};
|
|
139
144
|
|
|
140
145
|
const SchemaTag = builder.objectRef<TagObject>("SchemaTag").implement({
|
|
@@ -144,15 +149,19 @@ const SchemaTag = builder.objectRef<TagObject>("SchemaTag").implement({
|
|
|
144
149
|
operations: t.field({
|
|
145
150
|
type: [OperationItem],
|
|
146
151
|
resolve: (parent, _args, ctx) => {
|
|
147
|
-
const rootTags =
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
const rootTags = ctx.tags.map((tag) => tag.name);
|
|
153
|
+
return ctx.operations
|
|
154
|
+
.filter((item) =>
|
|
155
|
+
parent.name
|
|
156
|
+
? item.tags?.includes(parent.name)
|
|
157
|
+
: item.tags?.length === 0 ||
|
|
158
|
+
// If none of the tags are present in the root tags, then show them here
|
|
159
|
+
item.tags?.every((tag) => !rootTags.includes(tag)),
|
|
160
|
+
)
|
|
161
|
+
.map((item) => ({
|
|
162
|
+
...item,
|
|
163
|
+
parentTag: parent.name,
|
|
164
|
+
}));
|
|
156
165
|
},
|
|
157
166
|
}),
|
|
158
167
|
}),
|
|
@@ -300,12 +309,24 @@ const ResponseItem = builder
|
|
|
300
309
|
});
|
|
301
310
|
|
|
302
311
|
const OperationItem = builder
|
|
303
|
-
.objectRef<
|
|
304
|
-
OperationObject & { path: string; method: string; slug: string }
|
|
305
|
-
>("OperationItem")
|
|
312
|
+
.objectRef<GraphQLOperationObject>("OperationItem")
|
|
306
313
|
.implement({
|
|
307
314
|
fields: (t) => ({
|
|
308
|
-
slug: t.
|
|
315
|
+
slug: t.field({
|
|
316
|
+
type: "String",
|
|
317
|
+
resolve: (parent, _, ctx) => {
|
|
318
|
+
const slugData = {
|
|
319
|
+
summary: parent.summary,
|
|
320
|
+
operationId: parent.operationId,
|
|
321
|
+
path: parent.path,
|
|
322
|
+
method: parent.method,
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
//TODO: fix parent tag parent.tags
|
|
326
|
+
return createOperationSlug(ctx.slugify, slugData, parent.parentTag);
|
|
327
|
+
},
|
|
328
|
+
}),
|
|
329
|
+
|
|
309
330
|
path: t.exposeString("path"),
|
|
310
331
|
method: t.exposeString("method"),
|
|
311
332
|
operationId: t.exposeString("operationId", { nullable: true }),
|
|
@@ -414,8 +435,8 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
|
|
|
414
435
|
name: t.arg.string(),
|
|
415
436
|
},
|
|
416
437
|
type: [SchemaTag],
|
|
417
|
-
resolve: (root, args) => {
|
|
418
|
-
const tags = [...
|
|
438
|
+
resolve: (root, args, ctx) => {
|
|
439
|
+
const tags = [...ctx.tags, { name: "" }];
|
|
419
440
|
return args.name ? tags.filter((tag) => tag.name === args.name) : tags;
|
|
420
441
|
},
|
|
421
442
|
}),
|
|
@@ -426,15 +447,18 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
|
|
|
426
447
|
method: t.arg.string(),
|
|
427
448
|
operationId: t.arg.string(),
|
|
428
449
|
tag: t.arg.string(),
|
|
450
|
+
untagged: t.arg.boolean(),
|
|
429
451
|
},
|
|
430
|
-
resolve: (parent, args) =>
|
|
431
|
-
|
|
432
|
-
(
|
|
433
|
-
(!args.operationId ||
|
|
434
|
-
(!args.path ||
|
|
435
|
-
(!args.method ||
|
|
436
|
-
(!args.tag ||
|
|
437
|
-
|
|
452
|
+
resolve: (parent, args, ctx) =>
|
|
453
|
+
ctx.operations.filter((op) => {
|
|
454
|
+
return (
|
|
455
|
+
(!args.operationId || op.operationId === args.operationId) &&
|
|
456
|
+
(!args.path || op.path === args.path) &&
|
|
457
|
+
(!args.method || op.method === args.method) &&
|
|
458
|
+
(!args.tag || op.tags?.some((tag) => args.tag?.includes(tag))) &&
|
|
459
|
+
(!args.untagged || (op.tags ?? []).length === 0)
|
|
460
|
+
);
|
|
461
|
+
}),
|
|
438
462
|
}),
|
|
439
463
|
}),
|
|
440
464
|
});
|
|
@@ -467,6 +491,10 @@ builder.queryType({
|
|
|
467
491
|
}
|
|
468
492
|
|
|
469
493
|
ctx.schema = schema;
|
|
494
|
+
ctx.operations = getAllOperations(schema.paths);
|
|
495
|
+
ctx.slugify = slugifyWithCounter();
|
|
496
|
+
ctx.tags = getAllTags(schema);
|
|
497
|
+
|
|
470
498
|
return schema;
|
|
471
499
|
},
|
|
472
500
|
}),
|
|
@@ -89,10 +89,10 @@ export const ColorizedParam = ({
|
|
|
89
89
|
<span
|
|
90
90
|
{...{ [DATA_ATTR]: normalizedSlug }}
|
|
91
91
|
className={cn(
|
|
92
|
-
|
|
93
|
-
"rounded-lg",
|
|
92
|
+
// This may not contain (inline-)flex or (inline-)block otherwise it breaks the browser's full text search
|
|
93
|
+
"relative rounded transition-all duration-100 rounded-lg",
|
|
94
94
|
"border border-[--border-color] p-0.5 text-[--param-color] bg-[--background-color]",
|
|
95
|
-
"data-[active=true]:border-[--param-color] data-[active=true]:shadow data-[active=true]
|
|
95
|
+
"data-[active=true]:border-[--param-color] data-[active=true]:shadow data-[active=true]:bottom-px",
|
|
96
96
|
className,
|
|
97
97
|
)}
|
|
98
98
|
title={title}
|
|
@@ -77,14 +77,14 @@ export const Endpoint = () => {
|
|
|
77
77
|
setSelectedServer(e.target.value);
|
|
78
78
|
})
|
|
79
79
|
}
|
|
80
|
-
value={selectedServer ??
|
|
80
|
+
value={selectedServer ?? servers.at(0)!.url}
|
|
81
81
|
showChevrons={servers.length > 1}
|
|
82
82
|
options={servers.map((server) => ({
|
|
83
83
|
value: server.url,
|
|
84
84
|
label: server.url,
|
|
85
85
|
}))}
|
|
86
86
|
/>
|
|
87
|
-
<CopyButton url={selectedServer ??
|
|
87
|
+
<CopyButton url={selectedServer ?? servers.at(0)!.url} />
|
|
88
88
|
</div>
|
|
89
89
|
);
|
|
90
90
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Outlet
|
|
1
|
+
import { Outlet } from "react-router";
|
|
2
2
|
import { joinPath } from "../../util/joinPath.js";
|
|
3
3
|
import type { GraphQLClient } from "./client/GraphQLClient.js";
|
|
4
4
|
import { GraphQLProvider } from "./client/GraphQLContext.js";
|
|
@@ -8,16 +8,16 @@ import { type OasPluginConfig } from "./interfaces.js";
|
|
|
8
8
|
export const OpenApiRoute = ({
|
|
9
9
|
basePath,
|
|
10
10
|
versions,
|
|
11
|
+
version,
|
|
11
12
|
config,
|
|
12
13
|
client,
|
|
13
14
|
}: {
|
|
14
15
|
basePath: string;
|
|
16
|
+
version?: string;
|
|
15
17
|
versions: string[];
|
|
16
18
|
config: OasPluginConfig;
|
|
17
19
|
client: GraphQLClient;
|
|
18
20
|
}) => {
|
|
19
|
-
const { version } = useParams<"version">();
|
|
20
|
-
|
|
21
21
|
const input =
|
|
22
22
|
config.type === "file"
|
|
23
23
|
? {
|