zudoku 0.0.0-fb7d300 → 0.0.0-fc5c03b
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/client.d.ts +7 -0
- package/dist/app/entry.client.d.ts +1 -0
- package/dist/app/entry.client.js +13 -0
- package/dist/app/entry.client.js.map +1 -1
- package/dist/app/entry.server.d.ts +1 -0
- package/dist/app/entry.server.js +1 -0
- package/dist/app/entry.server.js.map +1 -1
- package/dist/app/main.js +2 -1
- package/dist/app/main.js.map +1 -1
- package/dist/app/sentry.d.ts +3 -0
- package/dist/app/sentry.js +19 -0
- package/dist/app/sentry.js.map +1 -0
- package/dist/app/tailwind.d.ts +2 -1
- package/dist/app/tailwind.js +64 -52
- package/dist/app/tailwind.js.map +1 -1
- package/dist/cli/cli.js +0 -2
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/common/logger.js +9 -0
- package/dist/cli/common/logger.js.map +1 -1
- package/dist/cli/common/outdated.js +2 -1
- package/dist/cli/common/outdated.js.map +1 -1
- package/dist/config/common.d.ts +8 -0
- package/dist/config/common.js +2 -0
- package/dist/config/common.js.map +1 -0
- package/dist/config/config.d.ts +3 -2
- package/dist/config/loader.d.ts +20 -0
- package/dist/config/loader.js +154 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/validators/InputSidebarSchema.d.ts +14 -13
- package/dist/config/validators/InputSidebarSchema.js.map +1 -1
- package/dist/config/validators/common.d.ts +4911 -0
- package/dist/config/validators/common.js +276 -0
- package/dist/config/validators/common.js.map +1 -0
- package/dist/config/validators/icon-types.d.ts +1 -0
- package/dist/config/validators/icon-types.js +2 -0
- package/dist/config/validators/icon-types.js.map +1 -0
- package/dist/config/validators/validate.d.ts +777 -521
- package/dist/config/validators/validate.js +9 -228
- package/dist/config/validators/validate.js.map +1 -1
- package/dist/lib/authentication/providers/openid.js +7 -2
- package/dist/lib/authentication/providers/openid.js.map +1 -1
- package/dist/lib/components/Heading.d.ts +4 -4
- package/dist/lib/components/Heading.js +1 -1
- package/dist/lib/components/Heading.js.map +1 -1
- package/dist/lib/components/Layout.js +3 -2
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/Markdown.js +1 -1
- package/dist/lib/components/Markdown.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/ReactMarkdown.d.ts +29 -0
- package/dist/lib/components/ReactMarkdown.js +182 -0
- package/dist/lib/components/ReactMarkdown.js.map +1 -0
- package/dist/lib/components/Search.d.ts +3 -1
- package/dist/lib/components/Search.js +3 -3
- package/dist/lib/components/Search.js.map +1 -1
- package/dist/lib/components/SyntaxHighlight.js +0 -4
- package/dist/lib/components/SyntaxHighlight.js.map +1 -1
- package/dist/lib/components/TopNavigation.d.ts +1 -1
- package/dist/lib/components/navigation/Sidebar.d.ts +3 -1
- package/dist/lib/components/navigation/Sidebar.js +2 -2
- package/dist/lib/components/navigation/Sidebar.js.map +1 -1
- package/dist/lib/components/navigation/SidebarCategory.d.ts +2 -2
- package/dist/lib/components/navigation/SidebarCategory.js +3 -4
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/components/navigation/SidebarItem.d.ts +2 -4
- package/dist/lib/components/navigation/SidebarItem.js +5 -10
- package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
- package/dist/lib/components/navigation/SidebarWrapper.js +1 -1
- package/dist/lib/components/navigation/SidebarWrapper.js.map +1 -1
- package/dist/lib/core/ZudokuContext.d.ts +1 -1
- package/dist/lib/oas/graphql/index.js +4 -1
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/oas/parser/upgrade/index.d.ts +2 -2
- package/dist/lib/oas/parser/upgrade/index.js +3 -20
- package/dist/lib/oas/parser/upgrade/index.js.map +1 -1
- package/dist/lib/plugins/api-catalog/Catalog.d.ts +6 -0
- package/dist/lib/plugins/api-catalog/Catalog.js +29 -0
- package/dist/lib/plugins/api-catalog/Catalog.js.map +1 -0
- package/dist/lib/plugins/api-catalog/index.d.ts +23 -0
- package/dist/lib/plugins/api-catalog/index.js +15 -0
- package/dist/lib/plugins/api-catalog/index.js.map +1 -0
- package/dist/lib/plugins/markdown/MdxPage.d.ts +9 -1
- package/dist/lib/plugins/markdown/MdxPage.js +15 -2
- package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
- package/dist/lib/plugins/markdown/index.d.ts +2 -1
- package/dist/lib/plugins/markdown/index.js +1 -1
- package/dist/lib/plugins/markdown/index.js.map +1 -1
- package/dist/lib/plugins/markdown/resolver.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +47 -2
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/client/GraphQLClient.js +12 -0
- package/dist/lib/plugins/openapi/client/GraphQLClient.js.map +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +1 -1
- package/dist/lib/plugins/openapi/client/useCreateQuery.js +4 -2
- package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.js +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +2 -0
- package/dist/lib/plugins/openapi/graphql/graphql.js +1 -0
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/interfaces.d.ts +1 -1
- 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/post-processors/removeExtensions.d.ts +6 -0
- package/dist/lib/plugins/openapi/post-processors/removeExtensions.js +14 -0
- package/dist/lib/plugins/openapi/post-processors/removeExtensions.js.map +1 -0
- package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.d.ts +1 -0
- package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js +125 -0
- package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js.map +1 -0
- package/dist/lib/plugins/openapi/post-processors/removePaths.d.ts +11 -0
- package/dist/lib/plugins/openapi/post-processors/removePaths.js +33 -0
- package/dist/lib/plugins/openapi/post-processors/removePaths.js.map +1 -0
- package/dist/lib/plugins/openapi/post-processors/removePaths.test.d.ts +1 -0
- package/dist/lib/plugins/openapi/post-processors/removePaths.test.js +104 -0
- package/dist/lib/plugins/openapi/post-processors/removePaths.test.js.map +1 -0
- package/dist/lib/plugins/openapi/post-processors/traverse.d.ts +1 -0
- package/dist/lib/plugins/openapi/post-processors/traverse.js +2 -0
- package/dist/lib/plugins/openapi/post-processors/traverse.js.map +1 -0
- package/dist/lib/plugins/redirect/index.d.ts +1 -1
- package/dist/lib/ui/Button.d.ts +1 -1
- package/dist/lib/ui/Command.d.ts +1 -1
- package/dist/lib/util/MdxComponents.d.ts +2 -3
- package/dist/lib/util/MdxComponents.js.map +1 -1
- package/dist/lib/util/traverse.d.ts +2 -0
- package/dist/lib/util/traverse.js +18 -0
- package/dist/lib/util/traverse.js.map +1 -0
- package/dist/vite/build.js +15 -3
- package/dist/vite/build.js.map +1 -1
- package/dist/vite/config.d.ts +6 -4
- package/dist/vite/config.js +54 -15
- package/dist/vite/config.js.map +1 -1
- package/dist/vite/config.test.js +7 -5
- package/dist/vite/config.test.js.map +1 -1
- package/dist/vite/dev-server.js +12 -3
- package/dist/vite/dev-server.js.map +1 -1
- package/dist/vite/output.d.ts +1 -1
- package/dist/vite/output.js +39 -10
- package/dist/vite/output.js.map +1 -1
- package/dist/vite/plugin-api.js +67 -20
- package/dist/vite/plugin-api.js.map +1 -1
- package/dist/vite/plugin-component.js +15 -19
- package/dist/vite/plugin-component.js.map +1 -1
- package/dist/vite/plugin-config-reload.d.ts +1 -2
- package/dist/vite/plugin-config-reload.js.map +1 -1
- package/dist/vite/plugin-config.js +20 -0
- package/dist/vite/plugin-config.js.map +1 -1
- package/dist/vite/plugin-docs.test.js +15 -23
- package/dist/vite/plugin-docs.test.js.map +1 -1
- package/dist/vite/plugin-mdx.js +58 -4
- package/dist/vite/plugin-mdx.js.map +1 -1
- package/dist/vite/{plugin-custom-css.d.ts → plugin-theme-css.d.ts} +2 -2
- package/dist/vite/{plugin-custom-css.js → plugin-theme-css.js} +10 -3
- package/dist/vite/plugin-theme-css.js.map +1 -0
- package/dist/vite/plugin.d.ts +1 -2
- package/dist/vite/plugin.js +2 -2
- package/dist/vite/plugin.js.map +1 -1
- package/dist/vite/prerender.d.ts +2 -1
- package/dist/vite/prerender.js +2 -2
- package/dist/vite/prerender.js.map +1 -1
- package/dist/vite/sitemap.d.ts +1 -1
- package/dist/zuplo/env.d.ts +6 -0
- package/dist/zuplo/env.js +9 -0
- package/dist/zuplo/env.js.map +1 -0
- package/dist/zuplo/with-zuplo.d.ts +3 -0
- package/dist/zuplo/with-zuplo.js +28 -0
- package/dist/zuplo/with-zuplo.js.map +1 -0
- package/lib/AnchorLink-BR0MvI7n.js +35 -0
- package/lib/AnchorLink-BR0MvI7n.js.map +1 -0
- package/lib/{Markdown-ievDDhFT.js → Markdown-CRsmPPfY.js} +13084 -13096
- package/lib/Markdown-CRsmPPfY.js.map +1 -0
- package/lib/MdxPage-Wp8QU0-q.js +188 -0
- package/lib/MdxPage-Wp8QU0-q.js.map +1 -0
- package/lib/{OperationList-BwBl1xrD.js → OperationList-u8xHU9-b.js} +1031 -1016
- package/lib/OperationList-u8xHU9-b.js.map +1 -0
- package/lib/{SlotletProvider-DyomlzGx.js → SlotletProvider-BgvYIPQe.js} +2 -2
- package/lib/{SlotletProvider-DyomlzGx.js.map → SlotletProvider-BgvYIPQe.js.map} +1 -1
- package/lib/{SyntaxHighlight-DkLOsjHS.js → SyntaxHighlight-C31iouiO.js} +1 -3
- package/lib/{SyntaxHighlight-DkLOsjHS.js.map → SyntaxHighlight-C31iouiO.js.map} +1 -1
- package/lib/assets/{worker-CPsGZsve.js → worker-C_2va8B8.js} +8 -9
- package/lib/assets/worker-C_2va8B8.js.map +1 -0
- package/lib/{createServer-DK-g7kbB.js → createServer-BCAHdrpE.js} +4461 -5248
- package/lib/createServer-BCAHdrpE.js.map +1 -0
- package/lib/{index-DNxQ_rCt.js → index-CmdLGbbk.js} +53 -47
- package/lib/index-CmdLGbbk.js.map +1 -0
- package/lib/{AnchorLink-CDlhr8gL.js → index.esm-Bm8pj-bc.js} +223 -254
- package/lib/index.esm-Bm8pj-bc.js.map +1 -0
- package/lib/object_hash-CvlLgU-M.js +785 -0
- package/lib/object_hash-CvlLgU-M.js.map +1 -0
- package/lib/post-processors/removeExtensions.js +11 -0
- package/lib/post-processors/removeExtensions.js.map +1 -0
- package/lib/post-processors/removePaths.js +28 -0
- package/lib/post-processors/removePaths.js.map +1 -0
- package/lib/post-processors/traverse.js +12 -0
- package/lib/post-processors/traverse.js.map +1 -0
- package/lib/ui/Drawer.js +79 -79
- package/lib/ui/Drawer.js.map +1 -1
- package/lib/zudoku.auth-openid.js +42 -37
- package/lib/zudoku.auth-openid.js.map +1 -1
- package/lib/zudoku.components.js +386 -367
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.openapi-worker.js +1 -1
- package/lib/zudoku.plugin-api-catalog.js +121 -0
- package/lib/zudoku.plugin-api-catalog.js.map +1 -0
- package/lib/zudoku.plugin-api-keys.js +1 -1
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +15 -14
- package/lib/zudoku.plugin-markdown.js.map +1 -1
- package/lib/zudoku.plugin-openapi.js +1 -1
- package/lib/zudoku.plugin-redirect.js.map +1 -1
- package/package.json +32 -9
- package/src/app/entry.client.tsx +15 -0
- package/src/app/entry.server.tsx +1 -0
- package/src/app/main.tsx +5 -1
- package/src/app/sentry.ts +24 -0
- package/src/app/tailwind.ts +67 -52
- package/src/lib/authentication/providers/openid.tsx +7 -2
- package/src/lib/components/Heading.tsx +13 -13
- package/src/lib/components/Layout.tsx +8 -3
- package/src/lib/components/Markdown.tsx +1 -1
- package/src/lib/components/MobileTopNavigation.tsx +18 -18
- package/src/lib/components/ReactMarkdown.license.txt +21 -0
- package/src/lib/components/ReactMarkdown.tsx +264 -0
- package/src/lib/components/Search.tsx +3 -3
- package/src/lib/components/SyntaxHighlight.tsx +0 -4
- package/src/lib/components/TopNavigation.tsx +1 -1
- package/src/lib/components/navigation/Sidebar.tsx +18 -8
- package/src/lib/components/navigation/SidebarCategory.tsx +10 -9
- package/src/lib/components/navigation/SidebarItem.tsx +10 -13
- package/src/lib/components/navigation/SidebarWrapper.tsx +1 -1
- package/src/lib/core/ZudokuContext.ts +1 -1
- package/src/lib/oas/graphql/index.ts +4 -1
- package/src/lib/oas/parser/upgrade/index.ts +4 -27
- package/src/lib/plugins/api-catalog/Catalog.tsx +124 -0
- package/src/lib/plugins/api-catalog/index.tsx +50 -0
- package/src/lib/plugins/markdown/MdxPage.tsx +27 -1
- package/src/lib/plugins/markdown/index.tsx +3 -1
- package/src/lib/plugins/markdown/resolver.ts +2 -4
- package/src/lib/plugins/openapi/OperationList.tsx +64 -3
- package/src/lib/plugins/openapi/client/GraphQLClient.tsx +17 -0
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +5 -2
- package/src/lib/plugins/openapi/graphql/gql.ts +2 -2
- package/src/lib/plugins/openapi/graphql/graphql.ts +3 -0
- package/src/lib/plugins/openapi/interfaces.ts +1 -1
- package/src/lib/plugins/openapi/playground/PathParams.tsx +1 -0
- package/src/lib/plugins/openapi/post-processors/removeExtensions.test.ts +144 -0
- package/src/lib/plugins/openapi/post-processors/removeExtensions.ts +24 -0
- package/src/lib/plugins/openapi/post-processors/removePaths.test.ts +126 -0
- package/src/lib/plugins/openapi/post-processors/removePaths.ts +55 -0
- package/src/lib/plugins/openapi/post-processors/traverse.ts +1 -0
- package/src/lib/plugins/redirect/index.tsx +1 -1
- package/src/lib/util/MdxComponents.tsx +2 -5
- package/src/lib/util/traverse.ts +25 -0
- package/dist/vite/plugin-custom-css.js.map +0 -1
- package/lib/AnchorLink-CDlhr8gL.js.map +0 -1
- package/lib/Markdown-ievDDhFT.js.map +0 -1
- package/lib/MdxPage-Bwn-VSsH.js +0 -174
- package/lib/MdxPage-Bwn-VSsH.js.map +0 -1
- package/lib/OperationList-BwBl1xrD.js.map +0 -1
- package/lib/assets/worker-CPsGZsve.js.map +0 -1
- package/lib/createServer-DK-g7kbB.js.map +0 -1
- package/lib/index-DNxQ_rCt.js.map +0 -1
- package/lib/prism-markup-templating-DZrrEs0A.js +0 -62
- package/lib/prism-markup-templating-DZrrEs0A.js.map +0 -1
- package/lib/prism-php.min-o7FpoMP_.js +0 -11
- package/lib/prism-php.min-o7FpoMP_.js.map +0 -1
|
@@ -10,10 +10,10 @@ import { useIsCategoryOpen } from "./utils.js";
|
|
|
10
10
|
|
|
11
11
|
export const SidebarCategory = ({
|
|
12
12
|
category,
|
|
13
|
-
|
|
13
|
+
onRequestClose,
|
|
14
14
|
}: {
|
|
15
15
|
category: SidebarItemCategory;
|
|
16
|
-
|
|
16
|
+
onRequestClose?: () => void;
|
|
17
17
|
}) => {
|
|
18
18
|
const isCategoryOpen = useIsCategoryOpen(category);
|
|
19
19
|
const [hasInteracted, setHasInteracted] = useState(false);
|
|
@@ -65,7 +65,6 @@ export const SidebarCategory = ({
|
|
|
65
65
|
onClick={() => setHasInteracted(true)}
|
|
66
66
|
className={navigationListItem({
|
|
67
67
|
isActive: false,
|
|
68
|
-
isTopLevel: level === 0,
|
|
69
68
|
className: [
|
|
70
69
|
"text-start",
|
|
71
70
|
isCollapsible
|
|
@@ -77,10 +76,7 @@ export const SidebarCategory = ({
|
|
|
77
76
|
{category.icon && (
|
|
78
77
|
<category.icon
|
|
79
78
|
size={16}
|
|
80
|
-
className={cn(
|
|
81
|
-
"align-[-0.125em] -translate-x-1",
|
|
82
|
-
isActive && "text-primary",
|
|
83
|
-
)}
|
|
79
|
+
className={cn("align-[-0.125em] ", isActive && "text-primary")}
|
|
84
80
|
/>
|
|
85
81
|
)}
|
|
86
82
|
{category.link?.type === "doc" ? (
|
|
@@ -116,9 +112,14 @@ export const SidebarCategory = ({
|
|
|
116
112
|
className={cn(
|
|
117
113
|
// CollapsibleContent class is used to animate and it should only be applied when the user has triggered the toggle
|
|
118
114
|
hasInteracted && "CollapsibleContent",
|
|
115
|
+
"ms-6 my-1",
|
|
119
116
|
)}
|
|
120
117
|
>
|
|
121
|
-
<ul
|
|
118
|
+
<ul
|
|
119
|
+
className={
|
|
120
|
+
"relative after:absolute after:-left-[--padding-nav-item] after:translate-x-[1.5px] after:top-0 after:bottom-0 after:w-px after:bg-border"
|
|
121
|
+
}
|
|
122
|
+
>
|
|
122
123
|
{category.items.map((item) => (
|
|
123
124
|
<SidebarItem
|
|
124
125
|
key={
|
|
@@ -126,7 +127,7 @@ export const SidebarCategory = ({
|
|
|
126
127
|
("href" in item ? item.href : "") +
|
|
127
128
|
item.label
|
|
128
129
|
}
|
|
129
|
-
|
|
130
|
+
onRequestClose={onRequestClose}
|
|
130
131
|
item={item}
|
|
131
132
|
/>
|
|
132
133
|
))}
|
|
@@ -13,10 +13,6 @@ export const navigationListItem = cva(
|
|
|
13
13
|
"flex items-center gap-2 px-[--padding-nav-item] py-1.5 rounded-lg hover:bg-accent transition-colors duration-300",
|
|
14
14
|
{
|
|
15
15
|
variants: {
|
|
16
|
-
isTopLevel: {
|
|
17
|
-
true: "font-medium -mx-[--padding-nav-item]",
|
|
18
|
-
false: "-mr-[--padding-nav-item] ml-[--padding-nav-item]",
|
|
19
|
-
},
|
|
20
16
|
isActive: {
|
|
21
17
|
true: "text-primary font-medium",
|
|
22
18
|
false: "text-foreground/80",
|
|
@@ -36,25 +32,25 @@ export const DATA_ANCHOR_ATTR = "data-anchor";
|
|
|
36
32
|
|
|
37
33
|
export const SidebarItem = ({
|
|
38
34
|
item,
|
|
39
|
-
|
|
35
|
+
onRequestClose,
|
|
40
36
|
}: {
|
|
41
37
|
item: SidebarItemType;
|
|
42
|
-
|
|
43
|
-
level?: number;
|
|
38
|
+
onRequestClose?: () => void;
|
|
44
39
|
}) => {
|
|
45
40
|
const { activeAnchor } = useViewportAnchor();
|
|
46
41
|
const [searchParams] = useSearchParams();
|
|
47
42
|
|
|
48
43
|
switch (item.type) {
|
|
49
44
|
case "category":
|
|
50
|
-
return
|
|
45
|
+
return (
|
|
46
|
+
<SidebarCategory category={item} onRequestClose={onRequestClose} />
|
|
47
|
+
);
|
|
51
48
|
case "doc":
|
|
52
49
|
return (
|
|
53
50
|
<NavLink
|
|
54
|
-
className={({ isActive }) =>
|
|
55
|
-
navigationListItem({ isActive, isTopLevel: level === 0 })
|
|
56
|
-
}
|
|
51
|
+
className={({ isActive }) => navigationListItem({ isActive })}
|
|
57
52
|
to={joinPath(item.id)}
|
|
53
|
+
onClick={onRequestClose}
|
|
58
54
|
>
|
|
59
55
|
{item.icon && <item.icon size={16} className="align-[-0.125em]" />}
|
|
60
56
|
{item.badge ? (
|
|
@@ -76,9 +72,9 @@ export const SidebarItem = ({
|
|
|
76
72
|
{...{ [DATA_ANCHOR_ATTR]: item.href.slice(1) }}
|
|
77
73
|
className={navigationListItem({
|
|
78
74
|
isActive: item.href.slice(1) === activeAnchor,
|
|
79
|
-
isTopLevel: level === 0,
|
|
80
75
|
className: item.badge?.placement !== "start" && "justify-between",
|
|
81
76
|
})}
|
|
77
|
+
onClick={onRequestClose}
|
|
82
78
|
>
|
|
83
79
|
{item.badge ? (
|
|
84
80
|
<>
|
|
@@ -111,10 +107,11 @@ export const SidebarItem = ({
|
|
|
111
107
|
</NavLink>
|
|
112
108
|
) : (
|
|
113
109
|
<a
|
|
114
|
-
className={navigationListItem(
|
|
110
|
+
className={navigationListItem()}
|
|
115
111
|
href={item.href}
|
|
116
112
|
target="_blank"
|
|
117
113
|
rel="noopener noreferrer"
|
|
114
|
+
onClick={onRequestClose}
|
|
118
115
|
>
|
|
119
116
|
<span className="whitespace-normal">{item.label}</span>
|
|
120
117
|
{/* This prevents that the icon would be positioned in its own line if the text fills a line entirely */}
|
|
@@ -13,7 +13,7 @@ export const SidebarWrapper = forwardRef<
|
|
|
13
13
|
data-navigation={String(pushMainContent)}
|
|
14
14
|
className={cn(
|
|
15
15
|
"scrollbar peer hidden lg:flex flex-col fixed text-sm overflow-y-auto shrink-0",
|
|
16
|
-
"
|
|
16
|
+
"-mx-[--padding-nav-item] pb-20 mt-[--padding-content-top]",
|
|
17
17
|
"w-[--side-nav-width] h-[calc(100%-var(--header-height))] scroll-pt-2 gap-2",
|
|
18
18
|
className,
|
|
19
19
|
)}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
+
import { TopNavigationItem } from "../../config/validators/common.js";
|
|
2
3
|
import type { SidebarConfig } from "../../config/validators/SidebarSchema.js";
|
|
3
|
-
import { TopNavigationItem } from "../../config/validators/validate.js";
|
|
4
4
|
import { type AuthenticationProvider } from "../authentication/authentication.js";
|
|
5
5
|
import type { ComponentsContextType } from "../components/context/ComponentsContext.js";
|
|
6
6
|
import { Slotlets } from "../components/SlotletProvider.js";
|
|
@@ -390,6 +390,10 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
|
|
|
390
390
|
resolve: (root) => root.info.description,
|
|
391
391
|
nullable: true,
|
|
392
392
|
}),
|
|
393
|
+
summary: t.string({
|
|
394
|
+
resolve: (root) => root.info.summary,
|
|
395
|
+
nullable: true,
|
|
396
|
+
}),
|
|
393
397
|
paths: t.field({
|
|
394
398
|
type: [PathItem],
|
|
395
399
|
resolve: (root) =>
|
|
@@ -439,7 +443,6 @@ const SchemaSource = builder.enumType("SchemaType", {
|
|
|
439
443
|
|
|
440
444
|
builder.queryType({
|
|
441
445
|
fields: (t) => ({
|
|
442
|
-
// https://tan-cow-main-bce8a06.d2.zuplo.dev/openapi
|
|
443
446
|
schema: t.field({
|
|
444
447
|
type: Schema,
|
|
445
448
|
args: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { type RecordAny, traverse } from "../../../util/traverse.js";
|
|
2
3
|
import type { OpenAPIDocument } from "../index.js";
|
|
3
4
|
/**
|
|
4
5
|
* Upgrade from OpenAPI 3.0.x to 3.1.0
|
|
@@ -6,30 +7,8 @@ import type { OpenAPIDocument } from "../index.js";
|
|
|
6
7
|
* Taken from https://github.com/scalar/openapi-parser/blob/main/packages/openapi-parser/src/utils/upgradeFromThreeToThreeOne.ts
|
|
7
8
|
* https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0
|
|
8
9
|
*/
|
|
9
|
-
export function traverse(
|
|
10
|
-
specification: Record<string, any>,
|
|
11
|
-
transform: (specification: Record<string, any>) => Record<string, any>,
|
|
12
|
-
) {
|
|
13
|
-
const result: Record<string, any> = {};
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
if (Array.isArray(value)) {
|
|
17
|
-
result[key] = value.map((item) =>
|
|
18
|
-
typeof item === "object" && item !== null
|
|
19
|
-
? traverse(item, transform)
|
|
20
|
-
: item,
|
|
21
|
-
);
|
|
22
|
-
} else if (typeof value === "object" && value !== null) {
|
|
23
|
-
result[key] = traverse(value, transform);
|
|
24
|
-
} else {
|
|
25
|
-
result[key] = value;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return transform(result);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const upgradeSchema = (schema: Record<string, any>): OpenAPIDocument => {
|
|
11
|
+
export const upgradeSchema = (schema: RecordAny): OpenAPIDocument => {
|
|
33
12
|
if (schema.openapi?.startsWith("3.0")) {
|
|
34
13
|
schema.openapi = "3.1.0";
|
|
35
14
|
}
|
|
@@ -64,9 +43,7 @@ export const upgradeSchema = (schema: Record<string, any>): OpenAPIDocument => {
|
|
|
64
43
|
schema = traverse(schema, (sub) => {
|
|
65
44
|
if (sub.example !== undefined) {
|
|
66
45
|
sub.examples = {
|
|
67
|
-
default:
|
|
68
|
-
value: sub.example,
|
|
69
|
-
},
|
|
46
|
+
default: sub.example,
|
|
70
47
|
};
|
|
71
48
|
delete sub.example;
|
|
72
49
|
}
|
|
@@ -77,7 +54,7 @@ export const upgradeSchema = (schema: Record<string, any>): OpenAPIDocument => {
|
|
|
77
54
|
schema = traverse(schema, (sub) => {
|
|
78
55
|
if (sub.type === "object" && sub.properties !== undefined) {
|
|
79
56
|
for (const [, value] of Object.entries(sub.properties)) {
|
|
80
|
-
const v = (value ?? {}) as
|
|
57
|
+
const v = (value ?? {}) as RecordAny;
|
|
81
58
|
if (v.type === "string" && v.format === "binary") {
|
|
82
59
|
v.contentEncoding = "application/octet-stream";
|
|
83
60
|
delete v.format;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import slugify from "@sindresorhus/slugify";
|
|
2
|
+
import { Fragment } from "react";
|
|
3
|
+
import { Head, Link } from "zudoku/components";
|
|
4
|
+
import { Markdown } from "../../components/Markdown.js";
|
|
5
|
+
import { useExposedProps } from "../../util/useExposedProps.js";
|
|
6
|
+
import type { ApiCatalogItem, CatalogCategory } from "./index.js";
|
|
7
|
+
|
|
8
|
+
export const Catalog = ({
|
|
9
|
+
items,
|
|
10
|
+
categories,
|
|
11
|
+
label = "API Library",
|
|
12
|
+
}: {
|
|
13
|
+
label: string;
|
|
14
|
+
items: ApiCatalogItem[];
|
|
15
|
+
categories: CatalogCategory[];
|
|
16
|
+
}) => {
|
|
17
|
+
const { searchParams, setSearchParams } = useExposedProps();
|
|
18
|
+
const activeCategory = searchParams.get("category");
|
|
19
|
+
return (
|
|
20
|
+
<section className="pt-[--padding-content-top] pb-[--padding-content-bottom]">
|
|
21
|
+
<Head>
|
|
22
|
+
<title>{label}</title>
|
|
23
|
+
</Head>
|
|
24
|
+
<div className="grid grid-cols-12 gap-12">
|
|
25
|
+
<div className="flex flex-col gap-4 col-span-3 px-4 not-prose sticky top-48">
|
|
26
|
+
<div className="justify-between">
|
|
27
|
+
{categories.map((category, idx) => (
|
|
28
|
+
<Fragment key={category.label}>
|
|
29
|
+
<div className="flex justify-between mb-2.5">
|
|
30
|
+
<span className="font-medium text-sm">{category.label}</span>
|
|
31
|
+
{idx === 0 && activeCategory && (
|
|
32
|
+
<button
|
|
33
|
+
type="button"
|
|
34
|
+
className="text-end text-sm mr-8 text-foreground/60 hover:text-foreground"
|
|
35
|
+
onClick={() => setSearchParams({})}
|
|
36
|
+
>
|
|
37
|
+
Clear
|
|
38
|
+
</button>
|
|
39
|
+
)}
|
|
40
|
+
</div>
|
|
41
|
+
<ul className="space-y-1 [&>li]:py-2">
|
|
42
|
+
{Array.from(
|
|
43
|
+
new Set(
|
|
44
|
+
category.tags
|
|
45
|
+
.map((tag) => ({
|
|
46
|
+
tag,
|
|
47
|
+
count: items.filter((api) =>
|
|
48
|
+
api.categories.find((c) => c.tags.includes(tag)),
|
|
49
|
+
).length,
|
|
50
|
+
}))
|
|
51
|
+
.map(({ tag, count }) => (
|
|
52
|
+
<li
|
|
53
|
+
key={slugify(category.label + " " + tag)}
|
|
54
|
+
className={`flex px-4 rounded-lg -translate-x-4 justify-between text-sm cursor-pointer hover:text-primary transition ${
|
|
55
|
+
slugify(tag) === activeCategory
|
|
56
|
+
? "font-medium bg-border/30 rounded"
|
|
57
|
+
: ""
|
|
58
|
+
}`}
|
|
59
|
+
onClick={() =>
|
|
60
|
+
setSearchParams({
|
|
61
|
+
category: slugify(category.label + " " + tag),
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
>
|
|
65
|
+
<span>{tag}</span>
|
|
66
|
+
<span
|
|
67
|
+
className={`flex items-center justify-center border rounded-md w-8 text-xs font-semibold ${
|
|
68
|
+
slugify(tag) === activeCategory
|
|
69
|
+
? "bg-primary border-primary text-primary-foreground"
|
|
70
|
+
: ""
|
|
71
|
+
}`}
|
|
72
|
+
>
|
|
73
|
+
{count}
|
|
74
|
+
</span>
|
|
75
|
+
</li>
|
|
76
|
+
)),
|
|
77
|
+
),
|
|
78
|
+
)}
|
|
79
|
+
</ul>
|
|
80
|
+
</Fragment>
|
|
81
|
+
))}
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
<div className="col-span-9">
|
|
85
|
+
<h3 className="mt-0 text-2xl font-bold mb-4">{label}</h3>
|
|
86
|
+
|
|
87
|
+
<div className="grid grid-cols-2 gap-4">
|
|
88
|
+
{items
|
|
89
|
+
.filter(
|
|
90
|
+
(api) =>
|
|
91
|
+
!activeCategory ||
|
|
92
|
+
api.categories.find((c) =>
|
|
93
|
+
c.tags.find(
|
|
94
|
+
(t) => slugify(c.label + " " + t) === activeCategory,
|
|
95
|
+
),
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
.map((api, i) => (
|
|
99
|
+
<Link
|
|
100
|
+
to={{
|
|
101
|
+
pathname: `/${api.path}`,
|
|
102
|
+
search: activeCategory ? `category=${activeCategory}` : "",
|
|
103
|
+
}}
|
|
104
|
+
className="no-underline hover:!text-foreground"
|
|
105
|
+
key={api.path}
|
|
106
|
+
>
|
|
107
|
+
<div
|
|
108
|
+
className="border h-full rounded p-4 flex flex-col gap-2 cursor-pointer hover:bg-border/20 font-normal"
|
|
109
|
+
key={i}
|
|
110
|
+
>
|
|
111
|
+
<span className="font-semibold">{api.label}</span>
|
|
112
|
+
<Markdown
|
|
113
|
+
className="text-sm whitespace-pre-wrap mb-6 line-clamp-2"
|
|
114
|
+
content={api.description}
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
</Link>
|
|
118
|
+
))}
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</section>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ZudokuPlugin } from "../../core/plugins.js";
|
|
2
|
+
import { Catalog } from "./Catalog.js";
|
|
3
|
+
|
|
4
|
+
export type ApiCatalogItem = {
|
|
5
|
+
path: string;
|
|
6
|
+
label: string;
|
|
7
|
+
description: string;
|
|
8
|
+
categories: CatalogCategory[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type CatalogCategory = {
|
|
12
|
+
label: string;
|
|
13
|
+
tags: string[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type ApiCatalogPluginOptions = {
|
|
17
|
+
navigationId: string;
|
|
18
|
+
label: string;
|
|
19
|
+
categories?: CatalogCategory[];
|
|
20
|
+
items: ApiCatalogItem[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const apiCatalogPlugin = ({
|
|
24
|
+
navigationId,
|
|
25
|
+
items,
|
|
26
|
+
label,
|
|
27
|
+
categories,
|
|
28
|
+
}: {
|
|
29
|
+
navigationId: string;
|
|
30
|
+
label: string;
|
|
31
|
+
categories?: CatalogCategory[];
|
|
32
|
+
items: ApiCatalogItem[];
|
|
33
|
+
}): ZudokuPlugin => {
|
|
34
|
+
return {
|
|
35
|
+
getRoutes: () => {
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
path: navigationId,
|
|
39
|
+
element: (
|
|
40
|
+
<Catalog
|
|
41
|
+
label={label}
|
|
42
|
+
items={items}
|
|
43
|
+
categories={categories ?? []}
|
|
44
|
+
/>
|
|
45
|
+
),
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useMDXComponents } from "@mdx-js/react";
|
|
2
2
|
import slugify from "@sindresorhus/slugify";
|
|
3
3
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
4
|
-
import { type PropsWithChildren } from "react";
|
|
4
|
+
import { type PropsWithChildren, useEffect } from "react";
|
|
5
5
|
import { Link } from "react-router-dom";
|
|
6
6
|
import { CategoryHeading } from "../../components/CategoryHeading.js";
|
|
7
7
|
import { Heading } from "../../components/Heading.js";
|
|
@@ -15,6 +15,14 @@ import { cn } from "../../util/cn.js";
|
|
|
15
15
|
import { Toc } from "./Toc.js";
|
|
16
16
|
import { MarkdownPluginDefaultOptions, MDXImport } from "./index.js";
|
|
17
17
|
|
|
18
|
+
declare global {
|
|
19
|
+
interface Window {
|
|
20
|
+
__getReactRefreshIgnoredExports?: (args: {
|
|
21
|
+
id: string;
|
|
22
|
+
}) => string[] | undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
18
26
|
const MarkdownHeadings = {
|
|
19
27
|
h2: ({ children, id }) => (
|
|
20
28
|
<Heading level={2} id={id} registerSidebarAnchor>
|
|
@@ -30,11 +38,14 @@ const MarkdownHeadings = {
|
|
|
30
38
|
|
|
31
39
|
export const MdxPage = ({
|
|
32
40
|
mdxComponent: MdxComponent,
|
|
41
|
+
file,
|
|
33
42
|
frontmatter = {},
|
|
34
43
|
defaultOptions,
|
|
35
44
|
tableOfContents,
|
|
45
|
+
excerpt,
|
|
36
46
|
}: PropsWithChildren<
|
|
37
47
|
Omit<MDXImport, "default"> & {
|
|
48
|
+
file: string;
|
|
38
49
|
mdxComponent: MDXImport["default"];
|
|
39
50
|
defaultOptions?: MarkdownPluginDefaultOptions;
|
|
40
51
|
}
|
|
@@ -57,10 +68,25 @@ export const MdxPage = ({
|
|
|
57
68
|
|
|
58
69
|
const { prev, next } = usePrevNext();
|
|
59
70
|
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (process.env.NODE_ENV === "development") {
|
|
73
|
+
window.__getReactRefreshIgnoredExports = ({ id }) => {
|
|
74
|
+
if (!id.endsWith(file)) return;
|
|
75
|
+
|
|
76
|
+
return ["frontmatter", "tableOfContents"];
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return () => {
|
|
80
|
+
window.__getReactRefreshIgnoredExports = undefined;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}, [file]);
|
|
84
|
+
|
|
60
85
|
return (
|
|
61
86
|
<div className="xl:grid grid-cols-[--sidecar-grid-cols] gap-8 justify-between">
|
|
62
87
|
<Helmet>
|
|
63
88
|
<title>{pageTitle}</title>
|
|
89
|
+
{excerpt && <meta name="description" content={excerpt} />}
|
|
64
90
|
</Helmet>
|
|
65
91
|
<div
|
|
66
92
|
className={cn(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Toc } from "@stefanprobst/rehype-extract-toc";
|
|
2
2
|
import type { MDXProps } from "mdx/types.js";
|
|
3
3
|
import { RouteObject } from "react-router-dom";
|
|
4
|
-
import { ZudokuDocsConfig } from "../../../config/validators/
|
|
4
|
+
import { ZudokuDocsConfig } from "../../../config/validators/common.js";
|
|
5
5
|
import type { ZudokuPlugin } from "../../core/plugins.js";
|
|
6
6
|
import { DocResolver } from "./resolver.js";
|
|
7
7
|
|
|
@@ -24,6 +24,7 @@ export type Frontmatter = {
|
|
|
24
24
|
export type MDXImport = {
|
|
25
25
|
tableOfContents: Toc;
|
|
26
26
|
frontmatter: Frontmatter;
|
|
27
|
+
excerpt?: string;
|
|
27
28
|
default: (props: MDXProps) => JSX.Element;
|
|
28
29
|
};
|
|
29
30
|
|
|
@@ -57,6 +58,7 @@ export const markdownPlugin = (
|
|
|
57
58
|
return {
|
|
58
59
|
element: (
|
|
59
60
|
<MdxPage
|
|
61
|
+
file={file}
|
|
60
62
|
mdxComponent={Component}
|
|
61
63
|
{...props}
|
|
62
64
|
defaultOptions={defaultOptions}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
ZudokuDocsConfig,
|
|
6
|
-
} from "../../../config/validators/validate.js";
|
|
3
|
+
import { ZudokuDocsConfig } from "../../../config/validators/common.js";
|
|
4
|
+
import { ZudokuConfig } from "../../../config/validators/validate.js";
|
|
7
5
|
|
|
8
6
|
const DEFAULT_DOCS_FILES = "/pages/**/*.{md,mdx}";
|
|
9
7
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ResultOf } from "@graphql-typed-document-node/core";
|
|
2
2
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
3
|
+
import { Helmet } from "@zudoku/react-helmet-async";
|
|
3
4
|
import { CategoryHeading } from "../../components/CategoryHeading.js";
|
|
4
5
|
import { Heading } from "../../components/Heading.js";
|
|
5
6
|
import { Markdown, ProseClasses } from "../../components/Markdown.js";
|
|
@@ -81,6 +82,7 @@ const AllOperationsQuery = graphql(/* GraphQL */ `
|
|
|
81
82
|
query AllOperations($input: JSON!, $type: SchemaType!) {
|
|
82
83
|
schema(input: $input, type: $type) {
|
|
83
84
|
description
|
|
85
|
+
summary
|
|
84
86
|
title
|
|
85
87
|
url
|
|
86
88
|
version
|
|
@@ -96,19 +98,77 @@ const AllOperationsQuery = graphql(/* GraphQL */ `
|
|
|
96
98
|
}
|
|
97
99
|
`);
|
|
98
100
|
|
|
101
|
+
/**
|
|
102
|
+
* @description Clean up a commonmark formatted description for use in the meta
|
|
103
|
+
* description.
|
|
104
|
+
*/
|
|
105
|
+
function cleanDescription(
|
|
106
|
+
description: string,
|
|
107
|
+
maxLength: number = 160,
|
|
108
|
+
): string {
|
|
109
|
+
if (!description) {
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Replace Markdown links [text](url) with just "text"
|
|
114
|
+
description = description.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
|
|
115
|
+
|
|
116
|
+
// Remove Markdown image syntax: 
|
|
117
|
+
description = description.replace(/!\[.*?\]\(.*?\)/g, "");
|
|
118
|
+
|
|
119
|
+
// Remove other Markdown syntax (e.g., **bold**, _italic_, `code`)
|
|
120
|
+
description = description.replace(/[_*`~]/g, "");
|
|
121
|
+
|
|
122
|
+
// Remove headings (# Heading), blockquotes (> Quote), and horizontal rules (--- or ***)
|
|
123
|
+
description = description.replace(/^(?:>|\s*#+|-{3,}|\*{3,})/gm, "");
|
|
124
|
+
|
|
125
|
+
// Remove any remaining formatting characters
|
|
126
|
+
description = description.replace(/[|>{}[\]]/g, "");
|
|
127
|
+
|
|
128
|
+
// Collapse multiple spaces and trim the text
|
|
129
|
+
description = description.replace(/\s+/g, " ").trim();
|
|
130
|
+
|
|
131
|
+
// Limit to the specified maximum length
|
|
132
|
+
description = description.substring(0, maxLength);
|
|
133
|
+
|
|
134
|
+
// Escape for HTML safety
|
|
135
|
+
return description
|
|
136
|
+
.replace(/&/g, "&")
|
|
137
|
+
.replace(/</g, "<")
|
|
138
|
+
.replace(/>/g, ">")
|
|
139
|
+
.replace(/"/g, """)
|
|
140
|
+
.replace(/'/g, "'");
|
|
141
|
+
}
|
|
142
|
+
|
|
99
143
|
export const OperationList = () => {
|
|
100
144
|
const { input, type } = useOasConfig();
|
|
101
145
|
const query = useCreateQuery(AllOperationsQuery, { input, type });
|
|
102
146
|
const result = useSuspenseQuery(query);
|
|
103
|
-
|
|
147
|
+
const title = result.data.schema.title;
|
|
148
|
+
const summary = result.data.schema.summary;
|
|
149
|
+
const description = result.data.schema.description;
|
|
150
|
+
// The summary property is preferable here as it is a short description of
|
|
151
|
+
// the API, whereas the description property is typically longer and supports
|
|
152
|
+
// commonmark formatting, making it ill-suited for use in the meta description
|
|
153
|
+
const metaDescription = summary
|
|
154
|
+
? summary
|
|
155
|
+
: description
|
|
156
|
+
? cleanDescription(description)
|
|
157
|
+
: undefined;
|
|
104
158
|
return (
|
|
105
159
|
<div className="pt-[--padding-content-top]">
|
|
160
|
+
<Helmet>
|
|
161
|
+
<title>{title}</title>
|
|
162
|
+
{metaDescription && (
|
|
163
|
+
<meta name="description" content={metaDescription} />
|
|
164
|
+
)}
|
|
165
|
+
</Helmet>
|
|
106
166
|
<div
|
|
107
167
|
className={cn(ProseClasses, "mb-16 max-w-full prose-img:max-w-prose")}
|
|
108
168
|
>
|
|
109
169
|
<CategoryHeading>Overview</CategoryHeading>
|
|
110
170
|
<Heading level={1} id="description" registerSidebarAnchor>
|
|
111
|
-
{
|
|
171
|
+
{title}
|
|
112
172
|
</Heading>
|
|
113
173
|
<Markdown content={result.data.schema.description ?? ""} />
|
|
114
174
|
</div>
|
|
@@ -120,7 +180,8 @@ export const OperationList = () => {
|
|
|
120
180
|
{result.data.schema.tags
|
|
121
181
|
.filter((tag) => tag.operations.length > 0)
|
|
122
182
|
.map((tag) => (
|
|
123
|
-
|
|
183
|
+
// px, -mx is so that `content-visibility` doesn't cut off overflown heading anchor links '#'
|
|
184
|
+
<div key={tag.name} className="px-6 -mx-6 [content-visibility:auto]">
|
|
124
185
|
{tag.name && <CategoryHeading>{tag.name}</CategoryHeading>}
|
|
125
186
|
{tag.description && (
|
|
126
187
|
<Markdown
|
|
@@ -15,6 +15,20 @@ type GraphQLResponse<TResult> = {
|
|
|
15
15
|
data: TResult;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
const resolveVariables = async (variables?: unknown) => {
|
|
19
|
+
if (!variables) return;
|
|
20
|
+
|
|
21
|
+
if (
|
|
22
|
+
typeof variables === "object" &&
|
|
23
|
+
"type" in variables &&
|
|
24
|
+
variables.type === "file" &&
|
|
25
|
+
"input" in variables &&
|
|
26
|
+
typeof variables.input === "function"
|
|
27
|
+
) {
|
|
28
|
+
variables.input = await variables.input();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
18
32
|
const throwIfError = (response: GraphQLResponse<unknown>) => {
|
|
19
33
|
if (!response.errors?.[0]) return;
|
|
20
34
|
|
|
@@ -47,6 +61,9 @@ export class GraphQLClient {
|
|
|
47
61
|
...[variables]: TVariables extends Record<string, never> ? [] : [TVariables]
|
|
48
62
|
) => {
|
|
49
63
|
const operationName = query.match(/query (\w+)/)?.[1];
|
|
64
|
+
|
|
65
|
+
await resolveVariables(variables);
|
|
66
|
+
|
|
50
67
|
const body = JSON.stringify({ query, variables, operationName });
|
|
51
68
|
|
|
52
69
|
switch (this.#mode) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import hashit from "object-hash";
|
|
2
|
+
import { useContext, useMemo } from "react";
|
|
2
3
|
import type { TypedDocumentString } from "../graphql/graphql.js";
|
|
3
4
|
import { GraphQLContext } from "./GraphQLContext.js";
|
|
4
5
|
|
|
@@ -11,8 +12,10 @@ export const useCreateQuery = <TResult, TVariables>(
|
|
|
11
12
|
throw new Error("useGraphQL must be used within a GraphQLProvider");
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
const hash = useMemo(() => hashit(variables[0] ?? {}), [variables]);
|
|
16
|
+
|
|
14
17
|
return {
|
|
15
18
|
queryFn: () => graphQLClient.fetch(query, ...variables),
|
|
16
|
-
queryKey: [query,
|
|
19
|
+
queryKey: [query, hash],
|
|
17
20
|
} as const;
|
|
18
21
|
};
|
|
@@ -17,7 +17,7 @@ const documents = {
|
|
|
17
17
|
types.ServersQueryDocument,
|
|
18
18
|
"\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n examples {\n name\n description\n externalValue\n value\n summary\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n examples {\n name\n description\n externalValue\n value\n summary\n }\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n":
|
|
19
19
|
types.OperationsFragmentFragmentDoc,
|
|
20
|
-
"\n query AllOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n description\n title\n url\n version\n tags {\n name\n description\n operations {\n slug\n ...OperationsFragment\n }\n }\n }\n }\n":
|
|
20
|
+
"\n query AllOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n description\n summary\n title\n url\n version\n tags {\n name\n description\n operations {\n slug\n ...OperationsFragment\n }\n }\n }\n }\n":
|
|
21
21
|
types.AllOperationsDocument,
|
|
22
22
|
"\n query getServerQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n":
|
|
23
23
|
types.GetServerQueryDocument,
|
|
@@ -41,7 +41,7 @@ export function graphql(
|
|
|
41
41
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
42
42
|
*/
|
|
43
43
|
export function graphql(
|
|
44
|
-
source: "\n query AllOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n description\n title\n url\n version\n tags {\n name\n description\n operations {\n slug\n ...OperationsFragment\n }\n }\n }\n }\n",
|
|
44
|
+
source: "\n query AllOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n description\n summary\n title\n url\n version\n tags {\n name\n description\n operations {\n slug\n ...OperationsFragment\n }\n }\n }\n }\n",
|
|
45
45
|
): typeof import("./graphql.js").AllOperationsDocument;
|
|
46
46
|
/**
|
|
47
47
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|